diff --git a/.eslintrc.js b/.eslintrc.js index 835f951d9750..16d950d13d56 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -7,6 +7,7 @@ module.exports = { // https://eslint.org/docs/4.0.0/user-guide/configuring#specifying-parser-options "parserOptions": { "ecmaVersion": 6, + "sourceType": "module", }, // http://eslint.org/docs/user-guide/configuring#specifying-environments diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 82651df5c040..926ae8247fbf 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -34,18 +34,19 @@ /corehq/warehouse/ @calellowitz /corehq/warnings.py @millerdev -/corehq/apps/accounting/ @dannyroberts @biyeun +/corehq/apps/accounting/ @dannyroberts @biyeun @nospame /corehq/apps/analytics/ @biyeun /corehq/apps/app_manager/ @orangejenny /corehq/apps/callcenter/ @snopoke -/corehq/apps/case_search/ @orangejenny @MartinRiese @esoergel @AddisonDunn @stephherbers @Robert-Costello @Jtang-1 @nospame +/corehq/apps/case_search/ @orangejenny @MartinRiese @esoergel @AddisonDunn @stephherbers @Robert-Costello @Jtang-1 /corehq/apps/change_feed/ @dannyroberts /corehq/apps/cleanup/management/commands/populate_sql_model_from_couch_model.py @millerdev -/corehq/apps/cloudcare/ @orangejenny @MartinRiese @AddisonDunn @stephherbers @Robert-Costello @Jtang-1 @nospame +/corehq/apps/cloudcare/ @MartinRiese @AddisonDunn @stephherbers @Robert-Costello @Jtang-1 @nospame /corehq/apps/commtrack/ @esoergel /corehq/apps/data_dictionary/ @esoergel @orangejenny @zandre-eng /corehq/apps/domain/decorators.py @esoergel /corehq/apps/domain/auth.py @esoergel +/corehq/apps/domain/views/accounting.py @nospame /corehq/apps/es/ @esoergel @amitphulera /corehq/apps/hqcase/ @esoergel /corehq/apps/hqwebapp/ @orangejenny @biyeun diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index db6fcdc3c852..fe40d498b91e 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -1,10 +1,10 @@ ## Product Description - + ## Technical Summary ## Feature Flag diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 1fe9c7707c5b..4a802c4cc8be 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -12,8 +12,8 @@ name: "CodeQL" on: - push: - branches: [ master ] +# push: +# branches: [ master ] # pull_request: # # The branches below must be a subset of the branches above # branches: [ master ] @@ -39,7 +39,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@v2 + uses: github/codeql-action/init@v3 with: languages: ${{ matrix.language }} # If you wish to specify custom queries, you can do so here or in a config file. @@ -50,7 +50,7 @@ jobs: # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). # If this step fails, then you should remove it and run the build manually (see below) - name: Autobuild - uses: github/codeql-action/autobuild@v2 + uses: github/codeql-action/autobuild@v3 # ℹī¸ Command-line programs to run using the OS shell. # 📚 https://git.io/JvXDl @@ -64,4 +64,4 @@ jobs: # make release - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v2 + uses: github/codeql-action/analyze@v3 diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index d7323fa20e35..796f48577ff7 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -10,6 +10,7 @@ on: schedule: # see corehq/apps/hqadmin/management/commands/static_analysis.py - cron: '47 12 * * *' + workflow_dispatch: jobs: tests: runs-on: ubuntu-22.04 diff --git a/.gitignore b/.gitignore index d3ae1d1011ed..d2beb6af5bae 100644 --- a/.gitignore +++ b/.gitignore @@ -85,3 +85,6 @@ corehq/apps/hqwebapp/static/hqwebapp/js/lib/modernizr.js # direnv .envrc .direnv + +# webpack build related +/webpack/_build/ diff --git a/DEV_FAQ.md b/DEV_FAQ.md index 04d8b580c1a9..31519c6e9fad 100644 --- a/DEV_FAQ.md +++ b/DEV_FAQ.md @@ -38,6 +38,11 @@ Formplayer isn't running properly. See [Formplayer](https://github.com/dimagi/co It happens, try restarting. +> I'm getting TemplateSyntaxErrors related to Webpack. + +Please run `yarn dev`. If this build is failing, and you didn't make any changes to JavaScript files on your branch, +please raise this as an issue. + ## Generating Sample Data ### SMS diff --git a/DEV_SETUP.md b/DEV_SETUP.md index e6582fe514e9..5bd76c3b3538 100644 --- a/DEV_SETUP.md +++ b/DEV_SETUP.md @@ -762,7 +762,23 @@ This can also be used to promote a user created by signing up to a superuser. Note that promoting a user to superuser status using this command will also give them the ability to assign other users as superuser in the in-app Superuser Management page. -### Step 11: Running CommCare HQ +### Step 11: Running `yarn dev` + +In order to build JavaScript bundles with Webpack, you will need to have `yarn dev` +running in the background. It will watch any existing Webpack Entry Point, aka modules +included on a page using the `js_entry` template tag. + +When you add a new entry point (`js_entry` tag), please remember to restart `yarn dev` so +that it can identify the new entry point it needs to watch. + +To build Webpack bundles like it's done in production environments, pleas use `yarn build`. +This command does not have a watch functionality, so it needs to be re-run every time you make +changes to javascript files bundled by Webpack. + +For more information about JavaScript and Static Files, please see the +[Dimagi JavaScript Guide](https://commcare-hq.readthedocs.io/js-guide/README.html) on Read the Docs. + +### Step 12: Running CommCare HQ Make sure the required services are running (PostgreSQL, Redis, CouchDB, Kafka, Elasticsearch). @@ -794,6 +810,9 @@ yarn install --frozen-lockfile ./manage.py fix_less_imports_collectstatic ``` +See the [Dimagi JavaScript Guide](https://commcare-hq.readthedocs.io/js-guide/README.html) for additional +useful background and tips. + ## Running Formplayer and submitting data with Web Apps Formplayer is a Java service that allows us to use applications on the web instead of on a mobile device. @@ -1196,54 +1215,3 @@ This script goes through the steps to prepare a report for test coverage of JavaScript files _that are touched by tests_, i.e., apps and files with 0% test coverage will not be shown. A coverage summary is output to the terminal and a detailed html report is generated at ``coverage-js/index.html``. - - -## Sniffer - -You can also use sniffer to auto run the Python tests. - -When running, sniffer auto-runs the specified tests whenever you save a file. - -For example, you are working on the `retire` method of `CommCareUser`. You are -writing a `RetireUserTestCase`, which you want to run every time you make a -small change to the `retire` method, or to the `testCase`. Sniffer to the -rescue! - - -### Sniffer Usage - -```sh -sniffer -x [:[.]] -``` - -In our example, we would run - -```sh -sniffer -x corehq.apps.users.tests.retire:RetireUserTestCase` -``` - -You can also add the regular `nose` environment variables, like: - -```sh -REUSE_DB=1 sniffer -x -``` - -For JavaScript tests, you can add `--js-` before the JavaScript app test name, -for example: - -```sh -sniffer -x --js-app_manager -``` - -You can combine the two to run the JavaScript tests when saving js files, and -run the Python tests when saving py files as follows: - -```sh -sniffer -x --js-app_manager -x corehq.apps.app_manager:AppManagerViewTest -``` - -### Sniffer Installation instructions - - (recommended to install `pywatchman` or -`macfsevents` for this to actually be worthwhile otherwise it takes a long time -to see the change). diff --git a/corehq/apps/accounting/decorators.py b/corehq/apps/accounting/decorators.py index 44fbad9819b1..b7416482b73e 100644 --- a/corehq/apps/accounting/decorators.py +++ b/corehq/apps/accounting/decorators.py @@ -1,7 +1,6 @@ -import json from functools import wraps -from django.http import HttpResponse +from django.http import HttpResponse, JsonResponse from django_prbac.decorators import requires_privilege from django_prbac.exceptions import PermissionDenied @@ -65,7 +64,7 @@ def requires_privilege_plaintext_response(slug, """ A version of the requires_privilege decorator which returns an HttpResponse object with HTTP Status Code of 412 by default and - content_type of tex/plain if the privilege is not found. + content_type of text/plain if the privilege is not found. """ def decorate(fn): @wraps(fn) @@ -114,8 +113,7 @@ def wrapped(request, *args, **kwargs): except PermissionDenied: error_message = "You have lost access to this feature." response = get_response(error_message, http_status_code) - return HttpResponse(json.dumps(response), - content_type="application/json", status=401) + return JsonResponse(response, status=401) return wrapped return decorate diff --git a/corehq/apps/accounting/forms.py b/corehq/apps/accounting/forms.py index 56e7a4224ad1..878eb70b92a0 100644 --- a/corehq/apps/accounting/forms.py +++ b/corehq/apps/accounting/forms.py @@ -13,8 +13,8 @@ from django.template.loader import render_to_string from django.urls import reverse from django.utils.dates import MONTHS -from django.utils.safestring import mark_safe from django.utils.html import format_html, format_html_join +from django.utils.safestring import mark_safe from django.utils.translation import gettext as _ from django.utils.translation import gettext_lazy, gettext_noop @@ -50,10 +50,12 @@ CustomerBillingRecord, CustomerInvoice, DefaultProductPlan, + DomainUserHistory, EntryPoint, Feature, FeatureRate, FeatureType, + FormSubmittingMobileWorkerHistory, FundingSource, Invoice, InvoicingPlan, @@ -68,7 +70,6 @@ Subscription, SubscriptionType, WireBillingRecord, - DomainUserHistory, ) from corehq.apps.accounting.tasks import send_subscription_reminder_emails from corehq.apps.accounting.utils import ( @@ -593,9 +594,12 @@ def __init__(self, subscription, account_id, web_user, *args, **kwargs): if is_existing: # circular import from corehq.apps.accounting.views import ( - SoftwarePlanVersionView, ManageBillingAccountView + ManageBillingAccountView, + SoftwarePlanVersionView, + ) + from corehq.apps.domain.views.settings import ( + DefaultProjectSettingsView, ) - from corehq.apps.domain.views.settings import DefaultProjectSettingsView self.fields['account'].initial = subscription.account.id account_field = hqcrispy.B3TextField( 'account', @@ -846,7 +850,9 @@ def clean(self): or not account.billingcontactinfo.email_list ) ): - from corehq.apps.accounting.views import ManageBillingAccountView + from corehq.apps.accounting.views import ( + ManageBillingAccountView, + ) raise forms.ValidationError(format_html(_( "Please update 'Client Contact Emails' " 'here ' @@ -1923,7 +1929,7 @@ def get_instance(self): return self.save(commit=False) -class EnterprisePlanContactForm(forms.Form): +class PlanContactForm(forms.Form): name = forms.CharField( label=gettext_noop("Name") ) @@ -1937,105 +1943,34 @@ class EnterprisePlanContactForm(forms.Form): widget=forms.Textarea(attrs={"class": "vertical-resize"}) ) - def __init__(self, domain, web_user, data=None, *args, **kwargs): - self.domain = domain - self.web_user = web_user - super(EnterprisePlanContactForm, self).__init__(data, *args, **kwargs) - from corehq.apps.domain.views.accounting import SelectPlanView - self.helper = FormHelper() - self.helper.label_class = 'col-sm-3 col-md-2' - self.helper.field_class = 'col-sm-9 col-md-8 col-lg-6' - self.helper.form_class = "form-horizontal" - self.helper.layout = crispy.Layout( - 'name', - 'company_name', - 'message', - hqcrispy.FormActions( - hqcrispy.LinkButton( - _("Select different plan"), - reverse(SelectPlanView.urlname, args=[self.domain]), - css_class="btn btn-default" - ), - StrictButton( - _("Request Quote"), - type="submit", - css_class="btn-primary", - ), - ) - ) - - def send_message(self): - subject = "[Enterprise Plan Request] %s" % self.domain - context = { - 'name': self.cleaned_data['name'], - 'company': self.cleaned_data['company_name'], - 'message': self.cleaned_data['message'], - 'domain': self.domain, - 'email': self.web_user.email - } - html_content = render_to_string('accounting/email/sales_request.html', context) - text_content = """ - Email: %(email)s - Name: %(name)s - Company: %(company)s - Domain: %(domain)s - Message: - %(message)s - """ % context - send_html_email_async.delay(subject, settings.BILLING_EMAIL, - html_content, text_content, - email_from=settings.DEFAULT_FROM_EMAIL) - + def __init__(self, domain, web_user, back_button=('Back', None), data=None, *args, **kwargs): + super().__init__(data, *args, **kwargs) -class AnnualPlanContactForm(forms.Form): - name = forms.CharField( - label=gettext_noop("Name") - ) - company_name = forms.CharField( - required=False, - label=gettext_noop("Company / Organization") - ) - message = forms.CharField( - required=False, - label=gettext_noop("Message"), - widget=forms.Textarea(attrs={"class": "vertical-resize"}) - ) - - def __init__(self, domain, web_user, on_annual_plan, data=None, *args, **kwargs): self.domain = domain self.web_user = web_user - super(AnnualPlanContactForm, self).__init__(data, *args, **kwargs) - from corehq.apps.domain.views.accounting import SelectPlanView, DomainSubscriptionView self.helper = FormHelper() self.helper.label_class = 'col-sm-3 col-md-2' self.helper.field_class = 'col-sm-9 col-md-8 col-lg-6' self.helper.form_class = "form-horizontal" - if on_annual_plan: - back_button_text = "Back to my Subscription" - urlname = DomainSubscriptionView.urlname - else: - back_button_text = "Select different plan" - urlname = SelectPlanView.urlname self.helper.layout = crispy.Layout( 'name', 'company_name', 'message', hqcrispy.FormActions( hqcrispy.LinkButton( - _(back_button_text), - reverse(urlname, args=[self.domain]), + *back_button, css_class="btn btn-default" ), StrictButton( - _("Submit"), + _("Submit Request"), type="submit", css_class="btn-primary", ), ) ) - def send_message(self): - subject = "[Annual Plan Request] %s" % self.domain + def send_message(self, request_type): + subject = f"[{request_type}] {self.domain}" context = { 'name': self.cleaned_data['name'], 'company': self.cleaned_data['company_name'], @@ -2061,12 +1996,17 @@ class TriggerInvoiceForm(forms.Form): month = forms.ChoiceField(label="Statement Period Month") year = forms.ChoiceField(label="Statement Period Year") domain = forms.CharField(label="Project Space", widget=forms.Select(choices=[])) - num_users = forms.IntegerField( - label="Number of Users", + num_mobile_workers = forms.IntegerField( + label="Number of Mobile Workers", required=False, - help_text="This is part of accounting tests and overwrites the " - "DomainUserHistory recorded for this month. Please leave " - "this blank to use what is already in the system." + help_text="This will overwrite the DomainUserHistory recorded for this month. " + "Please leave this blank to use what is already in the system." + ) + num_form_submitting_workers = forms.IntegerField( + label="Number of Form-Submitting Mobile Workers", + required=False, + help_text="This will overwrite the FormSubmittingMobileWorkerHistory recorded for this month. " + "Please leave this blank to use what is already in the system." ) def __init__(self, *args, **kwargs): @@ -2097,13 +2037,24 @@ def __init__(self, *args, **kwargs): placeholder="Search for Project" ) ] + self.helper.layout = crispy.Layout( + crispy.Fieldset(*details) + ) + if self.show_testing_options: - details.append(crispy.Field('num_users', css_class='input_large')) + testing_options = [ + 'Testing Options', + crispy.Field('num_mobile_workers', css_class='input_large'), + crispy.Field('num_form_submitting_workers', css_class='input_large'), + ] + self.helper.layout.append( + crispy.Fieldset(*testing_options) + ) else: - del self.fields['num_users'] + del self.fields['num_mobile_workers'] + del self.fields['num_form_submitting_workers'] - self.helper.layout = crispy.Layout( - crispy.Fieldset(*details), + self.helper.layout.append( hqcrispy.FormActions( StrictButton( "Trigger Invoice", @@ -2122,20 +2073,18 @@ def trigger_invoice(self): self.clean_previous_invoices(invoice_start, invoice_end, domain_obj.name) - if self.show_testing_options and self.cleaned_data['num_users']: - num_users = int(self.cleaned_data['num_users']) - existing_histories = DomainUserHistory.objects.filter( - domain=domain_obj.name, - record_date__gte=invoice_start, - record_date__lte=invoice_end, - ) - if existing_histories.exists(): - existing_histories.all().delete() - DomainUserHistory.objects.create( - domain=domain_obj.name, - record_date=invoice_end, - num_users=num_users - ) + if self.show_testing_options: + if self.cleaned_data['num_mobile_workers']: + num_users = int(self.cleaned_data['num_mobile_workers']) + self._overwrite_user_history( + DomainUserHistory, domain_obj.name, num_users, invoice_start, invoice_end + ) + if self.cleaned_data['num_form_submitting_workers']: + num_users = int(self.cleaned_data['num_form_submitting_workers']) + self._overwrite_user_history( + FormSubmittingMobileWorkerHistory, + domain_obj.name, num_users, invoice_start, invoice_end + ) invoice_factory = DomainInvoiceFactory( invoice_start, invoice_end, domain_obj, recipients=[settings.ACCOUNTS_EMAIL] @@ -2163,6 +2112,21 @@ def clean_previous_invoices(invoice_start, invoice_end, domain_name): ) ) + @staticmethod + def _overwrite_user_history(history_cls, domain, num_users, invoice_start, invoice_end): + existing_histories = history_cls.objects.filter( + domain=domain, + record_date__gte=invoice_start, + record_date__lte=invoice_end, + ) + if existing_histories.exists(): + existing_histories.all().delete() + history_cls.objects.create( + domain=domain, + record_date=invoice_end, + num_users=num_users + ) + def clean(self): today = datetime.date.today() year = int(self.cleaned_data['year']) diff --git a/corehq/apps/accounting/invoicing.py b/corehq/apps/accounting/invoicing.py index b07e1e843f7c..d45a50beed8f 100644 --- a/corehq/apps/accounting/invoicing.py +++ b/corehq/apps/accounting/invoicing.py @@ -32,6 +32,7 @@ DomainUserHistory, EntryPoint, FeatureType, + FormSubmittingMobileWorkerHistory, Invoice, InvoicingPlan, LineItem, @@ -554,6 +555,7 @@ def get_factory_by_feature_type(cls, feature_type): try: return { FeatureType.SMS: SmsLineItemFactory, + FeatureType.FORM_SUBMITTING_MOBILE_WORKER: FormSubmittingMobileWorkerLineItemFactory, FeatureType.USER: UserLineItemFactory, FeatureType.WEB_USER: WebUserLineItemFactory, }[feature_type] @@ -745,20 +747,24 @@ def quantity(self): dates = self.all_month_ends_in_invoice() excess_users = 0 for date in dates: - total_users = 0 - for domain in self.subscribed_domains: - try: - history = DomainUserHistory.objects.get(domain=domain, record_date=date) - total_users += history.num_users - except DomainUserHistory.DoesNotExist: - if not deleted_domain_exists(domain): - # this checks to see if the domain still exists - # before raising an error. If it was deleted the - # loop will continue - raise + total_users = self.total_users_for_date(date) excess_users += max(total_users - self.rate.monthly_limit, 0) return excess_users + def total_users_for_date(self, date): + total_users = 0 + for domain in self.subscribed_domains: + try: + history = DomainUserHistory.objects.get(domain=domain, record_date=date) + total_users += history.num_users + except DomainUserHistory.DoesNotExist: + if not deleted_domain_exists(domain): + # this checks to see if the domain still exists + # before raising an error. If it was deleted the + # loop will continue + raise + return total_users + def all_month_ends_in_invoice(self): _, month_end = get_first_last_days(self.invoice.date_end.year, self.invoice.date_end.month) dates = [] @@ -777,41 +783,43 @@ def _unit_description_by_user_type(self, user_type): ) ) if self.quantity > 0: - return ngettext( - "Per-{user} fee exceeding limit of {monthly_limit} {user} " - "with plan above.{prorated_notice}", - "Per-{user} fee exceeding limit of {monthly_limit} {user}s " - "with plan above.{prorated_notice}", - self.rate.monthly_limit - ).format( - monthly_limit=self.rate.monthly_limit, - prorated_notice=prorated_notice, - user=user_type - ) + return _("Fee for each {user} exceeding the plan limit of {monthly_limit}.").format( + user=_(user_type), monthly_limit=self.rate.monthly_limit + ) + prorated_notice @property def unit_description(self): return self._unit_description_by_user_type("mobile user") -class WebUserLineItemFactory(UserLineItemFactory): +class FormSubmittingMobileWorkerLineItemFactory(UserLineItemFactory): - @property - @memoized - def quantity(self): - # Iterate through all months in the invoice date range to aggregate total users into one line item - dates = self.all_month_ends_in_invoice() - excess_users = 0 - for date in dates: - total_users = 0 + def total_users_for_date(self, date): + total_users = 0 + for domain in self.subscribed_domains: try: - history = BillingAccountWebUserHistory.objects.get( - billing_account=self.subscription.account, record_date=date) + history = FormSubmittingMobileWorkerHistory.objects.get(domain=domain, record_date=date) total_users += history.num_users - except BillingAccountWebUserHistory.DoesNotExist: - raise - excess_users += max(total_users - self.rate.monthly_limit, 0) - return excess_users + except FormSubmittingMobileWorkerHistory.DoesNotExist: + if not deleted_domain_exists(domain): + raise + return total_users + + @property + def unit_description(self): + return super()._unit_description_by_user_type("form-submitting mobile worker") + + +class WebUserLineItemFactory(UserLineItemFactory): + + def total_users_for_date(self, date): + try: + history = BillingAccountWebUserHistory.objects.get( + billing_account=self.subscription.account, record_date=date) + total_users = history.num_users + except BillingAccountWebUserHistory.DoesNotExist: + raise + return total_users @property def unit_description(self): diff --git a/corehq/apps/accounting/models.py b/corehq/apps/accounting/models.py index 19a374b028fa..c93739521c22 100644 --- a/corehq/apps/accounting/models.py +++ b/corehq/apps/accounting/models.py @@ -532,7 +532,8 @@ def get_domains(self): 'subscriber__domain', flat=True)) def has_enterprise_admin(self, email): - return self.is_customer_billing_account and email in self.enterprise_admin_emails + lower_emails = [e.lower() for e in self.enterprise_admin_emails] + return self.is_customer_billing_account and email.lower() in lower_emails def update_autopay_user(self, new_user, domain): if self.auto_pay_enabled and new_user != self.auto_pay_user: @@ -828,7 +829,7 @@ class SoftwarePlan(models.Model): class Meta(object): app_label = 'accounting' - @quickcache(vary_on=['self.pk'], timeout=10) + @quickcache(vary_on=['self.pk'], timeout=10, skip_arg=lambda *a, **k: settings.UNIT_TESTING) def get_version(self): try: return self.softwareplanversion_set.filter(is_active=True).latest('date_created') @@ -3991,9 +3992,9 @@ class FormSubmittingMobileWorkerHistory(DomainUserHistoryBase): The number of mobile workers in a domain who have submitted one or more forms in the month preceeding the record_date. Ex: a record_date of 2024-07-09 includes all dates from 2024-06-09 to 2024-07-08, inclusive. - TODO: Create by task calculate_form_submitting_mobile_workers_in_all_domains - on the first of every month. Will be used to bill clients for the - appropriate number of form-submitting mobile workers. + Created by task calculate_form_submitting_mobile_workers_in_all_domains + on the first of every month. Used to bill clients for the appropriate + number of form-submitting mobile workers. """ pass diff --git a/corehq/apps/accounting/tasks.py b/corehq/apps/accounting/tasks.py index 4b219e2da3b3..29c75ef4c091 100644 --- a/corehq/apps/accounting/tasks.py +++ b/corehq/apps/accounting/tasks.py @@ -5,7 +5,7 @@ from datetime import date from django.conf import settings -from django.db import transaction +from django.db import IntegrityError, transaction from django.db.models import F, Q from django.http import HttpRequest, QueryDict from django.template.loader import render_to_string @@ -44,6 +44,7 @@ Currency, DomainUserHistory, FeatureType, + FormSubmittingMobileWorkerHistory, InvoicingPlan, Subscription, SubscriptionAdjustment, @@ -61,6 +62,7 @@ get_context_to_send_purchase_receipt, ) from corehq.apps.accounting.utils import ( + count_form_submitting_mobile_workers, get_change_status, log_accounting_error, log_accounting_info, @@ -810,6 +812,27 @@ def calculate_users_in_all_domains(today=None): auto_deactivate_mobile_workers.delay() +@periodic_task(run_every=crontab(hour=1, minute=0, day_of_month='1'), acks_late=True) +def calculate_form_submitting_mobile_workers_in_all_domains(today=None): + today = today or datetime.date.today() + date_start = today - relativedelta(months=1) + for domain in Domain.get_all_names(): + num_workers = count_form_submitting_mobile_workers(domain, date_start, today) + record_date = today - relativedelta(days=1) + try: + FormSubmittingMobileWorkerHistory.objects.create( + domain=domain, + num_users=num_workers, + record_date=record_date + ) + except IntegrityError as e: + log_accounting_error( + f"""Something went wrong while creating FormSubmittingMobileWorkerHistory + for domain {domain}: {e}""", + show_stack_trace=True, + ) + + @periodic_task(run_every=crontab(hour=1, minute=0, day_of_month='1'), acks_late=True) def calculate_web_users_in_all_billing_accounts(today=None): today = today or datetime.date.today() diff --git a/corehq/apps/accounting/templates/accounting/partials/confirm_plan_summary.html b/corehq/apps/accounting/templates/accounting/partials/confirm_plan_summary.html index ff87fb41aede..dd7219c56004 100644 --- a/corehq/apps/accounting/templates/accounting/partials/confirm_plan_summary.html +++ b/corehq/apps/accounting/templates/accounting/partials/confirm_plan_summary.html @@ -104,18 +104,5 @@

{% endif %} {% if downgrade_messages and not is_same_edition %} -
-

- {% trans 'Note: Selecting this plan will result in the following changes to your project.' %} -

- {% for message in downgrade_messages %} -
- {{ message.message }} -
    - {% for detail in message.details %} -
  • {{ detail }}
  • - {% endfor %} -
-
- {% endfor %} + {% include 'accounting/partials/downgrade_messages.html' with messages=downgrade_messages only %} {% endif %} diff --git a/corehq/apps/accounting/templates/accounting/partials/downgrade_messages.html b/corehq/apps/accounting/templates/accounting/partials/downgrade_messages.html new file mode 100644 index 000000000000..cd97e0791914 --- /dev/null +++ b/corehq/apps/accounting/templates/accounting/partials/downgrade_messages.html @@ -0,0 +1,16 @@ +{% load i18n %} + +
+

+ {% trans 'Note: Selecting this plan will result in the following changes to your project.' %} +

+{% for message in messages %} +
+ {{ message.message }} +
    + {% for detail in message.details %} +
  • {{ detail }}
  • + {% endfor %} +
+
+{% endfor %} diff --git a/corehq/apps/accounting/templates/accounting/partials/renew_plan_selection.html b/corehq/apps/accounting/templates/accounting/partials/renew_plan_selection.html index 44160fc124ca..1bbdd522b9ba 100644 --- a/corehq/apps/accounting/templates/accounting/partials/renew_plan_selection.html +++ b/corehq/apps/accounting/templates/accounting/partials/renew_plan_selection.html @@ -41,3 +41,7 @@

+ +{% if downgrade_messages %} + {% include 'accounting/partials/downgrade_messages.html' with messages=downgrade_messages only %} +{% endif %} diff --git a/corehq/apps/accounting/tests/generator.py b/corehq/apps/accounting/tests/generator.py index 9de9200ed608..ccd3c911ef21 100644 --- a/corehq/apps/accounting/tests/generator.py +++ b/corehq/apps/accounting/tests/generator.py @@ -22,7 +22,13 @@ BillingContactInfo, Currency, DefaultProductPlan, + Feature, + FeatureType, + SoftwarePlan, SoftwarePlanEdition, + SoftwarePlanVersion, + SoftwareProductRate, + Role, Subscriber, Subscription, SubscriptionType, @@ -112,6 +118,38 @@ def subscribable_plan_version(edition=SoftwarePlanEdition.STANDARD): return DefaultProductPlan.get_default_plan_version(edition) +@unit_testing_only +def default_feature_rates(edition=SoftwarePlanEdition.STANDARD): + feature_rates = [] + for feature_type in FeatureType.EDITIONED_FEATURES: + feature = Feature.objects.get( + feature_type=feature_type, + name=f"{feature_type} {edition}" + ) + feature_rates.append(feature.get_rate(default_instance=True)) + return feature_rates + + +@unit_testing_only +def custom_plan_version(name='Custom software plan', edition=SoftwarePlanEdition.STANDARD, + role_slug='standard_plan_v0', feature_rates=None): + plan = SoftwarePlan.objects.create(name=name, edition=edition) + product_rate = SoftwareProductRate.objects.create(name=name) + role = Role.objects.get(slug=role_slug) + plan_version = SoftwarePlanVersion.objects.create( + plan=plan, + product_rate=product_rate, + role=role + ) + if feature_rates is None: + feature_rates = default_feature_rates(edition) + for feature_rate in feature_rates: + feature_rate.save() + plan_version.feature_rates.add(feature_rate) + plan_version.save() + return plan_version + + @unit_testing_only def generate_domain_subscription(account, domain, date_start, date_end, plan_version=None, service_type=SubscriptionType.NOT_SET, diff --git a/corehq/apps/accounting/tests/test_forms.py b/corehq/apps/accounting/tests/test_forms.py index a0ec2841b5b4..db0131eaf98b 100644 --- a/corehq/apps/accounting/tests/test_forms.py +++ b/corehq/apps/accounting/tests/test_forms.py @@ -1,17 +1,27 @@ import datetime import random +from unittest.mock import patch from django.core.exceptions import ValidationError +from django.test import TestCase from dateutil.relativedelta import relativedelta -from corehq.apps.accounting.forms import AdjustBalanceForm, SubscriptionForm +from corehq.apps.accounting.exceptions import InvoiceError +from corehq.apps.accounting.forms import ( + AdjustBalanceForm, + PlanContactForm, + SubscriptionForm, + TriggerInvoiceForm, +) from corehq.apps.accounting.models import ( BillingAccount, CreditAdjustmentReason, CreditLine, CustomerInvoice, DefaultProductPlan, + DomainUserHistory, + FormSubmittingMobileWorkerHistory, Invoice, SoftwarePlanEdition, Subscription, @@ -25,6 +35,7 @@ from corehq.apps.accounting.tests.test_invoicing import BaseInvoiceTestCase from corehq.apps.domain.models import Domain from corehq.apps.users.models import WebUser +from corehq.util.dates import get_first_last_days class TestAdjustBalanceForm(BaseInvoiceTestCase): @@ -311,3 +322,118 @@ def test_customer_plan_not_added_to_regular_account(self): } self.assertRaises(ValidationError, lambda: subscription_form.clean_active_accounts()) + + +class TestTriggerInvoiceForm(BaseInvoiceTestCase): + + def setUp(self): + super().setUp() + statement_period = self.subscription.date_start + relativedelta(months=1) + self.statement_start, self.statement_end = get_first_last_days( + statement_period.year, statement_period.month + ) + calculate_users_in_all_domains(self.statement_end + datetime.timedelta(days=1)) + + def init_form(self, form_data, show_testing_options=False): + self.form = TriggerInvoiceForm( + data=form_data, + show_testing_options=show_testing_options + ) + + def form_data(self, **kwargs): + form_data = { + 'month': str(self.statement_start.month), + 'year': str(self.statement_start.year), + 'domain': self.domain.name, + } + form_data.update({k: str(v) for k, v in kwargs.items()}) + return form_data + + def test_trigger_invoice(self): + self.init_form(self.form_data()) + self.form.full_clean() + self.form.trigger_invoice() + + invoice = self.subscription.invoice_set.latest('date_created') + self.assertEqual(invoice.date_start, self.statement_start) + self.assertEqual(invoice.date_end, self.statement_end) + + def test_clean_previous_invoices(self): + prev_invoice = Invoice.objects.create( + date_start=self.statement_start, + date_end=self.statement_end, + subscription=self.subscription + ) + self.init_form(self.form_data()) + self.form.full_clean() + + with self.assertRaises(InvoiceError) as e: + self.form.clean_previous_invoices(self.statement_start, self.statement_end, self.domain.name) + self.assertIn(prev_invoice.invoice_number, str(e.exception)) + + def test_show_testing_options(self): + self.init_form(self.form_data(), show_testing_options=False) + self.assertNotIn('num_mobile_workers', self.form.fields) + self.assertNotIn('num_form_submitting_workers', self.form.fields) + + self.init_form(self.form_data(), show_testing_options=True) + self.assertIn('num_mobile_workers', self.form.fields) + self.assertIn('num_form_submitting_workers', self.form.fields) + + def test_num_mobile_workers(self): + num_users = 10 + self.init_form( + self.form_data(num_mobile_workers=num_users), + show_testing_options=True + ) + self.form.full_clean() + self.form.trigger_invoice() + + user_history = DomainUserHistory.objects.get( + domain=self.domain.name, record_date=self.statement_end + ) + self.assertEqual(user_history.num_users, num_users) + + def test_num_form_submitting_mobile_workers(self): + num_users = 5 + self.init_form( + self.form_data(num_form_submitting_workers=num_users), + show_testing_options=True + ) + self.form.full_clean() + self.form.trigger_invoice() + + user_history = FormSubmittingMobileWorkerHistory.objects.get( + domain=self.domain.name, record_date=self.statement_end + ) + self.assertEqual(user_history.num_users, num_users) + + +class TestPlanContactForm(TestCase): + def setUp(self): + super().setUp() + self.domain = generator.arbitrary_domain() + self.addCleanup(self.domain.delete) + self.web_user = generator.arbitrary_user(self.domain.name, is_webuser=True) + + @patch('corehq.apps.accounting.forms.send_html_email_async') + def test_send_message(self, mock_send): + data = { + 'name': 'Nelson Muntz', + 'company_name': 'Springfield Elementary', + 'message': 'Haw haw.' + } + form = PlanContactForm(self.domain.name, self.web_user, data=data) + form.full_clean() + + request_type = 'Testy McTestFace' + form.send_message(request_type) + mock_send.delay.assert_called_once() + + args = mock_send.delay.call_args[0] + subject = args[0] + text_content = args[3] + + expected_subject = f'[{request_type}] {self.domain.name}' + self.assertEqual(subject, expected_subject) + self.assertTrue(all(value in text_content for value in data.values())) diff --git a/corehq/apps/accounting/tests/test_invoicing.py b/corehq/apps/accounting/tests/test_invoicing.py index 5603e1b167ce..83fd1f1162d1 100644 --- a/corehq/apps/accounting/tests/test_invoicing.py +++ b/corehq/apps/accounting/tests/test_invoicing.py @@ -15,7 +15,11 @@ BillingAccount, BillingRecord, DefaultProductPlan, + DomainUserHistory, + Feature, + FeatureRate, FeatureType, + FormSubmittingMobileWorkerHistory, Invoice, SoftwarePlanEdition, Subscriber, @@ -59,17 +63,17 @@ def setUpClass(cls): cls.domain = generator.arbitrary_domain() cls.subscription_length = 15 # months - subscription_start_date = datetime.date(2016, 2, 23) + cls.subscription_start_date = datetime.date(2016, 2, 23) cls.subscription_is_active = False if cls.is_testing_web_user_feature: # make sure the subscription is still active when we count web users cls.subscription_is_active = True - subscription_end_date = add_months_to_date(subscription_start_date, cls.subscription_length) + cls.subscription_end_date = add_months_to_date(cls.subscription_start_date, cls.subscription_length) cls.subscription = generator.generate_domain_subscription( cls.account, cls.domain, - date_start=subscription_start_date, - date_end=subscription_end_date, + date_start=cls.subscription_start_date, + date_end=cls.subscription_end_date, is_active=cls.subscription_is_active ) @@ -450,6 +454,82 @@ def test_community_over_limit(self): self.assertEqual(user_line_item.total, num_to_charge * self.user_rate.per_excess_fee) +class TestFormSubmittingMobileWorkerLineItem(BaseInvoiceTestCase): + + @classmethod + def setUpClass(cls): + super().setUpClass() + cls.feature_rate = FeatureRate.objects.create( + feature=Feature.objects.get(name=FeatureType.FORM_SUBMITTING_MOBILE_WORKER), + monthly_limit=10, + per_excess_fee=Decimal('3.00') + ) + plan_feature_rates = generator.default_feature_rates() + [cls.feature_rate] + plan_version = generator.custom_plan_version(feature_rates=plan_feature_rates) + cls.subscription = generator.generate_domain_subscription( + cls.account, + cls.domain, + date_start=cls.subscription_start_date, + date_end=cls.subscription_end_date, + is_active=cls.subscription_is_active, + plan_version=plan_version + ) + + def setup_invoice(self, num_form_submitting_workers): + generator.arbitrary_commcare_users_for_domain(self.domain.name, num_form_submitting_workers) + + invoice_date = utils.months_from_date(self.subscription.date_start, 2) + record_date = invoice_date - datetime.timedelta(days=1) + self._create_worker_history(DomainUserHistory, record_date) + self._create_worker_history(FormSubmittingMobileWorkerHistory, + record_date, num_workers=num_form_submitting_workers) + + tasks.generate_invoices_based_on_date(invoice_date) + return self.subscription.invoice_set.latest('date_created') + + def _create_worker_history(self, history_cls, record_date, num_workers=0): + history_cls.objects.create( + domain=self.domain, + record_date=record_date, + num_users=num_workers + ) + + def test_under_limit(self): + """ + When usage is not chargeable, the Form-Submitting Mobile Worker line item produced: + - base_cost and unit_cost match FeatureRate defined on this test class + - quantity is 0, because there were no excess users + - unit_description is None, because its line item will not appear on invoice + """ + num_form_submitting_workers = self.feature_rate.monthly_limit + invoice = self.setup_invoice(num_form_submitting_workers) + worker_line_item = invoice.lineitem_set.get_feature_by_type( + FeatureType.FORM_SUBMITTING_MOBILE_WORKER).get() + + self.assertIsNone(worker_line_item.unit_description) + self.assertEqual(worker_line_item.base_cost, self.feature_rate.monthly_fee) + self.assertEqual(worker_line_item.unit_cost, self.feature_rate.per_excess_fee) + self.assertEqual(worker_line_item.quantity, 0) + + def test_over_limit(self): + """ + When usage is chargeable, the Form-Submitting Mobile Worker line item produced: + - base_cost and unit_cost match the FeatureRate defined on this test class + - quantity is the number of workers in excess of the FeatureRate's monthly_limit + - unit_description includes 'form-submitting mobile worker' + """ + num_excess = 3 + num_form_submitting_workers = self.feature_rate.monthly_limit + num_excess + invoice = self.setup_invoice(num_form_submitting_workers) + worker_line_item = invoice.lineitem_set.get_feature_by_type( + FeatureType.FORM_SUBMITTING_MOBILE_WORKER).get() + + self.assertIn('form-submitting mobile worker', worker_line_item.unit_description) + self.assertEqual(worker_line_item.quantity, num_excess) + self.assertEqual(worker_line_item.base_cost, self.feature_rate.monthly_fee) + self.assertEqual(worker_line_item.unit_cost, self.feature_rate.per_excess_fee) + + class TestWebUserLineItem(BaseInvoiceTestCase): is_using_test_plans = True diff --git a/corehq/apps/accounting/tests/test_models.py b/corehq/apps/accounting/tests/test_models.py index 63e18f19f187..4f7e5ae9d679 100644 --- a/corehq/apps/accounting/tests/test_models.py +++ b/corehq/apps/accounting/tests/test_models.py @@ -3,6 +3,7 @@ from django.core import mail from django.db import models +from django.test import SimpleTestCase from unittest import mock @@ -343,3 +344,9 @@ def test_unset_autopay(self, fake_customer): self.assertEqual(self.fake_card.metadata, {"auto_pay_{}".format(self.billing_account.id): 'False'}) self.assertIsNone(self.billing_account.auto_pay_user) self.assertFalse(self.billing_account.auto_pay_enabled) + + +class SimpleBillingAccountTest(SimpleTestCase): + def test_has_enterprise_admin_does_case_insensitive_match(self): + account = BillingAccount(is_customer_billing_account=True, enterprise_admin_emails=['TEST@dimagi.com']) + self.assertTrue(account.has_enterprise_admin('test@DIMAGI.com')) diff --git a/corehq/apps/accounting/tests/test_tasks.py b/corehq/apps/accounting/tests/test_tasks.py new file mode 100644 index 000000000000..6d6515e58d1e --- /dev/null +++ b/corehq/apps/accounting/tests/test_tasks.py @@ -0,0 +1,56 @@ +import datetime + +from corehq.apps.accounting import tasks +from corehq.apps.accounting.models import FormSubmittingMobileWorkerHistory +from corehq.apps.accounting.tests import generator +from corehq.apps.accounting.tests.test_invoicing import BaseInvoiceTestCase +from corehq.apps.domain.tests.test_utils import delete_all_domains +from corehq.apps.es.forms import form_adapter +from corehq.apps.es.tests.utils import es_test +from corehq.apps.users.dbaccessors import delete_all_users +from corehq.form_processor.utils.xform import TestFormMetadata +from corehq.util.test_utils import make_es_ready_form + + +@es_test(requires=[form_adapter], setup_class=True) +class TestCalculateFormSubmittingMobileWorkers(BaseInvoiceTestCase): + + @classmethod + def setUpClass(cls): + super().setUpClass() + num_workers = 5 + generator.arbitrary_commcare_users_for_domain(cls.domain.name, num_workers) + + cls.num_form_submitting_workers = 3 + cls.one_day_ago = datetime.date.today() - datetime.timedelta(days=1) + one_week_ago_dt = datetime.datetime.combine( + cls.one_day_ago - datetime.timedelta(days=6), datetime.time() + ) + for user in cls.domain.all_users()[:cls.num_form_submitting_workers]: + cls._submit_form(user, one_week_ago_dt) + + @classmethod + def _submit_form(cls, user, received_on): + form_pair = make_es_ready_form( + TestFormMetadata( + domain=cls.domain.name, + user_id=user.user_id, + received_on=received_on + ) + ) + form_adapter.index(form_pair.json_form, refresh=True) + + @classmethod + def tearDownClass(cls): + delete_all_users() + delete_all_domains() + return super().tearDownClass() + + def test_calculate_form_submitting_mobile_workers_in_all_domains(self): + tasks.calculate_form_submitting_mobile_workers_in_all_domains() + self.assertEqual(FormSubmittingMobileWorkerHistory.objects.count(), 1) + + worker_history = FormSubmittingMobileWorkerHistory.objects.first() + self.assertEqual(worker_history.domain, self.domain.name) + self.assertEqual(worker_history.num_users, self.num_form_submitting_workers) + self.assertEqual(worker_history.record_date, self.one_day_ago) diff --git a/corehq/apps/accounting/usage.py b/corehq/apps/accounting/usage.py index 91efe735f020..f9779368f0af 100644 --- a/corehq/apps/accounting/usage.py +++ b/corehq/apps/accounting/usage.py @@ -2,6 +2,7 @@ import datetime from corehq.apps.accounting.models import FeatureType +from corehq.apps.accounting.utils import count_form_submitting_mobile_workers from corehq.apps.smsbillables.models import SmsBillable from corehq.apps.users.models import CommCareUser, WebUser @@ -20,13 +21,19 @@ def __init__(self, feature_rate, domain_name, self.end_date = end_date or datetime.date( today.year, today.month, last_day) + @property + def usage_fns(self): + return { + FeatureType.USER: self._get_user_usage, + FeatureType.SMS: self._get_sms_usage, + FeatureType.WEB_USER: self._get_web_user_usage, + FeatureType.FORM_SUBMITTING_MOBILE_WORKER: self._get_form_submitting_mobile_worker_user_usage, + } + def get_usage(self): try: - return { - FeatureType.USER: self._get_user_usage(), - FeatureType.SMS: self._get_sms_usage(), - FeatureType.WEB_USER: self._get_web_user_usage(), - }[self.feature_rate.feature.feature_type] + usage_fn = self.usage_fns[self.feature_rate.feature.feature_type] + return usage_fn() except KeyError: pass @@ -44,3 +51,6 @@ def _get_sms_usage(self): def _get_web_user_usage(self): web_user_in_account = set(WebUser.ids_by_domain(self.domain)) return len(web_user_in_account) + + def _get_form_submitting_mobile_worker_user_usage(self): + return count_form_submitting_mobile_workers(self.domain, self.start_date, self.end_date) diff --git a/corehq/apps/accounting/user_text.py b/corehq/apps/accounting/user_text.py index 9b622084fb05..e3bcee05cc96 100644 --- a/corehq/apps/accounting/user_text.py +++ b/corehq/apps/accounting/user_text.py @@ -54,17 +54,14 @@ FeatureType.SMS: _("SMS Messages"), FeatureType.USER: _("Mobile Workers"), FeatureType.WEB_USER: _("Web Users"), + FeatureType.FORM_SUBMITTING_MOBILE_WORKER: _("Form-Submitting Mobile Workers"), } def get_feature_name(feature_type): if feature_type not in [f[0] for f in FeatureType.CHOICES]: raise ValueError("Unsupported Feature") - return { - FeatureType.USER: _("Mobile Users"), - FeatureType.SMS: _("SMS"), - FeatureType.WEB_USER: _("Web Users") - }[feature_type] + return FEATURE_TYPE_TO_NAME[feature_type] def get_feature_recurring_interval(feature_type): diff --git a/corehq/apps/accounting/utils/__init__.py b/corehq/apps/accounting/utils/__init__.py index 91e4d64a8afa..9c7b7ddbd51b 100644 --- a/corehq/apps/accounting/utils/__init__.py +++ b/corehq/apps/accounting/utils/__init__.py @@ -18,6 +18,7 @@ ProductPlanNotFoundError, ) from corehq.apps.domain.models import Domain +from corehq.apps.es.forms import FormES from corehq.toggles import domain_has_privilege_from_toggle from corehq.util.quickcache import quickcache from corehq.util.view_utils import absolute_reverse @@ -470,3 +471,20 @@ def get_paused_plan_context(request, domain): 'change_plan_url': reverse(SelectPlanView.urlname, args=[domain]), 'can_edit_billing_info': request.couch_user.is_domain_admin(domain), } + + +def count_form_submitting_mobile_workers(domain, start, end): + """ + Returns the count of mobile workers who have submitted a form in the time specified. + """ + form_counts_by_worker = ( + FormES(for_export=True) + .domain(domain) + .submitted(gte=start, lt=end) + .user_type('mobile') + .user_aggregation() + .size(0) + .run() + .aggregations.user.normalized_buckets + ) + return len(form_counts_by_worker) diff --git a/corehq/apps/aggregate_ucrs/tests/test_aggregation.py b/corehq/apps/aggregate_ucrs/tests/test_aggregation.py index 862bf8300f9d..d3ed8ebef06c 100644 --- a/corehq/apps/aggregate_ucrs/tests/test_aggregation.py +++ b/corehq/apps/aggregate_ucrs/tests/test_aggregation.py @@ -104,10 +104,17 @@ def setUpClass(cls): # the closed case causes there to be some data with an end_column cls.closed_case_id = cls._create_closed_case() + def cleanup_datasource(data_source, adapter): + data_source.get_db().delete_doc(data_source.get_id) + adapter.drop_table() + # populate the UCRs with the data we just created cls.form_adapter = get_indicator_adapter(cls.form_data_source) + cls.addClassCleanup(cleanup_datasource, cls.form_data_source, cls.form_adapter) cls.case_adapter = get_indicator_adapter(cls.case_data_source) + cls.addClassCleanup(cleanup_datasource, cls.case_data_source, cls.case_adapter) cls.parent_case_adapter = get_indicator_adapter(cls.parent_case_data_source) + cls.addClassCleanup(cleanup_datasource, cls.parent_case_data_source, cls.parent_case_adapter) cls.form_adapter.rebuild_table() cls.case_adapter.rebuild_table() diff --git a/corehq/apps/analytics/README.md b/corehq/apps/analytics/README.md index 48215479bd80..05fa1a2aa6cd 100644 --- a/corehq/apps/analytics/README.md +++ b/corehq/apps/analytics/README.md @@ -96,17 +96,13 @@ When troubleshooting in Hubspot's portal, it's often useful to create lists base This is the live chat feature available for new users. There's a [drift.js](https://github.com/dimagi/commcare-hq/blob/master/corehq/apps/analytics/static/analytix/js/drift.js) HQ module, though it doesn't do much. No server component. -### Fullstory - -Generally available in areas of interest to the product and growth teams: signup, app builder, report builder. We include their script but there's no other interaction with their code - no events, etc. Not much related code; there's a [fullstory.html](https://github.com/dimagi/commcare-hq/blob/master/corehq/apps/analytics/templates/analytics/fullstory.html) template to include their script but no HQ JavaScript module and no server component. - ### Facebook Pixel Their script is included in [signup](https://github.com/dimagi/commcare-hq/blob/master/corehq/apps/registration/templates/registration/register_new_user.html), but we don't do any event tracking or other interaction with it. Very little related code, just the script inclusion. ### Google Tag Manager (GTM) -Its script is available in the [gtm.js](https://github.com/dimagi/commcare-hq/blob/master/corehq/apps/analytics/static/analytix/js/gtm.js) which loads the GTM tracking script and sends the desired user properties to GTM. +Its script is available in the [gtx.js](https://github.com/dimagi/commcare-hq/blob/master/corehq/apps/analytics/static/analytix/js/gtx.js) which loads the GTM tracking script and sends the desired user properties to GTM. Any tracking of events should be configured at the GTM console end in tandem with the desired analytics tooling. The goal is to track specific features in HQ and also disable them when there is no need via the GTM console itself. Any `id` attribute added to html element for tracking through console should be prefixed with `gtm-` to indicate that this element is likely being tracked in GTM. This should potentially avoid accidental removal of id attribute from these elements. (Similar approach may be followed for any tooling in case of tracking of elements through console.) diff --git a/corehq/apps/analytics/static/analytix/js/gtm.js b/corehq/apps/analytics/static/analytix/js/gtx.js similarity index 94% rename from corehq/apps/analytics/static/analytix/js/gtm.js rename to corehq/apps/analytics/static/analytix/js/gtx.js index 3973795a1903..343a9ffdcdb7 100644 --- a/corehq/apps/analytics/static/analytix/js/gtm.js +++ b/corehq/apps/analytics/static/analytix/js/gtx.js @@ -1,8 +1,9 @@ "use strict"; /** - * Handles communication with the google tag manager API. + * Handles communication with the google tag manager API. + * gtx is the filename because some ad blockers blocks 'gtm.js'* */ -hqDefine('analytix/js/gtm', [ +hqDefine('analytix/js/gtx', [ 'jquery', 'underscore', 'analytix/js/initial', diff --git a/corehq/apps/analytics/templates/analytics/analytics_js.html b/corehq/apps/analytics/templates/analytics/analytics_js.html index d1112245b847..284a48d358c8 100644 --- a/corehq/apps/analytics/templates/analytics/analytics_js.html +++ b/corehq/apps/analytics/templates/analytics/analytics_js.html @@ -12,5 +12,6 @@ - + {# gtx is the filename because some adblockers blocks 'gtm.js' #} + {% endcompress %} diff --git a/corehq/apps/analytics/templates/analytics/fullstory.html b/corehq/apps/analytics/templates/analytics/fullstory.html deleted file mode 100644 index e9c802c80751..000000000000 --- a/corehq/apps/analytics/templates/analytics/fullstory.html +++ /dev/null @@ -1,18 +0,0 @@ -{% if ANALYTICS_IDS.FULLSTORY_ID and not request.project.restrict_superusers %} - {# This is fine as an inline script; it's independent of all HQ code and all third-party libraries #} - -{% endif %} diff --git a/corehq/apps/api/object_fetch_api.py b/corehq/apps/api/object_fetch_api.py index d30344b0815a..391aeccbb5cd 100644 --- a/corehq/apps/api/object_fetch_api.py +++ b/corehq/apps/api/object_fetch_api.py @@ -122,7 +122,7 @@ def get(self, request, domain, case_id=None, attachment_id=None): if attachment_meta is not None: mime_type = attachment_meta['content_type'] else: - mime_type = "plain/text" + mime_type = "text/plain" return StreamingHttpResponse(streaming_content=FileWrapper(attachment_stream), content_type=mime_type) diff --git a/corehq/apps/api/resources/auth.py b/corehq/apps/api/resources/auth.py index 4d3ee4088b2e..e18d1092a2f7 100644 --- a/corehq/apps/api/resources/auth.py +++ b/corehq/apps/api/resources/auth.py @@ -1,8 +1,7 @@ -import json from functools import wraps from django.core.exceptions import PermissionDenied -from django.http import Http404, HttpResponse, HttpResponseForbidden +from django.http import Http404, HttpResponseForbidden, JsonResponse from attrs import define, field from tastypie.authentication import Authentication @@ -28,11 +27,9 @@ def _inner(req, *args, **kwargs): return view_func(req, *args, **kwargs) except Http404 as e: if str(e): - return HttpResponse(json.dumps({"error": str(e)}), - content_type="application/json", - status=404) - return HttpResponse(json.dumps({"error": "not authorized"}), - content_type="application/json", + return JsonResponse({"error": str(e)}, + status=404) + return JsonResponse({"error": "not authorized"}, status=401) return _inner @@ -192,7 +189,7 @@ def _get_auth_decorator(self, request): class DomainAdminAuthentication(LoginAndDomainAuthentication): def is_authenticated(self, request, **kwargs): - permission_check = lambda couch_user, domain: couch_user.is_domain_admin(domain) + permission_check = lambda couch_user, domain: couch_user.is_domain_admin(domain) # noqa: E731 wrappers = [ require_permission_raw(permission_check, login_decorator=self._get_auth_decorator(request)), wrap_4xx_errors_for_apis, diff --git a/corehq/apps/api/resources/v0_5.py b/corehq/apps/api/resources/v0_5.py index 04596a18f61a..5a3f5a52ccb9 100644 --- a/corehq/apps/api/resources/v0_5.py +++ b/corehq/apps/api/resources/v0_5.py @@ -230,6 +230,8 @@ def detail_uri_kwargs(self, bundle_or_obj): class CommCareUserResource(v0_1.CommCareUserResource): + primary_location = fields.CharField() + locations = fields.ListField() class Meta(v0_1.CommCareUserResource.Meta): detail_allowed_methods = ['get', 'put', 'delete'] @@ -320,10 +322,22 @@ def obj_delete(self, bundle, **kwargs): deleted_via=USER_CHANGE_VIA_API) return ImmediateHttpResponse(response=http.HttpAccepted()) + def dehydrate_primary_location(self, bundle): + return bundle.obj.get_location_id(bundle.obj.domain) + + def dehydrate_locations(self, bundle): + return bundle.obj.get_location_ids(bundle.obj.domain) + @classmethod def _update(cls, bundle, user_change_logger=None): errors = [] - for key, value in bundle.data.items(): + + location_object = {'primary_location': bundle.data.pop('primary_location', None), + 'locations': bundle.data.pop('locations', None)} + + items_to_update = list(bundle.data.items()) + [('location', location_object)] + + for key, value in items_to_update: try: update(bundle.obj, key, value, user_change_logger) except UpdateUserException as e: diff --git a/corehq/apps/api/tests/test_ucr_resources.py b/corehq/apps/api/tests/test_ucr_resources.py index a7e732451dab..36657c383c87 100644 --- a/corehq/apps/api/tests/test_ucr_resources.py +++ b/corehq/apps/api/tests/test_ucr_resources.py @@ -27,6 +27,7 @@ ReportConfiguration, ) from corehq.apps.userreports.tasks import rebuild_indicators +from corehq.apps.userreports.tests.utils import cleanup_ucr from corehq.apps.users.models import Document, WebUser from corehq.form_processor.models import CommCareCase from corehq.util.test_utils import flag_enabled @@ -439,8 +440,8 @@ def setUpClass(cls): table_id=uuid.uuid4().hex, ) cls.data_source.save() - cls.addClassCleanup(cls.data_source.delete) rebuild_indicators(cls.data_source._id) + cls.addClassCleanup(cleanup_ucr, cls.data_source) cls.client = Client() def test_forbidden_when_feature_flag_not_enabled(self): diff --git a/corehq/apps/api/tests/user_resources.py b/corehq/apps/api/tests/test_user_resources.py similarity index 91% rename from corehq/apps/api/tests/user_resources.py rename to corehq/apps/api/tests/test_user_resources.py index 643343dad9ce..fffe39e8a127 100644 --- a/corehq/apps/api/tests/user_resources.py +++ b/corehq/apps/api/tests/test_user_resources.py @@ -19,6 +19,7 @@ from corehq.apps.es.tests.utils import es_test from corehq.apps.es.users import user_adapter from corehq.apps.groups.models import Group +from corehq.apps.locations.models import LocationType, SQLLocation from corehq.apps.users.analytics import update_analytics_indexes from corehq.apps.users.audit.change_messages import UserChangeMessage from corehq.apps.users.model_log import UserModelAction @@ -70,6 +71,11 @@ def setUpClass(cls): definition=cls.definition, ) cls.profile.save() + cls.loc_type = LocationType.objects.create(domain=cls.domain.name, name='loc_type') + cls.loc1 = SQLLocation.objects.create( + location_id='loc1', location_type=cls.loc_type, domain=cls.domain.name) + cls.loc2 = SQLLocation.objects.create( + location_id='loc2', location_type=cls.loc_type, domain=cls.domain.name) @classmethod def tearDownClass(cls): @@ -81,6 +87,8 @@ def test_get_list(self): commcare_user = CommCareUser.create(domain=self.domain.name, username='fake_user', password='*****', created_by=None, created_via=None) self.addCleanup(commcare_user.delete, self.domain.name, deleted_by=None) + commcare_user.set_location(self.loc1) + commcare_user.set_location(self.loc2) backend_id = commcare_user.get_id update_analytics_indexes() @@ -100,8 +108,13 @@ def test_get_list(self): 'last_name': '', 'phone_numbers': [], 'resource_uri': '/a/qwerty/api/v0.5/user/{}/'.format(backend_id), - 'user_data': {'commcare_project': 'qwerty', PROFILE_SLUG: '', 'imaginary': ''}, - 'username': 'fake_user' + 'user_data': {'commcare_project': 'qwerty', PROFILE_SLUG: '', 'imaginary': '', + 'commcare_location_id': self.loc2.location_id, + 'commcare_primary_case_sharing_id': self.loc2.location_id, + 'commcare_location_ids': f'{self.loc1.location_id} {self.loc2.location_id}'}, + 'username': 'fake_user', + 'primary_location': self.loc2.location_id, + 'locations': [self.loc1.location_id, self.loc2.location_id] }) @flaky @@ -109,6 +122,8 @@ def test_get_single(self): commcare_user = CommCareUser.create(domain=self.domain.name, username='fake_user', password='*****', created_by=None, created_via=None) self.addCleanup(commcare_user.delete, self.domain.name, deleted_by=None) + commcare_user.set_location(self.loc1) + commcare_user.set_location(self.loc2) backend_id = commcare_user._id response = self._assert_auth_get_resource(self.single_endpoint(backend_id)) @@ -126,8 +141,15 @@ def test_get_single(self): 'last_name': '', 'phone_numbers': [], 'resource_uri': '/a/qwerty/api/v0.5/user/{}/'.format(backend_id), - 'user_data': {'commcare_project': 'qwerty', PROFILE_SLUG: '', 'imaginary': ''}, + 'user_data': {'commcare_project': 'qwerty', + PROFILE_SLUG: '', + 'imaginary': '', + 'commcare_location_id': self.loc2.location_id, + 'commcare_primary_case_sharing_id': self.loc2.location_id, + 'commcare_location_ids': f'{self.loc1.location_id} {self.loc2.location_id}'}, 'username': 'fake_user', + 'primary_location': self.loc2.location_id, + 'locations': [self.loc1.location_id, self.loc2.location_id] }) def test_create(self): @@ -153,7 +175,10 @@ def test_create(self): ], "user_data": { "chw_id": "13/43/DFA" - } + }, + 'locations': [self.loc1.location_id, self.loc2.location_id], + 'primary_location': self.loc1.location_id + } response = self._assert_auth_post_resource(self.list_endpoint, json.dumps(user_json), @@ -171,6 +196,9 @@ def test_create(self): self.assertEqual(user_back.get_group_ids()[0], group._id) self.assertEqual(user_back.get_user_data(self.domain.name)["chw_id"], "13/43/DFA") self.assertEqual(user_back.default_phone_number, "50253311399") + self.assertEqual(user_back.get_location_ids(self.domain.name), + [self.loc1.location_id, self.loc2.location_id]) + self.assertEqual(user_back.get_location_id(self.domain.name), self.loc1.location_id) @flag_enabled('COMMCARE_CONNECT') def test_create_connect_user_no_password(self): @@ -266,7 +294,9 @@ def test_update(self): PROFILE_SLUG: self.profile.id, "chw_id": "13/43/DFA" }, - "password": "qwerty1234" + "password": "qwerty1234", + 'locations': [self.loc1.location_id, self.loc2.location_id], + 'primary_location': self.loc1.location_id } backend_id = user._id @@ -288,6 +318,9 @@ def test_update(self): self.assertEqual(user_data.profile_id, self.profile.id) self.assertEqual(user_data["imaginary"], "yes") self.assertEqual(modified.default_phone_number, "50253311399") + self.assertEqual(modified.get_location_ids(self.domain.name), + [self.loc1.location_id, self.loc2.location_id]) + self.assertEqual(modified.get_location_id(self.domain.name), self.loc1.location_id) # test user history audit user_history = UserHistory.objects.get(action=UserModelAction.UPDATE.value, @@ -300,6 +333,8 @@ def test_update(self): 'last_name': 'last', 'first_name': 'test', 'user_data': {'chw_id': '13/43/DFA'}, + 'location_id': 'loc1', + 'assigned_location_ids': ['loc1', 'loc2'] } ) self.assertTrue("50253311398" in diff --git a/corehq/apps/api/tests/test_user_updates.py b/corehq/apps/api/tests/test_user_updates.py index 955618af93e0..609321384d47 100644 --- a/corehq/apps/api/tests/test_user_updates.py +++ b/corehq/apps/api/tests/test_user_updates.py @@ -11,9 +11,11 @@ ) from corehq.apps.domain.shortcuts import create_domain from corehq.apps.groups.models import Group +from corehq.apps.locations.models import LocationType, SQLLocation from corehq.apps.user_importer.helpers import UserChangeLogger from corehq.apps.users.audit.change_messages import ( GROUPS_FIELD, + LOCATION_FIELD, PASSWORD_FIELD, ROLE_FIELD, ) @@ -31,6 +33,11 @@ def setUpClass(cls): cls.domain = 'test-domain' cls.domain_obj = create_domain(cls.domain) cls.addClassCleanup(cls.domain_obj.delete) + cls.loc_type = LocationType.objects.create(domain=cls.domain, name='loc_type') + cls.loc1 = SQLLocation.objects.create( + location_id='loc1', location_type=cls.loc_type, domain=cls.domain) + cls.loc2 = SQLLocation.objects.create( + location_id='loc2', location_type=cls.loc_type, domain=cls.domain) def setUp(self) -> None: super().setUp() @@ -135,6 +142,10 @@ def test_update_groups_fails(self): with self.assertRaises(ValidationError): update(self.user, 'groups', [group._id]) + def test_update_groups_with_fake_group_id_raises_exception(self): + with self.assertRaises(ValidationError): + update(self.user, 'groups', ["fake_id"]) + def test_update_unknown_field_raises_exception(self): with self.assertRaises(UpdateUserException) as cm: update(self.user, 'username', 'new-username') @@ -190,6 +201,48 @@ def _setup_profile(self): profile.save() return profile.id + def test_update_locations_raises_if_primary_location_not_in_location_list(self): + with self.assertRaises(UpdateUserException) as e: + update(self.user, 'location', + {'primary_location': self.loc2.location_id, 'locations': [self.loc1.location_id]}) + + self.assertEqual(str(e.exception), 'Primary location must be included in the list of locations.') + + def test_update_locations_raises_if_any_location_does_not_exist(self): + with self.assertRaises(UpdateUserException) as e: + update(self.user, 'location', + {'primary_location': 'fake_loc', 'locations': [self.loc1.location_id, 'fake_loc']}) + self.assertEqual(str(e.exception), "Could not find location ids: fake_loc.") + + def test_update_locations_raises_if_primary_location_not_provided(self): + with self.assertRaises(UpdateUserException) as e: + update(self.user, 'location', {'locations': [self.loc1.location_id]}) + self.assertEqual(str(e.exception), 'Both primary_location and locations must be provided together.') + + def test_update_locations_raises_if_locations_not_provided(self): + with self.assertRaises(UpdateUserException) as e: + update(self.user, 'location', {'primary_location': self.loc1.location_id}) + self.assertEqual(str(e.exception), 'Both primary_location and locations must be provided together.') + + def test_update_locations_do_nothing_if_nothing_provided(self): + self.user.set_location(self.loc1) + update(self.user, 'location', {'primary_location': None, 'locations': None}) + self.assertEqual(self.user.get_location_ids(self.domain), [self.loc1.location_id]) + self.assertEqual(self.user.get_location_id(self.domain), self.loc1.location_id) + + def test_update_locations_removes_locations_if_empty_string_provided(self): + self.user.set_location(self.loc1) + update(self.user, 'location', {'primary_location': '', 'locations': []}) + self.assertEqual(self.user.get_location_ids(self.domain), []) + self.assertEqual(self.user.get_location_id(self.domain), None) + + def test_update_locations_succeeds(self): + update(self.user, 'location', + {'primary_location': self.loc1.location_id, + 'locations': [self.loc1.location_id, self.loc2.location_id]}) + self.assertEqual(self.user.get_location_ids(self.domain), [self.loc1.location_id, self.loc2.location_id]) + self.assertEqual(self.user.get_location_id(self.domain), self.loc1.location_id) + class TestUpdateUserMethodsLogChanges(TestCase): @@ -199,6 +252,11 @@ def setUpClass(cls): cls.domain = 'test-domain' cls.domain_obj = create_domain(cls.domain) cls.addClassCleanup(cls.domain_obj.delete) + cls.loc_type = LocationType.objects.create(domain=cls.domain, name='loc_type') + cls.loc1 = SQLLocation.objects.create( + location_id='loc1', location_type=cls.loc_type, domain=cls.domain) + cls.loc2 = SQLLocation.objects.create( + location_id='loc2', location_type=cls.loc_type, domain=cls.domain) def setUp(self) -> None: super().setUp() @@ -332,3 +390,25 @@ def test_update_user_role_does_not_logs_change(self): update(self.user, 'role', 'edit-data', user_change_logger=self.user_change_logger) self.assertNotIn(ROLE_FIELD, self.user_change_logger.change_messages.keys()) + + def test_update_location_logs_change(self): + update(self.user, 'location', + {'primary_location': self.loc1.location_id, + 'locations': [self.loc1.location_id, self.loc2.location_id]}, + user_change_logger=self.user_change_logger) + self.assertIn(LOCATION_FIELD, self.user_change_logger.change_messages.keys()) + + def test_update_location_without_include_location_fields_does_not_log_change(self): + update(self.user, 'location', + {'primary_location': None, 'locations': None}, + user_change_logger=self.user_change_logger) + self.assertNotIn(LOCATION_FIELD, self.user_change_logger.change_messages.keys()) + + def test_update_location_with_current_locations_does_not_log_change(self): + self.user.set_location(self.loc2) + self.user.set_location(self.loc1) + update(self.user, 'location', + {'primary_location': self.loc1.location_id, + 'locations': [self.loc1.location_id, self.loc2.location_id]}, + user_change_logger=self.user_change_logger) + self.assertNotIn(LOCATION_FIELD, self.user_change_logger.change_messages.keys()) diff --git a/corehq/apps/api/user_updates.py b/corehq/apps/api/user_updates.py index 433fc6106f93..a823c80a4e52 100644 --- a/corehq/apps/api/user_updates.py +++ b/corehq/apps/api/user_updates.py @@ -1,5 +1,6 @@ from django.core.exceptions import ValidationError from django.utils.translation import gettext as _ +from corehq.apps.locations.models import SQLLocation from dimagi.utils.couch.bulk import get_docs @@ -35,6 +36,7 @@ def update(user, field, value, user_change_logger=None): 'phone_numbers': _update_phone_numbers, 'user_data': _update_user_data, 'role': _update_user_role, + 'location': _update_location, }.get(field) if not update_fn: @@ -165,3 +167,69 @@ def _log_phone_number_change(new_phone_numbers, old_phone_numbers, user_change_l if change_messages: user_change_logger.add_change_message({'phone_numbers': change_messages}) + + +def _update_location(user, location_object, user_change_logger): + primary_location_id = location_object.get('primary_location') + location_ids = location_object.get('locations') + + if primary_location_id is None and location_ids is None: + return + + current_primary_location_id = user.get_location_id(user.domain) + current_locations = user.get_location_ids(user.domain) + + if not primary_location_id and not location_ids: + _remove_all_locations(user, user_change_logger) + else: + if _validate_locations(primary_location_id, location_ids): + locations = _verify_location_ids(location_ids, user.domain) + if primary_location_id != current_primary_location_id: + _update_primary_location(user, primary_location_id, user_change_logger) + if set(current_locations) != set(location_ids): + _update_assigned_locations(user, locations, location_ids, user_change_logger) + + +def _validate_locations(primary_location_id, location_ids): + if not primary_location_id and not location_ids: + return False + if not primary_location_id or not location_ids: + raise UpdateUserException(_('Both primary_location and locations must be provided together.')) + if primary_location_id not in location_ids: + raise UpdateUserException(_('Primary location must be included in the list of locations.')) + return True + + +def _remove_all_locations(user, user_change_logger): + user.unset_location(commit=False) + user.reset_locations([], commit=False) + if user_change_logger: + user_change_logger.add_changes({'location_id': None}) + user_change_logger.add_info(UserChangeMessage.primary_location_removed()) + user_change_logger.add_changes({'assigned_location_ids': []}) + user_change_logger.add_info(UserChangeMessage.assigned_locations_info([])) + + +def _update_primary_location(user, primary_location_id, user_change_logger): + primary_location = SQLLocation.active_objects.get(location_id=primary_location_id) + user.set_location(primary_location, commit=False) + if user_change_logger: + user_change_logger.add_changes({'location_id': primary_location_id}) + user_change_logger.add_info(UserChangeMessage.primary_location_info(primary_location)) + + +def _verify_location_ids(location_ids, domain): + locations = SQLLocation.active_objects.filter(location_id__in=location_ids, domain=domain) + real_ids = [loc.location_id for loc in locations] + + if missing_ids := set(location_ids) - set(real_ids): + raise UpdateUserException(f"Could not find location ids: {', '.join(missing_ids)}.") + + return locations + + +def _update_assigned_locations(user, locations, location_ids, user_change_logger): + user.reset_locations(location_ids, commit=False) + if user_change_logger: + user_change_logger.add_changes({'assigned_location_ids': location_ids}) + user_change_logger.add_info(UserChangeMessage.assigned_locations_info(locations)) diff --git a/corehq/apps/app_execution/static/app_execution/js/workflow_logs.js b/corehq/apps/app_execution/static/app_execution/js/workflow_logs.js index c07d5b0e9527..1671727b9013 100644 --- a/corehq/apps/app_execution/static/app_execution/js/workflow_logs.js +++ b/corehq/apps/app_execution/static/app_execution/js/workflow_logs.js @@ -5,7 +5,7 @@ hqDefine("app_execution/js/workflow_logs", [ 'hqwebapp/js/initial_page_data', 'hqwebapp/js/tempus_dominus', 'app_execution/js/workflow_charts', - 'hqwebapp/js/bootstrap5/components.ko', + 'hqwebapp/js/components/pagination', ], function ($, ko, initialPageData, hqTempusDominus) { let logsModel = function () { let self = {}; diff --git a/corehq/apps/app_manager/app_strings.py b/corehq/apps/app_manager/app_strings.py index b3c0b30179b1..5683ad36d14b 100644 --- a/corehq/apps/app_manager/app_strings.py +++ b/corehq/apps/app_manager/app_strings.py @@ -22,6 +22,13 @@ from corehq.util.translation import localize +# If the language name is not showing up properly in the language menu, you can +# define those languages here, mapped to their two-letter language codes. +CUSTOM_LANGUAGE_NAMES = { + 'km': "ខ្មែរ", +} + + def non_empty_only(dct): return {key: value for key, value in dct.items() if value} @@ -60,8 +67,16 @@ def _create_custom_app_strings(app, lang, for_default=False, build_profile_id=No name = langcodes.get_name(lc) or lc if not name: continue - with localize(convert_to_two_letter_code(lc)): - name = gettext(name) + letter_code = convert_to_two_letter_code(lc) + + if letter_code in CUSTOM_LANGUAGE_NAMES.keys(): + # These are languages not installed on our machines, so localize does not understand them. + # Though we don't want to install these langauges, we still want to support projects + # who want to see the name written properly. + name = CUSTOM_LANGUAGE_NAMES[letter_code] + else: + with localize(letter_code): + name = gettext(name) yield lc, name yield id_strings.current_language(), lang diff --git a/corehq/apps/app_manager/const.py b/corehq/apps/app_manager/const.py index 172fbc6978d2..4784b2cf45d0 100644 --- a/corehq/apps/app_manager/const.py +++ b/corehq/apps/app_manager/const.py @@ -97,3 +97,9 @@ CALCULATED_SORT_FIELD_RX = r'^_cc_calculated_(\d+)$' CASE_LIST_FILTER_LOCATIONS_FIXTURE = 'Locations Fixture' + +MOBILE_UCR_V1_FIXTURE_IDENTIFIER = 'src="jr://fixture/commcare:reports' +MOBILE_UCR_V1_FIXTURE_PATTERN = r'<.*src="jr://fixture/commcare:reports.*>' +MOBILE_UCR_V1_REFERENCES_PATTERN = r"<.*instance\('reports'\)/reports/.*>" +MOBILE_UCR_V1_ALL_REFERENCES = f"{MOBILE_UCR_V1_FIXTURE_PATTERN}|{MOBILE_UCR_V1_REFERENCES_PATTERN}" +MOBILE_UCR_V1_CASE_LIST_REFERENCES_PATTERN = r"instance\('commcare:reports'\)/reports/report\[@id='.*'\]/rows/row" diff --git a/corehq/apps/app_manager/decorators.py b/corehq/apps/app_manager/decorators.py index fd6d2a731fd6..c4d53265a5a8 100644 --- a/corehq/apps/app_manager/decorators.py +++ b/corehq/apps/app_manager/decorators.py @@ -114,7 +114,8 @@ def _safe_cached_download(request, *args, **kwargs): if not username: content_response = dict(error="app.update.not.allowed.user.logged_out", default_response=_("Please log in to the app to check for an update.")) - return HttpResponse(status=406, content=json.dumps(content_response)) + return HttpResponse(status=406, content=json.dumps(content_response), + content_type='application/json') if latest and not target: latest_enabled_build = _get_latest_enabled_build(domain, username, app_id, request.GET.get('profile'), location_flag_enabled) diff --git a/corehq/apps/app_manager/fields.py b/corehq/apps/app_manager/fields.py index 889a26a4f376..557876f07b09 100644 --- a/corehq/apps/app_manager/fields.py +++ b/corehq/apps/app_manager/fields.py @@ -15,9 +15,10 @@ from corehq.apps.app_manager.analytics import get_exports_by_application from corehq.apps.app_manager.dbaccessors import get_app, get_apps_in_domain +from corehq.apps.export.const import ALL_CASE_TYPE_EXPORT +from corehq.apps.hqwebapp import crispy as hqcrispy from corehq.apps.registry.models import DataRegistry from corehq.apps.registry.utils import get_data_registry_dropdown_options -from corehq.apps.hqwebapp import crispy as hqcrispy from corehq.apps.reports.analytics.esaccessors import get_case_types_for_domain from corehq.apps.userreports.app_manager.data_source_meta import ( DATA_SOURCE_TYPE_CASE, @@ -26,7 +27,6 @@ ) from corehq.apps.userreports.dbaccessors import get_datasources_for_domain from corehq.toggles import AGGREGATE_UCRS -from corehq.apps.export.const import ALL_CASE_TYPE_EXPORT DataSource = collections.namedtuple('DataSource', ['application', 'source_type', 'source', 'registry_slug']) RMIDataChoice = collections.namedtuple('RMIDataChoice', ['id', 'text', 'data']) @@ -285,8 +285,10 @@ class ApplicationDataRMIHelper(object): APP_TYPE_NONE = 'no_app' APP_TYPE_UNKNOWN = 'unknown' - def __init__(self, domain, user, as_dict=True): + def __init__(self, domain, project, user, as_dict=True): self.domain = domain + self.domain_object = project + self.user = user self.as_dict = as_dict self.form_labels = AppFormRMIPlaceholder( @@ -420,14 +422,16 @@ def _sort_key_form(form): def _all_forms(self): forms = [] unknown_forms = [] - for f in get_exports_by_form(self.domain): + + for f in get_exports_by_form(self.domain, use_es=self.domain_object.exports_use_elasticsearch): form = f['value'] if form.get('app_deleted') and not form.get('submissions'): continue if 'app' in form: form['has_app'] = True forms.append(form) - else: + elif not self.domain_object.exports_use_elasticsearch: + # If the elasticsearch toggle is on, we don't care about forms without apps app_id = f['key'][1] or '' form['app'] = { 'id': app_id diff --git a/corehq/apps/app_manager/models.py b/corehq/apps/app_manager/models.py index c1d195048934..fb927c3f0014 100644 --- a/corehq/apps/app_manager/models.py +++ b/corehq/apps/app_manager/models.py @@ -4179,7 +4179,7 @@ def assert_app_v2(self): has_submissions = BooleanProperty(default=False) mobile_ucr_restore_version = StringProperty( - default=const.MOBILE_UCR_VERSION_1, choices=const.MOBILE_UCR_VERSIONS, required=False + default=const.MOBILE_UCR_VERSION_2, choices=const.MOBILE_UCR_VERSIONS, required=False ) location_fixture_restore = StringProperty( default=const.DEFAULT_LOCATION_FIXTURE_OPTION, choices=const.LOCATION_FIXTURE_OPTIONS, diff --git a/corehq/apps/app_manager/static/app_manager/js/download_async_modal.js b/corehq/apps/app_manager/static/app_manager/js/download_async_modal.js index 5c9fa5947e8c..22df1b1fb255 100644 --- a/corehq/apps/app_manager/static/app_manager/js/download_async_modal.js +++ b/corehq/apps/app_manager/static/app_manager/js/download_async_modal.js @@ -1,4 +1,10 @@ -hqDefine('app_manager/js/download_async_modal', function () { +hqDefine('app_manager/js/download_async_modal', [ + 'jquery', + 'underscore', +], function ( + $, + _ +) { var asyncDownloader = function ($el) { "use strict"; var self = {}; @@ -7,9 +13,9 @@ hqDefine('app_manager/js/download_async_modal', function () { "If you see this repeatedly please report an issue."); self.$el = $el; - self.el_id = $el.attr("id"); - self.$download_progress = self.$el.find("#" + self.el_id + "-download-progress"); - self.$downloading = self.$el.find("#" + self.el_id + "-downloading"); + self.elId = $el.attr("id"); + self.$download_progress = self.$el.find("#" + self.elId + "-download-progress"); + self.$downloading = self.$el.find("#" + self.elId + "-downloading"); self.init = function () { self.download_in_progress = false; @@ -40,29 +46,29 @@ hqDefine('app_manager/js/download_async_modal', function () { } }; - self.updateProgress = function (progress_response) { - if (progress_response.trim().length) { + self.updateProgress = function (progressResponse) { + if (progressResponse.trim().length) { self.$downloading.addClass("hide"); - self.$download_progress.html(progress_response).removeClass("hide"); + self.$download_progress.html(progressResponse).removeClass("hide"); } }; - self.isDone = function (progress_response) { - var ready_id = 'ready_' + self.download_poll_id, - error_id = 'error_' + self.download_poll_id; - return progress_response && - progress_response.trim().length && - _.any([ready_id, error_id], function (el_id) { - return progress_response.indexOf(el_id) >= 0; + self.isDone = function (progressResponse) { + var readyId = 'ready_' + self.download_poll_id, + errorId = 'error_' + self.download_poll_id; + return progressResponse && + progressResponse.trim().length && + _.any([readyId, errorId], function (elId) { + return progressResponse.indexOf(elId) >= 0; }); }; - self.generateDownload = function (download_url, params) { + self.generateDownload = function (downloadUrl, params) { // prevent multiple calls if (!self.download_in_progress) { self.download_in_progress = true; $.ajax({ - url: download_url, + url: downloadUrl, type: "GET", data: params, dataType: "json", diff --git a/corehq/apps/app_manager/static/app_manager/js/settings/commcare_settings.js b/corehq/apps/app_manager/static/app_manager/js/settings/commcare_settings.js index b2096b295ac0..7171259f8030 100644 --- a/corehq/apps/app_manager/static/app_manager/js/settings/commcare_settings.js +++ b/corehq/apps/app_manager/static/app_manager/js/settings/commcare_settings.js @@ -522,13 +522,3 @@ hqDefine('app_manager/js/settings/commcare_settings', function () { CommcareSettings: CommcareSettings, }; }); - -ko.bindingHandlers.passwordSetter = { - init: function (element, valueAccessor) { - var observableValue = valueAccessor(); - $(element).password_setter(); - $(element).on('textchange change', function () { - observableValue($(element).val()); - }); - }, -}; diff --git a/corehq/apps/app_manager/static/app_manager/js/settings/password_setter.jquery.js b/corehq/apps/app_manager/static/app_manager/js/settings/password_setter.jquery.js deleted file mode 100644 index dc7489c4699e..000000000000 --- a/corehq/apps/app_manager/static/app_manager/js/settings/password_setter.jquery.js +++ /dev/null @@ -1,43 +0,0 @@ -/* jQuery extension for password reset widget. Only used by app settings. */ - -$.fn.password_setter = function () { - var that = this, - randID = Math.floor(Math.random() * 1000), - password1ID = 'password-' + randID + '-1', - password2ID = 'password-' + randID + '-2', - $popupLink = $('').text(gettext("Reset")).attr({ - href: '#password-setter', - 'data-toggle': 'modal', - }), - $modal = $("#password-setter"), - $passwordRow = $modal.find(".password"), - $passwordInput = $passwordRow.find("input"), - $repeatRow = $modal.find(".repeat-password"), - $repeatInput = $repeatRow.find("input"), - $errorMismatch = $modal.find(".password-mismatch"), - $errorEmpty = $modal.find(".password-empty"); - - that.hide(); - that.after($popupLink); - $popupLink.click(function () { - $passwordRow.find("input").focus(); - }); - - $passwordRow.find("label").attr("for", password1ID); - $passwordInput.attr("id", password1ID); - $repeatRow.find("label").attr("for", password2ID); - $repeatInput.find("input").attr("id", password2ID); - - $modal.find("button.save").click(function () { - $errorMismatch.addClass("hide"); - $errorEmpty.addClass("hide"); - if ($passwordInput.val() !== $repeatInput.val()) { - $errorMismatch.removeClass("hide"); - } else if (!$passwordInput.val()) { - $errorEmpty.removeClass("hide"); - } else { - $modal.modal('hide'); - that.val($passwordInput.val()).trigger('textchange'); - } - }); -}; diff --git a/corehq/apps/app_manager/static/app_manager/js/summary/case_summary.js b/corehq/apps/app_manager/static/app_manager/js/summary/case_summary.js index 08e58ce564eb..83e440e9beff 100644 --- a/corehq/apps/app_manager/static/app_manager/js/summary/case_summary.js +++ b/corehq/apps/app_manager/static/app_manager/js/summary/case_summary.js @@ -7,7 +7,7 @@ hqDefine('app_manager/js/summary/case_summary',[ 'app_manager/js/summary/models', 'app_manager/js/menu', // enable lang switcher and "Updates to publish" banner 'hqwebapp/js/bootstrap3/knockout_bindings.ko', // popover - 'hqwebapp/js/bootstrap3/components.ko', // search box + 'hqwebapp/js/components/search_box', ], function ($, _, ko, initialPageData, assertProperties, models) { var caseTypeModel = function (caseType) { diff --git a/corehq/apps/app_manager/static/app_manager/js/summary/form_diff.js b/corehq/apps/app_manager/static/app_manager/js/summary/form_diff.js index a482d826b3de..186beac6c6ab 100644 --- a/corehq/apps/app_manager/static/app_manager/js/summary/form_diff.js +++ b/corehq/apps/app_manager/static/app_manager/js/summary/form_diff.js @@ -10,7 +10,7 @@ hqDefine('app_manager/js/summary/form_diff',[ 'hqwebapp/js/layout', 'app_manager/js/menu', // enable lang switcher and "Updates to publish" banner 'hqwebapp/js/bootstrap3/knockout_bindings.ko', // popover - 'hqwebapp/js/bootstrap3/components.ko', // search box + 'hqwebapp/js/components/search_box', ], function ($, _, ko, initialPageData, assertProperties, models, formModels, utils, layout) { $(function () { diff --git a/corehq/apps/app_manager/static/app_manager/js/summary/form_summary.js b/corehq/apps/app_manager/static/app_manager/js/summary/form_summary.js index d54e242a9b96..6dfadbacbcc9 100644 --- a/corehq/apps/app_manager/static/app_manager/js/summary/form_summary.js +++ b/corehq/apps/app_manager/static/app_manager/js/summary/form_summary.js @@ -9,7 +9,7 @@ hqDefine('app_manager/js/summary/form_summary',[ 'app_manager/js/summary/utils', 'app_manager/js/menu', // enable lang switcher and "Updates to publish" banner 'hqwebapp/js/bootstrap3/knockout_bindings.ko', // popover - 'hqwebapp/js/bootstrap3/components.ko', // search box + 'hqwebapp/js/components/search_box', ], function ($, _, ko, initialPageData, assertProperties, models, formModels, utils) { $(function () { var lang = initialPageData.get('lang'), diff --git a/corehq/apps/app_manager/static/app_manager/js/vellum/README.md b/corehq/apps/app_manager/static/app_manager/js/vellum/README.md index a15c93dc2b99..4bf32d4ce7b8 100644 --- a/corehq/apps/app_manager/static/app_manager/js/vellum/README.md +++ b/corehq/apps/app_manager/static/app_manager/js/vellum/README.md @@ -83,7 +83,7 @@ If not present, bundled versions will be loaded. --> ``` See -[here](https://github.com/dimagi/commcare-hq/blob/master/corehq/apps/app_manager/templates/app_manager/v1/form_designer.html) +[here](https://github.com/dimagi/commcare-hq/blob/master/corehq/apps/app_manager/static/app_manager/js/forms/form_designer.js) and `tests/main.js` for example options usage. Vellum targets modern browsers. IE8 and earlier are not supported. diff --git a/corehq/apps/app_manager/static/app_manager/js/vellum/manifest.txt b/corehq/apps/app_manager/static/app_manager/js/vellum/manifest.txt index 2ce6363d9f47..2cf1be72d0b6 100644 --- a/corehq/apps/app_manager/static/app_manager/js/vellum/manifest.txt +++ b/corehq/apps/app_manager/static/app_manager/js/vellum/manifest.txt @@ -87,8 +87,8 @@ ├─ brace-expansion@1.1.11 │ ├─ balanced-match@^1.0.0 │ └─ concat-map@0.0.1 -├─ braces@3.0.2 -│ └─ fill-range@^7.0.1 +├─ braces@3.0.3 +│ └─ fill-range@^7.1.1 ├─ browser-stdout@1.3.1 ├─ buffer-crc32@0.2.13 ├─ buffer@5.7.1 @@ -230,7 +230,7 @@ │ └─ websocket-driver@>=0.5.1 ├─ fd-slicer@1.1.0 │ └─ pend@~1.2.0 -├─ fill-range@7.0.1 +├─ fill-range@7.1.1 │ └─ to-regex-range@^5.0.1 ├─ finalhandler@1.1.2 │ ├─ debug@2.6.9 @@ -259,7 +259,7 @@ │ └─ parse-filepath@^1.0.1 ├─ flagged-respawn@1.0.1 ├─ flat@5.0.2 -├─ follow-redirects@1.15.5 +├─ follow-redirects@1.15.6 ├─ for-in@1.0.2 ├─ for-own@1.0.0 │ └─ for-in@^1.0.1 @@ -571,7 +571,6 @@ │ └─ uc.micro@^1.0.5 ├─ mdn-data@2.0.14 ├─ mdurl@1.0.1 -├─ MediaUploader@0.0.0 ├─ micromatch@4.0.4 │ ├─ braces@^3.0.1 │ ├─ picomatch@^2.2.3 @@ -793,7 +792,7 @@ │ ├─ requirejs@2.3.3 │ ├─ requirejs@2.3.3 │ └─ underscore@^1.8.3 -├─ requirejs@2.3.6 +├─ requirejs@2.3.7 ├─ requires-port@1.0.0 ├─ resolve-dir@1.0.1 │ ├─ expand-tilde@^2.0.0 @@ -978,7 +977,7 @@ │ ├─ string-width@^4.1.0 │ └─ strip-ansi@^6.0.0 ├─ wrappy@1.0.2 -├─ ws@5.2.3 +├─ ws@5.2.4 │ └─ async-limiter@~1.0.0 ├─ XMLWriter@1.1.0 ├─ xpath@0.0.8 @@ -1006,4 +1005,4 @@ │ ├─ buffer-crc32@~0.2.3 │ └─ fd-slicer@~1.1.0 └─ yocto-queue@0.1.0 -Done in 0.29s. +Done in 0.12s. diff --git a/corehq/apps/app_manager/static/app_manager/js/vellum/src/local-deps.js b/corehq/apps/app_manager/static/app_manager/js/vellum/src/local-deps.js index c7bfadcc3461..e5f6bf3e8135 100644 --- a/corehq/apps/app_manager/static/app_manager/js/vellum/src/local-deps.js +++ b/corehq/apps/app_manager/static/app_manager/js/vellum/src/local-deps.js @@ -16,4 +16,4 @@ n=r.y+s[0]l.height-n.height-a?l.height-n.height+s[2]:r.y,d=Mat var s=!0===o[a](t);i=r==CKEDITOR.VALIDATE_AND?i&&s:i||s}return!!i||n}},regex:function(e,t){return this.functions(function(t){return e.test(t)},t)},notEmpty:function(e){return this.functions(function(e){return 0X'),e.append(t),t.on("click",function(){n.editor.focus(),n.hide()}),e},_getClass:function(){return"progress"==this.type?"cke_notification_info":"cke_notification_"+this.type},_createProgressElement:function(){var e=new CKEDITOR.dom.element("span");return e.addClass("cke_notification_progress"),e.setStyle("width",this._getPercentageProgress()),e},_getPercentageProgress:function(){return Math.round(100*(this.progress||0))+"%"},_hideAfterTimeout:function(){var e,t=this;this._hideTimeoutId&&clearTimeout(this._hideTimeoutId),"number"==typeof this.duration?e=this.duration:"info"!=this.type&&"success"!=this.type||(e="number"==typeof this.editor.config.notification_duration?this.editor.config.notification_duration:5e3),e&&(t._hideTimeoutId=setTimeout(function(){t.hide()},e))}},t.prototype={add:function(e){this.notifications.push(e),this.element.append(e.element),1==this.element.getChildCount()&&(CKEDITOR.document.getBody().append(this.element),this._attachListeners()),this._layout()},remove:function(e){var t=CKEDITOR.tools.indexOf(this.notifications,e);0>t||(this.notifications.splice(t,1),e.element.remove(),this.element.getChildCount()||(this._removeListeners(),this.element.remove()))},_createElement:function(){var e=this.editor,t=e.config,n=new CKEDITOR.dom.element("div");return n.addClass("cke_notifications_area"),n.setAttribute("id","cke_notifications_area_"+e.name),n.setStyle("z-index",t.baseFloatZIndex-2),n},_attachListeners:function(){var e=CKEDITOR.document.getWindow(),t=this.editor;e.on("scroll",this._uiBuffer.input),e.on("resize",this._uiBuffer.input),t.on("change",this._changeBuffer.input),t.on("floatingSpaceLayout",this._layout,this,null,20),t.on("blur",this._layout,this,null,20)},_removeListeners:function(){var e=CKEDITOR.document.getWindow(),t=this.editor;e.removeListener("scroll",this._uiBuffer.input),e.removeListener("resize",this._uiBuffer.input),t.removeListener("change",this._changeBuffer.input),t.removeListener("floatingSpaceLayout",this._layout),t.removeListener("blur",this._layout)},_layout:function(){function e(){r.setStyle("left",p(m+a.width-d-c))}var t,n,i,r=this.element,o=this.editor,a=o.ui.contentsElement.getClientRect(),s=o.ui.contentsElement.getDocumentPosition(),l=r.getClientRect(),d=this._notificationWidth,c=this._notificationMargin;i=CKEDITOR.document.getWindow();var h=i.getScrollPosition(),u=i.getViewPaneSize(),f=CKEDITOR.document.getBody(),g=f.getDocumentPosition(),p=CKEDITOR.tools.cssLength;d&&c||(i=this.element.getChild(0),d=this._notificationWidth=i.getClientRect().width,c=this._notificationMargin=parseInt(i.getComputedStyle("margin-left"),10)+parseInt(i.getComputedStyle("margin-right"),10)),o.toolbar&&(t=o.ui.space(o.config.toolbarLocation),n=t.getClientRect()),t&&t.isVisible()&&n.bottom>a.top&&n.bottomh.y?r.setStyles({position:"fixed",top:0}):r.setStyles({position:"absolute",top:p(s.y+a.height-l.height)});var m="fixed"==r.getStyle("position")?a.left:"static"!=f.getComputedStyle("position")?s.x-g.x:s.x;a.widthh.x+u.width?e():r.setStyle("left",p(m)):s.x+d+c>h.x+u.width?r.setStyle("left",p(m)):s.x+a.width/2+d/2+c>h.x+u.width?r.setStyle("left",p(m-s.x+h.x+u.width-d-c)):0>a.left+a.width-d-c?e():0>a.left+a.width/2-d/2?r.setStyle("left",p(m-s.x+h.x)):r.setStyle("left",p(m+a.width/2-d/2-c/2))}},CKEDITOR.plugins.notification=e}(),function(){var e=' {label}{ariaShortcutSpace}{ariaShortcut}{arrowHtml}',n=CKEDITOR.addTemplate("buttonArrow",''+(CKEDITOR.env.hc?"▼":"")+""),i=CKEDITOR.addTemplate("button",e);CKEDITOR.plugins.add("button",{beforeInit:function(e){e.ui.addHandler(CKEDITOR.UI_BUTTON,CKEDITOR.ui.button.handler)}}),CKEDITOR.UI_BUTTON="button",CKEDITOR.ui.button=function(e){CKEDITOR.tools.extend(this,e,{isToggle:e.isToggle||!1,title:e.label,click:e.click||function(t){t.execCommand(e.command)}}),this._={}},CKEDITOR.ui.button.handler={create:function(e){return new CKEDITOR.ui.button(e)}},CKEDITOR.ui.button.prototype={render:function(e,t){function r(){var t=e.mode;t&&(t=this.modes[t]?void 0!==l[t]?l[t]:CKEDITOR.TRISTATE_OFF:CKEDITOR.TRISTATE_DISABLED,t=e.readOnly&&!this.readOnly?CKEDITOR.TRISTATE_DISABLED:t,this.setState(t),this.refresh&&this.refresh())}var o,a,s,l=null,d=CKEDITOR.env,c=this._.id=CKEDITOR.tools.getNextId(),h="",u=this.command;this._.editor=e;var f={id:c,button:this,editor:e,focus:function(){CKEDITOR.document.getById(c).focus()},execute:function(){this.button.click(e)},attach:function(e){this.button.attach(e)}},g=CKEDITOR.tools.addFunction(function(e){if(f.onkey)return e=new CKEDITOR.dom.event(e),!1!==f.onkey(f,e.getKeystroke())}),p=CKEDITOR.tools.addFunction(function(e){var t;return f.onfocus&&(t=!1!==f.onfocus(f,new CKEDITOR.dom.event(e))),t}),m=0;f.clickFn=o=CKEDITOR.tools.addFunction(function(){m&&(e.unlockSelection(1),m=0),f.execute(),d.iOS&&e.focus()}),this.modes?(l={},e.on("beforeModeUnload",function(){e.mode&&this._.state!=CKEDITOR.TRISTATE_DISABLED&&(l[e.mode]=this._.state)},this),e.on("activeFilterChange",r,this),e.on("mode",r,this),!this.readOnly&&e.on("readOnly",r,this)):u&&(u=e.getCommand(u))&&(u.on("state",function(){this.setState(u.state)},this),h+=u.state==CKEDITOR.TRISTATE_ON?"on":u.state==CKEDITOR.TRISTATE_DISABLED?"disabled":"off");var E;this.directional&&e.on("contentDirChanged",function(t){var n=CKEDITOR.document.getById(this._.id),i=n.getFirst();t=t.data,t!=e.lang.dir?n.addClass("cke_"+t):n.removeClass("cke_ltr").removeClass("cke_rtl"),i.setAttribute("style",CKEDITOR.skin.getIconStyle(E,"rtl"==t,this.icon,this.iconOffset))},this),u?(a=e.getCommandKeystroke(u))&&(s=CKEDITOR.tools.keystrokeToString(e.lang.common.keyboard,a)):h+="off",a=this.name||this.command;var _=null,T=this.icon;return E=a,this.icon&&!/\./.test(this.icon)?(E=this.icon,T=null):(this.icon&&(_=this.icon),CKEDITOR.env.hidpi&&this.iconHiDpi&&(_=this.iconHiDpi)),_?(CKEDITOR.skin.addIcon(_,_),T=null):_=E,h={id:c,name:a,iconName:E,label:this.label,cls:(this.hasArrow?"cke_button_expandable ":"")+(this.className||""),state:h,ariaDisabled:"disabled"==h?"true":"false",title:this.title+(s?" ("+s.display+")":""),ariaShortcutSpace:s?" ":"",ariaShortcut:s?e.lang.common.keyboardShortcut+" "+s.aria:"",titleJs:d.gecko&&!d.hc?"":(this.title||"").replace("'",""),hasArrow:"string"==typeof this.hasArrow&&this.hasArrow||(this.hasArrow?"true":"false"),keydownFn:g,focusFn:p,clickFn:o,style:CKEDITOR.skin.getIconStyle(_,"rtl"==e.lang.dir,T,this.iconOffset),arrowHtml:this.hasArrow?n.output():"",hasArrowAriaHtml:this.hasArrow?' aria-expanded="false"':"",toggleAriaHtml:this.isToggle?'aria-pressed="false"':""},i.output(h,t),this.onRender&&this.onRender(),f},setState:function(e){if(this._.state==e)return!1;this._.state=e;var t=CKEDITOR.document.getById(this._.id);return!!t&&(t.setState(e,"cke_button"),t.setAttribute("aria-disabled",e==CKEDITOR.TRISTATE_DISABLED),this.isToggle&&!this.hasArrow&&t.setAttribute("aria-pressed",e===CKEDITOR.TRISTATE_ON),!0)},getState:function(){return this._.state},toFeature:function(e){if(this._.feature)return this._.feature;var t=this;return this.allowedContent||this.requiredContent||!this.command||(t=e.getCommand(this.command)||t),this._.feature=t}},CKEDITOR.ui.prototype.addButton=function(e,t){this.add(e,CKEDITOR.UI_BUTTON,t)}}(),function(){function e(e){function n(){var t,n,i,r={};for(t in e.ui.items)n=e.ui.items[t],i=n.toolbar||"others",i=i.split(","),n=i[0],i=parseInt(i[1]||-1,10),r[n]||(r[n]=[]),r[n].push({name:t,order:i});for(n in r)r[n]=r[n].sort(function(e,t){return e.order==t.order?0:0>t.order?-1:0>e.order?1:e.order',t.lang.toolbar.toolbars,"",''],s=!1!==t.config.toolbarStartupExpanded;t.config.toolbarCanCollapse&&t.elementMode!=CKEDITOR.ELEMENT_MODE_INLINE&&l.push('":' style="display:none">'));for(var d=t.toolbox.toolbars,c=e(t),h=c.length,u=0;u"),a=r=0),"/"===E)l.push('');else{p=E.items||E;for(var T=0;T'),g&&l.push('',g,""),l.push('');var I=d.push(m)-1;0'),r=1):r&&(l.push(""),r=0),a&&(O(a),a=0),O(v)}}}r&&(l.push(""),a=r=0),m&&l.push('')}}if(t.config.toolbarCanCollapse&&l.push(""),t.config.toolbarCanCollapse&&t.elementMode!=CKEDITOR.ELEMENT_MODE_INLINE){var D=CKEDITOR.tools.addFunction(function(){t.execCommand("toolbarCollapse")});t.on("destroy",function(){CKEDITOR.tools.removeFunction(D)}),t.addCommand("toolbarCollapse",{readOnly:1,exec:function(e){var t=e.ui.space("toolbar_collapser"),n=t.getPrevious(),i=e.ui.space("contents"),r=n.getParent(),o=parseInt(i.$.style.height,10),a=r.$.offsetHeight,s=t.hasClass("cke_toolbox_collapser_min");s?(n.show(),t.removeClass("cke_toolbox_collapser_min"),t.setAttribute("title",e.lang.toolbar.toolbarCollapse)):(n.hide(),t.addClass("cke_toolbox_collapser_min"),t.setAttribute("title",e.lang.toolbar.toolbarExpand)),t.getFirst().setText(s?"\u25b2":"\u25c0"),i.setStyle("height",o-(r.$.offsetHeight-a)+"px"),e.fire("resize",{outerHeight:e.container.$.offsetHeight,contentsHeight:i.$.offsetHeight,outerWidth:e.container.$.offsetWidth})},modes:{wysiwyg:1,source:1}}),t.setKeystroke(CKEDITOR.ALT+(CKEDITOR.env.ie||CKEDITOR.env.webkit?189:109),"toolbarCollapse"),l.push('','',"")}l.push(""),i.data.html+=l.join("")}}),t.on("destroy",function(){if(this.toolbox){var e,t,n,i,r=0;for(e=this.toolbox.toolbars;r'),{}}}}})}}),CKEDITOR.ui.prototype.addToolbarGroup=function(e,n,i){var r=t(this.editor),o=0===n,a={name:e};if(i){if(i=CKEDITOR.tools.search(r,function(e){return e.name==i}))return!i.groups&&(i.groups=[]),n&&0<=(n=CKEDITOR.tools.indexOf(i.groups,n))?void i.groups.splice(n+1,0,e):void(o?i.groups.splice(0,0,e):i.groups.push(e));n=null}n&&(n=CKEDITOR.tools.indexOf(r,function(e){return e.name==n})),o?r.splice(0,0,e):"number"==typeof n?r.splice(n+1,0,a):r.push(e)}}(),CKEDITOR.UI_SEPARATOR="separator",CKEDITOR.config.toolbarLocation="top",function(){function e(e,t,n){return t.type||(t.type="auto"),!(n&&!1===e.fire("beforePaste",t)||!t.dataValue&&t.dataTransfer.isEmpty())&&(t.dataValue||(t.dataValue=""),CKEDITOR.env.gecko&&"drop"==t.method&&e.toolbox&&e.once("afterPaste",function(){e.toolbox.focus(),e.focus()}),e.fire("paste",t))}function t(t){function n(){var e=t.editable();if(CKEDITOR.plugins.clipboard.isCustomCopyCutSupported){var n=function(e){t.getSelection().isCollapsed()||(t.readOnly&&"cut"==e.name||p.initPasteDataTransfer(e,t),e.data.preventDefault())};e.on("copy",n),e.on("cut",n),e.on("cut",function(){t.readOnly||t.extractSelectedHtml()},null,null,999)}e.on(p.mainPasteEvent,function(e){"beforepaste"==p.mainPasteEvent&&m||u(e)}),"beforepaste"==p.mainPasteEvent&&(e.on("paste",function(e){E||(o(),e.data.preventDefault(),u(e),s("paste"))}),e.on("contextmenu",a,null,null,0),e.on("beforepaste",function(e){!e.data||e.data.$.ctrlKey||e.data.$.shiftKey||a()},null,null,0)),e.on("beforecut",function(){!m&&l()});var i;e.attachListener(CKEDITOR.env.ie?e:t.document.getDocumentElement(),"mouseup",function(){i=setTimeout(f,0)}),t.on("destroy",function(){clearTimeout(i)}),e.on("keyup",f)}function i(e){return{type:e,canUndo:"cut"==e,startDisabled:!0,fakeKeystroke:"cut"==e?CKEDITOR.CTRL+88:CKEDITOR.CTRL+67,exec:function(){"cut"==this.type&&l();var e,n=this.type;if(CKEDITOR.env.ie)e=s(n);else try{e=t.document.$.execCommand(n,!1,null)}catch(t){e=!1}return e||t.showNotification(t.lang.clipboard[this.type+"Error"]),e}}}function r(){return{canUndo:!1,async:!0,fakeKeystroke:CKEDITOR.CTRL+86,exec:function(t,n){function i(n,i){i=void 0===i||i,n?(n.method="paste",n.dataTransfer||(n.dataTransfer=p.initPasteDataTransfer()),e(t,n,i)):o&&!t._.forcePasteDialog&&t.showNotification(l,"info",t.config.clipboard_notificationDuration),t._.forcePasteDialog=!1,t.fire("afterCommandExec",{name:"paste",command:r,returnValue:!!n})}n=void 0!==n&&null!==n?n:{};var r=this,o=void 0===n.notification||n.notification,a=n.type,s=CKEDITOR.tools.keystrokeToString(t.lang.common.keyboard,t.getCommandKeystroke(this)),l="string"==typeof o?o:t.lang.clipboard.pasteNotification.replace(/%1/,''+s.display+""),s="string"==typeof n?n:n.dataValue;a&&!0!==t.config.forcePasteAsPlainText&&"allow-word"!==t.config.forcePasteAsPlainText?t._.nextPasteType=a:delete t._.nextPasteType,"string"==typeof s?i({dataValue:s}):t.getClipboardData(i)}}}function o(){E=1,setTimeout(function(){E=0},100)}function a(){m=1,setTimeout(function(){m=0},10)}function s(e){var n=t.document,i=n.getBody(),r=!1,o=function(){r=!0};return i.on(e,o),7]+data-cke-bookmark[^<]*?<\/span>/gi,""),r&&e(t,i)})}function f(){if("wysiwyg"==t.mode){var e=g("paste");t.getCommand("cut").setState(g("cut")),t.getCommand("copy").setState(g("copy")),t.getCommand("paste").setState(e),t.fire("pasteState",e)}}function g(e){var n=t.getSelection(),n=n&&n.getRanges()[0];return(t.readOnly||n&&n.checkReadOnly())&&e in{paste:1,cut:1}?CKEDITOR.TRISTATE_DISABLED:"paste"==e?CKEDITOR.TRISTATE_OFF:(e=t.getSelection(),n=e.getRanges(),e.getType()==CKEDITOR.SELECTION_NONE||1==n.length&&n[0].collapsed?CKEDITOR.TRISTATE_DISABLED:CKEDITOR.TRISTATE_OFF)}var p=CKEDITOR.plugins.clipboard,m=0,E=0;!function(){if(t.on("key",h),t.on("contentDom",n),t.on("selectionChange",f),t.contextMenu){t.contextMenu.addListener(function(){return{cut:g("cut"),copy:g("copy"),paste:g("paste")}});var e=null;t.on("menuShow",function(){e&&(e.removeListener(),e=null);var n=t.contextMenu.findItemByCommandName("paste");n&&n.element&&(e=n.element.on("touchend",function(){t._.forcePasteDialog=!0}))})}t.ui.addButton&&t.once("instanceReady",function(){t._.pasteButtons&&CKEDITOR.tools.array.forEach(t._.pasteButtons,function(e){(e=t.ui.get(e))&&(e=CKEDITOR.document.getById(e._.id))&&e.on("touchend",function(){t._.forcePasteDialog=!0})})})}(),function(){function e(e,n,i,r,o){var a=t.lang.clipboard[n];t.addCommand(n,i),t.ui.addButton&&t.ui.addButton(e,{label:a,command:n,toolbar:"clipboard,"+r}),t.addMenuItems&&t.addMenuItem(n,{label:a,command:n,group:"clipboard",order:o})}e("Cut","cut",i("cut"),10,1),e("Copy","copy",i("copy"),20,4),e("Paste","paste",r(),30,8),t._.pasteButtons||(t._.pasteButtons=[]),t._.pasteButtons.push("Paste")}(),t.getClipboardData=function(e,n){function i(e){e.removeListener(),e.cancel(),n(e.data)}function r(e){e.removeListener(),e.cancel(),n({type:a,dataValue:e.data.dataValue,dataTransfer:e.data.dataTransfer,method:"paste"})}var o=!1,a="auto";n||(n=e,e=null),t.on("beforePaste",function(e){e.removeListener(),o=!0,a=e.data.type},null,null,1e3),t.on("paste",i,null,null,0),!1===c()&&(t.removeListener("paste",i),t._.forcePasteDialog&&o&&t.fire("pasteDialog")?(t.on("pasteDialogCommit",r),t.on("dialogHide",function(e){e.removeListener(),e.data.removeListener("pasteDialogCommit",r),e.data._.committed||n(null)})):n(null))}}function n(e){if(CKEDITOR.env.webkit){if(!e.match(/^[^<]*$/g)&&!e.match(/^(
<\/div>|
[^<]*<\/div>)*$/gi))return"html"}else if(CKEDITOR.env.ie){if(!e.match(/^([^<]|)*$/gi)&&!e.match(/^(

([^<]|)*<\/p>|(\r\n))*$/gi))return"html"}else{if(!CKEDITOR.env.gecko)return"html";if(!e.match(/^([^<]|)*$/gi))return"html"}return"htmlifiedtext"}function i(e,t){function n(e){return CKEDITOR.tools.repeat("

",~~(e/2))+(1==e%2?"
":"")}return t=t.replace(/(?!\u3000)\s+/g," ").replace(/> +<").replace(/
/gi,"
"),t=t.replace(/<\/?[A-Z]+>/g,function(e){return e.toLowerCase()}),t.match(/^[^<]$/)?t:(CKEDITOR.env.webkit&&-1")&&(t=t.replace(/^(

(
|)<\/div>)(?!$|(
(
|)<\/div>))/g,"
").replace(/^(
(
|)<\/div>){2}(?!$)/g,"
"),t.match(/
(
|)<\/div>/)&&(t="

"+t.replace(/(

(
|)<\/div>)+/g,function(e){return n(e.split("
").length+1)})+"

"),t=t.replace(/<\/div>
/g,"
"),t=t.replace(/<\/?div>/g,"")),CKEDITOR.env.gecko&&e.enterMode!=CKEDITOR.ENTER_BR&&(CKEDITOR.env.gecko&&(t=t.replace(/^

$/,"
")),-1
")&&(t="

"+t.replace(/(
){2,}/g,function(e){return n(e.length/4)})+"

")),a(e,t))}function r(e){function t(){var e,t={};for(e in CKEDITOR.dtd)"$"!=e.charAt(0)&&"div"!=e&&"span"!=e&&(t[e]=1);return t}var n={};return{get:function(i){return"plain-text"==i?n.plainText||(n.plainText=new CKEDITOR.filter(e,"br")):"semantic-content"==i?((i=n.semanticContent)||(i=new CKEDITOR.filter(e,{}),i.allow({$1:{elements:t(),attributes:!0,styles:!1,classes:!1}}),i=n.semanticContent=i),i):i?new CKEDITOR.filter(e,i):null}}}function o(e,t,n){t=CKEDITOR.htmlParser.fragment.fromHtml(t);var i=new CKEDITOR.htmlParser.basicWriter;return n.applyTo(t,!0,!1,e.activeEnterMode),t.writeHtml(i),i.getHtml()}function a(e,t){return e.enterMode==CKEDITOR.ENTER_BR?t=t.replace(/(<\/p>

)+/g,function(e){return CKEDITOR.tools.repeat("
",e.length/7*2)}).replace(/<\/?p>/g,""):e.enterMode==CKEDITOR.ENTER_DIV&&(t=t.replace(/<(\/)?p>/g,"<$1div>")),t}function s(e){e.data.preventDefault(),e.data.$.dataTransfer.dropEffect="none"}function l(t){var n=CKEDITOR.plugins.clipboard;t.on("contentDom",function(){function i(n,i,r){i.select(),e(t,{dataTransfer:r,method:"drop"},1),r.sourceEditor.fire("saveSnapshot"),r.sourceEditor.editable().extractHtmlFromRange(n),r.sourceEditor.getSelection().selectRanges([n]),r.sourceEditor.fire("saveSnapshot")}function r(i,r){i.select(),e(t,{dataTransfer:r,method:"drop"},1),n.resetDragDataTransfer()}function o(e,n,i){var r={$:e.data.$,target:e.data.getTarget()};n&&(r.dragRange=n),i&&(r.dropRange=i),!1===t.fire(e.name,r)&&e.data.preventDefault()}function a(e){return e.type!=CKEDITOR.NODE_ELEMENT&&(e=e.getParent()),e.getChildCount()}var s=t.editable(),l=CKEDITOR.plugins.clipboard.getDropTarget(t),d=t.ui.space("top"),c=t.ui.space("bottom");n.preventDefaultDropOnElement(d),n.preventDefaultDropOnElement(c),s.attachListener(l,"dragstart",o), s.attachListener(t,"dragstart",n.resetDragDataTransfer,n,null,1),s.attachListener(t,"dragstart",function(e){n.initDragDataTransfer(e,t)},null,null,2),s.attachListener(t,"dragstart",function(){var e=n.dragRange=t.getSelection().getRanges()[0];CKEDITOR.env.ie&&10>CKEDITOR.env.version&&(n.dragStartContainerChildCount=e?a(e.startContainer):null,n.dragEndContainerChildCount=e?a(e.endContainer):null)},null,null,100),s.attachListener(l,"dragend",o),s.attachListener(t,"dragend",n.initDragDataTransfer,n,null,1),s.attachListener(t,"dragend",n.resetDragDataTransfer,n,null,100),s.attachListener(l,"dragover",function(e){if(CKEDITOR.env.edge)e.data.preventDefault();else{var t=e.data.getTarget();t&&t.is&&t.is("html")?e.data.preventDefault():CKEDITOR.env.ie&&CKEDITOR.plugins.clipboard.isFileApiSupported&&e.data.$.dataTransfer.types.contains("Files")&&e.data.preventDefault()}}),s.attachListener(l,"drop",function(e){if(!e.data.$.defaultPrevented&&(e.data.preventDefault(),!t.readOnly)){var i=e.data.getTarget();if(!i.isReadOnly()||i.type==CKEDITOR.NODE_ELEMENT&&i.is("html")){var i=n.getRangeAtDropPosition(e,t),r=n.dragRange;i&&o(e,r,i)}}},null,null,9999),s.attachListener(t,"drop",n.initDragDataTransfer,n,null,1),s.attachListener(t,"drop",function(e){if(e=e.data){var o=e.dropRange,a=e.dragRange,s=e.dataTransfer;s.getTransferType(t)==CKEDITOR.DATA_TRANSFER_INTERNAL?setTimeout(function(){n.internalDrop(a,o,s,t)},0):s.getTransferType(t)==CKEDITOR.DATA_TRANSFER_CROSS_EDITORS?i(a,o,s):r(o,s)}},null,null,9999)})}var d;CKEDITOR.plugins.add("clipboard",{requires:"dialog,notification,toolbar",_supportedFileMatchers:[],init:function(e){function a(t){return!!e.config.clipboard_handleImages&&-1!==CKEDITOR.tools.indexOf(["image/png","image/jpeg","image/gif"],t.type)}function s(t){return CKEDITOR.tools.array.some(e.plugins.clipboard._supportedFileMatchers,function(e){return e(t)})}function d(t){t.length&&(t=CKEDITOR.tools.array.unique(t),t=CKEDITOR.tools.array.filter(t,function(e){return!!CKEDITOR.tools.trim(e)}),t=c(t.join(", ")),e.showNotification(t,"info",e.config.clipboard_notificationDuration))}function c(t){return t?e.lang.clipboard.fileFormatNotSupportedNotification.replace(/\${formats\}/g,""+t+""):e.lang.clipboard.fileWithoutFormatNotSupportedNotification}function h(e,t){return!(CKEDITOR.env.ie&&e.data.fileTransferCancel||!(CKEDITOR.env.ie||t&&g!==t.id))&&(t.isFileTransfer()&&1===t.getFilesCount())}var u,f=r(e);e.config.forcePasteAsPlainText?u="plain-text":e.config.pasteFilter?u=e.config.pasteFilter:!CKEDITOR.env.webkit||"pasteFilter"in e.config||(u="semantic-content"),e.pasteFilter=f.get(u),t(e),l(e),CKEDITOR.dialog.add("paste",CKEDITOR.getUrl(this.path+"dialogs/paste.js"));var g,p=CKEDITOR.plugins.clipboard.isCustomDataTypesSupported||CKEDITOR.plugins.clipboard.isFileApiSupported;CKEDITOR.plugins.clipboard.addFileMatcher(e,a),e.on("paste",function(e){if(p){var t=e.data;if(e=t.dataTransfer,!t.dataValue){for(var t=[],n=0;n',e.fire("paste",t.data)},!1),r.addEventListener("abort",function(){CKEDITOR.env.ie&&(t.data.fileTransferCancel=!0),e.fire("paste",t.data)},!1),r.addEventListener("error",function(){CKEDITOR.env.ie&&(t.data.fileTransferCancel=!0),e.fire("paste",t.data)},!1),r.readAsDataURL(i),g=n.dataTransfer.id,t.stop()}}},null,null,1),e.on("paste",function(t){if(t.data.dataTransfer||(t.data.dataTransfer=new CKEDITOR.plugins.clipboard.dataTransfer),!t.data.dataValue){var n=t.data.dataTransfer,i=n.getData("text/html");i?(t.data.dataValue=i,t.data.type="html"):(i=n.getData("text/plain"))&&(t.data.dataValue=e.editable().transformPlainTextToHtml(i),t.data.type="text")}},null,null,1),e.on("paste",function(e){var t=e.data.dataValue,n=CKEDITOR.dtd.$block;if(-1 <\/span>/gi," "),"html"!=e.data.type&&(t=t.replace(/]*>([^<]*)<\/span>/gi,function(e,t){return t.replace(/\t/g,"    ")})),-1')&&(e.data.startsWithEOL=1,e.data.preSniffing="html",t=t.replace(/
/,"")),t=t.replace(/(<[^>]+) class="Apple-[^"]*"/gi,"$1")),t.match(/^<[^<]+cke_(editable|contents)/i)){var i,r,o=new CKEDITOR.dom.element("div");for(o.setHtml(t);1==o.getChildCount()&&(i=o.getFirst())&&i.type==CKEDITOR.NODE_ELEMENT&&(i.hasClass("cke_editable")||i.hasClass("cke_contents"));)o=r=i;r&&(t=r.getHtml().replace(/
$/i,""))}CKEDITOR.env.ie?t=t.replace(/^ (?: |\r\n)?<(\w+)/g,function(t,i){return i.toLowerCase()in n?(e.data.preSniffing="html","<"+i):t}):CKEDITOR.env.webkit?t=t.replace(/<\/(\w+)>


<\/div>$/,function(t,i){return i in n?(e.data.endsWithEOL=1,""):t}):CKEDITOR.env.gecko&&(t=t.replace(/(\s)
$/,"$1")),e.data.dataValue=t},null,null,3),e.on("paste",function(t){t=t.data;var r,a=e._.nextPasteType||t.type,s=t.dataValue,l=e.config.clipboard_defaultContentType||"html",d=t.dataTransfer.getTransferType(e)==CKEDITOR.DATA_TRANSFER_EXTERNAL,c=!0===e.config.forcePasteAsPlainText;r="html"==a||"html"==t.preSniffing?"html":n(s),delete e._.nextPasteType,"htmlifiedtext"==r&&(s=i(e.config,s)),"text"==a&&"html"==r?s=o(e,s,f.get("plain-text")):(d&&e.pasteFilter&&!t.dontFilter||c)&&(s=o(e,s,e.pasteFilter)),t.startsWithEOL&&(s='
'+s),t.endsWithEOL&&(s+='
'),"auto"==a&&(a="html"==r||"html"==l?"html":"text"),t.type=a,t.dataValue=s,delete t.preSniffing,delete t.startsWithEOL,delete t.endsWithEOL},null,null,6),e.on("paste",function(t){t=t.data,t.dataValue&&(e.insertHtml(t.dataValue,t.type,t.range),setTimeout(function(){e.fire("afterPaste")},0))},null,null,1e3),e.on("pasteDialog",function(t){setTimeout(function(){e.openDialog("paste",t.data)},0)})}}),CKEDITOR.plugins.clipboard={addFileMatcher:function(e,t){e.plugins.clipboard._supportedFileMatchers.push(t)},isCustomCopyCutSupported:!(CKEDITOR.env.ie&&16>CKEDITOR.env.version||CKEDITOR.env.iOS&&605>CKEDITOR.env.version),isCustomDataTypesSupported:!CKEDITOR.env.ie||16<=CKEDITOR.env.version,isFileApiSupported:!CKEDITOR.env.ie||9CKEDITOR.env.version||t.isInline()?t:e.document},fixSplitNodesAfterDrop:function(e,t,n,i){function r(e,n,i){var r=e;if(r.type==CKEDITOR.NODE_TEXT&&(r=e.getParent()),r.equals(n)&&i!=n.getChildCount())return e=t.startContainer.getChild(t.startOffset-1),n=t.startContainer.getChild(t.startOffset),e&&e.type==CKEDITOR.NODE_TEXT&&n&&n.type==CKEDITOR.NODE_TEXT&&(i=e.getLength(),e.setText(e.getText()+n.getText()),n.remove(),t.setStart(e,i),t.collapse(!0)),!0}var o=t.startContainer;"number"==typeof i&&"number"==typeof n&&o.type==CKEDITOR.NODE_ELEMENT&&(r(e.startContainer,o,n)||r(e.endContainer,o,i))},isDropRangeAffectedByDragRange:function(e,t){var n=t.startContainer,i=t.endOffset;return!!(e.endContainer.equals(n)&&e.endOffset<=i||e.startContainer.getParent().equals(n)&&e.startContainer.getIndex()CKEDITOR.env.version&&this.fixSplitNodesAfterDrop(t,n,s.dragStartContainerChildCount,s.dragEndContainerChildCount),(a=this.isDropRangeAffectedByDragRange(t,n))||(o=t.createBookmark(!1)),s=n.clone().createBookmark(!1),a&&(o=t.createBookmark(!1)),t=o.startNode,n=o.endNode,a=s.startNode,n&&t.getPosition(a)&CKEDITOR.POSITION_PRECEDING&&n.getPosition(a)&CKEDITOR.POSITION_FOLLOWING&&a.insertBefore(t),t=r.createRange(),t.moveToBookmark(o),l.extractHtmlFromRange(t,1),n=r.createRange(),s.startNode.getCommonAncestor(l)||(s=r.getSelection().createBookmarks()[0]),n.moveToBookmark(s),e(r,{dataTransfer:i,method:"drop",range:n},1),r.fire("unlockSnapshot")},getRangeAtDropPosition:function(e,t){var n=e.data.$,i=n.clientX,r=n.clientY,o=t.getSelection(!0).getRanges()[0],a=t.createRange();if(e.data.testRange)return e.data.testRange;if(document.caretRangeFromPoint&&t.document.$.caretRangeFromPoint(i,r))n=t.document.$.caretRangeFromPoint(i,r),a.setStart(CKEDITOR.dom.node(n.startContainer),n.startOffset),a.collapse(!0);else if(n.rangeParent)a.setStart(CKEDITOR.dom.node(n.rangeParent),n.rangeOffset),a.collapse(!0);else{if(CKEDITOR.env.ie&&8l&&!s;l++){if(!s)try{n.moveToPoint(i,r-l),s=!0}catch(e){}if(!s)try{n.moveToPoint(i,r+l),s=!0}catch(e){}}if(s){var d="cke-temp-"+(new Date).getTime();n.pasteHTML('\u200b');var c=t.document.getById(d);a.moveToPosition(c,CKEDITOR.POSITION_BEFORE_START),c.remove()}else{var h,u=t.document.$.elementFromPoint(i,r),f=new CKEDITOR.dom.element(u);if(f.equals(t.editable())||"html"==f.getName())return o&&o.startContainer&&!o.startContainer.equals(t.editable())?o:null;h=f.getClientRect(),i/i,fragmentRegExp:/\s*\x3c!--StartFragment--\x3e|\x3c!--EndFragment--\x3e\s*/g,types:[],data:{},files:[],nativeHtmlCache:"",normalizeType:function(e){return e=e.toLowerCase(),"text"==e||"text/plain"==e?"Text":"url"==e?"URL":"files"===e?"Files":e}},this._.fallbackDataTransfer=new CKEDITOR.plugins.clipboard.fallbackDataTransfer(this),this.id=this.getData(d),this.id||(this.id="Text"==d?"":"cke-"+CKEDITOR.tools.getUniqueId()),t&&(this.sourceEditor=t,this.setData("text/html",t.getSelectedHtml(1)),"Text"==d||this.getData("text/plain")||this.setData("text/plain",t.getSelection().getSelectedText()))},CKEDITOR.DATA_TRANSFER_INTERNAL=1,CKEDITOR.DATA_TRANSFER_CROSS_EDITORS=2,CKEDITOR.DATA_TRANSFER_EXTERNAL=3,CKEDITOR.plugins.clipboard.dataTransfer.prototype={getData:function(e,t){e=this._.normalizeType(e);var n="text/html"==e&&t?this._.nativeHtmlCache:this._.data[e];if(void 0===n||null===n||""===n){if(this._.fallbackDataTransfer.isRequired())n=this._.fallbackDataTransfer.getData(e,t);else try{n=this.$.getData(e)||""}catch(e){n=""}"text/html"!=e||t||(n=this._stripHtml(n))}if("Text"==e&&CKEDITOR.env.gecko&&this.getFilesCount()&&"file://"==n.substring(0,7)&&(n=""),"string"==typeof n)var i=n.indexOf(""),n=-1!==i?n.substring(0,i+7):n;return n},setData:function(e,t){if(e=this._.normalizeType(e),"text/html"==e?(this._.data[e]=this._stripHtml(t),this._.nativeHtmlCache=t):this._.data[e]=t,CKEDITOR.plugins.clipboard.isCustomDataTypesSupported||"URL"==e||"Text"==e)if("Text"==d&&"Text"==e&&(this.id=t),this._.fallbackDataTransfer.isRequired())this._.fallbackDataTransfer.setData(e,t);else try{this.$.setData(e,t)}catch(e){}},storeId:function(){"Text"!==d&&this.setData(d,this.id)},getTransferType:function(e){return this.sourceEditor?this.sourceEditor==e?CKEDITOR.DATA_TRANSFER_INTERNAL:CKEDITOR.DATA_TRANSFER_CROSS_EDITORS:CKEDITOR.DATA_TRANSFER_EXTERNAL},cacheData:function(){function e(e){e=r._.normalizeType(e);var t=r.getData(e);"text/html"==e&&(r._.nativeHtmlCache=r.getData(e,!0),t=r._stripHtml(t)),t&&(r._.data[e]=t),r._.types.push(e)}if(this.$){var t,n,i,r=this;if(CKEDITOR.plugins.clipboard.isCustomDataTypesSupported){if(this.$.types)for(t=0;t$/gi,"")}(e),e=e.replace(this._.metaRegExp,""),e=e.replace(this._.fragmentRegExp,"")),e}},CKEDITOR.plugins.clipboard.fallbackDataTransfer=function(e){this._dataTransfer=e,this._customDataFallbackType="text/html"},CKEDITOR.plugins.clipboard.fallbackDataTransfer._isCustomMimeTypeSupported=null,CKEDITOR.plugins.clipboard.fallbackDataTransfer._customTypes=[],CKEDITOR.plugins.clipboard.fallbackDataTransfer.prototype={isRequired:function(){var e=CKEDITOR.plugins.clipboard.fallbackDataTransfer,t=this._dataTransfer.$;if(null===e._isCustomMimeTypeSupported){if(!t)return!1;if(e._isCustomMimeTypeSupported=!1,CKEDITOR.env.edge&&17<=CKEDITOR.env.version)return!0;try{t.setData("cke/mimetypetest","cke test value"),e._isCustomMimeTypeSupported="cke test value"===t.getData("cke/mimetypetest"),t.clearData("cke/mimetypetest")}catch(e){}}return!e._isCustomMimeTypeSupported},getData:function(e,t){var n=this._getData(this._customDataFallbackType,!0);if(t)return n;var n=this._extractDataComment(n),i=null,i=e===this._customDataFallbackType?n.content:n.data&&n.data[e]?n.data[e]:this._getData(e,!0);return null!==i?i:""},setData:function(e,t){var n=e===this._customDataFallbackType;n&&(t=this._applyDataComment(t,this._getFallbackTypeData()));var i=t,r=this._dataTransfer.$;try{r.setData(e,i),n&&(this._dataTransfer._.nativeHtmlCache=i)}catch(t){if(this._isUnsupportedMimeTypeError(t)){n=CKEDITOR.plugins.clipboard.fallbackDataTransfer,-1===CKEDITOR.tools.indexOf(n._customTypes,e)&&n._customTypes.push(e);var n=this._getFallbackTypeContent(),o=this._getFallbackTypeData();o[e]=i;try{i=this._applyDataComment(n,o),r.setData(this._customDataFallbackType,i),this._dataTransfer._.nativeHtmlCache=i}catch(e){i=""}}}return i},_getData:function(e,t){var n=this._dataTransfer._.data;if(!t&&n[e])return n[e];try{return this._dataTransfer.$.getData(e)}catch(e){return null}},_getFallbackTypeContent:function(){var e=this._dataTransfer._.data[this._customDataFallbackType];return e||(e=this._extractDataComment(this._getData(this._customDataFallbackType,!0)).content),e},_getFallbackTypeData:function(){var e=CKEDITOR.plugins.clipboard.fallbackDataTransfer._customTypes,t=this._extractDataComment(this._getData(this._customDataFallbackType,!0)).data||{},n=this._dataTransfer._.data;return CKEDITOR.tools.array.forEach(e,function(e){void 0!==n[e]?t[e]=n[e]:void 0!==t[e]&&(t[e]=t[e])},this),t},_isUnsupportedMimeTypeError:function(e){return e.message&&-1!==e.message.search(/element not found/gi)},_extractDataComment:function(e){var t={data:null,content:e||""};if(e&&16"==e||"

 

"==e||"


"==e||"

"==e||"

 

"==e||" "==e||" "==e||" 
"==e||"
"==e)}function t(t){var n=t.editor;if(!n.readOnly){var i=n.editable(),r=t.listenerData;if(i){if("wysiwyg"==n.mode){if(CKEDITOR.dialog._.currentTop||!i)return;e(i.getHtml())&&(i.setHtml(r),i.addClass("placeholder"))}"source"==n.mode&&(o?"mode"==t.name&&i.setAttribute("placeholder",r):e(i.getValue())&&(i.setValue(r),i.addClass("placeholder")))}}}function n(e){e=e.editor;var t=e.editable();if(t){if("wysiwyg"==e.mode){if(!t.hasClass("placeholder"))return;if(t.removeClass("placeholder"),CKEDITOR.dtd[t.getName()].p){var n="";e.enterMode===CKEDITOR.ENTER_P?n="


":e.enterMode===CKEDITOR.ENTER_DIV?n="

":(n="
",(CKEDITOR.env.gecko||CKEDITOR.env.ie)&&(n=" ")),t.setHtml(n),n=new CKEDITOR.dom.range(e.document),n.moveToElementEditablePosition(t.getFirst(),!0),e.getSelection().selectRanges([n])}else t.setHtml(" ")}"source"==e.mode&&t.hasClass("placeholder")&&(t.removeClass("placeholder"),t.setValue(""))}}function i(e){e.editor.readOnly?n(e):t(e)}function r(e){return e?e.getAttribute("lang")||r(e.getParent()):null}var o="placeholder"in document.createElement("textarea");CKEDITOR.plugins.add("confighelper",{getPlaceholderCss:function(){return".placeholder{ color: #999; }"},onLoad:function(){CKEDITOR.addCss(this.getPlaceholderCss())},init:function(a){function s(e){if(a==e.editor){var t=e.data.name;e=e.data.definition;var n,i,r,o,s;if("tableProperties"==t&&(t="table"),"removeDialogFields"in a._||!a.config.removeDialogFields||(a._.removeDialogFields=c(a.config.removeDialogFields)),a._.removeDialogFields&&(n=a._.removeDialogFields[t]))for(r in n)if(o=n[r],s=e.getContents(r))for(i=0;iCKEDITOR.env.version?d.$.styleSheet.cssText="textarea.placeholder { color: #999; font-style: italic; }":d.$.innerHTML="textarea.placeholder { color: #999; font-style: italic; }",a.on("getData",function(e){var t=a.editable();t&&t.hasClass("placeholder")&&(e.data.dataValue="")}),a.on("setData",function(n){if(!(CKEDITOR.dialog._.currentTop||"source"==a.mode&&o)){var i=a.editable();i&&(e(n.data.dataValue)?t(n):i.hasClass("placeholder")&&i.removeClass("placeholder"))}}),a.on("blur",t,null,l),a.on("mode",t,null,l),a.on("contentDom",t,null,l),a.on("focus",n),a.on("key",n),a.on("beforeModeUnload",n),a.on("readOnly",i,null,l)}if((l=a.config.contentsLanguage||r(a.element))&&a.plugins.scayt&&!a.config.scayt_sLang){try{localStorage&&localStorage.removeItem("scayt_0_lang")}catch(e){}a.config.scayt_sLang={en:"en_US","en-us":"en_US","en-gb":"en_GB","pt-br":"pt_BR",da:"da_DK","da-dk":"da_DK","nl-nl":"nl_NL","en-ca":"en_CA","fi-fi":"fi_FI",fr:"fr_FR","fr-fr":"fr_FR","fr-ca":"fr_CA",de:"de_DE","de-de":"de_DE","el-gr":"el_GR",it:"it_IT","it-it":"it_IT","nb-no":"nb_NO",pt:"pt_PT","pt-pt":"pt_PT",es:"es_ES","es-es":"es_ES","sv-se":"sv_SE"}[l.toLowerCase()]}var c=function(e){if("object"==typeof e)return e;e=e.split(";");var t,n={};for(t=0;t",lt:"<",amp:"&",apos:"'",quot:'"'};if(e=e.replace(/\b(nbsp|shy|gt|lt|amp|apos|quot)(?:,|$)/g,function(e,o){var a=t?"&"+o+";":r[o];return n[a]=t?r[o]:"&"+o+";",i.push(a),""}),e=e.replace(/,$/,""),!t&&e){e=e.split(",");var o,a=document.createElement("div");for(a.innerHTML="&"+e.join(";&")+";",o=a.innerHTML,a=null,a=0;a=this.strokesLimit,this.typing||(this.hasUndo=this.typing=!0,this.hasRedo=!1,this.onChange()),t?(r=0,this.editor.fire("saveSnapshot")):this.editor.fire("change"),this.strokesRecorded[n]=r,this.previousKeyGroup=n},keyGroupChanged:function(e){return i.getKeyGroup(e)!=this.previousKeyGroup},reset:function(){this.snapshots=[],this.index=-1,this.currentImage=null,this.hasRedo=this.hasUndo=!1,this.locked=null,this.resetType()},resetType:function(){this.strokesRecorded=[0,0],this.typing=!1,this.previousKeyGroup=-1},refreshState:function(){this.hasUndo=!!this.getNextImage(!0),this.hasRedo=!!this.getNextImage(!1),this.resetType(),this.onChange()},save:function(e,t,n){var i=this.editor;if(this.locked||"ready"!=i.status||"wysiwyg"!=i.mode)return!1;var o=i.editable();if(!o||"ready"!=o.status)return!1;if(o=this.snapshots,t||(t=new r(i)),!1===t.contents)return!1;if(this.currentImage)if(t.equalsContent(this.currentImage)){if(e||t.equalsSelection(this.currentImage))return!1}else!1!==n&&i.fire("change");return o.splice(this.index+1,o.length-this.index-1),o.length==this.limit&&o.shift(),this.index=o.push(t)-1,this.currentImage=t,!1!==n&&this.refreshState(),!0},restoreImage:function(e){var t,n=this.editor;e.bookmarks&&(n.focus(),t=n.getSelection()),this.locked={level:999},this.editor.loadSnapshot(e.contents),e.bookmarks?t.selectBookmarks(e.bookmarks):CKEDITOR.env.ie&&(t=this.editor.document.getBody().$.createTextRange(),t.collapse(!0),t.select()),this.locked=null,this.index=e.index,this.currentImage=this.snapshots[this.index],this.update(),this.refreshState(),n.fire("change")},getNextImage:function(e){var t,n=this.snapshots,i=this.currentImage;if(i)if(e){for(t=this.index-1;0<=t;t--)if(e=n[t],!i.equalsContent(e))return e.index=t,e}else for(t=this.index+1;t=this.undoManager.strokesLimit&&(this.undoManager.type(e.keyCode,!0),this.keyEventsStack.resetInputs())}},onKeyup:function(e){var t=this.undoManager;e=e.data.getKey();var n=this.keyEventsStack.getTotalInputs();this.keyEventsStack.remove(e),i.ieFunctionalKeysBug(e)&&this.lastKeydownImage&&this.lastKeydownImage.equalsContent(new r(t.editor,!0))||(0=this.rect.right||e<=this.rect.top||e>=this.rect.bottom)&&this.hideVisible(),(0>=t||t>=this.winTopPane.width||0>=e||e>=this.winTopPane.height)&&this.hideVisible()},this),n.attachListener(e,"resize",i),n.attachListener(e,"mode",s),e.on("destroy",s),this.lineTpl=new CKEDITOR.template('
  
').output({lineStyle:CKEDITOR.tools.writeCssText(CKEDITOR.tools.extend({},o,this.lineStyle,!0)),tipLeftStyle:CKEDITOR.tools.writeCssText(CKEDITOR.tools.extend({},r,{left:"0px","border-left-color":"red","border-width":"6px 0 6px 6px"},this.tipCss,this.tipLeftStyle,!0)),tipRightStyle:CKEDITOR.tools.writeCssText(CKEDITOR.tools.extend({},r,{right:"0px","border-right-color":"red","border-width":"6px 6px 6px 0"},this.tipCss,this.tipRightStyle,!0))})}function i(e){var t;return(t=e&&e.type==CKEDITOR.NODE_ELEMENT)&&(t=!(a[e.getComputedStyle("float")]||a[e.getAttribute("align")])),t&&!s[e.getComputedStyle("position")]}CKEDITOR.plugins.add("lineutils"),CKEDITOR.LINEUTILS_BEFORE=1,CKEDITOR.LINEUTILS_AFTER=2,CKEDITOR.LINEUTILS_INSIDE=4,e.prototype={start:function(e){var t,n,i,r,o=this,a=this.editor,s=this.doc,l=CKEDITOR.tools.eventsBuffer(50,function(){a.readOnly||"wysiwyg"!=a.mode||(o.relations={},(n=s.$.elementFromPoint(i,r))&&n.nodeType&&(t=new CKEDITOR.dom.element(n),o.traverseSearch(t),isNaN(i+r)||o.pixelSearch(t,i,r),e&&e(o.relations,i,r)))});this.listener=this.editable.attachListener(this.target,"mousemove",function(e){i=e.data.$.clientX,r=e.data.$.clientY,l.input()}),this.editable.attachListener(this.inline?this.editable:this.frame,"mouseout",function(){l.reset()})},stop:function(){this.listener&&this.listener.removeListener()},getRange:function(){var e={};return e[CKEDITOR.LINEUTILS_BEFORE]=CKEDITOR.POSITION_BEFORE_START,e[CKEDITOR.LINEUTILS_AFTER]=CKEDITOR.POSITION_AFTER_END,e[CKEDITOR.LINEUTILS_INSIDE]=CKEDITOR.POSITION_AFTER_START,function(t){var n=this.editor.createRange();return n.moveToPosition(this.relations[t.uid].element,e[t.type]),n}}(),store:function(){function e(e,t,n){var i=e.getUniqueId();i in n?n[i].type|=t:n[i]={element:e,type:t}}return function(t,n){var r;n&CKEDITOR.LINEUTILS_AFTER&&i(r=t.getNext())&&r.isVisible()&&(e(r,CKEDITOR.LINEUTILS_BEFORE,this.relations),n^=CKEDITOR.LINEUTILS_AFTER),n&CKEDITOR.LINEUTILS_INSIDE&&i(r=t.getFirst())&&r.isVisible()&&(e(r,CKEDITOR.LINEUTILS_BEFORE,this.relations),n^=CKEDITOR.LINEUTILS_INSIDE),e(t,n,this.relations)}}(),traverseSearch:function(e){var t,n,r;do{if(!((r=e.$["data-cke-expando"])&&r in this.relations)){if(e.equals(this.editable))break;if(i(e))for(t in this.lookups)(n=this.lookups[t](e))&&this.store(e,n)}}while((!e||e.type!=CKEDITOR.NODE_ELEMENT||"true"!=e.getAttribute("contenteditable"))&&(e=e.getParent()))},pixelSearch:function(){function e(e,n,r,o,a){for(var s,l=0;a(r)&&(r+=o,25!=++l);)if(s=this.doc.$.elementFromPoint(n,r))if(s==e)l=0;else if(t(e,s)&&(l=0,i(s=new CKEDITOR.dom.element(s))))return s}var t=CKEDITOR.env.ie||CKEDITOR.env.webkit?function(e,t){return e.contains(t)}:function(e,t){return!!(16&e.compareDocumentPosition(t))};return function(t,n,r){var o=this.win.getViewPaneSize().height,a=e.call(this,t.$,n,r,-1,function(e){return 0this.rect.bottom)return!1;this.inline?r.left=n.elementRect.left-this.rect.relativeX:(0[^<]*[^<]*<");return new RegExp((e?"":"^")+t+(e?"$":""))},addSelectAllIntegration:function(e){var t=this;e.editable().attachListener(e,"beforeCommandExec",function(n){var i=e.editable();"selectAll"==n.data.name&&i&&t.addFillers(i)},null,null,9999)}}}(),function(){function e(e){this.editor=e,this.registered={},this.instances={},this.selected=[],this.widgetHoldingFocusedEditable=this.focused=null,this._={nextId:0,upcasts:[],upcastCallbacks:[],filters:{}},R(this),D(this),this.on("checkWidgets",a),this.editor.on("contentDomInvalidated",this.checkWidgets,this),I(this),C(this),v(this),T(this),O(this)}function t(e,n,i,r,o){var a=e.editor;CKEDITOR.tools.extend(this,r,{editor:a,id:n,inline:"span"==i.getParent().getName(),element:i,data:CKEDITOR.tools.extend({},"function"==typeof r.defaults?r.defaults():r.defaults),dataReady:!1,inited:!1,ready:!1,edit:t.prototype.edit,focusedEditable:null,definition:r,repository:e,draggable:!1!==r.draggable,_:{downcastFn:r.downcast&&"string"==typeof r.downcast?r.downcasts[r.downcast]:r.downcast}},!0),e.fire("instanceCreated",this),P(this,r),this.init&&this.init(),this.inited=!0,(e=this.element.data("cke-widget-data"))&&this.setData(JSON.parse(decodeURIComponent(e))),o&&this.setData(o),this.data.classes||this.setData("classes",this.getClasses()),this.dataReady=!0,W(this),this.fire("data",this.data),this.isInited()&&a.editable().contains(this.wrapper)&&(this.ready=!0,this.fire("ready"))}function n(e,t,n){CKEDITOR.dom.element.call(this,t.$),this.editor=e,this._={},t=this.filter=n.filter,CKEDITOR.dtd[this.getName()].p?(this.enterMode=t?t.getAllowedEnterMode(e.enterMode):e.enterMode,this.shiftEnterMode=t?t.getAllowedEnterMode(e.shiftEnterMode,!0):e.shiftEnterMode):this.enterMode=this.shiftEnterMode=CKEDITOR.ENTER_BR}function i(e,t){e.addCommand(t.name,{exec:function(e,n){function i(){e.widgets.finalizeCreation(s)}var r=e.widgets.focused;if(r&&r.name==t.name)r.edit();else if(t.insert)t.insert({editor:e,commandData:n});else if(t.template){var o,r="function"==typeof t.defaults?t.defaults():t.defaults,r=CKEDITOR.tools.object.merge(r||{},n&&n.startupData||{}),r=CKEDITOR.dom.element.createFromHtml(t.template.output(r),e.document),a=e.widgets.wrapElement(r,t.name),s=new CKEDITOR.dom.documentFragment(a.getDocument());s.append(a),(o=e.widgets.initOn(r,t,n&&n.startupData))?(r=o.once("edit",function(t){t.data.dialog?o.once("dialog",function(t){t=t.data;var n,r;n=t.once("ok",i,null,null,20),r=t.once("cancel",function(t){t.data&&!1===t.data.hide||e.widgets.destroy(o,!0)}),t.once("hide",function(){n.removeListener(),r.removeListener()})}):i()},null,null,999),o.edit(),r.removeListener()):i()}},allowedContent:t.allowedContent,requiredContent:t.requiredContent,contentForms:t.contentForms,contentTransformations:t.contentTransformations})}function r(e,t){function n(e,n){var i,r,o=t.upcast.split(",");for(r=0;ri});0>r&&(r=e._.upcasts.length),e._.upcasts.splice(r,0,[CKEDITOR.tools.bind(t,n),n.name,i])}var r=t.upcast,o=t.upcastPriority||10;r&&("string"==typeof r?i(n,t,o):i(r,t,o))}function o(e,t){if(e.focused=null,t.isInited()){var n=t.editor.checkDirty();e.fire("widgetBlurred",{widget:t}),t.setFocused(!1),!n&&t.editor.resetDirty()}}function a(e){if(e=e.data,"wysiwyg"==this.editor.mode){var n,i,r,o,a=this.editor.editable(),s=this.instances;if(a){for(n in s)s[n].isReady()&&!a.contains(s[n].wrapper)&&this.destroy(s[n],!0);if(e&&e.initOnlyNew)s=this.initOnAll();else{var l=a.find(".cke_widget_wrapper"),s=[];for(n=0,i=l.count();ne.selected.length||N(n,"cut"===t.name)}var n=e.editor;n.on("contentDom",function(){var e=n.editable();e.attachListener(e,"copy",t),e.attachListener(e,"cut",t)})}function I(e){function n(){var e=a.getSelection();if(e&&(e=e.getRanges()[0])&&!e.collapsed){var t=i(e.startContainer),n=i(e.endContainer);!t&&n?(e.setEndBefore(n.wrapper),e.select()):t&&!n&&(e.setStartAfter(t.wrapper),e.select())}}function i(e){return e?e.type==CKEDITOR.NODE_TEXT?i(e.getParent()):a.widgets.getByElement(e):null}function r(){e.fire("checkSelection")}var a=e.editor;a.on("selectionCheck",r),a.on("contentDom",function(){a.editable().attachListener(a,"key",function(){setTimeout(r,10)})}),CKEDITOR.env.ie||e.on("checkSelection",n),e.on("checkSelection",e.checkSelection,e),a.on("selectionChange",function(n){var i=(n=t.getNestedEditable(a.editable(),n.data.selection.getStartElement()))&&e.getByElement(n),r=e.widgetHoldingFocusedEditable;r?r===i&&r.focusedEditable.equals(n)||(m(e,r,null),i&&n&&m(e,i,n)):i&&n&&m(e,i,n)}),a.on("dataReady",function(){b(e).commit()}),a.on("blur",function(){var t;(t=e.focused)&&o(e,t),(t=e.widgetHoldingFocusedEditable)&&m(e,t,null)})}function D(e){var n=e.editor,i={};n.on("toDataFormat",function(n){var r=CKEDITOR.tools.getNextNumber(),o=[];n.data.downcastingSessionId=r,i[r]=o,n.data.dataValue.forEach(function(n){var i,r=n.attributes;if("data-cke-widget-white-space"in r){i=l(n);var a=d(n);i.parent.attributes["data-cke-white-space-first"]&&(i.value=i.value.replace(/^ /g," ")),a.parent.attributes["data-cke-white-space-last"]&&(a.value=a.value.replace(/ $/g," "))}if("data-cke-widget-id"in r)(r=e.instances[r["data-cke-widget-id"]])&&(i=n.getFirst(t.isParserWidgetElement),o.push({wrapper:n,element:i,widget:r,editables:{}}),i&&"1"!=i.attributes["data-cke-widget-keep-attr"]&&delete i.attributes["data-widget"]);else if("data-cke-widget-editable"in r)return 0CKEDITOR.tools.indexOf(t,e)&&n.push(e),e=CKEDITOR.tools.indexOf(i,e),0<=e&&i.splice(e,1),this},focus:function(e){return r=e,this},commit:function(){var a,s,l=e.focused!==r;for(e.editor.fire("lockSnapshot"),l&&(a=e.focused)&&o(e,a);a=i.pop();)t.splice(CKEDITOR.tools.indexOf(t,a),1),a.isInited()&&(s=a.editor.checkDirty(),a.setSelected(!1),!s&&a.editor.resetDirty());for(l&&r&&(s=e.editor.checkDirty(),e.focused=r,e.fire("widgetFocused",{widget:r}),r.setFocused(!0),!s&&e.editor.resetDirty());a=n.pop();)t.push(a),a.setSelected(!0);e.editor.fire("unlockSnapshot")}}}function y(e){e&&e.addFilterRule(function(e){return e.replace(/\s*cke_widget_selected/g,"").replace(/\s*cke_widget_focused/g,"")})}function K(e,t,n){var i=0;t=x(t);var r,o=e.data.classes||{};if(t){for(o=CKEDITOR.tools.clone(o);r=t.pop();)n?o[r]||(i=o[r]=1):o[r]&&(delete o[r],i=1);i&&e.setData("classes",o)}}function k(e){e.cancel()}function w(e,t){var n=function(e){return e==CKEDITOR.ENTER_BR?"br":e==CKEDITOR.ENTER_DIV?"div":"p"}(e.editor.config.enterMode),i=new CKEDITOR.dom.element(n);"br"!==n&&i.appendBogus(),"after"===t?i.insertAfter(e.wrapper):i.insertBefore(e.wrapper),function(t){var n=e.editor.createRange();n.setStart(t,0),e.editor.getSelection().selectRanges([n])}(i)}function N(e,t){var n,i,r,o=e.widgets.focused;J.hasCopyBin(e)||(i=new J(e,{beforeDestroy:function(){!t&&o&&o.focus(),r&&e.getSelection().selectBookmarks(r),n&&CKEDITOR.plugins.widgetselection.addFillers(e.editable())},afterDestroy:function(){t&&!e.readOnly&&(o?e.widgets.del(o):e.extractSelectedHtml(),e.fire("saveSnapshot"))}}),o||(n=CKEDITOR.env.webkit&&CKEDITOR.plugins.widgetselection.isWholeContentSelected(e.editable()),r=e.getSelection().createBookmarks(!0)),i.handle(L(e)))}function x(e){return(e=(e=e.getDefinition().attributes)&&e.class)?e.split(/\s+/):null}function S(){var e=CKEDITOR.document.getActive(),t=this.editor,n=t.editable();(n.isInline()?n:t.document.getWindow().getFrame()).equals(e)&&t.focusManager.focus(n)}function A(){CKEDITOR.env.gecko&&this.editor.unlockSelection(),CKEDITOR.env.webkit||(this.editor.forceNextSelectionCheck(),this.editor.selectionChange(1))}function L(e){var t=e.getSelectedHtml(!0);return e.widgets.focused?e.widgets.focused.getClipboardHtml():(e.once("toDataFormat",function(e){e.data.widgetsCopy=!0},null,null,-1),e.dataProcessor.toDataFormat(t))}function P(e,n){var i=e.editor.config.widget_keystrokeInsertLineBefore,r=e.editor.config.widget_keystrokeInsertLineAfter;F(e),j(e),B(e),$(e),q(e),V(e),z(e),CKEDITOR.env.ie&&9>CKEDITOR.env.version&&e.wrapper.on("dragstart",function(n){var i=n.data.getTarget();t.getNestedEditable(e,i)||e.inline&&t.isDomDragHandler(i)||n.data.preventDefault()}),e.wrapper.removeClass("cke_widget_new"),e.element.addClass("cke_widget_element"),e.on("key",function(t){if((t=t.data.keyCode)==i)w(e,"before"),e.editor.fire("saveSnapshot");else if(t==r)w(e,"after"),e.editor.fire("saveSnapshot");else if(13==t)e.edit();else{if(t==CKEDITOR.CTRL+67||t==CKEDITOR.CTRL+88)return void N(e.editor,t==CKEDITOR.CTRL+88);if(t in Y||CKEDITOR.CTRL&t||CKEDITOR.ALT&t)return}return!1},null,null,999),e.on("doubleclick",function(t){e.edit()&&t.cancel()}),n.data&&e.on("data",n.data),n.edit&&e.on("edit",n.edit)}function F(e){(e.wrapper=e.element.getParent()).setAttribute("data-cke-widget-id",e.id)}function j(e,t){if(e.partSelectors||(e.partSelectors=e.parts),e.parts){ -var n,i,r={};for(i in e.partSelectors)t||!e.parts[i]||"string"==typeof e.parts[i]?(n=e.wrapper.findOne(e.partSelectors[i]),r[i]=n):r[i]=e.parts[i];e.parts=r}}function B(e){var t,n,i=e.editables;if(e.editables={},e.editables)for(t in i)n=i[t],e.initEditable(t,"string"==typeof n?{selector:n}:n)}function $(e){if(!0===e.mask)M(e);else if(e.mask){var t,n,i=new CKEDITOR.tools.buffers.throttle(250,H,e),r=CKEDITOR.env.gecko?300:0;if(e.on("focus",function(){i.input(),t=e.editor.on("change",i.input),n=e.on("blur",function(){t.removeListener(),n.removeListener()})}),e.editor.on("instanceReady",function(){setTimeout(function(){i.input()},r)}),e.editor.on("mode",function(){setTimeout(function(){i.input()},r)}),CKEDITOR.env.gecko){var o=e.element.find("img");CKEDITOR.tools.array.forEach(o.toArray(),function(e){e.on("load",function(){i.input()})})}for(var a in e.editables)e.editables[a].on("focus",function(){e.editor.on("change",i.input),n&&n.removeListener()}),e.editables[a].on("blur",function(){e.editor.removeListener("change",i.input)});i.input()}}function M(e){var t=e.wrapper.findOne(".cke_widget_mask");t||(t=new CKEDITOR.dom.element("img",e.editor.document),t.setAttributes({src:CKEDITOR.tools.transparentImageData,class:"cke_reset cke_widget_mask"}),e.wrapper.append(t)),e.mask=t}function H(){if(this.wrapper){this.maskPart=this.maskPart||this.mask;var e,t=this.parts[this.maskPart];if(t&&"string"!=typeof t){e=this.wrapper.findOne(".cke_widget_partial_mask"),e||(e=new CKEDITOR.dom.element("img",this.editor.document),e.setAttributes({src:CKEDITOR.tools.transparentImageData,class:"cke_reset cke_widget_partial_mask"}),this.wrapper.append(e)),this.mask=e;var n=e.$,i=t.$,r=!(n.offsetTop==i.offsetTop&&n.offsetLeft==i.offsetLeft);(n.offsetWidth!=i.offsetWidth||n.offsetHeight!=i.offsetHeight||r)&&(n=t.getParent(),i=CKEDITOR.plugins.widget.isDomWidget(n),e.setStyles({top:t.$.offsetTop+(i?0:n.$.offsetTop)+"px",left:t.$.offsetLeft+(i?0:n.$.offsetLeft)+"px",width:t.$.offsetWidth+"px",height:t.$.offsetHeight+"px"}))}}}function q(e){if(e.draggable){var n,i=e.editor,r=e.wrapper.getLast(t.isDomDragHandlerContainer);r?n=r.findOne("img"):(r=new CKEDITOR.dom.element("span",i.document),r.setAttributes({class:"cke_reset cke_widget_drag_handler_container",style:"background:rgba(220,220,220,0.5);background-image:url("+i.plugins.widget.path+"images/handle.png);display:none;"}),n=new CKEDITOR.dom.element("img",i.document),n.setAttributes({class:"cke_reset cke_widget_drag_handler","data-cke-widget-drag-handler":"1",src:CKEDITOR.tools.transparentImageData,width:15,title:i.lang.widget.move,height:15,role:"presentation"}),e.inline&&n.setAttribute("draggable","true"),r.append(n),e.wrapper.append(r)),e.wrapper.on("dragover",function(e){e.data.preventDefault()}),e.wrapper.on("mouseenter",e.updateDragHandlerPosition,e),setTimeout(function(){e.on("data",e.updateDragHandlerPosition,e)},50),!e.inline&&(n.on("mousedown",U,e),CKEDITOR.env.ie&&9>CKEDITOR.env.version)&&n.on("dragstart",function(e){e.data.preventDefault(!0)}),e.dragHandlerContainer=r}}function U(e){function t(){var t;for(u.reset();t=d.pop();)t.removeListener();var n=c;t=e.sender;var i=this.repository.finder,r=this.repository.liner,o=this.editor,a=this.editor.editable();CKEDITOR.tools.isEmpty(r.visible)||(n=i.getRange(n[0]),this.focus(),o.fire("drop",{dropRange:n,target:n.startContainer})),a.removeClass("cke_widget_dragging"),r.hideVisible(),o.fire("dragend",{target:t})}if(CKEDITOR.tools.getMouseButton(e)===CKEDITOR.MOUSE_BUTTON_LEFT){var n,i,r=this.repository.finder,o=this.repository.locator,a=this.repository.liner,s=this.editor,l=s.editable(),d=[],c=[];this.repository._.draggedWidget=this;var h=r.greedySearch(),u=CKEDITOR.tools.eventsBuffer(50,function(){n=o.locate(h),c=o.sort(i,1),c.length&&(a.prepare(h,n),a.placeLine(c[0]),a.cleanup())});l.addClass("cke_widget_dragging"),d.push(l.on("mousemove",function(e){i=e.data.$.clientY,u.input()})),s.fire("dragstart",{target:e.sender}),d.push(s.document.once("mouseup",t,this)),l.isInline()||d.push(CKEDITOR.document.once("mouseup",t,this))}}function V(e){var t=null;e.on("data",function(){var e,n=this.data.classes;if(t!=n){for(e in t)n&&n[e]||this.removeClass(e);for(e in n)this.addClass(e);t=n}})}function z(e){e.on("data",function(){if(e.wrapper){var t=this.getLabel?this.getLabel():this.editor.lang.widget.label.replace(/%1/,this.pathName||this.element.getName());e.wrapper.setAttribute("role","region"),e.wrapper.setAttribute("aria-label",t)}},null,null,9999)}function W(e){e.element.data("cke-widget-data",encodeURIComponent(JSON.stringify(e.data)))}function G(){function e(){}function n(e,t,n){return!(!n||!this.checkElement(e))&&((e=n.widgets.getByElement(e,!0))&&e.checkStyleActive(this))}function i(e){var t,n=e.widget;r[n]||(r[n]={});for(var i=0,o=e.group.length;i.cke_widget_element{outline:2px solid #ffd25c;cursor:default}.cke_widget_wrapper:hover .cke_widget_editable{outline:2px solid #ffd25c}.cke_widget_wrapper.cke_widget_focused>.cke_widget_element,.cke_widget_wrapper .cke_widget_editable.cke_widget_editable_focused{outline:2px solid #47a4f5}.cke_widget_editable{cursor:text}.cke_widget_drag_handler_container{position:absolute;width:15px;height:0;display:block;opacity:0.75;transition:height 0s 0.2s;line-height:0}.cke_widget_wrapper:hover>.cke_widget_drag_handler_container{height:15px;transition:none}.cke_widget_drag_handler_container:hover{opacity:1}.cke_editable[contenteditable="false"] .cke_widget_drag_handler_container{display:none;}img.cke_widget_drag_handler{cursor:move;width:15px;height:15px;display:inline-block}.cke_widget_mask{position:absolute;top:0;left:0;width:100%;height:100%;display:block}.cke_widget_partial_mask{position:absolute;display:block}.cke_editable.cke_widget_dragging, .cke_editable.cke_widget_dragging *{cursor:move !important}'),G())},beforeInit:function(t){void 0!==CKEDITOR.document.$.querySelectorAll&&(t.widgets=new e(t))},afterInit:function(e){if(void 0!==CKEDITOR.document.$.querySelectorAll){var t,n,i,r=e.widgets.registered;for(n in r)t=r[n],(i=t.button)&&e.ui.addButton&&e.ui.addButton(CKEDITOR.tools.capitalize(t.name,!0),{label:i,command:t.name,toolbar:"insert,10"});E(e),y(e.undoManager)}}}),e.prototype={MIN_SELECTION_CHECK_INTERVAL:500,add:function(e,t){var n=this.editor;if(t=CKEDITOR.tools.prototypedCopy(t),t.name=e,t._=t._||{},n.fire("widgetDefinition",t),t.template&&(t.template=new CKEDITOR.template(t.template)),i(n,t),r(this,t),this.registered[e]=t,t.dialog&&n.plugins.dialog)var o=CKEDITOR.on("dialogDefinition",function(e){e=e.data.definition;var i=e.dialog;e.getMode||i.getName()!==t.dialog||(e.getMode=function(){var e=i.getModel(n);return e&&e instanceof CKEDITOR.plugins.widget&&e.ready?CKEDITOR.dialog.EDITING_MODE:CKEDITOR.dialog.CREATION_MODE}),o.removeListener()});return t},addUpcastCallback:function(e){this._.upcastCallbacks.push(e)},checkSelection:function(){if(this.editor.getSelection()){var e,n=this.editor.getSelection(),i=n.getSelectedElement(),r=b(this);if(i&&(e=this.getByElement(i,!0)))return r.focus(e).select(e).commit();if(!(n=n.getRanges()[0])||n.collapsed)return r.commit();for(n=new CKEDITOR.dom.walker(n),n.evaluator=t.isDomWidgetWrapper;i=n.next();)r.select(this.getByElement(i));r.commit()}},checkWidgets:function(e){this.fire("checkWidgets",CKEDITOR.tools.copy(e||{}))},del:function(e){if(this.focused===e){var t,n=e.editor,i=n.createRange();(t=i.moveToClosestEditablePosition(e.wrapper,!0))||(t=i.moveToClosestEditablePosition(e.wrapper,!1)),t&&n.getSelection().selectRanges([i])}e.wrapper.remove(),this.destroy(e,!0)},destroy:function(e,t){this.widgetHoldingFocusedEditable===e&&m(this,e,null,t),e.destroy(t),delete this.instances[e.id],this.fire("instanceDestroyed",e)},destroyAll:function(e,t){var n,i,r=this.instances;if(t&&!e){i=t.find(".cke_widget_wrapper");for(var r=i.count(),o=0;o)?(?:<(?:div|span)(?: style="[^"]+")?>)?]*data-cke-copybin-start="1"[^>]*>.?<\/span>([\s\S]+)]*data-cke-copybin-end="1"[^>]*>.?<\/span>(?:<\/(?:div|span)>)?(?:<\/(?:div|span)>)?$/i,Y={37:1,38:1,39:1,40:1,8:1,46:1};Y[CKEDITOR.SHIFT+121]=1;var J=CKEDITOR.tools.createClass({$:function(e,t){this._.createCopyBin(e,t),this._.createListeners(t)},_:{createCopyBin:function(e){var t=e.document,n=CKEDITOR.env.edge&&16<=CKEDITOR.env.version,i=!e.blockless&&!CKEDITOR.env.ie||n?"div":"span",n=t.createElement(i),t=t.createElement(i);t.setAttributes({id:"cke_copybin","data-cke-temp":"1"}),n.setStyles({position:"absolute",width:"1px",height:"1px",overflow:"hidden"}),n.setStyle("ltr"==e.config.contentsLangDirection?"left":"right","-5000px"),this.editor=e,this.copyBin=n,this.container=t},createListeners:function(e){e&&(e.beforeDestroy&&(this.beforeDestroy=e.beforeDestroy),e.afterDestroy&&(this.afterDestroy=e.afterDestroy))}},proto:{handle:function(e){var t,n,i,r=this.copyBin,o=this.editor,a=this.container,s=CKEDITOR.env.ie&&9>CKEDITOR.env.version,l=o.document.getDocumentElement().$,d=o.createRange(),c=this,h=CKEDITOR.env.mac&&CKEDITOR.env.webkit,u=h?100:0,f=window.requestAnimationFrame&&!h?requestAnimationFrame:setTimeout;return r.setHtml('\u200b'+e+'\u200b'),o.fire("lockSnapshot"),a.append(r),o.editable().append(a),t=o.on("selectionChange",k,null,null,0),n=o.widgets.on("checkSelection",k,null,null,0),s&&(i=l.scrollTop),d.selectNodeContents(r),d.select(),s&&(l.scrollTop=i),new CKEDITOR.tools.promise(function(e){f(function(){c.beforeDestroy&&c.beforeDestroy(),a.remove(),t.removeListener(),n.removeListener(),o.fire("unlockSnapshot"),c.afterDestroy&&c.afterDestroy(),e()},u)})}},statics:{hasCopyBin:function(e){return!!J.getCopyBin(e)},getCopyBin:function(e){return e.document.getById("cke_copybin")}}});CKEDITOR.plugins.widget=t,t.repository=e,t.nestedEditable=n}(),CKEDITOR.config.widget_keystrokeInsertLineBefore=CKEDITOR.SHIFT+CKEDITOR.ALT+13,CKEDITOR.config.widget_keystrokeInsertLineAfter=CKEDITOR.SHIFT+13,CKEDITOR.config.plugins="dialogui,dialog,notification,button,toolbar,clipboard,confighelper,entities,undo,lineutils,widgetselection,widget",CKEDITOR.config.skin="minimalist",function(){var e=function(e,t){var n=CKEDITOR.getUrl("plugins/"+t);e=e.split(",");for(var i=0;iCKEDITOR.env.version)&&n.on("dragstart",function(e){e.data.preventDefault(!0)}),e.dragHandlerContainer=r}}function U(e){function t(){var t;for(u.reset();t=d.pop();)t.removeListener();var n=c;t=e.sender;var i=this.repository.finder,r=this.repository.liner,o=this.editor,a=this.editor.editable();CKEDITOR.tools.isEmpty(r.visible)||(n=i.getRange(n[0]),this.focus(),o.fire("drop",{dropRange:n,target:n.startContainer})),a.removeClass("cke_widget_dragging"),r.hideVisible(),o.fire("dragend",{target:t})}if(CKEDITOR.tools.getMouseButton(e)===CKEDITOR.MOUSE_BUTTON_LEFT){var n,i,r=this.repository.finder,o=this.repository.locator,a=this.repository.liner,s=this.editor,l=s.editable(),d=[],c=[];this.repository._.draggedWidget=this;var h=r.greedySearch(),u=CKEDITOR.tools.eventsBuffer(50,function(){n=o.locate(h),c=o.sort(i,1),c.length&&(a.prepare(h,n),a.placeLine(c[0]),a.cleanup())});l.addClass("cke_widget_dragging"),d.push(l.on("mousemove",function(e){i=e.data.$.clientY,u.input()})),s.fire("dragstart",{target:e.sender}),d.push(s.document.once("mouseup",t,this)),l.isInline()||d.push(CKEDITOR.document.once("mouseup",t,this))}}function V(e){var t=null;e.on("data",function(){var e,n=this.data.classes;if(t!=n){for(e in t)n&&n[e]||this.removeClass(e);for(e in n)this.addClass(e);t=n}})}function z(e){e.on("data",function(){if(e.wrapper){var t=this.getLabel?this.getLabel():this.editor.lang.widget.label.replace(/%1/,this.pathName||this.element.getName());e.wrapper.setAttribute("role","region"),e.wrapper.setAttribute("aria-label",t)}},null,null,9999)}function W(e){e.element.data("cke-widget-data",encodeURIComponent(JSON.stringify(e.data)))}function G(){function e(){}function n(e,t,n){return!(!n||!this.checkElement(e))&&((e=n.widgets.getByElement(e,!0))&&e.checkStyleActive(this))}function i(e){var t,n=e.widget;r[n]||(r[n]={});for(var i=0,o=e.group.length;i.cke_widget_element{outline:2px solid #ffd25c;cursor:default}.cke_widget_wrapper:hover .cke_widget_editable{outline:2px solid #ffd25c}.cke_widget_wrapper.cke_widget_focused>.cke_widget_element,.cke_widget_wrapper .cke_widget_editable.cke_widget_editable_focused{outline:2px solid #47a4f5}.cke_widget_editable{cursor:text}.cke_widget_drag_handler_container{position:absolute;width:15px;height:0;display:block;opacity:0.75;transition:height 0s 0.2s;line-height:0}.cke_widget_wrapper:hover>.cke_widget_drag_handler_container{height:15px;transition:none}.cke_widget_drag_handler_container:hover{opacity:1}.cke_editable[contenteditable="false"] .cke_widget_drag_handler_container{display:none;}img.cke_widget_drag_handler{cursor:move;width:15px;height:15px;display:inline-block}.cke_widget_mask{position:absolute;top:0;left:0;width:100%;height:100%;display:block}.cke_widget_partial_mask{position:absolute;display:block}.cke_editable.cke_widget_dragging, .cke_editable.cke_widget_dragging *{cursor:move !important}'),G())},beforeInit:function(t){void 0!==CKEDITOR.document.$.querySelectorAll&&(t.widgets=new e(t))},afterInit:function(e){if(void 0!==CKEDITOR.document.$.querySelectorAll){var t,n,i,r=e.widgets.registered;for(n in r)t=r[n],(i=t.button)&&e.ui.addButton&&e.ui.addButton(CKEDITOR.tools.capitalize(t.name,!0),{label:i,command:t.name,toolbar:"insert,10"});E(e),y(e.undoManager)}}}),e.prototype={MIN_SELECTION_CHECK_INTERVAL:500,add:function(e,t){var n=this.editor;if(t=CKEDITOR.tools.prototypedCopy(t),t.name=e,t._=t._||{},n.fire("widgetDefinition",t),t.template&&(t.template=new CKEDITOR.template(t.template)),i(n,t),r(this,t),this.registered[e]=t,t.dialog&&n.plugins.dialog)var o=CKEDITOR.on("dialogDefinition",function(e){e=e.data.definition;var i=e.dialog;e.getMode||i.getName()!==t.dialog||(e.getMode=function(){var e=i.getModel(n);return e&&e instanceof CKEDITOR.plugins.widget&&e.ready?CKEDITOR.dialog.EDITING_MODE:CKEDITOR.dialog.CREATION_MODE}),o.removeListener()});return t},addUpcastCallback:function(e){this._.upcastCallbacks.push(e)},checkSelection:function(){if(this.editor.getSelection()){var e,n=this.editor.getSelection(),i=n.getSelectedElement(),r=b(this);if(i&&(e=this.getByElement(i,!0)))return r.focus(e).select(e).commit();if(!(n=n.getRanges()[0])||n.collapsed)return r.commit();for(n=new CKEDITOR.dom.walker(n),n.evaluator=t.isDomWidgetWrapper;i=n.next();)r.select(this.getByElement(i));r.commit()}},checkWidgets:function(e){this.fire("checkWidgets",CKEDITOR.tools.copy(e||{}))},del:function(e){if(this.focused===e){var t,n=e.editor,i=n.createRange();(t=i.moveToClosestEditablePosition(e.wrapper,!0))||(t=i.moveToClosestEditablePosition(e.wrapper,!1)),t&&n.getSelection().selectRanges([i])}e.wrapper.remove(),this.destroy(e,!0)},destroy:function(e,t){this.widgetHoldingFocusedEditable===e&&m(this,e,null,t),e.destroy(t),delete this.instances[e.id],this.fire("instanceDestroyed",e)},destroyAll:function(e,t){var n,i,r=this.instances;if(t&&!e){i=t.find(".cke_widget_wrapper");for(var r=i.count(),o=0;o)?(?:<(?:div|span)(?: style="[^"]+")?>)?]*data-cke-copybin-start="1"[^>]*>.?<\/span>([\s\S]+)]*data-cke-copybin-end="1"[^>]*>.?<\/span>(?:<\/(?:div|span)>)?(?:<\/(?:div|span)>)?$/i,Y={37:1,38:1,39:1,40:1,8:1,46:1};Y[CKEDITOR.SHIFT+121]=1;var J=CKEDITOR.tools.createClass({$:function(e,t){this._.createCopyBin(e,t),this._.createListeners(t)},_:{createCopyBin:function(e){var t=e.document,n=CKEDITOR.env.edge&&16<=CKEDITOR.env.version,i=!e.blockless&&!CKEDITOR.env.ie||n?"div":"span",n=t.createElement(i),t=t.createElement(i);t.setAttributes({id:"cke_copybin","data-cke-temp":"1"}),n.setStyles({position:"absolute",width:"1px",height:"1px",overflow:"hidden"}),n.setStyle("ltr"==e.config.contentsLangDirection?"left":"right","-5000px"),this.editor=e,this.copyBin=n,this.container=t},createListeners:function(e){e&&(e.beforeDestroy&&(this.beforeDestroy=e.beforeDestroy),e.afterDestroy&&(this.afterDestroy=e.afterDestroy))}},proto:{handle:function(e){var t,n,i,r=this.copyBin,o=this.editor,a=this.container,s=CKEDITOR.env.ie&&9>CKEDITOR.env.version,l=o.document.getDocumentElement().$,d=o.createRange(),c=this,h=CKEDITOR.env.mac&&CKEDITOR.env.webkit,u=h?100:0,f=window.requestAnimationFrame&&!h?requestAnimationFrame:setTimeout;return r.setHtml('\u200b'+e+'\u200b'),o.fire("lockSnapshot"),a.append(r),o.editable().append(a),t=o.on("selectionChange",k,null,null,0),n=o.widgets.on("checkSelection",k,null,null,0),s&&(i=l.scrollTop),d.selectNodeContents(r),d.select(),s&&(l.scrollTop=i),new CKEDITOR.tools.promise(function(e){f(function(){c.beforeDestroy&&c.beforeDestroy(),a.remove(),t.removeListener(),n.removeListener(),o.fire("unlockSnapshot"),c.afterDestroy&&c.afterDestroy(),e()},u)})}},statics:{hasCopyBin:function(e){return!!J.getCopyBin(e)},getCopyBin:function(e){return e.document.getById("cke_copybin")}}});CKEDITOR.plugins.widget=t,t.repository=e,t.nestedEditable=n}(),CKEDITOR.config.widget_keystrokeInsertLineBefore=CKEDITOR.SHIFT+CKEDITOR.ALT+13,CKEDITOR.config.widget_keystrokeInsertLineAfter=CKEDITOR.SHIFT+13,CKEDITOR.config.plugins="dialogui,dialog,notification,button,toolbar,clipboard,confighelper,entities,undo,lineutils,widgetselection,widget",CKEDITOR.config.skin="minimalist",function(){var e=function(e,t){var n=CKEDITOR.getUrl("plugins/"+t);e=e.split(",");for(var i=0;i 2 && arguments[2] !== undefined ? arguments[2] : {}; + Diff.prototype = { /*istanbul ignore start*/ + /*istanbul ignore end*/diff: function diff(oldString, newString) { + /*istanbul ignore start*/var /*istanbul ignore end*/options = arguments.length <= 2 || arguments[2] === undefined ? {} : arguments[2]; var callback = options.callback; if (typeof options === 'function') { @@ -3674,11 +3673,7 @@ return /******/ (function(modules) { // webpackBootstrap return oldPos; }, /*istanbul ignore start*/ /*istanbul ignore end*/equals: function equals(left, right) { - if (this.options.comparator) { - return this.options.comparator(left, right); - } else { - return left === right || this.options.ignoreCase && left.toLowerCase() === right.toLowerCase(); - } + return left === right; }, /*istanbul ignore start*/ /*istanbul ignore end*/removeEmpty: function removeEmpty(array) { var ret = []; @@ -3741,11 +3736,10 @@ return /******/ (function(modules) { // webpackBootstrap } } - // Special case handle for when one terminal is ignored (i.e. whitespace). - // For this case we merge the terminal into the prior string and drop the change. - // This is only available for string mode. + // Special case handle for when one terminal is ignored. For this case we merge the + // terminal into the prior string and drop the change. var lastComponent = components[componentLen - 1]; - if (componentLen > 1 && typeof lastComponent.value === 'string' && (lastComponent.added || lastComponent.removed) && diff.equals('', lastComponent.value)) { + if (componentLen > 1 && (lastComponent.added || lastComponent.removed) && diff.equals('', lastComponent.value)) { components[componentLen - 2].value += lastComponent.value; components.pop(); } @@ -3756,12 +3750,12 @@ return /******/ (function(modules) { // webpackBootstrap function clonePath(path) { return { newPos: path.newPos, components: path.components.slice(0) }; } - //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9kaWZmL2Jhc2UuanMiXSwibmFtZXMiOlsiRGlmZiIsInByb3RvdHlwZSIsImRpZmYiLCJvbGRTdHJpbmciLCJuZXdTdHJpbmciLCJvcHRpb25zIiwiY2FsbGJhY2siLCJzZWxmIiwiZG9uZSIsInZhbHVlIiwic2V0VGltZW91dCIsInVuZGVmaW5lZCIsImNhc3RJbnB1dCIsInJlbW92ZUVtcHR5IiwidG9rZW5pemUiLCJuZXdMZW4iLCJsZW5ndGgiLCJvbGRMZW4iLCJlZGl0TGVuZ3RoIiwibWF4RWRpdExlbmd0aCIsImJlc3RQYXRoIiwibmV3UG9zIiwiY29tcG9uZW50cyIsIm9sZFBvcyIsImV4dHJhY3RDb21tb24iLCJqb2luIiwiY291bnQiLCJleGVjRWRpdExlbmd0aCIsImRpYWdvbmFsUGF0aCIsImJhc2VQYXRoIiwiYWRkUGF0aCIsInJlbW92ZVBhdGgiLCJjYW5BZGQiLCJjYW5SZW1vdmUiLCJjbG9uZVBhdGgiLCJwdXNoQ29tcG9uZW50IiwiYnVpbGRWYWx1ZXMiLCJ1c2VMb25nZXN0VG9rZW4iLCJleGVjIiwicmV0IiwiYWRkZWQiLCJyZW1vdmVkIiwibGFzdCIsInB1c2giLCJjb21tb25Db3VudCIsImVxdWFscyIsImxlZnQiLCJyaWdodCIsImNvbXBhcmF0b3IiLCJpZ25vcmVDYXNlIiwidG9Mb3dlckNhc2UiLCJhcnJheSIsImkiLCJzcGxpdCIsImNoYXJzIiwiY29tcG9uZW50UG9zIiwiY29tcG9uZW50TGVuIiwiY29tcG9uZW50Iiwic2xpY2UiLCJtYXAiLCJvbGRWYWx1ZSIsInRtcCIsImxhc3RDb21wb25lbnQiLCJwb3AiLCJwYXRoIl0sIm1hcHBpbmdzIjoiOzs7NENBQXdCQSxJO0FBQVQsU0FBU0EsSUFBVCxHQUFnQixDQUFFOztBQUVqQ0EsS0FBS0MsU0FBTCxHQUFpQjtBQUFBLG1EQUNmQyxJQURlLGdCQUNWQyxTQURVLEVBQ0NDLFNBREQsRUFDMEI7QUFBQSx3REFBZEMsT0FBYyx1RUFBSixFQUFJOztBQUN2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RUFBd0JBLFNBQVNrQyxVQUFVL0IsS0FBM0MsQ0FBVixDQUFsQjtBQUNBSCxnQkFBVWtDLFVBQVUvQixLQUFwQjs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxVQUFJNkIsZ0JBQWdCakMsV0FBV2lDLGVBQWUsQ0FBMUIsRUFBNkJmLEtBQWpELEVBQXdEO0FBQ3RELFlBQUlxQixNQUFNdkMsV0FBV2lDLGVBQWUsQ0FBMUIsQ0FBVjtBQUNBakMsbUJBQVdpQyxlQUFlLENBQTFCLElBQStCakMsV0FBV2lDLFlBQVgsQ0FBL0I7QUFDQWpDLG1CQUFXaUMsWUFBWCxJQUEyQk0sR0FBM0I7QUFDRDtBQUNGO0FBQ0Y7O0FBRUQ7QUFDQTtBQUNBO0FBQ0EsTUFBSUMsZ0JBQWdCeEMsV0FBV2tDLGVBQWUsQ0FBMUIsQ0FBcEI7QUFDQSxNQUFJQSxlQUFlLENBQWYsSUFDRyxPQUFPTSxjQUFjckQsS0FBckIsS0FBK0IsUUFEbEMsS0FFSXFELGNBQWN0QixLQUFkLElBQXVCc0IsY0FBY3JCLE9BRnpDLEtBR0d2QyxLQUFLMkMsTUFBTCxDQUFZLEVBQVosRUFBZ0JpQixjQUFjckQsS0FBOUIsQ0FIUCxFQUc2QztBQUMzQ2EsZUFBV2tDLGVBQWUsQ0FBMUIsRUFBNkIvQyxLQUE3QixJQUFzQ3FELGNBQWNyRCxLQUFwRDtBQUNBYSxlQUFXeUMsR0FBWDtBQUNEOztBQUVELFNBQU96QyxVQUFQO0FBQ0Q7O0FBRUQsU0FBU1ksU0FBVCxDQUFtQjhCLElBQW5CLEVBQXlCO0FBQ3ZCLFNBQU8sRUFBRTNDLFFBQVEyQyxLQUFLM0MsTUFBZixFQUF1QkMsWUFBWTBDLEtBQUsxQyxVQUFMLENBQWdCb0MsS0FBaEIsQ0FBc0IsQ0FBdEIsQ0FBbkMsRUFBUDtBQUNEIiwiZmlsZSI6ImJhc2UuanMiLCJzb3VyY2VzQ29udGVudCI6WyJleHBvcnQgZGVmYXVsdCBmdW5jdGlvbiBEaWZmKCkge31cblxuRGlmZi5wcm90b3R5cGUgPSB7XG4gIGRpZmYob2xkU3RyaW5nLCBuZXdTdHJpbmcsIG9wdGlvbnMgPSB7fSkge1xuICAgIGxldCBjYWxsYmFjayA9IG9wdGlvbnMuY2FsbGJhY2s7XG4gICAgaWYgKHR5cGVvZiBvcHRpb25zID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICBjYWxsYmFjayA9IG9wdGlvbnM7XG4gICAgICBvcHRpb25zID0ge307XG4gICAgfVxuICAgIHRoaXMub3B0aW9ucyA9IG9wdGlvbnM7XG5cbiAgICBsZXQgc2VsZiA9IHRoaXM7XG5cbiAgICBmdW5jdGlvbiBkb25lKHZhbHVlKSB7XG4gICAgICBpZiAoY2FsbGJhY2spIHtcbiAgICAgICAgc2V0VGltZW91dChmdW5jdGlvbigpIHsgY2FsbGJhY2sodW5kZWZpbmVkLCB2YWx1ZSk7IH0sIDApO1xuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJldHVybiB2YWx1ZTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBBbGxvdyBzdWJjbGFzc2VzIHRvIG1hc3NhZ2UgdGhlIGlucHV0IHByaW9yIHRvIHJ1bm5pbmdcbiAgICBvbGRTdHJpbmcgPSB0aGlzLmNhc3RJbnB1dChvbGRTdHJpbmcpO1xuICAgIG5ld1N0cmluZyA9IHRoaXMuY2FzdElucHV0KG5ld1N0cmluZyk7XG5cbiAgICBvbGRTdHJpbmcgPSB0aGlzLnJlbW92ZUVtcHR5KHRoaXMudG9rZW5pemUob2xkU3RyaW5nKSk7XG4gICAgbmV3U3RyaW5nID0gdGhpcy5yZW1vdmVFbXB0eSh0aGlzLnRva2VuaXplKG5ld1N0cmluZykpO1xuXG4gICAgbGV0IG5ld0xlbiA9IG5ld1N0cmluZy5sZW5ndGgsIG9sZExlbiA9IG9sZFN0cmluZy5sZW5ndGg7XG4gICAgbGV0IGVkaXRMZW5ndGggPSAxO1xuICAgIGxldCBtYXhFZGl0TGVuZ3RoID0gbmV3TGVuICsgb2xkTGVuO1xuICAgIGxldCBiZXN0UGF0aCA9IFt7IG5ld1BvczogLTEsIGNvbXBvbmVudHM6IFtdIH1dO1xuXG4gICAgLy8gU2VlZCBlZGl0TGVuZ3RoID0gMCwgaS5lLiB0aGUgY29udGVudCBzdGFydHMgd2l0aCB0aGUgc2FtZSB2YWx1ZXNcbiAgICBsZXQgb2xkUG9zID0gdGhpcy5leHRyYWN0Q29tbW9uKGJlc3RQYXRoWzBdLCBuZXdTdHJpbmcsIG9sZFN0cmluZywgMCk7XG4gICAgaWYgKGJlc3RQYXRoWzBdLm5ld1BvcyArIDEgPj0gbmV3TGVuICYmIG9sZFBvcyArIDEgPj0gb2xkTGVuKSB7XG4gICAgICAvLyBJZGVudGl0eSBwZXIgdGhlIGVxdWFsaXR5IGFuZCB0b2tlbml6ZXJcbiAgICAgIHJldHVybiBkb25lKFt7dmFsdWU6IHRoaXMuam9pbihuZXdTdHJpbmcpLCBjb3VudDogbmV3U3RyaW5nLmxlbmd0aH1dKTtcbiAgICB9XG5cbiAgICAvLyBNYWluIHdvcmtlciBtZXRob2QuIGNoZWNrcyBhbGwgcGVybXV0YXRpb25zIG9mIGEgZ2l2ZW4gZWRpdCBsZW5ndGggZm9yIGFjY2VwdGFuY2UuXG4gICAgZnVuY3Rpb24gZXhlY0VkaXRMZW5ndGgoKSB7XG4gICAgICBmb3IgKGxldCBkaWFnb25hbFBhdGggPSAtMSAqIGVkaXRMZW5ndGg7IGRpYWdvbmFsUGF0aCA8PSBlZGl0TGVuZ3RoOyBkaWFnb25hbFBhdGggKz0gMikge1xuICAgICAgICBsZXQgYmFzZVBhdGg7XG4gICAgICAgIGxldCBhZGRQYXRoID0gYmVzdFBhdGhbZGlhZ29uYWxQYXRoIC0gMV0sXG4gICAgICAgICAgICByZW1vdmVQYXRoID0gYmVzdFBhdGhbZGlhZ29uYWxQYXRoICsgMV0sXG4gICAgICAgICAgICBvbGRQb3MgPSAocmVtb3ZlUGF0aCA/IHJlbW92ZVBhdGgubmV3UG9zIDogMCkgLSBkaWFnb25hbFBhdGg7XG4gICAgICAgIGlmIChhZGRQYXRoKSB7XG4gICAgICAgICAgLy8gTm8gb25lIGVsc2UgaXMgZ29pbmcgdG8gYXR0ZW1wdCB0byB1c2UgdGhpcyB2YWx1ZSwgY2xlYXIgaXRcbiAgICAgICAgICBiZXN0UGF0aFtkaWFnb25hbFBhdGggLSAxXSA9IHVuZGVmaW5lZDtcbiAgICAgICAgfVxuXG4gICAgICAgIGxldCBjYW5BZGQgPSBhZGRQYXRoICYmIGFkZFBhdGgubmV3UG9zICsgMSA8IG5ld0xlbixcbiAgICAgICAgICAgIGNhblJlbW92ZSA9IHJlbW92ZVBhdGggJiYgMCA8PSBvbGRQb3MgJiYgb2xkUG9zIDwgb2xkTGVuO1xuICAgICAgICBpZiAoIWNhbkFkZCAmJiAhY2FuUmVtb3ZlKSB7XG4gICAgICAgICAgLy8gSWYgdGhpcyBwYXRoIGlzIGEgdGVybWluYWwgdGhlbiBwcnVuZVxuICAgICAgICAgIGJlc3RQYXRoW2RpYWdvbmFsUGF0aF0gPSB1bmRlZmluZWQ7XG4gICAgICAgICAgY29udGludWU7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBTZWxlY3QgdGhlIGRpYWdvbmFsIHRoYXQgd2Ugd2FudCB0byBicmFuY2ggZnJvbS4gV2Ugc2VsZWN0IHRoZSBwcmlvclxuICAgICAgICAvLyBwYXRoIHdob3NlIHBvc2l0aW9uIGluIHRoZSBuZXcgc3RyaW5nIGlzIHRoZSBmYXJ0aGVzdCBmcm9tIHRoZSBvcmlnaW5cbiAgICAgICAgLy8gYW5kIGRvZXMgbm90IHBhc3MgdGhlIGJvdW5kcyBvZiB0aGUgZGlmZiBncmFwaFxuICAgICAgICBpZiAoIWNhbkFkZCB8fCAoY2FuUmVtb3ZlICYmIGFkZFBhdGgubmV3UG9zIDwgcmVtb3ZlUGF0aC5uZXdQb3MpKSB7XG4gICAgICAgICAgYmFzZVBhdGggPSBjbG9uZVBhdGgocmVtb3ZlUGF0aCk7XG4gICAgICAgICAgc2VsZi5wdXNoQ29tcG9uZW50KGJhc2VQYXRoLmNvbXBvbmVudHMsIHVuZGVmaW5lZCwgdHJ1ZSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgYmFzZVBhdGggPSBhZGRQYXRoOyAgIC8vIE5vIG5lZWQgdG8gY2xvbmUsIHdlJ3ZlIHB1bGxlZCBpdCBmcm9tIHRoZSBsaXN0XG4gICAgICAgICAgYmFzZVBhdGgubmV3UG9zKys7XG4gICAgICAgICAgc2VsZi5wdXNoQ29tcG9uZW50KGJhc2VQYXRoLmNvbXBvbmVudHMsIHRydWUsIHVuZGVmaW5lZCk7XG4gICAgICAgIH1cblxuICAgICAgICBvbGRQb3MgPSBzZWxmLmV4dHJhY3RDb21tb24oYmFzZVBhdGgsIG5ld1N0cmluZywgb2xkU3RyaW5nLCBkaWFnb25hbFBhdGgpO1xuXG4gICAgICAgIC8vIElmIHdlIGhhdmUgaGl0IHRoZSBlbmQgb2YgYm90aCBzdHJpbmdzLCB0aGVuIHdlIGFyZSBkb25lXG4gICAgICAgIGlmIChiYXNlUGF0aC5uZXdQb3MgKyAxID49IG5ld0xlbiAmJiBvbGRQb3MgKyAxID49IG9sZExlbikge1xuICAgICAgICAgIHJldHVybiBkb25lKGJ1aWxkVmFsdWVzKHNlbGYsIGJhc2VQYXRoLmNvbXBvbmVudHMsIG5ld1N0cmluZywgb2xkU3RyaW5nLCBzZWxmLnVzZUxvbmdlc3RUb2tlbikpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIC8vIE90aGVyd2lzZSB0cmFjayB0aGlzIHBhdGggYXMgYSBwb3RlbnRpYWwgY2FuZGlkYXRlIGFuZCBjb250aW51ZS5cbiAgICAgICAgICBiZXN0UGF0aFtkaWFnb25hbFBhdGhdID0gYmFzZVBhdGg7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgZWRpdExlbmd0aCsrO1xuICAgIH1cblxuICAgIC8vIFBlcmZvcm1zIHRoZSBsZW5ndGggb2YgZWRpdCBpdGVyYXRpb24uIElzIGEgYml0IGZ1Z2x5IGFzIHRoaXMgaGFzIHRvIHN1cHBvcnQgdGhlXG4gICAgLy8gc3luYyBhbmQgYXN5bmMgbW9kZSB3aGljaCBpcyBuZXZlciBmdW4uIExvb3BzIG92ZXIgZXhlY0VkaXRMZW5ndGggdW50aWwgYSB2YWx1ZVxuICAgIC8vIGlzIHByb2R1Y2VkLlxuICAgIGlmIChjYWxsYmFjaykge1xuICAgICAgKGZ1bmN0aW9uIGV4ZWMoKSB7XG4gICAgICAgIHNldFRpbWVvdXQoZnVuY3Rpb24oKSB7XG4gICAgICAgICAgLy8gVGhpcyBzaG91bGQgbm90IGhhcHBlbiwgYnV0IHdlIHdhbnQgdG8gYmUgc2FmZS5cbiAgICAgICAgICAvKiBpc3RhbmJ1bCBpZ25vcmUgbmV4dCAqL1xuICAgICAgICAgIGlmIChlZGl0TGVuZ3RoID4gbWF4RWRpdExlbmd0aCkge1xuICAgICAgICAgICAgcmV0dXJuIGNhbGxiYWNrKCk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgaWYgKCFleGVjRWRpdExlbmd0aCgpKSB7XG4gICAgICAgICAgICBleGVjKCk7XG4gICAgICAgICAgfVxuICAgICAgICB9LCAwKTtcbiAgICAgIH0oKSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHdoaWxlIChlZGl0TGVuZ3RoIDw9IG1heEVkaXRMZW5ndGgpIHtcbiAgICAgICAgbGV0IHJldCA9IGV4ZWNFZGl0TGVuZ3RoKCk7XG4gICAgICAgIGlmIChyZXQpIHtcbiAgICAgICAgICByZXR1cm4gcmV0O1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICB9LFxuXG4gIHB1c2hDb21wb25lbnQoY29tcG9uZW50cywgYWRkZWQsIHJlbW92ZWQpIHtcbiAgICBsZXQgbGFzdCA9IGNvbXBvbmVudHNbY29tcG9uZW50cy5sZW5ndGggLSAxXTtcbiAgICBpZiAobGFzdCAmJiBsYXN0LmFkZGVkID09PSBhZGRlZCAmJiBsYXN0LnJlbW92ZWQgPT09IHJlbW92ZWQpIHtcbiAgICAgIC8vIFdlIG5lZWQgdG8gY2xvbmUgaGVyZSBhcyB0aGUgY29tcG9uZW50IGNsb25lIG9wZXJhdGlvbiBpcyBqdXN0XG4gICAgICAvLyBhcyBzaGFsbG93IGFycmF5IGNsb25lXG4gICAgICBjb21wb25lbnRzW2NvbXBvbmVudHMubGVuZ3RoIC0gMV0gPSB7Y291bnQ6IGxhc3QuY291bnQgKyAxLCBhZGRlZDogYWRkZWQsIHJlbW92ZWQ6IHJlbW92ZWQgfTtcbiAgICB9IGVsc2Uge1xuICAgICAgY29tcG9uZW50cy5wdXNoKHtjb3VudDogMSwgYWRkZWQ6IGFkZGVkLCByZW1vdmVkOiByZW1vdmVkIH0pO1xuICAgIH1cbiAgfSxcbiAgZXh0cmFjdENvbW1vbihiYXNlUGF0aCwgbmV3U3RyaW5nLCBvbGRTdHJpbmcsIGRpYWdvbmFsUGF0aCkge1xuICAgIGxldCBuZXdMZW4gPSBuZXdTdHJpbmcubGVuZ3RoLFxuICAgICAgICBvbGRMZW4gPSBvbGRTdHJpbmcubGVuZ3RoLFxuICAgICAgICBuZXdQb3MgPSBiYXNlUGF0aC5uZXdQb3MsXG4gICAgICAgIG9sZFBvcyA9IG5ld1BvcyAtIGRpYWdvbmFsUGF0aCxcblxuICAgICAgICBjb21tb25Db3VudCA9IDA7XG4gICAgd2hpbGUgKG5ld1BvcyArIDEgPCBuZXdMZW4gJiYgb2xkUG9zICsgMSA8IG9sZExlbiAmJiB0aGlzLmVxdWFscyhuZXdTdHJpbmdbbmV3UG9zICsgMV0sIG9sZFN0cmluZ1tvbGRQb3MgKyAxXSkpIHtcbiAgICAgIG5ld1BvcysrO1xuICAgICAgb2xkUG9zKys7XG4gICAgICBjb21tb25Db3VudCsrO1xuICAgIH1cblxuICAgIGlmIChjb21tb25Db3VudCkge1xuICAgICAgYmFzZVBhdGguY29tcG9uZW50cy5wdXNoKHtjb3VudDogY29tbW9uQ291bnR9KTtcbiAgICB9XG5cbiAgICBiYXNlUGF0aC5uZXdQb3MgPSBuZXdQb3M7XG4gICAgcmV0dXJuIG9sZFBvcztcbiAgfSxcblxuICBlcXVhbHMobGVmdCwgcmlnaHQpIHtcbiAgICBpZiAodGhpcy5vcHRpb25zLmNvbXBhcmF0b3IpIHtcbiAgICAgIHJldHVybiB0aGlzLm9wdGlvbnMuY29tcGFyYXRvcihsZWZ0LCByaWdodCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiBsZWZ0ID09PSByaWdodFxuICAgICAgICB8fCAodGhpcy5vcHRpb25zLmlnbm9yZUNhc2UgJiYgbGVmdC50b0xvd2VyQ2FzZSgpID09PSByaWdodC50b0xvd2VyQ2FzZSgpKTtcbiAgICB9XG4gIH0sXG4gIHJlbW92ZUVtcHR5KGFycmF5KSB7XG4gICAgbGV0IHJldCA9IFtdO1xuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgYXJyYXkubGVuZ3RoOyBpKyspIHtcbiAgICAgIGlmIChhcnJheVtpXSkge1xuICAgICAgICByZXQucHVzaChhcnJheVtpXSk7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiByZXQ7XG4gIH0sXG4gIGNhc3RJbnB1dCh2YWx1ZSkge1xuICAgIHJldHVybiB2YWx1ZTtcbiAgfSxcbiAgdG9rZW5pemUodmFsdWUpIHtcbiAgICByZXR1cm4gdmFsdWUuc3BsaXQoJycpO1xuICB9LFxuICBqb2luKGNoYXJzKSB7XG4gICAgcmV0dXJuIGNoYXJzLmpvaW4oJycpO1xuICB9XG59O1xuXG5mdW5jdGlvbiBidWlsZFZhbHVlcyhkaWZmLCBjb21wb25lbnRzLCBuZXdTdHJpbmcsIG9sZFN0cmluZywgdXNlTG9uZ2VzdFRva2VuKSB7XG4gIGxldCBjb21wb25lbnRQb3MgPSAwLFxuICAgICAgY29tcG9uZW50TGVuID0gY29tcG9uZW50cy5sZW5ndGgsXG4gICAgICBuZXdQb3MgPSAwLFxuICAgICAgb2xkUG9zID0gMDtcblxuICBmb3IgKDsgY29tcG9uZW50UG9zIDwgY29tcG9uZW50TGVuOyBjb21wb25lbnRQb3MrKykge1xuICAgIGxldCBjb21wb25lbnQgPSBjb21wb25lbnRzW2NvbXBvbmVudFBvc107XG4gICAgaWYgKCFjb21wb25lbnQucmVtb3ZlZCkge1xuICAgICAgaWYgKCFjb21wb25lbnQuYWRkZWQgJiYgdXNlTG9uZ2VzdFRva2VuKSB7XG4gICAgICAgIGxldCB2YWx1ZSA9IG5ld1N0cmluZy5zbGljZShuZXdQb3MsIG5ld1BvcyArIGNvbXBvbmVudC5jb3VudCk7XG4gICAgICAgIHZhbHVlID0gdmFsdWUubWFwKGZ1bmN0aW9uKHZhbHVlLCBpKSB7XG4gICAgICAgICAgbGV0IG9sZFZhbHVlID0gb2xkU3RyaW5nW29sZFBvcyArIGldO1xuICAgICAgICAgIHJldHVybiBvbGRWYWx1ZS5sZW5ndGggPiB2YWx1ZS5sZW5ndGggPyBvbGRWYWx1ZSA6IHZhbHVlO1xuICAgICAgICB9KTtcblxuICAgICAgICBjb21wb25lbnQudmFsdWUgPSBkaWZmLmpvaW4odmFsdWUpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgY29tcG9uZW50LnZhbHVlID0gZGlmZi5qb2luKG5ld1N0cmluZy5zbGljZShuZXdQb3MsIG5ld1BvcyArIGNvbXBvbmVudC5jb3VudCkpO1xuICAgICAgfVxuICAgICAgbmV3UG9zICs9IGNvbXBvbmVudC5jb3VudDtcblxuICAgICAgLy8gQ29tbW9uIGNhc2VcbiAgICAgIGlmICghY29tcG9uZW50LmFkZGVkKSB7XG4gICAgICAgIG9sZFBvcyArPSBjb21wb25lbnQuY291bnQ7XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIGNvbXBvbmVudC52YWx1ZSA9IGRpZmYuam9pbihvbGRTdHJpbmcuc2xpY2Uob2xkUG9zLCBvbGRQb3MgKyBjb21wb25lbnQuY291bnQpKTtcbiAgICAgIG9sZFBvcyArPSBjb21wb25lbnQuY291bnQ7XG5cbiAgICAgIC8vIFJldmVyc2UgYWRkIGFuZCByZW1vdmUgc28gcmVtb3ZlcyBhcmUgb3V0cHV0IGZpcnN0IHRvIG1hdGNoIGNvbW1vbiBjb252ZW50aW9uXG4gICAgICAvLyBUaGUgZGlmZmluZyBhbGdvcml0aG0gaXMgdGllZCB0byBhZGQgdGhlbiByZW1vdmUgb3V0cHV0IGFuZCB0aGlzIGlzIHRoZSBzaW1wbGVzdFxuICAgICAgLy8gcm91dGUgdG8gZ2V0IHRoZSBkZXNpcmVkIG91dHB1dCB3aXRoIG1pbmltYWwgb3ZlcmhlYWQuXG4gICAgICBpZiAoY29tcG9uZW50UG9zICYmIGNvbXBvbmVudHNbY29tcG9uZW50UG9zIC0gMV0uYWRkZWQpIHtcbiAgICAgICAgbGV0IHRtcCA9IGNvbXBvbmVudHNbY29tcG9uZW50UG9zIC0gMV07XG4gICAgICAgIGNvbXBvbmVudHNbY29tcG9uZW50UG9zIC0gMV0gPSBjb21wb25lbnRzW2NvbXBvbmVudFBvc107XG4gICAgICAgIGNvbXBvbmVudHNbY29tcG9uZW50UG9zXSA9IHRtcDtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICAvLyBTcGVjaWFsIGNhc2UgaGFuZGxlIGZvciB3aGVuIG9uZSB0ZXJtaW5hbCBpcyBpZ25vcmVkIChpLmUuIHdoaXRlc3BhY2UpLlxuICAvLyBGb3IgdGhpcyBjYXNlIHdlIG1lcmdlIHRoZSB0ZXJtaW5hbCBpbnRvIHRoZSBwcmlvciBzdHJpbmcgYW5kIGRyb3AgdGhlIGNoYW5nZS5cbiAgLy8gVGhpcyBpcyBvbmx5IGF2YWlsYWJsZSBmb3Igc3RyaW5nIG1vZGUuXG4gIGxldCBsYXN0Q29tcG9uZW50ID0gY29tcG9uZW50c1tjb21wb25lbnRMZW4gLSAxXTtcbiAgaWYgKGNvbXBvbmVudExlbiA+IDFcbiAgICAgICYmIHR5cGVvZiBsYXN0Q29tcG9uZW50LnZhbHVlID09PSAnc3RyaW5nJ1xuICAgICAgJiYgKGxhc3RDb21wb25lbnQuYWRkZWQgfHwgbGFzdENvbXBvbmVudC5yZW1vdmVkKVxuICAgICAgJiYgZGlmZi5lcXVhbHMoJycsIGxhc3RDb21wb25lbnQudmFsdWUpKSB7XG4gICAgY29tcG9uZW50c1tjb21wb25lbnRMZW4gLSAyXS52YWx1ZSArPSBsYXN0Q29tcG9uZW50LnZhbHVlO1xuICAgIGNvbXBvbmVudHMucG9wKCk7XG4gIH1cblxuICByZXR1cm4gY29tcG9uZW50cztcbn1cblxuZnVuY3Rpb24gY2xvbmVQYXRoKHBhdGgpIHtcbiAgcmV0dXJuIHsgbmV3UG9zOiBwYXRoLm5ld1BvcywgY29tcG9uZW50czogcGF0aC5jb21wb25lbnRzLnNsaWNlKDApIH07XG59XG4iXX0= + //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9kaWZmL2Jhc2UuanMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7OzRDQUF3QixJO0FBQVQsU0FBUyxJQUFULEdBQWdCLENBQUU7O0FBRWpDLEtBQUssU0FBTCxHQUFpQixFO3lCQUNmLElBRGUsZ0JBQ1YsU0FEVSxFQUNDLFNBREQsRUFDMEI7NkJBQUEsSSx1QkFBZCxPQUFjLHlEQUFKLEVBQUk7O0FBQ3ZDLFFBQUksV0FBVyxRQUFRLFFBQXZCO0FBQ0EsUUFBSSxPQUFPLE9BQVAsS0FBbUIsVUFBdkIsRUFBbUM7QUFDakMsaUJBQVcsT0FBWDtBQUNBLGdCQUFVLEVBQVY7QUFDRDtBQUNELFNBQUssT0FBTCxHQUFlLE9BQWY7O0FBRUEsUUFBSSxPQUFPLElBQVg7O0FBRUEsYUFBUyxJQUFULENBQWMsS0FBZCxFQUFxQjtBQUNuQixVQUFJLFFBQUosRUFBYztBQUNaLG1CQUFXLFlBQVc7QUFBRSxtQkFBUyxTQUFULEVBQW9CLEtBQXBCO0FBQTZCLFNBQXJELEVBQXVELENBQXZEO0FBQ0EsZUFBTyxJQUFQO0FBQ0QsT0FIRCxNQUdPO0FBQ0wsZUFBTyxLQUFQO0FBQ0Q7QUFDRjs7O0FBR0QsZ0JBQVksS0FBSyxTQUFMLENBQWUsU0FBZixDQUFaO0FBQ0EsZ0JBQVksS0FBSyxTQUFMLENBQWUsU0FBZixDQUFaOztBQUVBLGdCQUFZLEtBQUssV0FBTCxDQUFpQixLQUFLLFFBQUwsQ0FBYyxTQUFkLENBQWpCLENBQVo7QUFDQSxnQkFBWSxLQUFLLFdBQUwsQ0FBaUIsS0FBSyxRQUFMLENBQWMsU0FBZCxDQUFqQixDQUFaOztBQUVBLFFBQUksU0FBUyxVQUFVLE1BQXZCO0FBQUEsUUFBK0IsU0FBUyxVQUFVLE1BQWxEO0FBQ0EsUUFBSSxhQUFhLENBQWpCO0FBQ0EsUUFBSSxnQkFBZ0IsU0FBUyxNQUE3QjtBQUNBLFFBQUksV0FBVyxDQUFDLEVBQUUsUUFBUSxDQUFDLENBQVgsRUFBYyxZQUFZLEVBQTFCLEVBQUQsQ0FBZjs7O0FBR0EsUUFB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LFVBQUwsQ0FBZ0IsS0FBaEIsQ0FBc0IsQ0FBdEIsQ0FBbkMsRUFBUDtBQUNEIiwiZmlsZSI6ImJhc2UuanMiLCJzb3VyY2VzQ29udGVudCI6WyJleHBvcnQgZGVmYXVsdCBmdW5jdGlvbiBEaWZmKCkge31cblxuRGlmZi5wcm90b3R5cGUgPSB7XG4gIGRpZmYob2xkU3RyaW5nLCBuZXdTdHJpbmcsIG9wdGlvbnMgPSB7fSkge1xuICAgIGxldCBjYWxsYmFjayA9IG9wdGlvbnMuY2FsbGJhY2s7XG4gICAgaWYgKHR5cGVvZiBvcHRpb25zID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICBjYWxsYmFjayA9IG9wdGlvbnM7XG4gICAgICBvcHRpb25zID0ge307XG4gICAgfVxuICAgIHRoaXMub3B0aW9ucyA9IG9wdGlvbnM7XG5cbiAgICBsZXQgc2VsZiA9IHRoaXM7XG5cbiAgICBmdW5jdGlvbiBkb25lKHZhbHVlKSB7XG4gICAgICBpZiAoY2FsbGJhY2spIHtcbiAgICAgICAgc2V0VGltZW91dChmdW5jdGlvbigpIHsgY2FsbGJhY2sodW5kZWZpbmVkLCB2YWx1ZSk7IH0sIDApO1xuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJldHVybiB2YWx1ZTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBBbGxvdyBzdWJjbGFzc2VzIHRvIG1hc3NhZ2UgdGhlIGlucHV0IHByaW9yIHRvIHJ1bm5pbmdcbiAgICBvbGRTdHJpbmcgPSB0aGlzLmNhc3RJbnB1dChvbGRTdHJpbmcpO1xuICAgIG5ld1N0cmluZyA9IHRoaXMuY2FzdElucHV0KG5ld1N0cmluZyk7XG5cbiAgICBvbGRTdHJpbmcgPSB0aGlzLnJlbW92ZUVtcHR5KHRoaXMudG9rZW5pemUob2xkU3RyaW5nKSk7XG4gICAgbmV3U3RyaW5nID0gdGhpcy5yZW1vdmVFbXB0eSh0aGlzLnRva2VuaXplKG5ld1N0cmluZykpO1xuXG4gICAgbGV0IG5ld0xlbiA9IG5ld1N0cmluZy5sZW5ndGgsIG9sZExlbiA9IG9sZFN0cmluZy5sZW5ndGg7XG4gICAgbGV0IGVkaXRMZW5ndGggPSAxO1xuICAgIGxldCBtYXhFZGl0TGVuZ3RoID0gbmV3TGVuICsgb2xkTGVuO1xuICAgIGxldCBiZXN0UGF0aCA9IFt7IG5ld1BvczogLTEsIGNvbXBvbmVudHM6IFtdIH1dO1xuXG4gICAgLy8gU2VlZCBlZGl0TGVuZ3RoID0gMCwgaS5lLiB0aGUgY29udGVudCBzdGFydHMgd2l0aCB0aGUgc2FtZSB2YWx1ZXNcbiAgICBsZXQgb2xkUG9zID0gdGhpcy5leHRyYWN0Q29tbW9uKGJlc3RQYXRoWzBdLCBuZXdTdHJpbmcsIG9sZFN0cmluZywgMCk7XG4gICAgaWYgKGJlc3RQYXRoWzBdLm5ld1BvcyArIDEgPj0gbmV3TGVuICYmIG9sZFBvcyArIDEgPj0gb2xkTGVuKSB7XG4gICAgICAvLyBJZGVudGl0eSBwZXIgdGhlIGVxdWFsaXR5IGFuZCB0b2tlbml6ZXJcbiAgICAgIHJldHVybiBkb25lKFt7dmFsdWU6IHRoaXMuam9pbihuZXdTdHJpbmcpLCBjb3VudDogbmV3U3RyaW5nLmxlbmd0aH1dKTtcbiAgICB9XG5cbiAgICAvLyBNYWluIHdvcmtlciBtZXRob2QuIGNoZWNrcyBhbGwgcGVybXV0YXRpb25zIG9mIGEgZ2l2ZW4gZWRpdCBsZW5ndGggZm9yIGFjY2VwdGFuY2UuXG4gICAgZnVuY3Rpb24gZXhlY0VkaXRMZW5ndGgoKSB7XG4gICAgICBmb3IgKGxldCBkaWFnb25hbFBhdGggPSAtMSAqIGVkaXRMZW5ndGg7IGRpYWdvbmFsUGF0aCA8PSBlZGl0TGVuZ3RoOyBkaWFnb25hbFBhdGggKz0gMikge1xuICAgICAgICBsZXQgYmFzZVBhdGg7XG4gICAgICAgIGxldCBhZGRQYXRoID0gYmVzdFBhdGhbZGlhZ29uYWxQYXRoIC0gMV0sXG4gICAgICAgICAgICByZW1vdmVQYXRoID0gYmVzdFBhdGhbZGlhZ29uYWxQYXRoICsgMV0sXG4gICAgICAgICAgICBvbGRQb3MgPSAocmVtb3ZlUGF0aCA/IHJlbW92ZVBhdGgubmV3UG9zIDogMCkgLSBkaWFnb25hbFBhdGg7XG4gICAgICAgIGlmIChhZGRQYXRoKSB7XG4gICAgICAgICAgLy8gTm8gb25lIGVsc2UgaXMgZ29pbmcgdG8gYXR0ZW1wdCB0byB1c2UgdGhpcyB2YWx1ZSwgY2xlYXIgaXRcbiAgICAgICAgICBiZXN0UGF0aFtkaWFnb25hbFBhdGggLSAxXSA9IHVuZGVmaW5lZDtcbiAgICAgICAgfVxuXG4gICAgICAgIGxldCBjYW5BZGQgPSBhZGRQYXRoICYmIGFkZFBhdGgubmV3UG9zICsgMSA8IG5ld0xlbixcbiAgICAgICAgICAgIGNhblJlbW92ZSA9IHJlbW92ZVBhdGggJiYgMCA8PSBvbGRQb3MgJiYgb2xkUG9zIDwgb2xkTGVuO1xuICAgICAgICBpZiAoIWNhbkFkZCAmJiAhY2FuUmVtb3ZlKSB7XG4gICAgICAgICAgLy8gSWYgdGhpcyBwYXRoIGlzIGEgdGVybWluYWwgdGhlbiBwcnVuZVxuICAgICAgICAgIGJlc3RQYXRoW2RpYWdvbmFsUGF0aF0gPSB1bmRlZmluZWQ7XG4gICAgICAgICAgY29udGludWU7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBTZWxlY3QgdGhlIGRpYWdvbmFsIHRoYXQgd2Ugd2FudCB0byBicmFuY2ggZnJvbS4gV2Ugc2VsZWN0IHRoZSBwcmlvclxuICAgICAgICAvLyBwYXRoIHdob3NlIHBvc2l0aW9uIGluIHRoZSBuZXcgc3RyaW5nIGlzIHRoZSBmYXJ0aGVzdCBmcm9tIHRoZSBvcmlnaW5cbiAgICAgICAgLy8gYW5kIGRvZXMgbm90IHBhc3MgdGhlIGJvdW5kcyBvZiB0aGUgZGlmZiBncmFwaFxuICAgICAgICBpZiAoIWNhbkFkZCB8fCAoY2FuUmVtb3ZlICYmIGFkZFBhdGgubmV3UG9zIDwgcmVtb3ZlUGF0aC5uZXdQb3MpKSB7XG4gICAgICAgICAgYmFzZVBhdGggPSBjbG9uZVBhdGgocmVtb3ZlUGF0aCk7XG4gICAgICAgICAgc2VsZi5wdXNoQ29tcG9uZW50KGJhc2VQYXRoLmNvbXBvbmVudHMsIHVuZGVmaW5lZCwgdHJ1ZSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgYmFzZVBhdGggPSBhZGRQYXRoOyAgIC8vIE5vIG5lZWQgdG8gY2xvbmUsIHdlJ3ZlIHB1bGxlZCBpdCBmcm9tIHRoZSBsaXN0XG4gICAgICAgICAgYmFzZVBhdGgubmV3UG9zKys7XG4gICAgICAgICAgc2VsZi5wdXNoQ29tcG9uZW50KGJhc2VQYXRoLmNvbXBvbmVudHMsIHRydWUsIHVuZGVmaW5lZCk7XG4gICAgICAgIH1cblxuICAgICAgICBvbGRQb3MgPSBzZWxmLmV4dHJhY3RDb21tb24oYmFzZVBhdGgsIG5ld1N0cmluZywgb2xkU3RyaW5nLCBkaWFnb25hbFBhdGgpO1xuXG4gICAgICAgIC8vIElmIHdlIGhhdmUgaGl0IHRoZSBlbmQgb2YgYm90aCBzdHJpbmdzLCB0aGVuIHdlIGFyZSBkb25lXG4gICAgICAgIGlmIChiYXNlUGF0aC5uZXdQb3MgKyAxID49IG5ld0xlbiAmJiBvbGRQb3MgKyAxID49IG9sZExlbikge1xuICAgICAgICAgIHJldHVybiBkb25lKGJ1aWxkVmFsdWVzKHNlbGYsIGJhc2VQYXRoLmNvbXBvbmVudHMsIG5ld1N0cmluZywgb2xkU3RyaW5nLCBzZWxmLnVzZUxvbmdlc3RUb2tlbikpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIC8vIE90aGVyd2lzZSB0cmFjayB0aGlzIHBhdGggYXMgYSBwb3RlbnRpYWwgY2FuZGlkYXRlIGFuZCBjb250aW51ZS5cbiAgICAgICAgICBiZXN0UGF0aFtkaWFnb25hbFBhdGhdID0gYmFzZVBhdGg7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgZWRpdExlbmd0aCsrO1xuICAgIH1cblxuICAgIC8vIFBlcmZvcm1zIHRoZSBsZW5ndGggb2YgZWRpdCBpdGVyYXRpb24uIElzIGEgYml0IGZ1Z2x5IGFzIHRoaXMgaGFzIHRvIHN1cHBvcnQgdGhlXG4gICAgLy8gc3luYyBhbmQgYXN5bmMgbW9kZSB3aGljaCBpcyBuZXZlciBmdW4uIExvb3BzIG92ZXIgZXhlY0VkaXRMZW5ndGggdW50aWwgYSB2YWx1ZVxuICAgIC8vIGlzIHByb2R1Y2VkLlxuICAgIGlmIChjYWxsYmFjaykge1xuICAgICAgKGZ1bmN0aW9uIGV4ZWMoKSB7XG4gICAgICAgIHNldFRpbWVvdXQoZnVuY3Rpb24oKSB7XG4gICAgICAgICAgLy8gVGhpcyBzaG91bGQgbm90IGhhcHBlbiwgYnV0IHdlIHdhbnQgdG8gYmUgc2FmZS5cbiAgICAgICAgICAvKiBpc3RhbmJ1bCBpZ25vcmUgbmV4dCAqL1xuICAgICAgICAgIGlmIChlZGl0TGVuZ3RoID4gbWF4RWRpdExlbmd0aCkge1xuICAgICAgICAgICAgcmV0dXJuIGNhbGxiYWNrKCk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgaWYgKCFleGVjRWRpdExlbmd0aCgpKSB7XG4gICAgICAgICAgICBleGVjKCk7XG4gICAgICAgICAgfVxuICAgICAgICB9LCAwKTtcbiAgICAgIH0oKSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHdoaWxlIChlZGl0TGVuZ3RoIDw9IG1heEVkaXRMZW5ndGgpIHtcbiAgICAgICAgbGV0IHJldCA9IGV4ZWNFZGl0TGVuZ3RoKCk7XG4gICAgICAgIGlmIChyZXQpIHtcbiAgICAgICAgICByZXR1cm4gcmV0O1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICB9LFxuXG4gIHB1c2hDb21wb25lbnQoY29tcG9uZW50cywgYWRkZWQsIHJlbW92ZWQpIHtcbiAgICBsZXQgbGFzdCA9IGNvbXBvbmVudHNbY29tcG9uZW50cy5sZW5ndGggLSAxXTtcbiAgICBpZiAobGFzdCAmJiBsYXN0LmFkZGVkID09PSBhZGRlZCAmJiBsYXN0LnJlbW92ZWQgPT09IHJlbW92ZWQpIHtcbiAgICAgIC8vIFdlIG5lZWQgdG8gY2xvbmUgaGVyZSBhcyB0aGUgY29tcG9uZW50IGNsb25lIG9wZXJhdGlvbiBpcyBqdXN0XG4gICAgICAvLyBhcyBzaGFsbG93IGFycmF5IGNsb25lXG4gICAgICBjb21wb25lbnRzW2NvbXBvbmVudHMubGVuZ3RoIC0gMV0gPSB7Y291bnQ6IGxhc3QuY291bnQgKyAxLCBhZGRlZDogYWRkZWQsIHJlbW92ZWQ6IHJlbW92ZWQgfTtcbiAgICB9IGVsc2Uge1xuICAgICAgY29tcG9uZW50cy5wdXNoKHtjb3VudDogMSwgYWRkZWQ6IGFkZGVkLCByZW1vdmVkOiByZW1vdmVkIH0pO1xuICAgIH1cbiAgfSxcbiAgZXh0cmFjdENvbW1vbihiYXNlUGF0aCwgbmV3U3RyaW5nLCBvbGRTdHJpbmcsIGRpYWdvbmFsUGF0aCkge1xuICAgIGxldCBuZXdMZW4gPSBuZXdTdHJpbmcubGVuZ3RoLFxuICAgICAgICBvbGRMZW4gPSBvbGRTdHJpbmcubGVuZ3RoLFxuICAgICAgICBuZXdQb3MgPSBiYXNlUGF0aC5uZXdQb3MsXG4gICAgICAgIG9sZFBvcyA9IG5ld1BvcyAtIGRpYWdvbmFsUGF0aCxcblxuICAgICAgICBjb21tb25Db3VudCA9IDA7XG4gICAgd2hpbGUgKG5ld1BvcyArIDEgPCBuZXdMZW4gJiYgb2xkUG9zICsgMSA8IG9sZExlbiAmJiB0aGlzLmVxdWFscyhuZXdTdHJpbmdbbmV3UG9zICsgMV0sIG9sZFN0cmluZ1tvbGRQb3MgKyAxXSkpIHtcbiAgICAgIG5ld1BvcysrO1xuICAgICAgb2xkUG9zKys7XG4gICAgICBjb21tb25Db3VudCsrO1xuICAgIH1cblxuICAgIGlmIChjb21tb25Db3VudCkge1xuICAgICAgYmFzZVBhdGguY29tcG9uZW50cy5wdXNoKHtjb3VudDogY29tbW9uQ291bnR9KTtcbiAgICB9XG5cbiAgICBiYXNlUGF0aC5uZXdQb3MgPSBuZXdQb3M7XG4gICAgcmV0dXJuIG9sZFBvcztcbiAgfSxcblxuICBlcXVhbHMobGVmdCwgcmlnaHQpIHtcbiAgICByZXR1cm4gbGVmdCA9PT0gcmlnaHQ7XG4gIH0sXG4gIHJlbW92ZUVtcHR5KGFycmF5KSB7XG4gICAgbGV0IHJldCA9IFtdO1xuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgYXJyYXkubGVuZ3RoOyBpKyspIHtcbiAgICAgIGlmIChhcnJheVtpXSkge1xuICAgICAgICByZXQucHVzaChhcnJheVtpXSk7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiByZXQ7XG4gIH0sXG4gIGNhc3RJbnB1dCh2YWx1ZSkge1xuICAgIHJldHVybiB2YWx1ZTtcbiAgfSxcbiAgdG9rZW5pemUodmFsdWUpIHtcbiAgICByZXR1cm4gdmFsdWUuc3BsaXQoJycpO1xuICB9LFxuICBqb2luKGNoYXJzKSB7XG4gICAgcmV0dXJuIGNoYXJzLmpvaW4oJycpO1xuICB9XG59O1xuXG5mdW5jdGlvbiBidWlsZFZhbHVlcyhkaWZmLCBjb21wb25lbnRzLCBuZXdTdHJpbmcsIG9sZFN0cmluZywgdXNlTG9uZ2VzdFRva2VuKSB7XG4gIGxldCBjb21wb25lbnRQb3MgPSAwLFxuICAgICAgY29tcG9uZW50TGVuID0gY29tcG9uZW50cy5sZW5ndGgsXG4gICAgICBuZXdQb3MgPSAwLFxuICAgICAgb2xkUG9zID0gMDtcblxuICBmb3IgKDsgY29tcG9uZW50UG9zIDwgY29tcG9uZW50TGVuOyBjb21wb25lbnRQb3MrKykge1xuICAgIGxldCBjb21wb25lbnQgPSBjb21wb25lbnRzW2NvbXBvbmVudFBvc107XG4gICAgaWYgKCFjb21wb25lbnQucmVtb3ZlZCkge1xuICAgICAgaWYgKCFjb21wb25lbnQuYWRkZWQgJiYgdXNlTG9uZ2VzdFRva2VuKSB7XG4gICAgICAgIGxldCB2YWx1ZSA9IG5ld1N0cmluZy5zbGljZShuZXdQb3MsIG5ld1BvcyArIGNvbXBvbmVudC5jb3VudCk7XG4gICAgICAgIHZhbHVlID0gdmFsdWUubWFwKGZ1bmN0aW9uKHZhbHVlLCBpKSB7XG4gICAgICAgICAgbGV0IG9sZFZhbHVlID0gb2xkU3RyaW5nW29sZFBvcyArIGldO1xuICAgICAgICAgIHJldHVybiBvbGRWYWx1ZS5sZW5ndGggPiB2YWx1ZS5sZW5ndGggPyBvbGRWYWx1ZSA6IHZhbHVlO1xuICAgICAgICB9KTtcblxuICAgICAgICBjb21wb25lbnQudmFsdWUgPSBkaWZmLmpvaW4odmFsdWUpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgY29tcG9uZW50LnZhbHVlID0gZGlmZi5qb2luKG5ld1N0cmluZy5zbGljZShuZXdQb3MsIG5ld1BvcyArIGNvbXBvbmVudC5jb3VudCkpO1xuICAgICAgfVxuICAgICAgbmV3UG9zICs9IGNvbXBvbmVudC5jb3VudDtcblxuICAgICAgLy8gQ29tbW9uIGNhc2VcbiAgICAgIGlmICghY29tcG9uZW50LmFkZGVkKSB7XG4gICAgICAgIG9sZFBvcyArPSBjb21wb25lbnQuY291bnQ7XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIGNvbXBvbmVudC52YWx1ZSA9IGRpZmYuam9pbihvbGRTdHJpbmcuc2xpY2Uob2xkUG9zLCBvbGRQb3MgKyBjb21wb25lbnQuY291bnQpKTtcbiAgICAgIG9sZFBvcyArPSBjb21wb25lbnQuY291bnQ7XG5cbiAgICAgIC8vIFJldmVyc2UgYWRkIGFuZCByZW1vdmUgc28gcmVtb3ZlcyBhcmUgb3V0cHV0IGZpcnN0IHRvIG1hdGNoIGNvbW1vbiBjb252ZW50aW9uXG4gICAgICAvLyBUaGUgZGlmZmluZyBhbGdvcml0aG0gaXMgdGllZCB0byBhZGQgdGhlbiByZW1vdmUgb3V0cHV0IGFuZCB0aGlzIGlzIHRoZSBzaW1wbGVzdFxuICAgICAgLy8gcm91dGUgdG8gZ2V0IHRoZSBkZXNpcmVkIG91dHB1dCB3aXRoIG1pbmltYWwgb3ZlcmhlYWQuXG4gICAgICBpZiAoY29tcG9uZW50UG9zICYmIGNvbXBvbmVudHNbY29tcG9uZW50UG9zIC0gMV0uYWRkZWQpIHtcbiAgICAgICAgbGV0IHRtcCA9IGNvbXBvbmVudHNbY29tcG9uZW50UG9zIC0gMV07XG4gICAgICAgIGNvbXBvbmVudHNbY29tcG9uZW50UG9zIC0gMV0gPSBjb21wb25lbnRzW2NvbXBvbmVudFBvc107XG4gICAgICAgIGNvbXBvbmVudHNbY29tcG9uZW50UG9zXSA9IHRtcDtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICAvLyBTcGVjaWFsIGNhc2UgaGFuZGxlIGZvciB3aGVuIG9uZSB0ZXJtaW5hbCBpcyBpZ25vcmVkLiBGb3IgdGhpcyBjYXNlIHdlIG1lcmdlIHRoZVxuICAvLyB0ZXJtaW5hbCBpbnRvIHRoZSBwcmlvciBzdHJpbmcgYW5kIGRyb3AgdGhlIGNoYW5nZS5cbiAgbGV0IGxhc3RDb21wb25lbnQgPSBjb21wb25lbnRzW2NvbXBvbmVudExlbiAtIDFdO1xuICBpZiAoY29tcG9uZW50TGVuID4gMVxuICAgICAgJiYgKGxhc3RDb21wb25lbnQuYWRkZWQgfHwgbGFzdENvbXBvbmVudC5yZW1vdmVkKVxuICAgICAgJiYgZGlmZi5lcXVhbHMoJycsIGxhc3RDb21wb25lbnQudmFsdWUpKSB7XG4gICAgY29tcG9uZW50c1tjb21wb25lbnRMZW4gLSAyXS52YWx1ZSArPSBsYXN0Q29tcG9uZW50LnZhbHVlO1xuICAgIGNvbXBvbmVudHMucG9wKCk7XG4gIH1cblxuICByZXR1cm4gY29tcG9uZW50cztcbn1cblxuZnVuY3Rpb24gY2xvbmVQYXRoKHBhdGgpIHtcbiAgcmV0dXJuIHsgbmV3UG9zOiBwYXRoLm5ld1BvcywgY29tcG9uZW50czogcGF0aC5jb21wb25lbnRzLnNsaWNlKDApIH07XG59XG4iXX0= -/***/ }), +/***/ }, /* 2 */ -/***/ (function(module, exports, __webpack_require__) { +/***/ function(module, exports, __webpack_require__) { /*istanbul ignore start*/'use strict'; @@ -3771,20 +3765,21 @@ return /******/ (function(modules) { // webpackBootstrap var /*istanbul ignore start*/_base = __webpack_require__(1) /*istanbul ignore end*/; - /*istanbul ignore start*/var _base2 = _interopRequireDefault(_base); + /*istanbul ignore start*/ + var _base2 = _interopRequireDefault(_base); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } - /*istanbul ignore end*/var characterDiff = /*istanbul ignore start*/exports. /*istanbul ignore end*/characterDiff = new /*istanbul ignore start*/_base2['default'] /*istanbul ignore end*/(); - function diffChars(oldStr, newStr, options) { - return characterDiff.diff(oldStr, newStr, options); + /*istanbul ignore end*/var characterDiff = /*istanbul ignore start*/exports. /*istanbul ignore end*/characterDiff = new /*istanbul ignore start*/_base2['default']() /*istanbul ignore end*/; + function diffChars(oldStr, newStr, callback) { + return characterDiff.diff(oldStr, newStr, callback); } - //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9kaWZmL2NoYXJhY3Rlci5qcyJdLCJuYW1lcyI6WyJkaWZmQ2hhcnMiLCJjaGFyYWN0ZXJEaWZmIiwib2xkU3RyIiwibmV3U3RyIiwib3B0aW9ucyIsImRpZmYiXSwibWFwcGluZ3MiOiI7Ozs7Z0NBR2dCQSxTLEdBQUFBLFM7O0FBSGhCOzs7Ozs7dUJBRU8sSUFBTUMseUZBQWdCLHdFQUF0QjtBQUNBLFNBQVNELFNBQVQsQ0FBbUJFLE1BQW5CLEVBQTJCQyxNQUEzQixFQUFtQ0MsT0FBbkMsRUFBNEM7QUFBRSxTQUFPSCxjQUFjSSxJQUFkLENBQW1CSCxNQUFuQixFQUEyQkMsTUFBM0IsRUFBbUNDLE9BQW5DLENBQVA7QUFBcUQiLCJmaWxlIjoiY2hhcmFjdGVyLmpzIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IERpZmYgZnJvbSAnLi9iYXNlJztcblxuZXhwb3J0IGNvbnN0IGNoYXJhY3RlckRpZmYgPSBuZXcgRGlmZigpO1xuZXhwb3J0IGZ1bmN0aW9uIGRpZmZDaGFycyhvbGRTdHIsIG5ld1N0ciwgb3B0aW9ucykgeyByZXR1cm4gY2hhcmFjdGVyRGlmZi5kaWZmKG9sZFN0ciwgbmV3U3RyLCBvcHRpb25zKTsgfVxuIl19 + //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9kaWZmL2NoYXJhY3Rlci5qcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7O2dDQUdnQixTLEdBQUEsUzs7QUFIaEIsSSx5QkFBQSx5Qix3QkFBQTs7Ozs7Ozt1QkFFTyxJQUFNLGdCLHlCQUFBLFEsd0JBQUEsZ0JBQWdCLEkseUJBQUEsbUIsd0JBQXRCO0FBQ0EsU0FBUyxTQUFULENBQW1CLE1BQW5CLEVBQTJCLE1BQTNCLEVBQW1DLFFBQW5DLEVBQTZDO0FBQUUsU0FBTyxjQUFjLElBQWQsQ0FBbUIsTUFBbkIsRUFBMkIsTUFBM0IsRUFBbUMsUUFBbkMsQ0FBUDtBQUFzRCIsImZpbGUiOiJjaGFyYWN0ZXIuanMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgRGlmZiBmcm9tICcuL2Jhc2UnO1xuXG5leHBvcnQgY29uc3QgY2hhcmFjdGVyRGlmZiA9IG5ldyBEaWZmKCk7XG5leHBvcnQgZnVuY3Rpb24gZGlmZkNoYXJzKG9sZFN0ciwgbmV3U3RyLCBjYWxsYmFjaykgeyByZXR1cm4gY2hhcmFjdGVyRGlmZi5kaWZmKG9sZFN0ciwgbmV3U3RyLCBjYWxsYmFjayk7IH1cbiJdfQ== -/***/ }), +/***/ }, /* 3 */ -/***/ (function(module, exports, __webpack_require__) { +/***/ function(module, exports, __webpack_require__) { /*istanbul ignore start*/'use strict'; @@ -3795,13 +3790,18 @@ return /******/ (function(modules) { // webpackBootstrap var /*istanbul ignore start*/_base = __webpack_require__(1) /*istanbul ignore end*/; - /*istanbul ignore start*/var _base2 = _interopRequireDefault(_base); + /*istanbul ignore start*/ + var _base2 = _interopRequireDefault(_base); - /*istanbul ignore end*/var /*istanbul ignore start*/_params = __webpack_require__(4) /*istanbul ignore end*/; + /*istanbul ignore end*/ + var /*istanbul ignore start*/_params = __webpack_require__(4) /*istanbul ignore end*/; - /*istanbul ignore start*/function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } + /*istanbul ignore start*/ + function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } - /*istanbul ignore end*/ // Based on https://en.wikipedia.org/wiki/Latin_script_in_Unicode + /*istanbul ignore end*/ + + // Based on https://en.wikipedia.org/wiki/Latin_script_in_Unicode // // Ranges and exceptions: // Latin-1 Supplement, 0080–00FF @@ -3823,12 +3823,8 @@ return /******/ (function(modules) { // webpackBootstrap var reWhitespace = /\S/; - var wordDiff = /*istanbul ignore start*/exports. /*istanbul ignore end*/wordDiff = new /*istanbul ignore start*/_base2['default'] /*istanbul ignore end*/(); + var wordDiff = /*istanbul ignore start*/exports. /*istanbul ignore end*/wordDiff = new /*istanbul ignore start*/_base2['default']() /*istanbul ignore end*/; wordDiff.equals = function (left, right) { - if (this.options.ignoreCase) { - left = left.toLowerCase(); - right = right.toLowerCase(); - } return left === right || this.options.ignoreWhitespace && !reWhitespace.test(left) && !reWhitespace.test(right); }; wordDiff.tokenize = function (value) { @@ -3847,20 +3843,19 @@ return /******/ (function(modules) { // webpackBootstrap return tokens; }; - function diffWords(oldStr, newStr, options) { - options = /*istanbul ignore start*/(0, _params.generateOptions) /*istanbul ignore end*/(options, { ignoreWhitespace: true }); + function diffWords(oldStr, newStr, callback) { + var options = /*istanbul ignore start*/(0, _params.generateOptions) /*istanbul ignore end*/(callback, { ignoreWhitespace: true }); return wordDiff.diff(oldStr, newStr, options); } - - function diffWordsWithSpace(oldStr, newStr, options) { - return wordDiff.diff(oldStr, newStr, options); + function diffWordsWithSpace(oldStr, newStr, callback) { + return wordDiff.diff(oldStr, newStr, callback); } - //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9kaWZmL3dvcmQuanMiXSwibmFtZXMiOlsiZGlmZldvcmRzIiwiZGlmZldvcmRzV2l0aFNwYWNlIiwiZXh0ZW5kZWRXb3JkQ2hhcnMiLCJyZVdoaXRlc3BhY2UiLCJ3b3JkRGlmZiIsImVxdWFscyIsImxlZnQiLCJyaWdodCIsIm9wdGlvbnMiLCJpZ25vcmVDYXNlIiwidG9Mb3dlckNhc2UiLCJpZ25vcmVXaGl0ZXNwYWNlIiwidGVzdCIsInRva2VuaXplIiwidmFsdWUiLCJ0b2tlbnMiLCJzcGxpdCIsImkiLCJsZW5ndGgiLCJzcGxpY2UiLCJvbGRTdHIiLCJuZXdTdHIiLCJkaWZmIl0sIm1hcHBpbmdzIjoiOzs7O2dDQW1EZ0JBLFMsR0FBQUEsUzt5REFLQUMsa0IsR0FBQUEsa0I7O0FBeERoQjs7Ozt1QkFDQTs7Ozt3QkFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFNQyxvQkFBb0IsK0RBQTFCOztBQUVBLElBQU1DLGVBQWUsSUFBckI7O0FBRU8sSUFBTUMsK0VBQVcsd0VBQWpCO0FBQ1BBLFNBQVNDLE1BQVQsR0FBa0IsVUFBU0MsSUFBVCxFQUFlQyxLQUFmLEVBQXNCO0FBQ3RDLE1BQUksS0FBS0MsT0FBTCxDQUFhQyxVQUFqQixFQUE2QjtBQUMzQkgsV0FBT0EsS0FBS0ksV0FBTCxFQUFQO0FBQ0FILFlBQVFBLE1BQU1HLFdBQU4sRUFBUjtBQUNEO0FBQ0QsU0FBT0osU0FBU0MsS0FBVCxJQUFtQixLQUFLQyxPQUFMLENBQWFHLGdCQUFiLElBQWlDLENBQUNSLGFBQWFTLElBQWIsQ0FBa0JOLElBQWxCLENBQWxDLElBQTZELENBQUNILGFBQWFTLElBQWIsQ0FBa0JMLEtBQWxCLENBQXhGO0FBQ0QsQ0FORDtBQU9BSCxTQUFTUyxRQUFULEdBQW9CLFVBQVNDLEtBQVQsRUFBZ0I7QUFDbEMsTUFBSUMsU0FBU0QsTUFBTUUsS0FBTixDQUFZLFVBQVosQ0FBYjs7QUFFQTtBQUNBLE9BQUssSUFBSUMsSUFBSSxDQUFiLEVBQWdCQSxJQUFJRixPQUFPRyxNQUFQLEdBQWdCLENBQXBDLEVBQXVDRCxHQUF2QyxFQUE0QztBQUMxQztBQUNBLFFBQUksQ0FBQ0YsT0FBT0UsSUFBSSxDQUFYLENBQUQsSUFBa0JGLE9BQU9FLElBQUksQ0FBWCxDQUFsQixJQUNLZixrQkFBa0JVLElBQWxCLENBQXVCRyxPQUFPRSxDQUFQLENBQXZCLENBREwsSUFFS2Ysa0JBQWtCVSxJQUFsQixDQUF1QkcsT0FBT0UsSUFBSSxDQUFYLENBQXZCLENBRlQsRUFFZ0Q7QUFDOUNGLGFBQU9FLENBQVAsS0FBYUYsT0FBT0UsSUFBSSxDQUFYLENBQWI7QUFDQUYsYUFBT0ksTUFBUCxDQUFjRixJQUFJLENBQWxCLEVBQXFCLENBQXJCO0FBQ0FBO0FBQ0Q7QUFDRjs7QUFFRCxTQUFPRixNQUFQO0FBQ0QsQ0FoQkQ7O0FBa0JPLFNBQVNmLFNBQVQsQ0FBbUJvQixNQUFuQixFQUEyQkMsTUFBM0IsRUFBbUNiLE9BQW5DLEVBQTRDO0FBQ2pEQSxZQUFVLDhFQUFnQkEsT0FBaEIsRUFBeUIsRUFBQ0csa0JBQWtCLElBQW5CLEVBQXpCLENBQVY7QUFDQSxTQUFPUCxTQUFTa0IsSUFBVCxDQUFjRixNQUFkLEVBQXNCQyxNQUF0QixFQUE4QmIsT0FBOUIsQ0FBUDtBQUNEOztBQUVNLFNBQVNQLGtCQUFULENBQTRCbUIsTUFBNUIsRUFBb0NDLE1BQXBDLEVBQTRDYixPQUE1QyxFQUFxRDtBQUMxRCxTQUFPSixTQUFTa0IsSUFBVCxDQUFjRixNQUFkLEVBQXNCQyxNQUF0QixFQUE4QmIsT0FBOUIsQ0FBUDtBQUNEIiwiZmlsZSI6IndvcmQuanMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgRGlmZiBmcm9tICcuL2Jhc2UnO1xuaW1wb3J0IHtnZW5lcmF0ZU9wdGlvbnN9IGZyb20gJy4uL3V0aWwvcGFyYW1zJztcblxuLy8gQmFzZWQgb24gaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvTGF0aW5fc2NyaXB0X2luX1VuaWNvZGVcbi8vXG4vLyBSYW5nZXMgYW5kIGV4Y2VwdGlvbnM6XG4vLyBMYXRpbi0xIFN1cHBsZW1lbnQsIDAwODDigJMwMEZGXG4vLyAgLSBVKzAwRDcgIMOXIE11bHRpcGxpY2F0aW9uIHNpZ25cbi8vICAtIFUrMDBGNyAgw7cgRGl2aXNpb24gc2lnblxuLy8gTGF0aW4gRXh0ZW5kZWQtQSwgMDEwMOKAkzAxN0Zcbi8vIExhdGluIEV4dGVuZGVkLUIsIDAxODDigJMwMjRGXG4vLyBJUEEgRXh0ZW5zaW9ucywgMDI1MOKAkzAyQUZcbi8vIFNwYWNpbmcgTW9kaWZpZXIgTGV0dGVycywgMDJCMOKAkzAyRkZcbi8vICAtIFUrMDJDNyAgy4cgJiM3MTE7ICBDYXJvblxuLy8gIC0gVSswMkQ4ICDLmCAmIzcyODsgIEJyZXZlXG4vLyAgLSBVKzAyRDkgIMuZICYjNzI5OyAgRG90IEFib3ZlXG4vLyAgLSBVKzAyREEgIMuaICYjNzMwOyAgUmluZyBBYm92ZVxuLy8gIC0gVSswMkRCICDLmyAmIzczMTsgIE9nb25la1xuLy8gIC0gVSswMkRDICDLnCAmIzczMjsgIFNtYWxsIFRpbGRlXG4vLyAgLSBVKzAyREQgIMudICYjNzMzOyAgRG91YmxlIEFjdXRlIEFjY2VudFxuLy8gTGF0aW4gRXh0ZW5kZWQgQWRkaXRpb25hbCwgMUUwMOKAkzFFRkZcbmNvbnN0IGV4dGVuZGVkV29yZENoYXJzID0gL15bYS16QS1aXFx1e0MwfS1cXHV7RkZ9XFx1e0Q4fS1cXHV7RjZ9XFx1e0Y4fS1cXHV7MkM2fVxcdXsyQzh9LVxcdXsyRDd9XFx1ezJERX0tXFx1ezJGRn1cXHV7MUUwMH0tXFx1ezFFRkZ9XSskL3U7XG5cbmNvbnN0IHJlV2hpdGVzcGFjZSA9IC9cXFMvO1xuXG5leHBvcnQgY29uc3Qgd29yZERpZmYgPSBuZXcgRGlmZigpO1xud29yZERpZmYuZXF1YWxzID0gZnVuY3Rpb24obGVmdCwgcmlnaHQpIHtcbiAgaWYgKHRoaXMub3B0aW9ucy5pZ25vcmVDYXNlKSB7XG4gICAgbGVmdCA9IGxlZnQudG9Mb3dlckNhc2UoKTtcbiAgICByaWdodCA9IHJpZ2h0LnRvTG93ZXJDYXNlKCk7XG4gIH1cbiAgcmV0dXJuIGxlZnQgPT09IHJpZ2h0IHx8ICh0aGlzLm9wdGlvbnMuaWdub3JlV2hpdGVzcGFjZSAmJiAhcmVXaGl0ZXNwYWNlLnRlc3QobGVmdCkgJiYgIXJlV2hpdGVzcGFjZS50ZXN0KHJpZ2h0KSk7XG59O1xud29yZERpZmYudG9rZW5pemUgPSBmdW5jdGlvbih2YWx1ZSkge1xuICBsZXQgdG9rZW5zID0gdmFsdWUuc3BsaXQoLyhcXHMrfFxcYikvKTtcblxuICAvLyBKb2luIHRoZSBib3VuZGFyeSBzcGxpdHMgdGhhdCB3ZSBkbyBub3QgY29uc2lkZXIgdG8gYmUgYm91bmRhcmllcy4gVGhpcyBpcyBwcmltYXJpbHkgdGhlIGV4dGVuZGVkIExhdGluIGNoYXJhY3RlciBzZXQuXG4gIGZvciAobGV0IGkgPSAwOyBpIDwgdG9rZW5zLmxlbmd0aCAtIDE7IGkrKykge1xuICAgIC8vIElmIHdlIGhhdmUgYW4gZW1wdHkgc3RyaW5nIGluIHRoZSBuZXh0IGZpZWxkIGFuZCB3ZSBoYXZlIG9ubHkgd29yZCBjaGFycyBiZWZvcmUgYW5kIGFmdGVyLCBtZXJnZVxuICAgIGlmICghdG9rZW5zW2kgKyAxXSAmJiB0b2tlbnNbaSArIDJdXG4gICAgICAgICAgJiYgZXh0ZW5kZWRXb3JkQ2hhcnMudGVzdCh0b2tlbnNbaV0pXG4gICAgICAgICAgJiYgZXh0ZW5kZWRXb3JkQ2hhcnMudGVzdCh0b2tlbnNbaSArIDJdKSkge1xuICAgICAgdG9rZW5zW2ldICs9IHRva2Vuc1tpICsgMl07XG4gICAgICB0b2tlbnMuc3BsaWNlKGkgKyAxLCAyKTtcbiAgICAgIGktLTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gdG9rZW5zO1xufTtcblxuZXhwb3J0IGZ1bmN0aW9uIGRpZmZXb3JkcyhvbGRTdHIsIG5ld1N0ciwgb3B0aW9ucykge1xuICBvcHRpb25zID0gZ2VuZXJhdGVPcHRpb25zKG9wdGlvbnMsIHtpZ25vcmVXaGl0ZXNwYWNlOiB0cnVlfSk7XG4gIHJldHVybiB3b3JkRGlmZi5kaWZmKG9sZFN0ciwgbmV3U3RyLCBvcHRpb25zKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGRpZmZXb3Jkc1dpdGhTcGFjZShvbGRTdHIsIG5ld1N0ciwgb3B0aW9ucykge1xuICByZXR1cm4gd29yZERpZmYuZGlmZihvbGRTdHIsIG5ld1N0ciwgb3B0aW9ucyk7XG59XG4iXX0= + //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9kaWZmL3dvcmQuanMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7OztnQ0ErQ2dCLFMsR0FBQSxTO3lEQUlBLGtCLEdBQUEsa0I7O0FBbkRoQixJLHlCQUFBLHlCLHdCQUFBOzs7Ozs7QUFDQSxJLHlCQUFBLG1DLHdCQUFBOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBb0JBLElBQU0sb0JBQW9CLCtEQUExQjs7QUFFQSxJQUFNLGVBQWUsSUFBckI7O0FBRU8sSUFBTSxXLHlCQUFBLFEsd0JBQUEsV0FBVyxJLHlCQUFBLG1CLHdCQUFqQjtBQUNQLFNBQVMsTUFBVCxHQUFrQixVQUFTLElBQVQsRUFBZSxLQUFmLEVBQXNCO0FBQ3RDLFNBQU8sU0FBUyxLQUFULElBQW1CLEtBQUssT0FBTCxDQUFhLGdCQUFiLElBQWlDLENBQUMsYUFBYSxJQUFiLENBQWtCLElBQWxCLENBQWxDLElBQTZELENBQUMsYUFBYSxJQUFiLENBQWtCLEtBQWxCLENBQXhGO0FBQ0QsQ0FGRDtBQUdBLFNBQVMsUUFBVCxHQUFvQixVQUFTLEtBQVQsRUFBZ0I7QUFDbEMsTUFBSSxTQUFTLE1BQU0sS0FBTixDQUFZLFVBQVosQ0FBYjs7O0FBR0EsT0FBSyxJQUFJLElBQUksQ0FBYixFQUFnQixJQUFJLE9BQU8sTUFBUCxHQUFnQixDQUFwQyxFQUF1QyxHQUF2QyxFQUE0Qzs7QUFFMUMsUUFBSSxDQUFDLE9BQU8sSUFBSSxDQUFYLENBQUQsSUFBa0IsT0FBTyxJQUFJLENBQVgsQ0FBbEIsSUFDSyxrQkFBa0IsSUFBbEIsQ0FBdUIsT0FBTyxDQUFQLENBQXZCLENBREwsSUFFSyxrQkFBa0IsSUFBbEIsQ0FBdUIsT0FBTyxJQUFJLENBQVgsQ0FBdkIsQ0FGVCxFQUVnRDtBQUM5QyxhQUFPLENBQVAsS0FBYSxPQUFPLElBQUksQ0FBWCxDQUFiO0FBQ0EsYUFBTyxNQUFQLENBQWMsSUFBSSxDQUFsQixFQUFxQixDQUFyQjtBQUNBO0FBQ0Q7QUFDRjs7QUFFRCxTQUFPLE1BQVA7QUFDRCxDQWhCRDs7QUFrQk8sU0FBUyxTQUFULENBQW1CLE1BQW5CLEVBQTJCLE1BQTNCLEVBQW1DLFFBQW5DLEVBQTZDO0FBQ2xELE1BQUksVSx5QkFBVSw0Qix3QkFBQSxDQUFnQixRQUFoQixFQUEwQixFQUFDLGtCQUFrQixJQUFuQixFQUExQixDQUFkO0FBQ0EsU0FBTyxTQUFTLElBQVQsQ0FBYyxNQUFkLEVBQXNCLE1BQXRCLEVBQThCLE9BQTlCLENBQVA7QUFDRDtBQUNNLFNBQVMsa0JBQVQsQ0FBNEIsTUFBNUIsRUFBb0MsTUFBcEMsRUFBNEMsUUFBNUMsRUFBc0Q7QUFDM0QsU0FBTyxTQUFTLElBQVQsQ0FBYyxNQUFkLEVBQXNCLE1BQXRCLEVBQThCLFFBQTlCLENBQVA7QUFDRCIsImZpbGUiOiJ3b3JkLmpzIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IERpZmYgZnJvbSAnLi9iYXNlJztcbmltcG9ydCB7Z2VuZXJhdGVPcHRpb25zfSBmcm9tICcuLi91dGlsL3BhcmFtcyc7XG5cbi8vIEJhc2VkIG9uIGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL0xhdGluX3NjcmlwdF9pbl9Vbmljb2RlXG4vL1xuLy8gUmFuZ2VzIGFuZCBleGNlcHRpb25zOlxuLy8gTGF0aW4tMSBTdXBwbGVtZW50LCAwMDgw4oCTMDBGRlxuLy8gIC0gVSswMEQ3ICDDlyBNdWx0aXBsaWNhdGlvbiBzaWduXG4vLyAgLSBVKzAwRjcgIMO3IERpdmlzaW9uIHNpZ25cbi8vIExhdGluIEV4dGVuZGVkLUEsIDAxMDDigJMwMTdGXG4vLyBMYXRpbiBFeHRlbmRlZC1CLCAwMTgw4oCTMDI0RlxuLy8gSVBBIEV4dGVuc2lvbnMsIDAyNTDigJMwMkFGXG4vLyBTcGFjaW5nIE1vZGlmaWVyIExldHRlcnMsIDAyQjDigJMwMkZGXG4vLyAgLSBVKzAyQzcgIMuHICYjNzExOyAgQ2Fyb25cbi8vICAtIFUrMDJEOCAgy5ggJiM3Mjg7ICBCcmV2ZVxuLy8gIC0gVSswMkQ5ICDLmSAmIzcyOTsgIERvdCBBYm92ZVxuLy8gIC0gVSswMkRBICDLmiAmIzczMDsgIFJpbmcgQWJvdmVcbi8vICAtIFUrMDJEQiAgy5sgJiM3MzE7ICBPZ29uZWtcbi8vICAtIFUrMDJEQyAgy5wgJiM3MzI7ICBTbWFsbCBUaWxkZVxuLy8gIC0gVSswMkREICDLnSAmIzczMzsgIERvdWJsZSBBY3V0ZSBBY2NlbnRcbi8vIExhdGluIEV4dGVuZGVkIEFkZGl0aW9uYWwsIDFFMDDigJMxRUZGXG5jb25zdCBleHRlbmRlZFdvcmRDaGFycyA9IC9eW2EtekEtWlxcdXtDMH0tXFx1e0ZGfVxcdXtEOH0tXFx1e0Y2fVxcdXtGOH0tXFx1ezJDNn1cXHV7MkM4fS1cXHV7MkQ3fVxcdXsyREV9LVxcdXsyRkZ9XFx1ezFFMDB9LVxcdXsxRUZGfV0rJC91O1xuXG5jb25zdCByZVdoaXRlc3BhY2UgPSAvXFxTLztcblxuZXhwb3J0IGNvbnN0IHdvcmREaWZmID0gbmV3IERpZmYoKTtcbndvcmREaWZmLmVxdWFscyA9IGZ1bmN0aW9uKGxlZnQsIHJpZ2h0KSB7XG4gIHJldHVybiBsZWZ0ID09PSByaWdodCB8fCAodGhpcy5vcHRpb25zLmlnbm9yZVdoaXRlc3BhY2UgJiYgIXJlV2hpdGVzcGFjZS50ZXN0KGxlZnQpICYmICFyZVdoaXRlc3BhY2UudGVzdChyaWdodCkpO1xufTtcbndvcmREaWZmLnRva2VuaXplID0gZnVuY3Rpb24odmFsdWUpIHtcbiAgbGV0IHRva2VucyA9IHZhbHVlLnNwbGl0KC8oXFxzK3xcXGIpLyk7XG5cbiAgLy8gSm9pbiB0aGUgYm91bmRhcnkgc3BsaXRzIHRoYXQgd2UgZG8gbm90IGNvbnNpZGVyIHRvIGJlIGJvdW5kYXJpZXMuIFRoaXMgaXMgcHJpbWFyaWx5IHRoZSBleHRlbmRlZCBMYXRpbiBjaGFyYWN0ZXIgc2V0LlxuICBmb3IgKGxldCBpID0gMDsgaSA8IHRva2Vucy5sZW5ndGggLSAxOyBpKyspIHtcbiAgICAvLyBJZiB3ZSBoYXZlIGFuIGVtcHR5IHN0cmluZyBpbiB0aGUgbmV4dCBmaWVsZCBhbmQgd2UgaGF2ZSBvbmx5IHdvcmQgY2hhcnMgYmVmb3JlIGFuZCBhZnRlciwgbWVyZ2VcbiAgICBpZiAoIXRva2Vuc1tpICsgMV0gJiYgdG9rZW5zW2kgKyAyXVxuICAgICAgICAgICYmIGV4dGVuZGVkV29yZENoYXJzLnRlc3QodG9rZW5zW2ldKVxuICAgICAgICAgICYmIGV4dGVuZGVkV29yZENoYXJzLnRlc3QodG9rZW5zW2kgKyAyXSkpIHtcbiAgICAgIHRva2Vuc1tpXSArPSB0b2tlbnNbaSArIDJdO1xuICAgICAgdG9rZW5zLnNwbGljZShpICsgMSwgMik7XG4gICAgICBpLS07XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHRva2Vucztcbn07XG5cbmV4cG9ydCBmdW5jdGlvbiBkaWZmV29yZHMob2xkU3RyLCBuZXdTdHIsIGNhbGxiYWNrKSB7XG4gIGxldCBvcHRpb25zID0gZ2VuZXJhdGVPcHRpb25zKGNhbGxiYWNrLCB7aWdub3JlV2hpdGVzcGFjZTogdHJ1ZX0pO1xuICByZXR1cm4gd29yZERpZmYuZGlmZihvbGRTdHIsIG5ld1N0ciwgb3B0aW9ucyk7XG59XG5leHBvcnQgZnVuY3Rpb24gZGlmZldvcmRzV2l0aFNwYWNlKG9sZFN0ciwgbmV3U3RyLCBjYWxsYmFjaykge1xuICByZXR1cm4gd29yZERpZmYuZGlmZihvbGRTdHIsIG5ld1N0ciwgY2FsbGJhY2spO1xufVxuIl19 -/***/ }), +/***/ }, /* 4 */ -/***/ (function(module, exports) { +/***/ function(module, exports) { /*istanbul ignore start*/'use strict'; @@ -3879,12 +3874,12 @@ return /******/ (function(modules) { // webpackBootstrap } return defaults; } - //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy91dGlsL3BhcmFtcy5qcyJdLCJuYW1lcyI6WyJnZW5lcmF0ZU9wdGlvbnMiLCJvcHRpb25zIiwiZGVmYXVsdHMiLCJjYWxsYmFjayIsIm5hbWUiLCJoYXNPd25Qcm9wZXJ0eSJdLCJtYXBwaW5ncyI6Ijs7O2dDQUFnQkEsZSxHQUFBQSxlO0FBQVQsU0FBU0EsZUFBVCxDQUF5QkMsT0FBekIsRUFBa0NDLFFBQWxDLEVBQTRDO0FBQ2pELE1BQUksT0FBT0QsT0FBUCxLQUFtQixVQUF2QixFQUFtQztBQUNqQ0MsYUFBU0MsUUFBVCxHQUFvQkYsT0FBcEI7QUFDRCxHQUZELE1BRU8sSUFBSUEsT0FBSixFQUFhO0FBQ2xCLFNBQUssSUFBSUcsSUFBVCxJQUFpQkgsT0FBakIsRUFBMEI7QUFDeEI7QUFDQSxVQUFJQSxRQUFRSSxjQUFSLENBQXVCRCxJQUF2QixDQUFKLEVBQWtDO0FBQ2hDRixpQkFBU0UsSUFBVCxJQUFpQkgsUUFBUUcsSUFBUixDQUFqQjtBQUNEO0FBQ0Y7QUFDRjtBQUNELFNBQU9GLFFBQVA7QUFDRCIsImZpbGUiOiJwYXJhbXMuanMiLCJzb3VyY2VzQ29udGVudCI6WyJleHBvcnQgZnVuY3Rpb24gZ2VuZXJhdGVPcHRpb25zKG9wdGlvbnMsIGRlZmF1bHRzKSB7XG4gIGlmICh0eXBlb2Ygb3B0aW9ucyA9PT0gJ2Z1bmN0aW9uJykge1xuICAgIGRlZmF1bHRzLmNhbGxiYWNrID0gb3B0aW9ucztcbiAgfSBlbHNlIGlmIChvcHRpb25zKSB7XG4gICAgZm9yIChsZXQgbmFtZSBpbiBvcHRpb25zKSB7XG4gICAgICAvKiBpc3RhbmJ1bCBpZ25vcmUgZWxzZSAqL1xuICAgICAgaWYgKG9wdGlvbnMuaGFzT3duUHJvcGVydHkobmFtZSkpIHtcbiAgICAgICAgZGVmYXVsdHNbbmFtZV0gPSBvcHRpb25zW25hbWVdO1xuICAgICAgfVxuICAgIH1cbiAgfVxuICByZXR1cm4gZGVmYXVsdHM7XG59XG4iXX0= + //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy91dGlsL3BhcmFtcy5qcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Z0NBQWdCLGUsR0FBQSxlO0FBQVQsU0FBUyxlQUFULENBQXlCLE9BQXpCLEVBQWtDLFFBQWxDLEVBQTRDO0FBQ2pELE1BQUksT0FBTyxPQUFQLEtBQW1CLFVBQXZCLEVBQW1DO0FBQ2pDLGFBQVMsUUFBVCxHQUFvQixPQUFwQjtBQUNELEdBRkQsTUFFTyxJQUFJLE9BQUosRUFBYTtBQUNsQixTQUFLLElBQUksSUFBVCxJQUFpQixPQUFqQixFQUEwQjs7QUFFeEIsVUFBSSxRQUFRLGNBQVIsQ0FBdUIsSUFBdkIsQ0FBSixFQUFrQztBQUNoQyxpQkFBUyxJQUFULElBQWlCLFFBQVEsSUFBUixDQUFqQjtBQUNEO0FBQ0Y7QUFDRjtBQUNELFNBQU8sUUFBUDtBQUNEIiwiZmlsZSI6InBhcmFtcy5qcyIsInNvdXJjZXNDb250ZW50IjpbImV4cG9ydCBmdW5jdGlvbiBnZW5lcmF0ZU9wdGlvbnMob3B0aW9ucywgZGVmYXVsdHMpIHtcbiAgaWYgKHR5cGVvZiBvcHRpb25zID09PSAnZnVuY3Rpb24nKSB7XG4gICAgZGVmYXVsdHMuY2FsbGJhY2sgPSBvcHRpb25zO1xuICB9IGVsc2UgaWYgKG9wdGlvbnMpIHtcbiAgICBmb3IgKGxldCBuYW1lIGluIG9wdGlvbnMpIHtcbiAgICAgIC8qIGlzdGFuYnVsIGlnbm9yZSBlbHNlICovXG4gICAgICBpZiAob3B0aW9ucy5oYXNPd25Qcm9wZXJ0eShuYW1lKSkge1xuICAgICAgICBkZWZhdWx0c1tuYW1lXSA9IG9wdGlvbnNbbmFtZV07XG4gICAgICB9XG4gICAgfVxuICB9XG4gIHJldHVybiBkZWZhdWx0cztcbn1cbiJdfQ== -/***/ }), +/***/ }, /* 5 */ -/***/ (function(module, exports, __webpack_require__) { +/***/ function(module, exports, __webpack_require__) { /*istanbul ignore start*/'use strict'; @@ -3895,13 +3890,16 @@ return /******/ (function(modules) { // webpackBootstrap var /*istanbul ignore start*/_base = __webpack_require__(1) /*istanbul ignore end*/; - /*istanbul ignore start*/var _base2 = _interopRequireDefault(_base); + /*istanbul ignore start*/ + var _base2 = _interopRequireDefault(_base); - /*istanbul ignore end*/var /*istanbul ignore start*/_params = __webpack_require__(4) /*istanbul ignore end*/; + /*istanbul ignore end*/ + var /*istanbul ignore start*/_params = __webpack_require__(4) /*istanbul ignore end*/; - /*istanbul ignore start*/function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } + /*istanbul ignore start*/ + function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } - /*istanbul ignore end*/var lineDiff = /*istanbul ignore start*/exports. /*istanbul ignore end*/lineDiff = new /*istanbul ignore start*/_base2['default'] /*istanbul ignore end*/(); + /*istanbul ignore end*/var lineDiff = /*istanbul ignore start*/exports. /*istanbul ignore end*/lineDiff = new /*istanbul ignore start*/_base2['default']() /*istanbul ignore end*/; lineDiff.tokenize = function (value) { var retLines = [], linesAndNewlines = value.split(/(\n|\r\n)/); @@ -3935,12 +3933,12 @@ return /******/ (function(modules) { // webpackBootstrap var options = /*istanbul ignore start*/(0, _params.generateOptions) /*istanbul ignore end*/(callback, { ignoreWhitespace: true }); return lineDiff.diff(oldStr, newStr, options); } - //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9kaWZmL2xpbmUuanMiXSwibmFtZXMiOlsiZGlmZkxpbmVzIiwiZGlmZlRyaW1tZWRMaW5lcyIsImxpbmVEaWZmIiwidG9rZW5pemUiLCJ2YWx1ZSIsInJldExpbmVzIiwibGluZXNBbmROZXdsaW5lcyIsInNwbGl0IiwibGVuZ3RoIiwicG9wIiwiaSIsImxpbmUiLCJvcHRpb25zIiwibmV3bGluZUlzVG9rZW4iLCJpZ25vcmVXaGl0ZXNwYWNlIiwidHJpbSIsInB1c2giLCJvbGRTdHIiLCJuZXdTdHIiLCJjYWxsYmFjayIsImRpZmYiXSwibWFwcGluZ3MiOiI7Ozs7Z0NBOEJnQkEsUyxHQUFBQSxTO3lEQUNBQyxnQixHQUFBQSxnQjs7QUEvQmhCOzs7O3VCQUNBOzs7O3VCQUVPLElBQU1DLCtFQUFXLHdFQUFqQjtBQUNQQSxTQUFTQyxRQUFULEdBQW9CLFVBQVNDLEtBQVQsRUFBZ0I7QUFDbEMsTUFBSUMsV0FBVyxFQUFmO0FBQUEsTUFDSUMsbUJBQW1CRixNQUFNRyxLQUFOLENBQVksV0FBWixDQUR2Qjs7QUFHQTtBQUNBLE1BQUksQ0FBQ0QsaUJBQWlCQSxpQkFBaUJFLE1BQWpCLEdBQTBCLENBQTNDLENBQUwsRUFBb0Q7QUFDbERGLHFCQUFpQkcsR0FBakI7QUFDRDs7QUFFRDtBQUNBLE9BQUssSUFBSUMsSUFBSSxDQUFiLEVBQWdCQSxJQUFJSixpQkFBaUJFLE1BQXJDLEVBQTZDRSxHQUE3QyxFQUFrRDtBQUNoRCxRQUFJQyxPQUFPTCxpQkFBaUJJLENBQWpCLENBQVg7O0FBRUEsUUFBSUEsSUFBSSxDQUFKLElBQVMsQ0FBQyxLQUFLRSxPQUFMLENBQWFDLGNBQTNCLEVBQTJDO0FBQ3pDUixlQUFTQSxTQUFTRyxNQUFULEdBQWtCLENBQTNCLEtBQWlDRyxJQUFqQztBQUNELEtBRkQsTUFFTztBQUNMLFVBQUksS0FBS0MsT0FBTCxDQUFhRSxnQkFBakIsRUFBbUM7QUFDakNILGVBQU9BLEtBQUtJLElBQUwsRUFBUDtBQUNEO0FBQ0RWLGVBQVNXLElBQVQsQ0FBY0wsSUFBZDtBQUNEO0FBQ0Y7O0FBRUQsU0FBT04sUUFBUDtBQUNELENBeEJEOztBQTBCTyxTQUFTTCxTQUFULENBQW1CaUIsTUFBbkIsRUFBMkJDLE1BQTNCLEVBQW1DQyxRQUFuQyxFQUE2QztBQUFFLFNBQU9qQixTQUFTa0IsSUFBVCxDQUFjSCxNQUFkLEVBQXNCQyxNQUF0QixFQUE4QkMsUUFBOUIsQ0FBUDtBQUFpRDtBQUNoRyxTQUFTbEIsZ0JBQVQsQ0FBMEJnQixNQUExQixFQUFrQ0MsTUFBbEMsRUFBMENDLFFBQTFDLEVBQW9EO0FBQ3pELE1BQUlQLFVBQVUsOEVBQWdCTyxRQUFoQixFQUEwQixFQUFDTCxrQkFBa0IsSUFBbkIsRUFBMUIsQ0FBZDtBQUNBLFNBQU9aLFNBQVNrQixJQUFULENBQWNILE1BQWQsRUFBc0JDLE1BQXRCLEVBQThCTixPQUE5QixDQUFQO0FBQ0QiLCJmaWxlIjoibGluZS5qcyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCBEaWZmIGZyb20gJy4vYmFzZSc7XG5pbXBvcnQge2dlbmVyYXRlT3B0aW9uc30gZnJvbSAnLi4vdXRpbC9wYXJhbXMnO1xuXG5leHBvcnQgY29uc3QgbGluZURpZmYgPSBuZXcgRGlmZigpO1xubGluZURpZmYudG9rZW5pemUgPSBmdW5jdGlvbih2YWx1ZSkge1xuICBsZXQgcmV0TGluZXMgPSBbXSxcbiAgICAgIGxpbmVzQW5kTmV3bGluZXMgPSB2YWx1ZS5zcGxpdCgvKFxcbnxcXHJcXG4pLyk7XG5cbiAgLy8gSWdub3JlIHRoZSBmaW5hbCBlbXB0eSB0b2tlbiB0aGF0IG9jY3VycyBpZiB0aGUgc3RyaW5nIGVuZHMgd2l0aCBhIG5ldyBsaW5lXG4gIGlmICghbGluZXNBbmROZXdsaW5lc1tsaW5lc0FuZE5ld2xpbmVzLmxlbmd0aCAtIDFdKSB7XG4gICAgbGluZXNBbmROZXdsaW5lcy5wb3AoKTtcbiAgfVxuXG4gIC8vIE1lcmdlIHRoZSBjb250ZW50IGFuZCBsaW5lIHNlcGFyYXRvcnMgaW50byBzaW5nbGUgdG9rZW5zXG4gIGZvciAobGV0IGkgPSAwOyBpIDwgbGluZXNBbmROZXdsaW5lcy5sZW5ndGg7IGkrKykge1xuICAgIGxldCBsaW5lID0gbGluZXNBbmROZXdsaW5lc1tpXTtcblxuICAgIGlmIChpICUgMiAmJiAhdGhpcy5vcHRpb25zLm5ld2xpbmVJc1Rva2VuKSB7XG4gICAgICByZXRMaW5lc1tyZXRMaW5lcy5sZW5ndGggLSAxXSArPSBsaW5lO1xuICAgIH0gZWxzZSB7XG4gICAgICBpZiAodGhpcy5vcHRpb25zLmlnbm9yZVdoaXRlc3BhY2UpIHtcbiAgICAgICAgbGluZSA9IGxpbmUudHJpbSgpO1xuICAgICAgfVxuICAgICAgcmV0TGluZXMucHVzaChsaW5lKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gcmV0TGluZXM7XG59O1xuXG5leHBvcnQgZnVuY3Rpb24gZGlmZkxpbmVzKG9sZFN0ciwgbmV3U3RyLCBjYWxsYmFjaykgeyByZXR1cm4gbGluZURpZmYuZGlmZihvbGRTdHIsIG5ld1N0ciwgY2FsbGJhY2spOyB9XG5leHBvcnQgZnVuY3Rpb24gZGlmZlRyaW1tZWRMaW5lcyhvbGRTdHIsIG5ld1N0ciwgY2FsbGJhY2spIHtcbiAgbGV0IG9wdGlvbnMgPSBnZW5lcmF0ZU9wdGlvbnMoY2FsbGJhY2ssIHtpZ25vcmVXaGl0ZXNwYWNlOiB0cnVlfSk7XG4gIHJldHVybiBsaW5lRGlmZi5kaWZmKG9sZFN0ciwgbmV3U3RyLCBvcHRpb25zKTtcbn1cbiJdfQ== + //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9kaWZmL2xpbmUuanMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7OztnQ0E4QmdCLFMsR0FBQSxTO3lEQUNBLGdCLEdBQUEsZ0I7O0FBL0JoQixJLHlCQUFBLHlCLHdCQUFBOzs7Ozs7QUFDQSxJLHlCQUFBLG1DLHdCQUFBOzs7Ozt1QkFFTyxJQUFNLFcseUJBQUEsUSx3QkFBQSxXQUFXLEkseUJBQUEsbUIsd0JBQWpCO0FBQ1AsU0FBUyxRQUFULEdBQW9CLFVBQVMsS0FBVCxFQUFnQjtBQUNsQyxNQUFJLFdBQVcsRUFBZjtBQUFBLE1BQ0ksbUJBQW1CLE1BQU0sS0FBTixDQUFZLFdBQVosQ0FEdkI7OztBQUlBLE1BQUksQ0FBQyxpQkFBaUIsaUJBQWlCLE1BQWpCLEdBQTBCLENBQTNDLENBQUwsRUFBb0Q7QUFDbEQscUJBQWlCLEdBQWpCO0FBQ0Q7OztBQUdELE9BQUssSUFBSSxJQUFJLENBQWIsRUFBZ0IsSUFBSSxpQkFBaUIsTUFBckMsRUFBNkMsR0FBN0MsRUFBa0Q7QUFDaEQsUUFBSSxPQUFPLGlCQUFpQixDQUFqQixDQUFYOztBQUVBLFFBQUksSUFBSSxDQUFKLElBQVMsQ0FBQyxLQUFLLE9BQUwsQ0FBYSxjQUEzQixFQUEyQztBQUN6QyxlQUFTLFNBQVMsTUFBVCxHQUFrQixDQUEzQixLQUFpQyxJQUFqQztBQUNELEtBRkQsTUFFTztBQUNMLFVBQUksS0FBSyxPQUFMLENBQWEsZ0JBQWpCLEVBQW1DO0FBQ2pDLGVBQU8sS0FBSyxJQUFMLEVBQVA7QUFDRDtBQUNELGVBQVMsSUFBVCxDQUFjLElBQWQ7QUFDRDtBQUNGOztBQUVELFNBQU8sUUFBUDtBQUNELENBeEJEOztBQTBCTyxTQUFTLFNBQVQsQ0FBbUIsTUFBbkIsRUFBMkIsTUFBM0IsRUFBbUMsUUFBbkMsRUFBNkM7QUFBRSxTQUFPLFNBQVMsSUFBVCxDQUFjLE1BQWQsRUFBc0IsTUFBdEIsRUFBOEIsUUFBOUIsQ0FBUDtBQUFpRDtBQUNoRyxTQUFTLGdCQUFULENBQTBCLE1BQTFCLEVBQWtDLE1BQWxDLEVBQTBDLFFBQTFDLEVBQW9EO0FBQ3pELE1BQUksVSx5QkFBVSw0Qix3QkFBQSxDQUFnQixRQUFoQixFQUEwQixFQUFDLGtCQUFrQixJQUFuQixFQUExQixDQUFkO0FBQ0EsU0FBTyxTQUFTLElBQVQsQ0FBYyxNQUFkLEVBQXNCLE1BQXRCLEVBQThCLE9BQTlCLENBQVA7QUFDRCIsImZpbGUiOiJsaW5lLmpzIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IERpZmYgZnJvbSAnLi9iYXNlJztcbmltcG9ydCB7Z2VuZXJhdGVPcHRpb25zfSBmcm9tICcuLi91dGlsL3BhcmFtcyc7XG5cbmV4cG9ydCBjb25zdCBsaW5lRGlmZiA9IG5ldyBEaWZmKCk7XG5saW5lRGlmZi50b2tlbml6ZSA9IGZ1bmN0aW9uKHZhbHVlKSB7XG4gIGxldCByZXRMaW5lcyA9IFtdLFxuICAgICAgbGluZXNBbmROZXdsaW5lcyA9IHZhbHVlLnNwbGl0KC8oXFxufFxcclxcbikvKTtcblxuICAvLyBJZ25vcmUgdGhlIGZpbmFsIGVtcHR5IHRva2VuIHRoYXQgb2NjdXJzIGlmIHRoZSBzdHJpbmcgZW5kcyB3aXRoIGEgbmV3IGxpbmVcbiAgaWYgKCFsaW5lc0FuZE5ld2xpbmVzW2xpbmVzQW5kTmV3bGluZXMubGVuZ3RoIC0gMV0pIHtcbiAgICBsaW5lc0FuZE5ld2xpbmVzLnBvcCgpO1xuICB9XG5cbiAgLy8gTWVyZ2UgdGhlIGNvbnRlbnQgYW5kIGxpbmUgc2VwYXJhdG9ycyBpbnRvIHNpbmdsZSB0b2tlbnNcbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBsaW5lc0FuZE5ld2xpbmVzLmxlbmd0aDsgaSsrKSB7XG4gICAgbGV0IGxpbmUgPSBsaW5lc0FuZE5ld2xpbmVzW2ldO1xuXG4gICAgaWYgKGkgJSAyICYmICF0aGlzLm9wdGlvbnMubmV3bGluZUlzVG9rZW4pIHtcbiAgICAgIHJldExpbmVzW3JldExpbmVzLmxlbmd0aCAtIDFdICs9IGxpbmU7XG4gICAgfSBlbHNlIHtcbiAgICAgIGlmICh0aGlzLm9wdGlvbnMuaWdub3JlV2hpdGVzcGFjZSkge1xuICAgICAgICBsaW5lID0gbGluZS50cmltKCk7XG4gICAgICB9XG4gICAgICByZXRMaW5lcy5wdXNoKGxpbmUpO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiByZXRMaW5lcztcbn07XG5cbmV4cG9ydCBmdW5jdGlvbiBkaWZmTGluZXMob2xkU3RyLCBuZXdTdHIsIGNhbGxiYWNrKSB7IHJldHVybiBsaW5lRGlmZi5kaWZmKG9sZFN0ciwgbmV3U3RyLCBjYWxsYmFjayk7IH1cbmV4cG9ydCBmdW5jdGlvbiBkaWZmVHJpbW1lZExpbmVzKG9sZFN0ciwgbmV3U3RyLCBjYWxsYmFjaykge1xuICBsZXQgb3B0aW9ucyA9IGdlbmVyYXRlT3B0aW9ucyhjYWxsYmFjaywge2lnbm9yZVdoaXRlc3BhY2U6IHRydWV9KTtcbiAgcmV0dXJuIGxpbmVEaWZmLmRpZmYob2xkU3RyLCBuZXdTdHIsIG9wdGlvbnMpO1xufVxuIl19 -/***/ }), +/***/ }, /* 6 */ -/***/ (function(module, exports, __webpack_require__) { +/***/ function(module, exports, __webpack_require__) { /*istanbul ignore start*/'use strict'; @@ -3950,11 +3948,12 @@ return /******/ (function(modules) { // webpackBootstrap var /*istanbul ignore start*/_base = __webpack_require__(1) /*istanbul ignore end*/; - /*istanbul ignore start*/var _base2 = _interopRequireDefault(_base); + /*istanbul ignore start*/ + var _base2 = _interopRequireDefault(_base); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } - /*istanbul ignore end*/var sentenceDiff = /*istanbul ignore start*/exports. /*istanbul ignore end*/sentenceDiff = new /*istanbul ignore start*/_base2['default'] /*istanbul ignore end*/(); + /*istanbul ignore end*/var sentenceDiff = /*istanbul ignore start*/exports. /*istanbul ignore end*/sentenceDiff = new /*istanbul ignore start*/_base2['default']() /*istanbul ignore end*/; sentenceDiff.tokenize = function (value) { return value.split(/(\S.+?[.!?])(?=\s+|$)/); }; @@ -3962,12 +3961,12 @@ return /******/ (function(modules) { // webpackBootstrap function diffSentences(oldStr, newStr, callback) { return sentenceDiff.diff(oldStr, newStr, callback); } - //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9kaWZmL3NlbnRlbmNlLmpzIl0sIm5hbWVzIjpbImRpZmZTZW50ZW5jZXMiLCJzZW50ZW5jZURpZmYiLCJ0b2tlbml6ZSIsInZhbHVlIiwic3BsaXQiLCJvbGRTdHIiLCJuZXdTdHIiLCJjYWxsYmFjayIsImRpZmYiXSwibWFwcGluZ3MiOiI7Ozs7Z0NBUWdCQSxhLEdBQUFBLGE7O0FBUmhCOzs7Ozs7dUJBR08sSUFBTUMsdUZBQWUsd0VBQXJCO0FBQ1BBLGFBQWFDLFFBQWIsR0FBd0IsVUFBU0MsS0FBVCxFQUFnQjtBQUN0QyxTQUFPQSxNQUFNQyxLQUFOLENBQVksdUJBQVosQ0FBUDtBQUNELENBRkQ7O0FBSU8sU0FBU0osYUFBVCxDQUF1QkssTUFBdkIsRUFBK0JDLE1BQS9CLEVBQXVDQyxRQUF2QyxFQUFpRDtBQUFFLFNBQU9OLGFBQWFPLElBQWIsQ0FBa0JILE1BQWxCLEVBQTBCQyxNQUExQixFQUFrQ0MsUUFBbEMsQ0FBUDtBQUFxRCIsImZpbGUiOiJzZW50ZW5jZS5qcyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCBEaWZmIGZyb20gJy4vYmFzZSc7XG5cblxuZXhwb3J0IGNvbnN0IHNlbnRlbmNlRGlmZiA9IG5ldyBEaWZmKCk7XG5zZW50ZW5jZURpZmYudG9rZW5pemUgPSBmdW5jdGlvbih2YWx1ZSkge1xuICByZXR1cm4gdmFsdWUuc3BsaXQoLyhcXFMuKz9bLiE/XSkoPz1cXHMrfCQpLyk7XG59O1xuXG5leHBvcnQgZnVuY3Rpb24gZGlmZlNlbnRlbmNlcyhvbGRTdHIsIG5ld1N0ciwgY2FsbGJhY2spIHsgcmV0dXJuIHNlbnRlbmNlRGlmZi5kaWZmKG9sZFN0ciwgbmV3U3RyLCBjYWxsYmFjayk7IH1cbiJdfQ== + //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9kaWZmL3NlbnRlbmNlLmpzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Z0NBUWdCLGEsR0FBQSxhOztBQVJoQixJLHlCQUFBLHlCLHdCQUFBOzs7Ozs7O3VCQUdPLElBQU0sZSx5QkFBQSxRLHdCQUFBLGVBQWUsSSx5QkFBQSxtQix3QkFBckI7QUFDUCxhQUFhLFFBQWIsR0FBd0IsVUFBUyxLQUFULEVBQWdCO0FBQ3RDLFNBQU8sTUFBTSxLQUFOLENBQVksdUJBQVosQ0FBUDtBQUNELENBRkQ7O0FBSU8sU0FBUyxhQUFULENBQXVCLE1BQXZCLEVBQStCLE1BQS9CLEVBQXVDLFFBQXZDLEVBQWlEO0FBQUUsU0FBTyxhQUFhLElBQWIsQ0FBa0IsTUFBbEIsRUFBMEIsTUFBMUIsRUFBa0MsUUFBbEMsQ0FBUDtBQUFxRCIsImZpbGUiOiJzZW50ZW5jZS5qcyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCBEaWZmIGZyb20gJy4vYmFzZSc7XG5cblxuZXhwb3J0IGNvbnN0IHNlbnRlbmNlRGlmZiA9IG5ldyBEaWZmKCk7XG5zZW50ZW5jZURpZmYudG9rZW5pemUgPSBmdW5jdGlvbih2YWx1ZSkge1xuICByZXR1cm4gdmFsdWUuc3BsaXQoLyhcXFMuKz9bLiE/XSkoPz1cXHMrfCQpLyk7XG59O1xuXG5leHBvcnQgZnVuY3Rpb24gZGlmZlNlbnRlbmNlcyhvbGRTdHIsIG5ld1N0ciwgY2FsbGJhY2spIHsgcmV0dXJuIHNlbnRlbmNlRGlmZi5kaWZmKG9sZFN0ciwgbmV3U3RyLCBjYWxsYmFjayk7IH1cbiJdfQ== -/***/ }), +/***/ }, /* 7 */ -/***/ (function(module, exports, __webpack_require__) { +/***/ function(module, exports, __webpack_require__) { /*istanbul ignore start*/'use strict'; @@ -3977,11 +3976,12 @@ return /******/ (function(modules) { // webpackBootstrap var /*istanbul ignore start*/_base = __webpack_require__(1) /*istanbul ignore end*/; - /*istanbul ignore start*/var _base2 = _interopRequireDefault(_base); + /*istanbul ignore start*/ + var _base2 = _interopRequireDefault(_base); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } - /*istanbul ignore end*/var cssDiff = /*istanbul ignore start*/exports. /*istanbul ignore end*/cssDiff = new /*istanbul ignore start*/_base2['default'] /*istanbul ignore end*/(); + /*istanbul ignore end*/var cssDiff = /*istanbul ignore start*/exports. /*istanbul ignore end*/cssDiff = new /*istanbul ignore start*/_base2['default']() /*istanbul ignore end*/; cssDiff.tokenize = function (value) { return value.split(/([{}:;,]|\s+)/); }; @@ -3989,39 +3989,44 @@ return /******/ (function(modules) { // webpackBootstrap function diffCss(oldStr, newStr, callback) { return cssDiff.diff(oldStr, newStr, callback); } - //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9kaWZmL2Nzcy5qcyJdLCJuYW1lcyI6WyJkaWZmQ3NzIiwiY3NzRGlmZiIsInRva2VuaXplIiwidmFsdWUiLCJzcGxpdCIsIm9sZFN0ciIsIm5ld1N0ciIsImNhbGxiYWNrIiwiZGlmZiJdLCJtYXBwaW5ncyI6Ijs7OztnQ0FPZ0JBLE8sR0FBQUEsTzs7QUFQaEI7Ozs7Ozt1QkFFTyxJQUFNQyw2RUFBVSx3RUFBaEI7QUFDUEEsUUFBUUMsUUFBUixHQUFtQixVQUFTQyxLQUFULEVBQWdCO0FBQ2pDLFNBQU9BLE1BQU1DLEtBQU4sQ0FBWSxlQUFaLENBQVA7QUFDRCxDQUZEOztBQUlPLFNBQVNKLE9BQVQsQ0FBaUJLLE1BQWpCLEVBQXlCQyxNQUF6QixFQUFpQ0MsUUFBakMsRUFBMkM7QUFBRSxTQUFPTixRQUFRTyxJQUFSLENBQWFILE1BQWIsRUFBcUJDLE1BQXJCLEVBQTZCQyxRQUE3QixDQUFQO0FBQWdEIiwiZmlsZSI6ImNzcy5qcyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCBEaWZmIGZyb20gJy4vYmFzZSc7XG5cbmV4cG9ydCBjb25zdCBjc3NEaWZmID0gbmV3IERpZmYoKTtcbmNzc0RpZmYudG9rZW5pemUgPSBmdW5jdGlvbih2YWx1ZSkge1xuICByZXR1cm4gdmFsdWUuc3BsaXQoLyhbe306OyxdfFxccyspLyk7XG59O1xuXG5leHBvcnQgZnVuY3Rpb24gZGlmZkNzcyhvbGRTdHIsIG5ld1N0ciwgY2FsbGJhY2spIHsgcmV0dXJuIGNzc0RpZmYuZGlmZihvbGRTdHIsIG5ld1N0ciwgY2FsbGJhY2spOyB9XG4iXX0= + //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9kaWZmL2Nzcy5qcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7O2dDQU9nQixPLEdBQUEsTzs7QUFQaEIsSSx5QkFBQSx5Qix3QkFBQTs7Ozs7Ozt1QkFFTyxJQUFNLFUseUJBQUEsUSx3QkFBQSxVQUFVLEkseUJBQUEsbUIsd0JBQWhCO0FBQ1AsUUFBUSxRQUFSLEdBQW1CLFVBQVMsS0FBVCxFQUFnQjtBQUNqQyxTQUFPLE1BQU0sS0FBTixDQUFZLGVBQVosQ0FBUDtBQUNELENBRkQ7O0FBSU8sU0FBUyxPQUFULENBQWlCLE1BQWpCLEVBQXlCLE1BQXpCLEVBQWlDLFFBQWpDLEVBQTJDO0FBQUUsU0FBTyxRQUFRLElBQVIsQ0FBYSxNQUFiLEVBQXFCLE1BQXJCLEVBQTZCLFFBQTdCLENBQVA7QUFBZ0QiLCJmaWxlIjoiY3NzLmpzIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IERpZmYgZnJvbSAnLi9iYXNlJztcblxuZXhwb3J0IGNvbnN0IGNzc0RpZmYgPSBuZXcgRGlmZigpO1xuY3NzRGlmZi50b2tlbml6ZSA9IGZ1bmN0aW9uKHZhbHVlKSB7XG4gIHJldHVybiB2YWx1ZS5zcGxpdCgvKFt7fTo7LF18XFxzKykvKTtcbn07XG5cbmV4cG9ydCBmdW5jdGlvbiBkaWZmQ3NzKG9sZFN0ciwgbmV3U3RyLCBjYWxsYmFjaykgeyByZXR1cm4gY3NzRGlmZi5kaWZmKG9sZFN0ciwgbmV3U3RyLCBjYWxsYmFjayk7IH1cbiJdfQ== -/***/ }), +/***/ }, /* 8 */ -/***/ (function(module, exports, __webpack_require__) { +/***/ function(module, exports, __webpack_require__) { /*istanbul ignore start*/'use strict'; exports.__esModule = true; exports.jsonDiff = undefined; - var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; + var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol ? "symbol" : typeof obj; }; exports. /*istanbul ignore end*/diffJson = diffJson; /*istanbul ignore start*/exports. /*istanbul ignore end*/canonicalize = canonicalize; var /*istanbul ignore start*/_base = __webpack_require__(1) /*istanbul ignore end*/; - /*istanbul ignore start*/var _base2 = _interopRequireDefault(_base); + /*istanbul ignore start*/ + var _base2 = _interopRequireDefault(_base); - /*istanbul ignore end*/var /*istanbul ignore start*/_line = __webpack_require__(5) /*istanbul ignore end*/; + /*istanbul ignore end*/ + var /*istanbul ignore start*/_line = __webpack_require__(5) /*istanbul ignore end*/; + + /*istanbul ignore start*/ + function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } - /*istanbul ignore start*/function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } + /*istanbul ignore end*/ - /*istanbul ignore end*/var objectPrototypeToString = Object.prototype.toString; + var objectPrototypeToString = Object.prototype.toString; - var jsonDiff = /*istanbul ignore start*/exports. /*istanbul ignore end*/jsonDiff = new /*istanbul ignore start*/_base2['default'] /*istanbul ignore end*/(); + var jsonDiff = /*istanbul ignore start*/exports. /*istanbul ignore end*/jsonDiff = new /*istanbul ignore start*/_base2['default']() /*istanbul ignore end*/; // Discriminate between two lines of pretty-printed, serialized JSON where one of them has a // dangling comma and the other doesn't. Turns out including the dangling comma yields the nicest output: jsonDiff.useLongestToken = true; - jsonDiff.tokenize = /*istanbul ignore start*/_line.lineDiff /*istanbul ignore end*/.tokenize; + jsonDiff.tokenize = /*istanbul ignore start*/_line.lineDiff. /*istanbul ignore end*/tokenize; jsonDiff.castInput = function (value) { /*istanbul ignore start*/var /*istanbul ignore end*/undefinedReplacement = this.options.undefinedReplacement; @@ -4035,7 +4040,7 @@ return /******/ (function(modules) { // webpackBootstrap }, ' '); }; jsonDiff.equals = function (left, right) { - return (/*istanbul ignore start*/_base2['default'] /*istanbul ignore end*/.prototype.equals.call(jsonDiff, left.replace(/,([\r\n])/g, '$1'), right.replace(/,([\r\n])/g, '$1')) + return (/*istanbul ignore start*/_base2['default']. /*istanbul ignore end*/prototype.equals(left.replace(/,([\r\n])/g, '$1'), right.replace(/,([\r\n])/g, '$1')) ); }; @@ -4099,12 +4104,12 @@ return /******/ (function(modules) { // webpackBootstrap } return canonicalizedObj; } - //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9kaWZmL2pzb24uanMiXSwibmFtZXMiOlsiZGlmZkpzb24iLCJjYW5vbmljYWxpemUiLCJvYmplY3RQcm90b3R5cGVUb1N0cmluZyIsIk9iamVjdCIsInByb3RvdHlwZSIsInRvU3RyaW5nIiwianNvbkRpZmYiLCJ1c2VMb25nZXN0VG9rZW4iLCJ0b2tlbml6ZSIsImNhc3RJbnB1dCIsInZhbHVlIiwidW5kZWZpbmVkUmVwbGFjZW1lbnQiLCJvcHRpb25zIiwiSlNPTiIsInN0cmluZ2lmeSIsImsiLCJ2IiwiZXF1YWxzIiwibGVmdCIsInJpZ2h0IiwiY2FsbCIsInJlcGxhY2UiLCJvbGRPYmoiLCJuZXdPYmoiLCJkaWZmIiwib2JqIiwic3RhY2siLCJyZXBsYWNlbWVudFN0YWNrIiwiaSIsImxlbmd0aCIsImNhbm9uaWNhbGl6ZWRPYmoiLCJwdXNoIiwiQXJyYXkiLCJwb3AiLCJ0b0pTT04iLCJzb3J0ZWRLZXlzIiwia2V5IiwiaGFzT3duUHJvcGVydHkiLCJzb3J0Il0sIm1hcHBpbmdzIjoiOzs7Ozs7O2dDQTJCZ0JBLFEsR0FBQUEsUTt5REFJQUMsWSxHQUFBQSxZOztBQS9CaEI7Ozs7dUJBQ0E7Ozs7dUJBRUEsSUFBTUMsMEJBQTBCQyxPQUFPQyxTQUFQLENBQWlCQyxRQUFqRDs7QUFHTyxJQUFNQywrRUFBVyx3RUFBakI7QUFDUDtBQUNBO0FBQ0FBLFNBQVNDLGVBQVQsR0FBMkIsSUFBM0I7O0FBRUFELFNBQVNFLFFBQVQsR0FBb0IsZ0VBQVNBLFFBQTdCO0FBQ0FGLFNBQVNHLFNBQVQsR0FBcUIsVUFBU0MsS0FBVCxFQUFnQjtBQUFBLHNEQUM1QkMsb0JBRDRCLEdBQ0osS0FBS0MsT0FERCxDQUM1QkQsb0JBRDRCOzs7QUFHbkMsU0FBTyxPQUFPRCxLQUFQLEtBQWlCLFFBQWpCLEdBQTRCQSxLQUE1QixHQUFvQ0csS0FBS0MsU0FBTCxDQUFlYixhQUFhUyxLQUFiLENBQWYsRUFBb0MsVUFBU0ssQ0FBVCxFQUFZQyxDQUFaLEVBQWU7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QUNELEdBbkJELE1BbUJPO0FBQ0xILHVCQUFtQkwsR0FBbkI7QUFDRDtBQUNELFNBQU9LLGdCQUFQO0FBQ0QiLCJmaWxlIjoianNvbi5qcyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCBEaWZmIGZyb20gJy4vYmFzZSc7XG5pbXBvcnQge2xpbmVEaWZmfSBmcm9tICcuL2xpbmUnO1xuXG5jb25zdCBvYmplY3RQcm90b3R5cGVUb1N0cmluZyA9IE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmc7XG5cblxuZXhwb3J0IGNvbnN0IGpzb25EaWZmID0gbmV3IERpZmYoKTtcbi8vIERpc2NyaW1pbmF0ZSBiZXR3ZWVuIHR3byBsaW5lcyBvZiBwcmV0dHktcHJpbnRlZCwgc2VyaWFsaXplZCBKU09OIHdoZXJlIG9uZSBvZiB0aGVtIGhhcyBhXG4vLyBkYW5nbGluZyBjb21tYSBhbmQgdGhlIG90aGVyIGRvZXNuJ3QuIFR1cm5zIG91dCBpbmNsdWRpbmcgdGhlIGRhbmdsaW5nIGNvbW1hIHlpZWxkcyB0aGUgbmljZXN0IG91dHB1dDpcbmpzb25EaWZmLnVzZUxvbmdlc3RUb2tlbiA9IHRydWU7XG5cbmpzb25EaWZmLnRva2VuaXplID0gbGluZURpZmYudG9rZW5pemU7XG5qc29uRGlmZi5jYXN0SW5wdXQgPSBmdW5jdGlvbih2YWx1ZSkge1xuICBjb25zdCB7dW5kZWZpbmVkUmVwbGFjZW1lbnR9ID0gdGhpcy5vcHRpb25zO1xuXG4gIHJldHVybiB0eXBlb2YgdmFsdWUgPT09ICdzdHJpbmcnID8gdmFsdWUgOiBKU09OLnN0cmluZ2lmeShjYW5vbmljYWxpemUodmFsdWUpLCBmdW5jdGlvbihrLCB2KSB7XG4gICAgaWYgKHR5cGVvZiB2ID09PSAndW5kZWZpbmVkJykge1xuICAgICAgcmV0dXJuIHVuZGVmaW5lZFJlcGxhY2VtZW50O1xuICAgIH1cblxuICAgIHJldHVybiB2O1xuICB9LCAnICAnKTtcbn07XG5qc29uRGlmZi5lcXVhbHMgPSBmdW5jdGlvbihsZWZ0LCByaWdodCkge1xuICByZXR1cm4gRGlmZi5wcm90b3R5cGUuZXF1YWxzLmNhbGwoanNvbkRpZmYsIGxlZnQucmVwbGFjZSgvLChbXFxyXFxuXSkvZywgJyQxJyksIHJpZ2h0LnJlcGxhY2UoLywoW1xcclxcbl0pL2csICckMScpKTtcbn07XG5cbmV4cG9ydCBmdW5jdGlvbiBkaWZmSnNvbihvbGRPYmosIG5ld09iaiwgb3B0aW9ucykgeyByZXR1cm4ganNvbkRpZmYuZGlmZihvbGRPYmosIG5ld09iaiwgb3B0aW9ucyk7IH1cblxuLy8gVGhpcyBmdW5jdGlvbiBoYW5kbGVzIHRoZSBwcmVzZW5jZSBvZiBjaXJjdWxhciByZWZlcmVuY2VzIGJ5IGJhaWxpbmcgb3V0IHdoZW4gZW5jb3VudGVyaW5nIGFuXG4vLyBvYmplY3QgdGhhdCBpcyBhbHJlYWR5IG9uIHRoZSBcInN0YWNrXCIgb2YgaXRlbXMgYmVpbmcgcHJvY2Vzc2VkLlxuZXhwb3J0IGZ1bmN0aW9uIGNhbm9uaWNhbGl6ZShvYmosIHN0YWNrLCByZXBsYWNlbWVudFN0YWNrKSB7XG4gIHN0YWNrID0gc3RhY2sgfHwgW107XG4gIHJlcGxhY2VtZW50U3RhY2sgPSByZXBsYWNlbWVudFN0YWNrIHx8IFtdO1xuXG4gIGxldCBpO1xuXG4gIGZvciAoaSA9IDA7IGkgPCBzdGFjay5sZW5ndGg7IGkgKz0gMSkge1xuICAgIGlmIChzdGFja1tpXSA9PT0gb2JqKSB7XG4gICAgICByZXR1cm4gcmVwbGFjZW1lbnRTdGFja1tpXTtcbiAgICB9XG4gIH1cblxuICBsZXQgY2Fub25pY2FsaXplZE9iajtcblxuICBpZiAoJ1tvYmplY3QgQXJyYXldJyA9PT0gb2JqZWN0UHJvdG90eXBlVG9TdHJpbmcuY2FsbChvYmopKSB7XG4gICAgc3RhY2sucHVzaChvYmopO1xuICAgIGNhbm9uaWNhbGl6ZWRPYmogPSBuZXcgQXJyYXkob2JqLmxlbmd0aCk7XG4gICAgcmVwbGFjZW1lbnRTdGFjay5wdXNoKGNhbm9uaWNhbGl6ZWRPYmopO1xuICAgIGZvciAoaSA9IDA7IGkgPCBvYmoubGVuZ3RoOyBpICs9IDEpIHtcbiAgICAgIGNhbm9uaWNhbGl6ZWRPYmpbaV0gPSBjYW5vbmljYWxpemUob2JqW2ldLCBzdGFjaywgcmVwbGFjZW1lbnRTdGFjayk7XG4gICAgfVxuICAgIHN0YWNrLnBvcCgpO1xuICAgIHJlcGxhY2VtZW50U3RhY2sucG9wKCk7XG4gICAgcmV0dXJuIGNhbm9uaWNhbGl6ZWRPYmo7XG4gIH1cblxuICBpZiAob2JqICYmIG9iai50b0pTT04pIHtcbiAgICBvYmogPSBvYmoudG9KU09OKCk7XG4gIH1cblxuICBpZiAodHlwZW9mIG9iaiA9PT0gJ29iamVjdCcgJiYgb2JqICE9PSBudWxsKSB7XG4gICAgc3RhY2sucHVzaChvYmopO1xuICAgIGNhbm9uaWNhbGl6ZWRPYmogPSB7fTtcbiAgICByZXBsYWNlbWVudFN0YWNrLnB1c2goY2Fub25pY2FsaXplZE9iaik7XG4gICAgbGV0IHNvcnRlZEtleXMgPSBbXSxcbiAgICAgICAga2V5O1xuICAgIGZvciAoa2V5IGluIG9iaikge1xuICAgICAgLyogaXN0YW5idWwgaWdub3JlIGVsc2UgKi9cbiAgICAgIGlmIChvYmouaGFzT3duUHJvcGVydHkoa2V5KSkge1xuICAgICAgICBzb3J0ZWRLZXlzLnB1c2goa2V5KTtcbiAgICAgIH1cbiAgICB9XG4gICAgc29ydGVkS2V5cy5zb3J0KCk7XG4gICAgZm9yIChpID0gMDsgaSA8IHNvcnRlZEtleXMubGVuZ3RoOyBpICs9IDEpIHtcbiAgICAgIGtleSA9IHNvcnRlZEtleXNbaV07XG4gICAgICBjYW5vbmljYWxpemVkT2JqW2tleV0gPSBjYW5vbmljYWxpemUob2JqW2tleV0sIHN0YWNrLCByZXBsYWNlbWVudFN0YWNrKTtcbiAgICB9XG4gICAgc3RhY2sucG9wKCk7XG4gICAgcmVwbGFjZW1lbnRTdGFjay5wb3AoKTtcbiAgfSBlbHNlIHtcbiAgICBjYW5vbmljYWxpemVkT2JqID0gb2JqO1xuICB9XG4gIHJldHVybiBjYW5vbmljYWxpemVkT2JqO1xufVxuIl19 + //# sourceMappingURL=data:application/json;base64,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QWlCLElBQWpCLENBQXNCLGdCQUF0QjtBQUNBLFFBQUksYUFBYSxFQUFqQjtBQUFBLFFBQ0ksTSx5QkFBQSxNLHdCQURKO0FBRUEsU0FBSyxHQUFMLElBQVksR0FBWixFQUFpQjs7QUFFZixVQUFJLElBQUksY0FBSixDQUFtQixHQUFuQixDQUFKLEVBQTZCO0FBQzNCLG1CQUFXLElBQVgsQ0FBZ0IsR0FBaEI7QUFDRDtBQUNGO0FBQ0QsZUFBVyxJQUFYO0FBQ0EsU0FBSyxJQUFJLENBQVQsRUFBWSxJQUFJLFdBQVcsTUFBM0IsRUFBbUMsS0FBSyxDQUF4QyxFQUEyQztBQUN6QyxZQUFNLFdBQVcsQ0FBWCxDQUFOO0FBQ0EsdUJBQWlCLEdBQWpCLElBQXdCLGFBQWEsSUFBSSxHQUFKLENBQWIsRUFBdUIsS0FBdkIsRUFBOEIsZ0JBQTlCLENBQXhCO0FBQ0Q7QUFDRCxVQUFNLEdBQU47QUFDQSxxQkFBaUIsR0FBakI7QUFDRCxHQW5CRCxNQW1CTztBQUNMLHVCQUFtQixHQUFuQjtBQUNEO0FBQ0QsU0FBTyxnQkFBUDtBQUNEIiwiZmlsZSI6Impzb24uanMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgRGlmZiBmcm9tICcuL2Jhc2UnO1xuaW1wb3J0IHtsaW5lRGlmZn0gZnJvbSAnLi9saW5lJztcblxuY29uc3Qgb2JqZWN0UHJvdG90eXBlVG9TdHJpbmcgPSBPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nO1xuXG5cbmV4cG9ydCBjb25zdCBqc29uRGlmZiA9IG5ldyBEaWZmKCk7XG4vLyBEaXNjcmltaW5hdGUgYmV0d2VlbiB0d28gbGluZXMgb2YgcHJldHR5LXByaW50ZWQsIHNlcmlhbGl6ZWQgSlNPTiB3aGVyZSBvbmUgb2YgdGhlbSBoYXMgYVxuLy8gZGFuZ2xpbmcgY29tbWEgYW5kIHRoZSBvdGhlciBkb2Vzbid0LiBUdXJucyBvdXQgaW5jbHVkaW5nIHRoZSBkYW5nbGluZyBjb21tYSB5aWVsZHMgdGhlIG5pY2VzdCBvdXRwdXQ6XG5qc29uRGlmZi51c2VMb25nZXN0VG9rZW4gPSB0cnVlO1xuXG5qc29uRGlmZi50b2tlbml6ZSA9IGxpbmVEaWZmLnRva2VuaXplO1xuanNvbkRpZmYuY2FzdElucHV0ID0gZnVuY3Rpb24odmFsdWUpIHtcbiAgY29uc3Qge3VuZGVmaW5lZFJlcGxhY2VtZW50fSA9IHRoaXMub3B0aW9ucztcblxuICByZXR1cm4gdHlwZW9mIHZhbHVlID09PSAnc3RyaW5nJyA/IHZhbHVlIDogSlNPTi5zdHJpbmdpZnkoY2Fub25pY2FsaXplKHZhbHVlKSwgZnVuY3Rpb24oaywgdikge1xuICAgIGlmICh0eXBlb2YgdiA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgIHJldHVybiB1bmRlZmluZWRSZXBsYWNlbWVudDtcbiAgICB9XG5cbiAgICByZXR1cm4gdjtcbiAgfSwgJyAgJyk7XG59O1xuanNvbkRpZmYuZXF1YWxzID0gZnVuY3Rpb24obGVmdCwgcmlnaHQpIHtcbiAgcmV0dXJuIERpZmYucHJvdG90eXBlLmVxdWFscyhsZWZ0LnJlcGxhY2UoLywoW1xcclxcbl0pL2csICckMScpLCByaWdodC5yZXBsYWNlKC8sKFtcXHJcXG5dKS9nLCAnJDEnKSk7XG59O1xuXG5leHBvcnQgZnVuY3Rpb24gZGlmZkpzb24ob2xkT2JqLCBuZXdPYmosIG9wdGlvbnMpIHsgcmV0dXJuIGpzb25EaWZmLmRpZmYob2xkT2JqLCBuZXdPYmosIG9wdGlvbnMpOyB9XG5cbi8vIFRoaXMgZnVuY3Rpb24gaGFuZGxlcyB0aGUgcHJlc2VuY2Ugb2YgY2lyY3VsYXIgcmVmZXJlbmNlcyBieSBiYWlsaW5nIG91dCB3aGVuIGVuY291bnRlcmluZyBhblxuLy8gb2JqZWN0IHRoYXQgaXMgYWxyZWFkeSBvbiB0aGUgXCJzdGFja1wiIG9mIGl0ZW1zIGJlaW5nIHByb2Nlc3NlZC5cbmV4cG9ydCBmdW5jdGlvbiBjYW5vbmljYWxpemUob2JqLCBzdGFjaywgcmVwbGFjZW1lbnRTdGFjaykge1xuICBzdGFjayA9IHN0YWNrIHx8IFtdO1xuICByZXBsYWNlbWVudFN0YWNrID0gcmVwbGFjZW1lbnRTdGFjayB8fCBbXTtcblxuICBsZXQgaTtcblxuICBmb3IgKGkgPSAwOyBpIDwgc3RhY2subGVuZ3RoOyBpICs9IDEpIHtcbiAgICBpZiAoc3RhY2tbaV0gPT09IG9iaikge1xuICAgICAgcmV0dXJuIHJlcGxhY2VtZW50U3RhY2tbaV07XG4gICAgfVxuICB9XG5cbiAgbGV0IGNhbm9uaWNhbGl6ZWRPYmo7XG5cbiAgaWYgKCdbb2JqZWN0IEFycmF5XScgPT09IG9iamVjdFByb3RvdHlwZVRvU3RyaW5nLmNhbGwob2JqKSkge1xuICAgIHN0YWNrLnB1c2gob2JqKTtcbiAgICBjYW5vbmljYWxpemVkT2JqID0gbmV3IEFycmF5KG9iai5sZW5ndGgpO1xuICAgIHJlcGxhY2VtZW50U3RhY2sucHVzaChjYW5vbmljYWxpemVkT2JqKTtcbiAgICBmb3IgKGkgPSAwOyBpIDwgb2JqLmxlbmd0aDsgaSArPSAxKSB7XG4gICAgICBjYW5vbmljYWxpemVkT2JqW2ldID0gY2Fub25pY2FsaXplKG9ialtpXSwgc3RhY2ssIHJlcGxhY2VtZW50U3RhY2spO1xuICAgIH1cbiAgICBzdGFjay5wb3AoKTtcbiAgICByZXBsYWNlbWVudFN0YWNrLnBvcCgpO1xuICAgIHJldHVybiBjYW5vbmljYWxpemVkT2JqO1xuICB9XG5cbiAgaWYgKG9iaiAmJiBvYmoudG9KU09OKSB7XG4gICAgb2JqID0gb2JqLnRvSlNPTigpO1xuICB9XG5cbiAgaWYgKHR5cGVvZiBvYmogPT09ICdvYmplY3QnICYmIG9iaiAhPT0gbnVsbCkge1xuICAgIHN0YWNrLnB1c2gob2JqKTtcbiAgICBjYW5vbmljYWxpemVkT2JqID0ge307XG4gICAgcmVwbGFjZW1lbnRTdGFjay5wdXNoKGNhbm9uaWNhbGl6ZWRPYmopO1xuICAgIGxldCBzb3J0ZWRLZXlzID0gW10sXG4gICAgICAgIGtleTtcbiAgICBmb3IgKGtleSBpbiBvYmopIHtcbiAgICAgIC8qIGlzdGFuYnVsIGlnbm9yZSBlbHNlICovXG4gICAgICBpZiAob2JqLmhhc093blByb3BlcnR5KGtleSkpIHtcbiAgICAgICAgc29ydGVkS2V5cy5wdXNoKGtleSk7XG4gICAgICB9XG4gICAgfVxuICAgIHNvcnRlZEtleXMuc29ydCgpO1xuICAgIGZvciAoaSA9IDA7IGkgPCBzb3J0ZWRLZXlzLmxlbmd0aDsgaSArPSAxKSB7XG4gICAgICBrZXkgPSBzb3J0ZWRLZXlzW2ldO1xuICAgICAgY2Fub25pY2FsaXplZE9ialtrZXldID0gY2Fub25pY2FsaXplKG9ialtrZXldLCBzdGFjaywgcmVwbGFjZW1lbnRTdGFjayk7XG4gICAgfVxuICAgIHN0YWNrLnBvcCgpO1xuICAgIHJlcGxhY2VtZW50U3RhY2sucG9wKCk7XG4gIH0gZWxzZSB7XG4gICAgY2Fub25pY2FsaXplZE9iaiA9IG9iajtcbiAgfVxuICByZXR1cm4gY2Fub25pY2FsaXplZE9iajtcbn1cbiJdfQ== -/***/ }), +/***/ }, /* 9 */ -/***/ (function(module, exports, __webpack_require__) { +/***/ function(module, exports, __webpack_require__) { /*istanbul ignore start*/'use strict'; @@ -4114,27 +4119,25 @@ return /******/ (function(modules) { // webpackBootstrap var /*istanbul ignore start*/_base = __webpack_require__(1) /*istanbul ignore end*/; - /*istanbul ignore start*/var _base2 = _interopRequireDefault(_base); + /*istanbul ignore start*/ + var _base2 = _interopRequireDefault(_base); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } - /*istanbul ignore end*/var arrayDiff = /*istanbul ignore start*/exports. /*istanbul ignore end*/arrayDiff = new /*istanbul ignore start*/_base2['default'] /*istanbul ignore end*/(); + /*istanbul ignore end*/var arrayDiff = /*istanbul ignore start*/exports. /*istanbul ignore end*/arrayDiff = new /*istanbul ignore start*/_base2['default']() /*istanbul ignore end*/; arrayDiff.tokenize = arrayDiff.join = function (value) { return value.slice(); }; - arrayDiff.removeEmpty = function (value) { - return value; - }; function diffArrays(oldArr, newArr, callback) { return arrayDiff.diff(oldArr, newArr, callback); } - //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9kaWZmL2FycmF5LmpzIl0sIm5hbWVzIjpbImRpZmZBcnJheXMiLCJhcnJheURpZmYiLCJ0b2tlbml6ZSIsImpvaW4iLCJ2YWx1ZSIsInNsaWNlIiwicmVtb3ZlRW1wdHkiLCJvbGRBcnIiLCJuZXdBcnIiLCJjYWxsYmFjayIsImRpZmYiXSwibWFwcGluZ3MiOiI7Ozs7Z0NBVWdCQSxVLEdBQUFBLFU7O0FBVmhCOzs7Ozs7dUJBRU8sSUFBTUMsaUZBQVksd0VBQWxCO0FBQ1BBLFVBQVVDLFFBQVYsR0FBcUJELFVBQVVFLElBQVYsR0FBaUIsVUFBU0MsS0FBVCxFQUFnQjtBQUNwRCxTQUFPQSxNQUFNQyxLQUFOLEVBQVA7QUFDRCxDQUZEO0FBR0FKLFVBQVVLLFdBQVYsR0FBd0IsVUFBU0YsS0FBVCxFQUFnQjtBQUN0QyxTQUFPQSxLQUFQO0FBQ0QsQ0FGRDs7QUFJTyxTQUFTSixVQUFULENBQW9CTyxNQUFwQixFQUE0QkMsTUFBNUIsRUFBb0NDLFFBQXBDLEVBQThDO0FBQUUsU0FBT1IsVUFBVVMsSUFBVixDQUFlSCxNQUFmLEVBQXVCQyxNQUF2QixFQUErQkMsUUFBL0IsQ0FBUDtBQUFrRCIsImZpbGUiOiJhcnJheS5qcyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCBEaWZmIGZyb20gJy4vYmFzZSc7XG5cbmV4cG9ydCBjb25zdCBhcnJheURpZmYgPSBuZXcgRGlmZigpO1xuYXJyYXlEaWZmLnRva2VuaXplID0gYXJyYXlEaWZmLmpvaW4gPSBmdW5jdGlvbih2YWx1ZSkge1xuICByZXR1cm4gdmFsdWUuc2xpY2UoKTtcbn07XG5hcnJheURpZmYucmVtb3ZlRW1wdHkgPSBmdW5jdGlvbih2YWx1ZSkge1xuICByZXR1cm4gdmFsdWU7XG59O1xuXG5leHBvcnQgZnVuY3Rpb24gZGlmZkFycmF5cyhvbGRBcnIsIG5ld0FyciwgY2FsbGJhY2spIHsgcmV0dXJuIGFycmF5RGlmZi5kaWZmKG9sZEFyciwgbmV3QXJyLCBjYWxsYmFjayk7IH1cbiJdfQ== + //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9kaWZmL2FycmF5LmpzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Z0NBT2dCLFUsR0FBQSxVOztBQVBoQixJLHlCQUFBLHlCLHdCQUFBOzs7Ozs7O3VCQUVPLElBQU0sWSx5QkFBQSxRLHdCQUFBLFlBQVksSSx5QkFBQSxtQix3QkFBbEI7QUFDUCxVQUFVLFFBQVYsR0FBcUIsVUFBVSxJQUFWLEdBQWlCLFVBQVMsS0FBVCxFQUFnQjtBQUNwRCxTQUFPLE1BQU0sS0FBTixFQUFQO0FBQ0QsQ0FGRDs7QUFJTyxTQUFTLFVBQVQsQ0FBb0IsTUFBcEIsRUFBNEIsTUFBNUIsRUFBb0MsUUFBcEMsRUFBOEM7QUFBRSxTQUFPLFVBQVUsSUFBVixDQUFlLE1BQWYsRUFBdUIsTUFBdkIsRUFBK0IsUUFBL0IsQ0FBUDtBQUFrRCIsImZpbGUiOiJhcnJheS5qcyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCBEaWZmIGZyb20gJy4vYmFzZSc7XG5cbmV4cG9ydCBjb25zdCBhcnJheURpZmYgPSBuZXcgRGlmZigpO1xuYXJyYXlEaWZmLnRva2VuaXplID0gYXJyYXlEaWZmLmpvaW4gPSBmdW5jdGlvbih2YWx1ZSkge1xuICByZXR1cm4gdmFsdWUuc2xpY2UoKTtcbn07XG5cbmV4cG9ydCBmdW5jdGlvbiBkaWZmQXJyYXlzKG9sZEFyciwgbmV3QXJyLCBjYWxsYmFjaykgeyByZXR1cm4gYXJyYXlEaWZmLmRpZmYob2xkQXJyLCBuZXdBcnIsIGNhbGxiYWNrKTsgfVxuIl19 -/***/ }), +/***/ }, /* 10 */ -/***/ (function(module, exports, __webpack_require__) { +/***/ function(module, exports, __webpack_require__) { /*istanbul ignore start*/'use strict'; @@ -4146,12 +4149,13 @@ return /******/ (function(modules) { // webpackBootstrap var /*istanbul ignore start*/_distanceIterator = __webpack_require__(12) /*istanbul ignore end*/; - /*istanbul ignore start*/var _distanceIterator2 = _interopRequireDefault(_distanceIterator); + /*istanbul ignore start*/ + var _distanceIterator2 = _interopRequireDefault(_distanceIterator); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } /*istanbul ignore end*/function applyPatch(source, uniDiff) { - /*istanbul ignore start*/var /*istanbul ignore end*/options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; + /*istanbul ignore start*/var /*istanbul ignore end*/options = arguments.length <= 2 || arguments[2] === undefined ? {} : arguments[2]; if (typeof uniDiff === 'string') { uniDiff = /*istanbul ignore start*/(0, _parse.parsePatch) /*istanbul ignore end*/(uniDiff); @@ -4231,15 +4235,11 @@ return /******/ (function(modules) { // webpackBootstrap } // Apply patch hunks - var diffOffset = 0; for (var _i = 0; _i < hunks.length; _i++) { var _hunk = hunks[_i], - _toPos = _hunk.oldStart + _hunk.offset + diffOffset - 1; - diffOffset += _hunk.newLines - _hunk.oldLines; - - if (_toPos < 0) { - // Creating a new file - _toPos = 0; + _toPos = _hunk.offset + _hunk.newStart - 1; + if (_hunk.newLines == 0) { + _toPos++; } for (var j = 0; j < _hunk.lines.length; j++) { @@ -4255,17 +4255,17 @@ return /******/ (function(modules) { // webpackBootstrap delimiters.splice(_toPos, 1); /* istanbul ignore else */ } else if (operation === '+') { - lines.splice(_toPos, 0, content); - delimiters.splice(_toPos, 0, delimiter); - _toPos++; - } else if (operation === '\\') { - var previousOperation = _hunk.lines[j - 1] ? _hunk.lines[j - 1][0] : null; - if (previousOperation === '+') { - removeEOFNL = true; - } else if (previousOperation === '-') { - addEOFNL = true; + lines.splice(_toPos, 0, content); + delimiters.splice(_toPos, 0, delimiter); + _toPos++; + } else if (operation === '\\') { + var previousOperation = _hunk.lines[j - 1] ? _hunk.lines[j - 1][0] : null; + if (previousOperation === '+') { + removeEOFNL = true; + } else if (previousOperation === '-') { + addEOFNL = true; + } } - } } } @@ -4315,19 +4315,19 @@ return /******/ (function(modules) { // webpackBootstrap } processIndex(); } - //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9wYXRjaC9hcHBseS5qcyJdLCJuYW1lcyI6WyJhcHBseVBhdGNoIiwiYXBwbHlQYXRjaGVzIiwic291cmNlIiwidW5pRGlmZiIsIm9wdGlvbnMiLCJBcnJheSIsImlzQXJyYXkiLCJsZW5ndGgiLCJFcnJvciIsImxpbmVzIiwic3BsaXQiLCJkZWxpbWl0ZXJzIiwibWF0Y2giLCJodW5rcyIsImNvbXBhcmVMaW5lIiwibGluZU51bWJlciIsImxpbmUiLCJvcGVyYXRpb24iLCJwYXRjaENvbnRlbnQiLCJlcnJvckNvdW50IiwiZnV6ekZhY3RvciIsIm1pbkxpbmUiLCJvZmZzZXQiLCJyZW1vdmVFT0ZOTCIsImFkZEVPRk5MIiwiaHVua0ZpdHMiLCJodW5rIiwidG9Qb3MiLCJqIiwiY29udGVudCIsInN1YnN0ciIsImkiLCJtYXhMaW5lIiwib2xkTGluZXMiLCJsb2NhbE9mZnNldCIsIm9sZFN0YXJ0IiwiaXRlcmF0b3IiLCJ1bmRlZmluZWQiLCJkaWZmT2Zmc2V0IiwibmV3TGluZXMiLCJkZWxpbWl0ZXIiLCJsaW5lZGVsaW1pdGVycyIsInNwbGljZSIsInByZXZpb3VzT3BlcmF0aW9uIiwicG9wIiwicHVzaCIsIl9rIiwiam9pbiIsImN1cnJlbnRJbmRleCIsInByb2Nlc3NJbmRleCIsImluZGV4IiwiY29tcGxldGUiLCJsb2FkRmlsZSIsImVyciIsImRhdGEiLCJ1cGRhdGVkQ29udGVudCIsInBhdGNoZWQiXSwibWFwcGluZ3MiOiI7OztnQ0FHZ0JBLFUsR0FBQUEsVTt5REFvSUFDLFksR0FBQUEsWTs7QUF2SWhCOztBQUNBOzs7Ozs7dUJBRU8sU0FBU0QsVUFBVCxDQUFvQkUsTUFBcEIsRUFBNEJDLE9BQTVCLEVBQW1EO0FBQUEsc0RBQWRDLE9BQWMsdUVBQUosRUFBSTs7QUFDeEQsTUFBSSxPQUFPRCxPQUFQLEtBQW1CLFFBQXZCLEVBQWlDO0FBQy9CQSxjQUFVLHdFQUFXQSxPQUFYLENBQVY7QUFDRDs7QUFFRCxNQUFJRSxNQUFNQyxP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QUFQO0FBQ0Q7O0FBRUQsVUFBSUUsaUJBQWlCdkQsV0FBV3NELElBQVgsRUFBaUJKLEtBQWpCLEVBQXdCOUMsT0FBeEIsQ0FBckI7QUFDQUEsY0FBUW9ELE9BQVIsQ0FBZ0JOLEtBQWhCLEVBQXVCSyxjQUF2QixFQUF1QyxVQUFTRixHQUFULEVBQWM7QUFDbkQsWUFBSUEsR0FBSixFQUFTO0FBQ1AsaUJBQU9qRCxRQUFRK0MsUUFBUixDQUFpQkUsR0FBakIsQ0FBUDtBQUNEOztBQUVESjtBQUNELE9BTkQ7QUFPRCxLQWJEO0FBY0Q7QUFDREE7QUFDRCIsImZpbGUiOiJhcHBseS5qcyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7cGFyc2VQYXRjaH0gZnJvbSAnLi9wYXJzZSc7XG5pbXBvcnQgZGlzdGFuY2VJdGVyYXRvciBmcm9tICcuLi91dGlsL2Rpc3RhbmNlLWl0ZXJhdG9yJztcblxuZXhwb3J0IGZ1bmN0aW9uIGFwcGx5UGF0Y2goc291cmNlLCB1bmlEaWZmLCBvcHRpb25zID0ge30pIHtcbiAgaWYgKHR5cGVvZiB1bmlEaWZmID09PSAnc3RyaW5nJykge1xuICAgIHVuaURpZmYgPSBwYXJzZVBhdGNoKHVuaURpZmYpO1xuICB9XG5cbiAgaWYgKEFycmF5LmlzQXJyYXkodW5pRGlmZikpIHtcbiAgICBpZiAodW5pRGlmZi5sZW5ndGggPiAxKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ2FwcGx5UGF0Y2ggb25seSB3b3JrcyB3aXRoIGEgc2luZ2xlIGlucHV0LicpO1xuICAgIH1cblxuICAgIHVuaURpZmYgPSB1bmlEaWZmWzBdO1xuICB9XG5cbiAgLy8gQXBwbHkgdGhlIGRpZmYgdG8gdGhlIGlucHV0XG4gIGxldCBsaW5lcyA9IHNvdXJjZS5zcGxpdCgvXFxyXFxufFtcXG5cXHZcXGZcXHJcXHg4NV0vKSxcbiAgICAgIGRlbGltaXRlcnMgPSBzb3VyY2UubWF0Y2goL1xcclxcbnxbXFxuXFx2XFxmXFxyXFx4ODVdL2cpIHx8IFtdLFxuICAgICAgaHVua3MgPSB1bmlEaWZmLmh1bmtzLFxuXG4gICAgICBjb21wYXJlTGluZSA9IG9wdGlvbnMuY29tcGFyZUxpbmUgfHwgKChsaW5lTnVtYmVyLCBsaW5lLCBvcGVyYXRpb24sIHBhdGNoQ29udGVudCkgPT4gbGluZSA9PT0gcGF0Y2hDb250ZW50KSxcbiAgICAgIGVycm9yQ291bnQgPSAwLFxuICAgICAgZnV6ekZhY3RvciA9IG9wdGlvbnMuZnV6ekZhY3RvciB8fCAwLFxuICAgICAgbWluTGluZSA9IDAsXG4gICAgICBvZmZzZXQgPSAwLFxuXG4gICAgICByZW1vdmVFT0ZOTCxcbiAgICAgIGFkZEVPRk5MO1xuXG4gIC8qKlxuICAgKiBDaGVja3MgaWYgdGhlIGh1bmsgZXhhY3RseSBmaXRzIG9uIHRoZSBwcm92aWRlZCBsb2NhdGlvblxuICAgKi9cbiAgZnVuY3Rpb24gaHVua0ZpdHMoaHVuaywgdG9Qb3MpIHtcbiAgICBmb3IgKGxldCBqID0gMDsgaiA8IGh1bmsubGluZXMubGVuZ3RoOyBqKyspIHtcbiAgICAgIGxldCBsaW5lID0gaHVuay5saW5lc1tqXSxcbiAgICAgICAgICBvcGVyYXRpb24gPSBsaW5lWzBdLFxuICAgICAgICAgIGNvbnRlbnQgPSBsaW5lLnN1YnN0cigxKTtcblxuICAgICAgaWYgKG9wZXJhdGlvbiA9PT0gJyAnIHx8IG9wZXJhdGlvbiA9PT0gJy0nKSB7XG4gICAgICAgIC8vIENvbnRleHQgc2FuaXR5IGNoZWNrXG4gICAgICAgIGlmICghY29tcGFyZUxpbmUodG9Qb3MgKyAxLCBsaW5lc1t0b1Bvc10sIG9wZXJhdGlvbiwgY29udGVudCkpIHtcbiAgICAgICAgICBlcnJvckNvdW50Kys7XG5cbiAgICAgICAgICBpZiAoZXJyb3JDb3VudCA+IGZ1enpGYWN0b3IpIHtcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgdG9Qb3MrKztcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gdHJ1ZTtcbiAgfVxuXG4gIC8vIFNlYXJjaCBiZXN0IGZpdCBvZmZzZXRzIGZvciBlYWNoIGh1bmsgYmFzZWQgb24gdGhlIHByZXZpb3VzIG9uZXNcbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBodW5rcy5sZW5ndGg7IGkrKykge1xuICAgIGxldCBodW5rID0gaHVua3NbaV0sXG4gICAgICAgIG1heExpbmUgPSBsaW5lcy5sZW5ndGggLSBodW5rLm9sZExpbmVzLFxuICAgICAgICBsb2NhbE9mZnNldCA9IDAsXG4gICAgICAgIHRvUG9zID0gb2Zmc2V0ICsgaHVuay5vbGRTdGFydCAtIDE7XG5cbiAgICBsZXQgaXRlcmF0b3IgPSBkaXN0YW5jZUl0ZXJhdG9yKHRvUG9zLCBtaW5MaW5lLCBtYXhMaW5lKTtcblxuICAgIGZvciAoOyBsb2NhbE9mZnNldCAhPT0gdW5kZWZpbmVkOyBsb2NhbE9mZnNldCA9IGl0ZXJhdG9yKCkpIHtcbiAgICAgIGlmIChodW5rRml0cyhodW5rLCB0b1BvcyArIGxvY2FsT2Zmc2V0KSkge1xuICAgICAgICBodW5rLm9mZnNldCA9IG9mZnNldCArPSBsb2NhbE9mZnNldDtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgfVxuXG4gICAgaWYgKGxvY2FsT2Zmc2V0ID09PSB1bmRlZmluZWQpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICAvLyBTZXQgbG93ZXIgdGV4dCBsaW1pdCB0byBlbmQgb2YgdGhlIGN1cnJlbnQgaHVuaywgc28gbmV4dCBvbmVzIGRvbid0IHRyeVxuICAgIC8vIHRvIGZpdCBvdmVyIGFscmVhZHkgcGF0Y2hlZCB0ZXh0XG4gICAgbWluTGluZSA9IGh1bmsub2Zmc2V0ICsgaHVuay5vbGRTdGFydCArIGh1bmsub2xkTGluZXM7XG4gIH1cblxuICAvLyBBcHBseSBwYXRjaCBodW5rc1xuICBsZXQgZGlmZk9mZnNldCA9IDA7XG4gIGZvciAobGV0IGkgPSAwOyBpIDwgaHVua3MubGVuZ3RoOyBpKyspIHtcbiAgICBsZXQgaHVuayA9IGh1bmtzW2ldLFxuICAgICAgICB0b1BvcyA9IGh1bmsub2xkU3RhcnQgKyBodW5rLm9mZnNldCArIGRpZmZPZmZzZXQgLSAxO1xuICAgIGRpZmZPZmZzZXQgKz0gaHVuay5uZXdMaW5lcyAtIGh1bmsub2xkTGluZXM7XG5cbiAgICBpZiAodG9Qb3MgPCAwKSB7IC8vIENyZWF0aW5nIGEgbmV3IGZpbGVcbiAgICAgIHRvUG9zID0gMDtcbiAgICB9XG5cbiAgICBmb3IgKGxldCBqID0gMDsgaiA8IGh1bmsubGluZXMubGVuZ3RoOyBqKyspIHtcbiAgICAgIGxldCBsaW5lID0gaHVuay5saW5lc1tqXSxcbiAgICAgICAgICBvcGVyYXRpb24gPSBsaW5lWzBdLFxuICAgICAgICAgIGNvbnRlbnQgPSBsaW5lLnN1YnN0cigxKSxcbiAgICAgICAgICBkZWxpbWl0ZXIgPSBodW5rLmxpbmVkZWxpbWl0ZXJzW2pdO1xuXG4gICAgICBpZiAob3BlcmF0aW9uID09PSAnICcpIHtcbiAgICAgICAgdG9Qb3MrKztcbiAgICAgIH0gZWxzZSBpZiAob3BlcmF0aW9uID09PSAnLScpIHtcbiAgICAgICAgbGluZXMuc3BsaWNlKHRvUG9zLCAxKTtcbiAgICAgICAgZGVsaW1pdGVycy5zcGxpY2UodG9Qb3MsIDEpO1xuICAgICAgLyogaXN0YW5idWwgaWdub3JlIGVsc2UgKi9cbiAgICAgIH0gZWxzZSBpZiAob3BlcmF0aW9uID09PSAnKycpIHtcbiAgICAgICAgbGluZXMuc3BsaWNlKHRvUG9zLCAwLCBjb250ZW50KTtcbiAgICAgICAgZGVsaW1pdGVycy5zcGxpY2UodG9Qb3MsIDAsIGRlbGltaXRlcik7XG4gICAgICAgIHRvUG9zKys7XG4gICAgICB9IGVsc2UgaWYgKG9wZXJhdGlvbiA9PT0gJ1xcXFwnKSB7XG4gICAgICAgIGxldCBwcmV2aW91c09wZXJhdGlvbiA9IGh1bmsubGluZXNbaiAtIDFdID8gaHVuay5saW5lc1tqIC0gMV1bMF0gOiBudWxsO1xuICAgICAgICBpZiAocHJldmlvdXNPcGVyYXRpb24gPT09ICcrJykge1xuICAgICAgICAgIHJlbW92ZUVPRk5MID0gdHJ1ZTtcbiAgICAgICAgfSBlbHNlIGlmIChwcmV2aW91c09wZXJhdGlvbiA9PT0gJy0nKSB7XG4gICAgICAgICAgYWRkRU9GTkwgPSB0cnVlO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLy8gSGFuZGxlIEVPRk5MIGluc2VydGlvbi9yZW1vdmFsXG4gIGlmIChyZW1vdmVFT0ZOTCkge1xuICAgIHdoaWxlICghbGluZXNbbGluZXMubGVuZ3RoIC0gMV0pIHtcbiAgICAgIGxpbmVzLnBvcCgpO1xuICAgICAgZGVsaW1pdGVycy5wb3AoKTtcbiAgICB9XG4gIH0gZWxzZSBpZiAoYWRkRU9GTkwpIHtcbiAgICBsaW5lcy5wdXNoKCcnKTtcbiAgICBkZWxpbWl0ZXJzLnB1c2goJ1xcbicpO1xuICB9XG4gIGZvciAobGV0IF9rID0gMDsgX2sgPCBsaW5lcy5sZW5ndGggLSAxOyBfaysrKSB7XG4gICAgbGluZXNbX2tdID0gbGluZXNbX2tdICsgZGVsaW1pdGVyc1tfa107XG4gIH1cbiAgcmV0dXJuIGxpbmVzLmpvaW4oJycpO1xufVxuXG4vLyBXcmFwcGVyIHRoYXQgc3VwcG9ydHMgbXVsdGlwbGUgZmlsZSBwYXRjaGVzIHZpYSBjYWxsYmFja3MuXG5leHBvcnQgZnVuY3Rpb24gYXBwbHlQYXRjaGVzKHVuaURpZmYsIG9wdGlvbnMpIHtcbiAgaWYgKHR5cGVvZiB1bmlEaWZmID09PSAnc3RyaW5nJykge1xuICAgIHVuaURpZmYgPSBwYXJzZVBhdGNoKHVuaURpZmYpO1xuICB9XG5cbiAgbGV0IGN1cnJlbnRJbmRleCA9IDA7XG4gIGZ1bmN0aW9uIHByb2Nlc3NJbmRleCgpIHtcbiAgICBsZXQgaW5kZXggPSB1bmlEaWZmW2N1cnJlbnRJbmRleCsrXTtcbiAgICBpZiAoIWluZGV4KSB7XG4gICAgICByZXR1cm4gb3B0aW9ucy5jb21wbGV0ZSgpO1xuICAgIH1cblxuICAgIG9wdGlvbnMubG9hZEZpbGUoaW5kZXgsIGZ1bmN0aW9uKGVyciwgZGF0YSkge1xuICAgICAgaWYgKGVycikge1xuICAgICAgICByZXR1cm4gb3B0aW9ucy5jb21wbGV0ZShlcnIpO1xuICAgICAgfVxuXG4gICAgICBsZXQgdXBkYXRlZENvbnRlbnQgPSBhcHBseVBhdGNoKGRhdGEsIGluZGV4LCBvcHRpb25zKTtcbiAgICAgIG9wdGlvbnMucGF0Y2hlZChpbmRleCwgdXBkYXRlZENvbnRlbnQsIGZ1bmN0aW9uKGVycikge1xuICAgICAgICBpZiAoZXJyKSB7XG4gICAgICAgICAgcmV0dXJuIG9wdGlvbnMuY29tcGxldGUoZXJyKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHByb2Nlc3NJbmRleCgpO1xuICAgICAgfSk7XG4gICAgfSk7XG4gIH1cbiAgcHJvY2Vzc0luZGV4KCk7XG59XG4iXX0= + //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9wYXRjaC9hcHBseS5qcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Z0NBR2dCLFUsR0FBQSxVO3lEQStIQSxZLEdBQUEsWTs7QUFsSWhCLEkseUJBQUEsMkIsd0JBQUE7O0FBQ0EsSSx5QkFBQSx3RCx3QkFBQTs7Ozs7Ozt1QkFFTyxTQUFTLFVBQVQsQ0FBb0IsTUFBcEIsRUFBNEIsT0FBNUIsRUFBbUQ7MkJBQUEsSSx1QkFBZCxPQUFjLHlEQUFKLEVBQUk7O0FBQ3hELE1BQUksT0FBTyxPQUFQLEtBQW1CLFFBQXZCLEVBQWlDO0FBQy9CLGMseUJBQVUsc0Isd0JBQUEsQ0FBVyxPQUFYLENBQVY7QUFDRDs7QUFFRCxNQUFJLE1BQU0sT0FBTixDQUFjLE9BQWQsQ0FBSixFQUE0QjtBQUMxQixRQUFJLFFBQVEsTUFBUixHQUFpQixDQUFyQixFQUF3QjtBQUN0QixZQUFNLElBQUksS0FBSixDQUFVLDRDQUFWLENBQU47QUFDRDs7QUFFRCxjQUFVLFFBQVEsQ0FBUixDQUFWO0FBQ0Q7OztBQUdELE1BQUksUUFBUSxPQUFPLEtBQVAsQ0FBYSxxQkFBYixDQUFaO0FBQUEsTUFDSSxhQUFhLE9BQU8sS0FBUCxDQUFhLHNCQUFiLEtBQXdDLEVBRHpEO0FBQUEsTUFFSSxRQUFRLFFBQVEsS0FGcEI7QUFBQSxNQUlJLGNBQWMsUUFBUSxXQUFSLElBQXdCLFVBQUMsVUFBRCxFQUFhLElBQWIsRUFBbUIsU0FBbkIsRUFBOEIsWUFBOUIsRSx5QkFBQTtBQUFBLFcsd0JBQStDLFNBQVM7QUFBeEQ7QUFBQSxHQUoxQztBQUFBLE1BS0ksYUFBYSxDQUxqQjtBQUFBLE1BTUksYUFBYSxRQUFRLFVBQVIsSUFBc0IsQ0FOdkM7QUFBQSxNQU9JLFVBQVUsQ0FQZDtBQUFBLE1BUUksU0FBUyxDQVJiO0FBQUEsTUFVSSxjLHlCQUFBLE0sd0JBVko7QUFBQSxNQVdJLFcseUJBQUEsTSx3QkFYSjs7Ozs7QUFnQkEsV0FBUyxRQUFULENBQWtCLElBQWxCLEVBQXdC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QUFFRCxVQUFJLGlCQUFpQixXQUFXLElBQVgsRUFBaUIsS0FBakIsRUFBd0IsT0FBeEIsQ0FBckI7QUFDQSxjQUFRLE9BQVIsQ0FBZ0IsS0FBaEIsRUFBdUIsY0FBdkIsRUFBdUMsVUFBUyxHQUFULEVBQWM7QUFDbkQsWUFBSSxHQUFKLEVBQVM7QUFDUCxpQkFBTyxRQUFRLFFBQVIsQ0FBaUIsR0FBakIsQ0FBUDtBQUNEOztBQUVEO0FBQ0QsT0FORDtBQU9ELEtBYkQ7QUFjRDtBQUNEO0FBQ0QiLCJmaWxlIjoiYXBwbHkuanMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge3BhcnNlUGF0Y2h9IGZyb20gJy4vcGFyc2UnO1xuaW1wb3J0IGRpc3RhbmNlSXRlcmF0b3IgZnJvbSAnLi4vdXRpbC9kaXN0YW5jZS1pdGVyYXRvcic7XG5cbmV4cG9ydCBmdW5jdGlvbiBhcHBseVBhdGNoKHNvdXJjZSwgdW5pRGlmZiwgb3B0aW9ucyA9IHt9KSB7XG4gIGlmICh0eXBlb2YgdW5pRGlmZiA9PT0gJ3N0cmluZycpIHtcbiAgICB1bmlEaWZmID0gcGFyc2VQYXRjaCh1bmlEaWZmKTtcbiAgfVxuXG4gIGlmIChBcnJheS5pc0FycmF5KHVuaURpZmYpKSB7XG4gICAgaWYgKHVuaURpZmYubGVuZ3RoID4gMSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdhcHBseVBhdGNoIG9ubHkgd29ya3Mgd2l0aCBhIHNpbmdsZSBpbnB1dC4nKTtcbiAgICB9XG5cbiAgICB1bmlEaWZmID0gdW5pRGlmZlswXTtcbiAgfVxuXG4gIC8vIEFwcGx5IHRoZSBkaWZmIHRvIHRoZSBpbnB1dFxuICBsZXQgbGluZXMgPSBzb3VyY2Uuc3BsaXQoL1xcclxcbnxbXFxuXFx2XFxmXFxyXFx4ODVdLyksXG4gICAgICBkZWxpbWl0ZXJzID0gc291cmNlLm1hdGNoKC9cXHJcXG58W1xcblxcdlxcZlxcclxceDg1XS9nKSB8fCBbXSxcbiAgICAgIGh1bmtzID0gdW5pRGlmZi5odW5rcyxcblxuICAgICAgY29tcGFyZUxpbmUgPSBvcHRpb25zLmNvbXBhcmVMaW5lIHx8ICgobGluZU51bWJlciwgbGluZSwgb3BlcmF0aW9uLCBwYXRjaENvbnRlbnQpID0+IGxpbmUgPT09IHBhdGNoQ29udGVudCksXG4gICAgICBlcnJvckNvdW50ID0gMCxcbiAgICAgIGZ1enpGYWN0b3IgPSBvcHRpb25zLmZ1enpGYWN0b3IgfHwgMCxcbiAgICAgIG1pbkxpbmUgPSAwLFxuICAgICAgb2Zmc2V0ID0gMCxcblxuICAgICAgcmVtb3ZlRU9GTkwsXG4gICAgICBhZGRFT0ZOTDtcblxuICAvKipcbiAgICogQ2hlY2tzIGlmIHRoZSBodW5rIGV4YWN0bHkgZml0cyBvbiB0aGUgcHJvdmlkZWQgbG9jYXRpb25cbiAgICovXG4gIGZ1bmN0aW9uIGh1bmtGaXRzKGh1bmssIHRvUG9zKSB7XG4gICAgZm9yIChsZXQgaiA9IDA7IGogPCBodW5rLmxpbmVzLmxlbmd0aDsgaisrKSB7XG4gICAgICBsZXQgbGluZSA9IGh1bmsubGluZXNbal0sXG4gICAgICAgICAgb3BlcmF0aW9uID0gbGluZVswXSxcbiAgICAgICAgICBjb250ZW50ID0gbGluZS5zdWJzdHIoMSk7XG5cbiAgICAgIGlmIChvcGVyYXRpb24gPT09ICcgJyB8fCBvcGVyYXRpb24gPT09ICctJykge1xuICAgICAgICAvLyBDb250ZXh0IHNhbml0eSBjaGVja1xuICAgICAgICBpZiAoIWNvbXBhcmVMaW5lKHRvUG9zICsgMSwgbGluZXNbdG9Qb3NdLCBvcGVyYXRpb24sIGNvbnRlbnQpKSB7XG4gICAgICAgICAgZXJyb3JDb3VudCsrO1xuXG4gICAgICAgICAgaWYgKGVycm9yQ291bnQgPiBmdXp6RmFjdG9yKSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHRvUG9zKys7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHRydWU7XG4gIH1cblxuICAvLyBTZWFyY2ggYmVzdCBmaXQgb2Zmc2V0cyBmb3IgZWFjaCBodW5rIGJhc2VkIG9uIHRoZSBwcmV2aW91cyBvbmVzXG4gIGZvciAobGV0IGkgPSAwOyBpIDwgaHVua3MubGVuZ3RoOyBpKyspIHtcbiAgICBsZXQgaHVuayA9IGh1bmtzW2ldLFxuICAgICAgICBtYXhMaW5lID0gbGluZXMubGVuZ3RoIC0gaHVuay5vbGRMaW5lcyxcbiAgICAgICAgbG9jYWxPZmZzZXQgPSAwLFxuICAgICAgICB0b1BvcyA9IG9mZnNldCArIGh1bmsub2xkU3RhcnQgLSAxO1xuXG4gICAgbGV0IGl0ZXJhdG9yID0gZGlzdGFuY2VJdGVyYXRvcih0b1BvcywgbWluTGluZSwgbWF4TGluZSk7XG5cbiAgICBmb3IgKDsgbG9jYWxPZmZzZXQgIT09IHVuZGVmaW5lZDsgbG9jYWxPZmZzZXQgPSBpdGVyYXRvcigpKSB7XG4gICAgICBpZiAoaHVua0ZpdHMoaHVuaywgdG9Qb3MgKyBsb2NhbE9mZnNldCkpIHtcbiAgICAgICAgaHVuay5vZmZzZXQgPSBvZmZzZXQgKz0gbG9jYWxPZmZzZXQ7XG4gICAgICAgIGJyZWFrO1xuICAgICAgfVxuICAgIH1cblxuICAgIGlmIChsb2NhbE9mZnNldCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgLy8gU2V0IGxvd2VyIHRleHQgbGltaXQgdG8gZW5kIG9mIHRoZSBjdXJyZW50IGh1bmssIHNvIG5leHQgb25lcyBkb24ndCB0cnlcbiAgICAvLyB0byBmaXQgb3ZlciBhbHJlYWR5IHBhdGNoZWQgdGV4dFxuICAgIG1pbkxpbmUgPSBodW5rLm9mZnNldCArIGh1bmsub2xkU3RhcnQgKyBodW5rLm9sZExpbmVzO1xuICB9XG5cbiAgLy8gQXBwbHkgcGF0Y2ggaHVua3NcbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBodW5rcy5sZW5ndGg7IGkrKykge1xuICAgIGxldCBodW5rID0gaHVua3NbaV0sXG4gICAgICAgIHRvUG9zID0gaHVuay5vZmZzZXQgKyBodW5rLm5ld1N0YXJ0IC0gMTtcbiAgICBpZiAoaHVuay5uZXdMaW5lcyA9PSAwKSB7IHRvUG9zKys7IH1cblxuICAgIGZvciAobGV0IGogPSAwOyBqIDwgaHVuay5saW5lcy5sZW5ndGg7IGorKykge1xuICAgICAgbGV0IGxpbmUgPSBodW5rLmxpbmVzW2pdLFxuICAgICAgICAgIG9wZXJhdGlvbiA9IGxpbmVbMF0sXG4gICAgICAgICAgY29udGVudCA9IGxpbmUuc3Vic3RyKDEpLFxuICAgICAgICAgIGRlbGltaXRlciA9IGh1bmsubGluZWRlbGltaXRlcnNbal07XG5cbiAgICAgIGlmIChvcGVyYXRpb24gPT09ICcgJykge1xuICAgICAgICB0b1BvcysrO1xuICAgICAgfSBlbHNlIGlmIChvcGVyYXRpb24gPT09ICctJykge1xuICAgICAgICBsaW5lcy5zcGxpY2UodG9Qb3MsIDEpO1xuICAgICAgICBkZWxpbWl0ZXJzLnNwbGljZSh0b1BvcywgMSk7XG4gICAgICAvKiBpc3RhbmJ1bCBpZ25vcmUgZWxzZSAqL1xuICAgICAgfSBlbHNlIGlmIChvcGVyYXRpb24gPT09ICcrJykge1xuICAgICAgICBsaW5lcy5zcGxpY2UodG9Qb3MsIDAsIGNvbnRlbnQpO1xuICAgICAgICBkZWxpbWl0ZXJzLnNwbGljZSh0b1BvcywgMCwgZGVsaW1pdGVyKTtcbiAgICAgICAgdG9Qb3MrKztcbiAgICAgIH0gZWxzZSBpZiAob3BlcmF0aW9uID09PSAnXFxcXCcpIHtcbiAgICAgICAgbGV0IHByZXZpb3VzT3BlcmF0aW9uID0gaHVuay5saW5lc1tqIC0gMV0gPyBodW5rLmxpbmVzW2ogLSAxXVswXSA6IG51bGw7XG4gICAgICAgIGlmIChwcmV2aW91c09wZXJhdGlvbiA9PT0gJysnKSB7XG4gICAgICAgICAgcmVtb3ZlRU9GTkwgPSB0cnVlO1xuICAgICAgICB9IGVsc2UgaWYgKHByZXZpb3VzT3BlcmF0aW9uID09PSAnLScpIHtcbiAgICAgICAgICBhZGRFT0ZOTCA9IHRydWU7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICAvLyBIYW5kbGUgRU9GTkwgaW5zZXJ0aW9uL3JlbW92YWxcbiAgaWYgKHJlbW92ZUVPRk5MKSB7XG4gICAgd2hpbGUgKCFsaW5lc1tsaW5lcy5sZW5ndGggLSAxXSkge1xuICAgICAgbGluZXMucG9wKCk7XG4gICAgICBkZWxpbWl0ZXJzLnBvcCgpO1xuICAgIH1cbiAgfSBlbHNlIGlmIChhZGRFT0ZOTCkge1xuICAgIGxpbmVzLnB1c2goJycpO1xuICAgIGRlbGltaXRlcnMucHVzaCgnXFxuJyk7XG4gIH1cbiAgZm9yIChsZXQgX2sgPSAwOyBfayA8IGxpbmVzLmxlbmd0aCAtIDE7IF9rKyspIHtcbiAgICBsaW5lc1tfa10gPSBsaW5lc1tfa10gKyBkZWxpbWl0ZXJzW19rXTtcbiAgfVxuICByZXR1cm4gbGluZXMuam9pbignJyk7XG59XG5cbi8vIFdyYXBwZXIgdGhhdCBzdXBwb3J0cyBtdWx0aXBsZSBmaWxlIHBhdGNoZXMgdmlhIGNhbGxiYWNrcy5cbmV4cG9ydCBmdW5jdGlvbiBhcHBseVBhdGNoZXModW5pRGlmZiwgb3B0aW9ucykge1xuICBpZiAodHlwZW9mIHVuaURpZmYgPT09ICdzdHJpbmcnKSB7XG4gICAgdW5pRGlmZiA9IHBhcnNlUGF0Y2godW5pRGlmZik7XG4gIH1cblxuICBsZXQgY3VycmVudEluZGV4ID0gMDtcbiAgZnVuY3Rpb24gcHJvY2Vzc0luZGV4KCkge1xuICAgIGxldCBpbmRleCA9IHVuaURpZmZbY3VycmVudEluZGV4KytdO1xuICAgIGlmICghaW5kZXgpIHtcbiAgICAgIHJldHVybiBvcHRpb25zLmNvbXBsZXRlKCk7XG4gICAgfVxuXG4gICAgb3B0aW9ucy5sb2FkRmlsZShpbmRleCwgZnVuY3Rpb24oZXJyLCBkYXRhKSB7XG4gICAgICBpZiAoZXJyKSB7XG4gICAgICAgIHJldHVybiBvcHRpb25zLmNvbXBsZXRlKGVycik7XG4gICAgICB9XG5cbiAgICAgIGxldCB1cGRhdGVkQ29udGVudCA9IGFwcGx5UGF0Y2goZGF0YSwgaW5kZXgsIG9wdGlvbnMpO1xuICAgICAgb3B0aW9ucy5wYXRjaGVkKGluZGV4LCB1cGRhdGVkQ29udGVudCwgZnVuY3Rpb24oZXJyKSB7XG4gICAgICAgIGlmIChlcnIpIHtcbiAgICAgICAgICByZXR1cm4gb3B0aW9ucy5jb21wbGV0ZShlcnIpO1xuICAgICAgICB9XG5cbiAgICAgICAgcHJvY2Vzc0luZGV4KCk7XG4gICAgICB9KTtcbiAgICB9KTtcbiAgfVxuICBwcm9jZXNzSW5kZXgoKTtcbn1cbiJdfQ== -/***/ }), +/***/ }, /* 11 */ -/***/ (function(module, exports) { +/***/ function(module, exports) { /*istanbul ignore start*/'use strict'; exports.__esModule = true; exports. /*istanbul ignore end*/parsePatch = parsePatch; function parsePatch(uniDiff) { - /*istanbul ignore start*/var /*istanbul ignore end*/options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + /*istanbul ignore start*/var /*istanbul ignore end*/options = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1]; var diffstr = uniDiff.split(/\r\n|[\n\v\f\r\x85]/), delimiters = uniDiff.match(/\r\n|[\n\v\f\r\x85]/g) || [], @@ -4387,11 +4387,7 @@ return /******/ (function(modules) { // webpackBootstrap var fileHeader = headerPattern.exec(diffstr[i]); if (fileHeader) { var keyPrefix = fileHeader[1] === '---' ? 'old' : 'new'; - var fileName = fileHeader[2].replace(/\\\\/g, '\\'); - if (/^".*"$/.test(fileName)) { - fileName = fileName.substr(1, fileName.length - 2); - } - index[keyPrefix + 'FileName'] = fileName; + index[keyPrefix + 'FileName'] = fileHeader[2]; index[keyPrefix + 'Header'] = fileHeader[3]; i++; @@ -4468,12 +4464,12 @@ return /******/ (function(modules) { // webpackBootstrap return list; } - //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9wYXRjaC9wYXJzZS5qcyJdLCJuYW1lcyI6WyJwYXJzZVBhdGNoIiwidW5pRGlmZiIsIm9wdGlvbnMiLCJkaWZmc3RyIiwic3BsaXQiLCJkZWxpbWl0ZXJzIiwibWF0Y2giLCJsaXN0IiwiaSIsInBhcnNlSW5kZXgiLCJpbmRleCIsInB1c2giLCJsZW5ndGgiLCJsaW5lIiwidGVzdCIsImhlYWRlciIsImV4ZWMiLCJwYXJzZUZpbGVIZWFkZXIiLCJodW5rcyIsInBhcnNlSHVuayIsInN0cmljdCIsIkVycm9yIiwiSlNPTiIsInN0cmluZ2lmeSIsImhlYWRlclBhdHRlcm4iLCJmaWxlSGVhZGVyIiwia2V5UHJlZml4IiwiZmlsZU5hbWUiLCJyZXBsYWNlIiwic3Vic3RyIiwiY2h1bmtIZWFkZXJJbmRleCIsImNodW5rSGVhZGVyTGluZSIsImNodW5rSGVhZGVyIiwiaHVuayIsIm9sZFN0YXJ0Iiwib2xkTGluZXMiLCJuZXdTdGFydCIsIm5ld0xpbmVzIiwibGluZXMiLCJsaW5lZGVsaW1pdGVycyIsImFkZENvdW50IiwicmVtb3ZlQ291bnQiLCJpbmRleE9mIiwib3BlcmF0aW9uIl0sIm1hcHBpbmdzIjoiOzs7Z0NBQWdCQSxVLEdBQUFBLFU7QUFBVCxTQUFTQSxVQUFULENBQW9CQyxPQUFwQixFQUEyQztBQUFBLHNEQUFkQyxPQUFjLHVFQUFKLEVBQUk7O0FBQ2hELE1BQUlDLFVBQVVGLFFBQVFHLEtBQVIsQ0FBYyxxQkFBZCxDQUFkO0FBQUEsTUFDSUMsYUFBYUosUUFBUUssS0FBUixDQUFjLHNCQUFkLEtBQXlDLEVBRDFEO0FBQUEsTUFFSUMsT0FBTyxFQUZYO0FBQUEsTUFHSUMsSUFBSSxDQUhSOztBQUtBLFdBQVNDLFVBQVQsR0FBc0I7QUFDcEIsUUFBSUMsUUFBUSxFQUFaO0FBQ0FILFNBQUtJLElBQUwsQ0FBVUQsS0FBVjs7QUFFQTtBQUNBLFdBQU9GLElBQUlMLFFBQVFTLE1BQW5CLEVBQTJCO0FBQ3pCLFVBQUlDLE9BQU9WLFFB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Q0FBVSx3REFBd0RTLG1CQUFtQixDQUEzRSxDQUFWLENBQU47QUFDRDtBQUNGOztBQUVELFdBQU9HLElBQVA7QUFDRDs7QUFFRCxTQUFPekIsSUFBSUwsUUFBUVMsTUFBbkIsRUFBMkI7QUFDekJIO0FBQ0Q7O0FBRUQsU0FBT0YsSUFBUDtBQUNEIiwiZmlsZSI6InBhcnNlLmpzIiwic291cmNlc0NvbnRlbnQiOlsiZXhwb3J0IGZ1bmN0aW9uIHBhcnNlUGF0Y2godW5pRGlmZiwgb3B0aW9ucyA9IHt9KSB7XG4gIGxldCBkaWZmc3RyID0gdW5pRGlmZi5zcGxpdCgvXFxyXFxufFtcXG5cXHZcXGZcXHJcXHg4NV0vKSxcbiAgICAgIGRlbGltaXRlcnMgPSB1bmlEaWZmLm1hdGNoKC9cXHJcXG58W1xcblxcdlxcZlxcclxceDg1XS9nKSB8fCBbXSxcbiAgICAgIGxpc3QgPSBbXSxcbiAgICAgIGkgPSAwO1xuXG4gIGZ1bmN0aW9uIHBhcnNlSW5kZXgoKSB7XG4gICAgbGV0IGluZGV4ID0ge307XG4gICAgbGlzdC5wdXNoKGluZGV4KTtcblxuICAgIC8vIFBhcnNlIGRpZmYgbWV0YWRhdGFcbiAgICB3aGlsZSAoaSA8IGRpZmZzdHIubGVuZ3RoKSB7XG4gICAgICBsZXQgbGluZSA9IGRpZmZzdHJbaV07XG5cbiAgICAgIC8vIEZpbGUgaGVhZGVyIGZvdW5kLCBlbmQgcGFyc2luZyBkaWZmIG1ldGFkYXRhXG4gICAgICBpZiAoL14oXFwtXFwtXFwtfFxcK1xcK1xcK3xAQClcXHMvLnRlc3QobGluZSkpIHtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG5cbiAgICAgIC8vIERpZmYgaW5kZXhcbiAgICAgIGxldCBoZWFkZXIgPSAoL14oPzpJbmRleDp8ZGlmZig/OiAtciBcXHcrKSspXFxzKyguKz8pXFxzKiQvKS5leGVjKGxpbmUpO1xuICAgICAgaWYgKGhlYWRlcikge1xuICAgICAgICBpbmRleC5pbmRleCA9IGhlYWRlclsxXTtcbiAgICAgIH1cblxuICAgICAgaSsrO1xuICAgIH1cblxuICAgIC8vIFBhcnNlIGZpbGUgaGVhZGVycyBpZiB0aGV5IGFyZSBkZWZpbmVkLiBVbmlmaWVkIGRpZmYgcmVxdWlyZXMgdGhlbSwgYnV0XG4gICAgLy8gdGhlcmUncyBubyB0ZWNobmljYWwgaXNzdWVzIHRvIGhhdmUgYW4gaXNvbGF0ZWQgaHVuayB3aXRob3V0IGZpbGUgaGVhZGVyXG4gICAgcGFyc2VGaWxlSGVhZGVyKGluZGV4KTtcbiAgICBwYXJzZUZpbGVIZWFkZXIoaW5kZXgpO1xuXG4gICAgLy8gUGFyc2UgaHVua3NcbiAgICBpbmRleC5odW5rcyA9IFtdO1xuXG4gICAgd2hpbGUgKGkgPCBkaWZmc3RyLmxlbmd0aCkge1xuICAgICAgbGV0IGxpbmUgPSBkaWZmc3RyW2ldO1xuXG4gICAgICBpZiAoL14oSW5kZXg6fGRpZmZ8XFwtXFwtXFwtfFxcK1xcK1xcKylcXHMvLnRlc3QobGluZSkpIHtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9IGVsc2UgaWYgKC9eQEAvLnRlc3QobGluZSkpIHtcbiAgICAgICAgaW5kZXguaHVua3MucHVzaChwYXJzZUh1bmsoKSk7XG4gICAgICB9IGVsc2UgaWYgKGxpbmUgJiYgb3B0aW9ucy5zdHJpY3QpIHtcbiAgICAgICAgLy8gSWdub3JlIHVuZXhwZWN0ZWQgY29udGVudCB1bmxlc3MgaW4gc3RyaWN0IG1vZGVcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdVbmtub3duIGxpbmUgJyArIChpICsgMSkgKyAnICcgKyBKU09OLnN0cmluZ2lmeShsaW5lKSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBpKys7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLy8gUGFyc2VzIHRoZSAtLS0gYW5kICsrKyBoZWFkZXJzLCBpZiBub25lIGFyZSBmb3VuZCwgbm8gbGluZXNcbiAgLy8gYXJlIGNvbnN1bWVkLlxuICBmdW5jdGlvbiBwYXJzZUZpbGVIZWFkZXIoaW5kZXgpIHtcbiAgICBjb25zdCBoZWFkZXJQYXR0ZXJuID0gL14oLS0tfFxcK1xcK1xcKylcXHMrKFtcXFMgXSopKD86XFx0KC4qPylcXHMqKT8kLztcbiAgICBjb25zdCBmaWxlSGVhZGVyID0gaGVhZGVyUGF0dGVybi5leGVjKGRpZmZzdHJbaV0pO1xuICAgIGlmIChmaWxlSGVhZGVyKSB7XG4gICAgICBsZXQga2V5UHJlZml4ID0gZmlsZUhlYWRlclsxXSA9PT0gJy0tLScgPyAnb2xkJyA6ICduZXcnO1xuICAgICAgbGV0IGZpbGVOYW1lID0gZmlsZUhlYWRlclsyXS5yZXBsYWNlKC9cXFxcXFxcXC9nLCAnXFxcXCcpO1xuICAgICAgaWYgKC9eXCIuKlwiJC8udGVzdChmaWxlTmFtZSkpIHtcbiAgICAgICAgZmlsZU5hbWUgPSBmaWxlTmFtZS5zdWJzdHIoMSwgZmlsZU5hbWUubGVuZ3RoIC0gMik7XG4gICAgICB9XG4gICAgICBpbmRleFtrZXlQcmVmaXggKyAnRmlsZU5hbWUnXSA9IGZpbGVOYW1lO1xuICAgICAgaW5kZXhba2V5UHJlZml4ICsgJ0hlYWRlciddID0gZmlsZUhlYWRlclszXTtcblxuICAgICAgaSsrO1xuICAgIH1cbiAgfVxuXG4gIC8vIFBhcnNlcyBhIGh1bmtcbiAgLy8gVGhpcyBhc3N1bWVzIHRoYXQgd2UgYXJlIGF0IHRoZSBzdGFydCBvZiBhIGh1bmsuXG4gIGZ1bmN0aW9uIHBhcnNlSHVuaygpIHtcbiAgICBsZXQgY2h1bmtIZWFkZXJJbmRleCA9IGksXG4gICAgICAgIGNodW5rSGVhZGVyTGluZSA9IGRpZmZzdHJbaSsrXSxcbiAgICAgICAgY2h1bmtIZWFkZXIgPSBjaHVua0hlYWRlckxpbmUuc3BsaXQoL0BAIC0oXFxkKykoPzosKFxcZCspKT8gXFwrKFxcZCspKD86LChcXGQrKSk/IEBALyk7XG5cbiAgICBsZXQgaHVuayA9IHtcbiAgICAgIG9sZFN0YXJ0OiArY2h1bmtIZWFkZXJbMV0sXG4gICAgICBvbGRMaW5lczogK2NodW5rSGVhZGVyWzJdIHx8IDEsXG4gICAgICBuZXdTdGFydDogK2NodW5rSGVhZGVyWzNdLFxuICAgICAgbmV3TGluZXM6ICtjaHVua0hlYWRlcls0XSB8fCAxLFxuICAgICAgbGluZXM6IFtdLFxuICAgICAgbGluZWRlbGltaXRlcnM6IFtdXG4gICAgfTtcblxuICAgIGxldCBhZGRDb3VudCA9IDAsXG4gICAgICAgIHJlbW92ZUNvdW50ID0gMDtcbiAgICBmb3IgKDsgaSA8IGRpZmZzdHIubGVuZ3RoOyBpKyspIHtcbiAgICAgIC8vIExpbmVzIHN0YXJ0aW5nIHdpdGggJy0tLScgY291bGQgYmUgbWlzdGFrZW4gZm9yIHRoZSBcInJlbW92ZSBsaW5lXCIgb3BlcmF0aW9uXG4gICAgICAvLyBCdXQgdGhleSBjb3VsZCBiZSB0aGUgaGVhZGVyIGZvciB0aGUgbmV4dCBmaWxlLiBUaGVyZWZvcmUgcHJ1bmUgc3VjaCBjYXNlcyBvdXQuXG4gICAgICBpZiAoZGlmZnN0cltpXS5pbmRleE9mKCctLS0gJykgPT09IDBcbiAgICAgICAgICAgICYmIChpICsgMiA8IGRpZmZzdHIubGVuZ3RoKVxuICAgICAgICAgICAgJiYgZGlmZnN0cltpICsgMV0uaW5kZXhPZignKysrICcpID09PSAwXG4gICAgICAgICAgICAmJiBkaWZmc3RyW2kgKyAyXS5pbmRleE9mKCdAQCcpID09PSAwKSB7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgICBsZXQgb3BlcmF0aW9uID0gZGlmZnN0cltpXVswXTtcblxuICAgICAgaWYgKG9wZXJhdGlvbiA9PT0gJysnIHx8IG9wZXJhdGlvbiA9PT0gJy0nIHx8IG9wZXJhdGlvbiA9PT0gJyAnIHx8IG9wZXJhdGlvbiA9PT0gJ1xcXFwnKSB7XG4gICAgICAgIGh1bmsubGluZXMucHVzaChkaWZmc3RyW2ldKTtcbiAgICAgICAgaHVuay5saW5lZGVsaW1pdGVycy5wdXNoKGRlbGltaXRlcnNbaV0gfHwgJ1xcbicpO1xuXG4gICAgICAgIGlmIChvcGVyYXRpb24gPT09ICcrJykge1xuICAgICAgICAgIGFkZENvdW50Kys7XG4gICAgICAgIH0gZWxzZSBpZiAob3BlcmF0aW9uID09PSAnLScpIHtcbiAgICAgICAgICByZW1vdmVDb3VudCsrO1xuICAgICAgICB9IGVsc2UgaWYgKG9wZXJhdGlvbiA9PT0gJyAnKSB7XG4gICAgICAgICAgYWRkQ291bnQrKztcbiAgICAgICAgICByZW1vdmVDb3VudCsrO1xuICAgICAgICB9XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBicmVhaztcbiAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBIYW5kbGUgdGhlIGVtcHR5IGJsb2NrIGNvdW50IGNhc2VcbiAgICBpZiAoIWFkZENvdW50ICYmIGh1bmsubmV3TGluZXMgPT09IDEpIHtcbiAgICAgIGh1bmsubmV3TGluZXMgPSAwO1xuICAgIH1cbiAgICBpZiAoIXJlbW92ZUNvdW50ICYmIGh1bmsub2xkTGluZXMgPT09IDEpIHtcbiAgICAgIGh1bmsub2xkTGluZXMgPSAwO1xuICAgIH1cblxuICAgIC8vIFBlcmZvcm0gb3B0aW9uYWwgc2FuaXR5IGNoZWNraW5nXG4gICAgaWYgKG9wdGlvbnMuc3RyaWN0KSB7XG4gICAgICBpZiAoYWRkQ291bnQgIT09IGh1bmsubmV3TGluZXMpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdBZGRlZCBsaW5lIGNvdW50IGRpZCBub3QgbWF0Y2ggZm9yIGh1bmsgYXQgbGluZSAnICsgKGNodW5rSGVhZGVySW5kZXggKyAxKSk7XG4gICAgICB9XG4gICAgICBpZiAocmVtb3ZlQ291bnQgIT09IGh1bmsub2xkTGluZXMpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdSZW1vdmVkIGxpbmUgY291bnQgZGlkIG5vdCBtYXRjaCBmb3IgaHVuayBhdCBsaW5lICcgKyAoY2h1bmtIZWFkZXJJbmRleCArIDEpKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gaHVuaztcbiAgfVxuXG4gIHdoaWxlIChpIDwgZGlmZnN0ci5sZW5ndGgpIHtcbiAgICBwYXJzZUluZGV4KCk7XG4gIH1cblxuICByZXR1cm4gbGlzdDtcbn1cbiJdfQ== + //# sourceMappingURL=data:application/json;base64,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LEtBQUosQ0FBVSx3REFBd0QsbUJBQW1CLENBQTNFLENBQVYsQ0FBTjtBQUNEO0FBQ0Y7O0FBRUQsV0FBTyxJQUFQO0FBQ0Q7O0FBRUQsU0FBTyxJQUFJLFFBQVEsTUFBbkIsRUFBMkI7QUFDekI7QUFDRDs7QUFFRCxTQUFPLElBQVA7QUFDRCIsImZpbGUiOiJwYXJzZS5qcyIsInNvdXJjZXNDb250ZW50IjpbImV4cG9ydCBmdW5jdGlvbiBwYXJzZVBhdGNoKHVuaURpZmYsIG9wdGlvbnMgPSB7fSkge1xuICBsZXQgZGlmZnN0ciA9IHVuaURpZmYuc3BsaXQoL1xcclxcbnxbXFxuXFx2XFxmXFxyXFx4ODVdLyksXG4gICAgICBkZWxpbWl0ZXJzID0gdW5pRGlmZi5tYXRjaCgvXFxyXFxufFtcXG5cXHZcXGZcXHJcXHg4NV0vZykgfHwgW10sXG4gICAgICBsaXN0ID0gW10sXG4gICAgICBpID0gMDtcblxuICBmdW5jdGlvbiBwYXJzZUluZGV4KCkge1xuICAgIGxldCBpbmRleCA9IHt9O1xuICAgIGxpc3QucHVzaChpbmRleCk7XG5cbiAgICAvLyBQYXJzZSBkaWZmIG1ldGFkYXRhXG4gICAgd2hpbGUgKGkgPCBkaWZmc3RyLmxlbmd0aCkge1xuICAgICAgbGV0IGxpbmUgPSBkaWZmc3RyW2ldO1xuXG4gICAgICAvLyBGaWxlIGhlYWRlciBmb3VuZCwgZW5kIHBhcnNpbmcgZGlmZiBtZXRhZGF0YVxuICAgICAgaWYgKC9eKFxcLVxcLVxcLXxcXCtcXCtcXCt8QEApXFxzLy50ZXN0KGxpbmUpKSB7XG4gICAgICAgIGJyZWFrO1xuICAgICAgfVxuXG4gICAgICAvLyBEaWZmIGluZGV4XG4gICAgICBsZXQgaGVhZGVyID0gKC9eKD86SW5kZXg6fGRpZmYoPzogLXIgXFx3KykrKVxccysoLis/KVxccyokLykuZXhlYyhsaW5lKTtcbiAgICAgIGlmIChoZWFkZXIpIHtcbiAgICAgICAgaW5kZXguaW5kZXggPSBoZWFkZXJbMV07XG4gICAgICB9XG5cbiAgICAgIGkrKztcbiAgICB9XG5cbiAgICAvLyBQYXJzZSBmaWxlIGhlYWRlcnMgaWYgdGhleSBhcmUgZGVmaW5lZC4gVW5pZmllZCBkaWZmIHJlcXVpcmVzIHRoZW0sIGJ1dFxuICAgIC8vIHRoZXJlJ3Mgbm8gdGVjaG5pY2FsIGlzc3VlcyB0byBoYXZlIGFuIGlzb2xhdGVkIGh1bmsgd2l0aG91dCBmaWxlIGhlYWRlclxuICAgIHBhcnNlRmlsZUhlYWRlcihpbmRleCk7XG4gICAgcGFyc2VGaWxlSGVhZGVyKGluZGV4KTtcblxuICAgIC8vIFBhcnNlIGh1bmtzXG4gICAgaW5kZXguaHVua3MgPSBbXTtcblxuICAgIHdoaWxlIChpIDwgZGlmZnN0ci5sZW5ndGgpIHtcbiAgICAgIGxldCBsaW5lID0gZGlmZnN0cltpXTtcblxuICAgICAgaWYgKC9eKEluZGV4OnxkaWZmfFxcLVxcLVxcLXxcXCtcXCtcXCspXFxzLy50ZXN0KGxpbmUpKSB7XG4gICAgICAgIGJyZWFrO1xuICAgICAgfSBlbHNlIGlmICgvXkBALy50ZXN0KGxpbmUpKSB7XG4gICAgICAgIGluZGV4Lmh1bmtzLnB1c2gocGFyc2VIdW5rKCkpO1xuICAgICAgfSBlbHNlIGlmIChsaW5lICYmIG9wdGlvbnMuc3RyaWN0KSB7XG4gICAgICAgIC8vIElnbm9yZSB1bmV4cGVjdGVkIGNvbnRlbnQgdW5sZXNzIGluIHN0cmljdCBtb2RlXG4gICAgICAgIHRocm93IG5ldyBFcnJvcignVW5rbm93biBsaW5lICcgKyAoaSArIDEpICsgJyAnICsgSlNPTi5zdHJpbmdpZnkobGluZSkpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgaSsrO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIC8vIFBhcnNlcyB0aGUgLS0tIGFuZCArKysgaGVhZGVycywgaWYgbm9uZSBhcmUgZm91bmQsIG5vIGxpbmVzXG4gIC8vIGFyZSBjb25zdW1lZC5cbiAgZnVuY3Rpb24gcGFyc2VGaWxlSGVhZGVyKGluZGV4KSB7XG4gICAgY29uc3QgaGVhZGVyUGF0dGVybiA9IC9eKC0tLXxcXCtcXCtcXCspXFxzKyhbXFxTIF0qKSg/OlxcdCguKj8pXFxzKik/JC87XG4gICAgY29uc3QgZmlsZUhlYWRlciA9IGhlYWRlclBhdHRlcm4uZXhlYyhkaWZmc3RyW2ldKTtcbiAgICBpZiAoZmlsZUhlYWRlcikge1xuICAgICAgbGV0IGtleVByZWZpeCA9IGZpbGVIZWFkZXJbMV0gPT09ICctLS0nID8gJ29sZCcgOiAnbmV3JztcbiAgICAgIGluZGV4W2tleVByZWZpeCArICdGaWxlTmFtZSddID0gZmlsZUhlYWRlclsyXTtcbiAgICAgIGluZGV4W2tleVByZWZpeCArICdIZWFkZXInXSA9IGZpbGVIZWFkZXJbM107XG5cbiAgICAgIGkrKztcbiAgICB9XG4gIH1cblxuICAvLyBQYXJzZXMgYSBodW5rXG4gIC8vIFRoaXMgYXNzdW1lcyB0aGF0IHdlIGFyZSBhdCB0aGUgc3RhcnQgb2YgYSBodW5rLlxuICBmdW5jdGlvbiBwYXJzZUh1bmsoKSB7XG4gICAgbGV0IGNodW5rSGVhZGVySW5kZXggPSBpLFxuICAgICAgICBjaHVua0hlYWRlckxpbmUgPSBkaWZmc3RyW2krK10sXG4gICAgICAgIGNodW5rSGVhZGVyID0gY2h1bmtIZWFkZXJMaW5lLnNwbGl0KC9AQCAtKFxcZCspKD86LChcXGQrKSk/IFxcKyhcXGQrKSg/OiwoXFxkKykpPyBAQC8pO1xuXG4gICAgbGV0IGh1bmsgPSB7XG4gICAgICBvbGRTdGFydDogK2NodW5rSGVhZGVyWzFdLFxuICAgICAgb2xkTGluZXM6ICtjaHVua0hlYWRlclsyXSB8fCAxLFxuICAgICAgbmV3U3RhcnQ6ICtjaHVua0hlYWRlclszXSxcbiAgICAgIG5ld0xpbmVzOiArY2h1bmtIZWFkZXJbNF0gfHwgMSxcbiAgICAgIGxpbmVzOiBbXSxcbiAgICAgIGxpbmVkZWxpbWl0ZXJzOiBbXVxuICAgIH07XG5cbiAgICBsZXQgYWRkQ291bnQgPSAwLFxuICAgICAgICByZW1vdmVDb3VudCA9IDA7XG4gICAgZm9yICg7IGkgPCBkaWZmc3RyLmxlbmd0aDsgaSsrKSB7XG4gICAgICAvLyBMaW5lcyBzdGFydGluZyB3aXRoICctLS0nIGNvdWxkIGJlIG1pc3Rha2VuIGZvciB0aGUgXCJyZW1vdmUgbGluZVwiIG9wZXJhdGlvblxuICAgICAgLy8gQnV0IHRoZXkgY291bGQgYmUgdGhlIGhlYWRlciBmb3IgdGhlIG5leHQgZmlsZS4gVGhlcmVmb3JlIHBydW5lIHN1Y2ggY2FzZXMgb3V0LlxuICAgICAgaWYgKGRpZmZzdHJbaV0uaW5kZXhPZignLS0tICcpID09PSAwXG4gICAgICAgICAgICAmJiAoaSArIDIgPCBkaWZmc3RyLmxlbmd0aClcbiAgICAgICAgICAgICYmIGRpZmZzdHJbaSArIDFdLmluZGV4T2YoJysrKyAnKSA9PT0gMFxuICAgICAgICAgICAgJiYgZGlmZnN0cltpICsgMl0uaW5kZXhPZignQEAnKSA9PT0gMCkge1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgfVxuICAgICAgbGV0IG9wZXJhdGlvbiA9IGRpZmZzdHJbaV1bMF07XG5cbiAgICAgIGlmIChvcGVyYXRpb24gPT09ICcrJyB8fCBvcGVyYXRpb24gPT09ICctJyB8fCBvcGVyYXRpb24gPT09ICcgJyB8fCBvcGVyYXRpb24gPT09ICdcXFxcJykge1xuICAgICAgICBodW5rLmxpbmVzLnB1c2goZGlmZnN0cltpXSk7XG4gICAgICAgIGh1bmsubGluZWRlbGltaXRlcnMucHVzaChkZWxpbWl0ZXJzW2ldIHx8ICdcXG4nKTtcblxuICAgICAgICBpZiAob3BlcmF0aW9uID09PSAnKycpIHtcbiAgICAgICAgICBhZGRDb3VudCsrO1xuICAgICAgICB9IGVsc2UgaWYgKG9wZXJhdGlvbiA9PT0gJy0nKSB7XG4gICAgICAgICAgcmVtb3ZlQ291bnQrKztcbiAgICAgICAgfSBlbHNlIGlmIChvcGVyYXRpb24gPT09ICcgJykge1xuICAgICAgICAgIGFkZENvdW50Kys7XG4gICAgICAgICAgcmVtb3ZlQ291bnQrKztcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgfVxuXG4gICAgLy8gSGFuZGxlIHRoZSBlbXB0eSBibG9jayBjb3VudCBjYXNlXG4gICAgaWYgKCFhZGRDb3VudCAmJiBodW5rLm5ld0xpbmVzID09PSAxKSB7XG4gICAgICBodW5rLm5ld0xpbmVzID0gMDtcbiAgICB9XG4gICAgaWYgKCFyZW1vdmVDb3VudCAmJiBodW5rLm9sZExpbmVzID09PSAxKSB7XG4gICAgICBodW5rLm9sZExpbmVzID0gMDtcbiAgICB9XG5cbiAgICAvLyBQZXJmb3JtIG9wdGlvbmFsIHNhbml0eSBjaGVja2luZ1xuICAgIGlmIChvcHRpb25zLnN0cmljdCkge1xuICAgICAgaWYgKGFkZENvdW50ICE9PSBodW5rLm5ld0xpbmVzKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignQWRkZWQgbGluZSBjb3VudCBkaWQgbm90IG1hdGNoIGZvciBodW5rIGF0IGxpbmUgJyArIChjaHVua0hlYWRlckluZGV4ICsgMSkpO1xuICAgICAgfVxuICAgICAgaWYgKHJlbW92ZUNvdW50ICE9PSBodW5rLm9sZExpbmVzKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignUmVtb3ZlZCBsaW5lIGNvdW50IGRpZCBub3QgbWF0Y2ggZm9yIGh1bmsgYXQgbGluZSAnICsgKGNodW5rSGVhZGVySW5kZXggKyAxKSk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIGh1bms7XG4gIH1cblxuICB3aGlsZSAoaSA8IGRpZmZzdHIubGVuZ3RoKSB7XG4gICAgcGFyc2VJbmRleCgpO1xuICB9XG5cbiAgcmV0dXJuIGxpc3Q7XG59XG4iXX0= -/***/ }), +/***/ }, /* 12 */ -/***/ (function(module, exports) { +/***/ function(module, exports) { /*istanbul ignore start*/"use strict"; @@ -4517,418 +4513,16 @@ return /******/ (function(modules) { // webpackBootstrap return iterator(); } - // We tried to fit hunk before text beginning and beyond text length, then + // We tried to fit hunk before text beginning and beyond text lenght, then // hunk can't fit on the text. Return undefined }; }; - //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy91dGlsL2Rpc3RhbmNlLWl0ZXJhdG9yLmpzIl0sIm5hbWVzIjpbInN0YXJ0IiwibWluTGluZSIsIm1heExpbmUiLCJ3YW50Rm9yd2FyZCIsImJhY2t3YXJkRXhoYXVzdGVkIiwiZm9yd2FyZEV4aGF1c3RlZCIsImxvY2FsT2Zmc2V0IiwiaXRlcmF0b3IiXSwibWFwcGluZ3MiOiI7Ozs7NENBR2UsVUFBU0EsS0FBVCxFQUFnQkMsT0FBaEIsRUFBeUJDLE9BQXpCLEVBQWtDO0FBQy9DLE1BQUlDLGNBQWMsSUFBbEI7QUFBQSxNQUNJQyxvQkFBb0IsS0FEeEI7QUFBQSxNQUVJQyxtQkFBbUIsS0FGdkI7QUFBQSxNQUdJQyxjQUFjLENBSGxCOztBQUtBLFNBQU8sU0FBU0MsUUFBVCxHQUFvQjtBQUN6QixRQUFJSixlQUFlLENBQUNFLGdCQUFwQixFQUFzQztBQUNwQyxVQUFJRCxpQkFBSixFQUF1QjtBQUNyQkU7QUFDRCxPQUZELE1BRU87QUFDTEgsc0JBQWMsS0FBZDtBQUNEOztBQUVEO0FBQ0E7QUFDQSxVQUFJSCxRQUFRTSxXQUFSLElBQXVCSixPQUEzQixFQUFvQztBQUNsQyxlQUFPSSxXQUFQO0FBQ0Q7O0FBRURELHlCQUFtQixJQUFuQjtBQUNEOztBQUVELFFBQUksQ0FBQ0QsaUJBQUwsRUFBd0I7QUFDdEIsVUFBSSxDQUFDQyxnQkFBTCxFQUF1QjtBQUNyQkYsc0JBQWMsSUFBZDtBQUNEOztBQUVEO0FBQ0E7QUFDQSxVQUFJRixXQUFXRCxRQUFRTSxXQUF2QixFQUFvQztBQUNsQyxlQUFPLENBQUNBLGFBQVI7QUFDRDs7QUFFREYsMEJBQW9CLElBQXBCO0FBQ0EsYUFBT0csVUFBUDtBQUNEOztBQUVEO0FBQ0E7QUFDRCxHQWxDRDtBQW1DRCxDIiwiZmlsZSI6ImRpc3RhbmNlLWl0ZXJhdG9yLmpzIiwic291cmNlc0NvbnRlbnQiOlsiLy8gSXRlcmF0b3IgdGhhdCB0cmF2ZXJzZXMgaW4gdGhlIHJhbmdlIG9mIFttaW4sIG1heF0sIHN0ZXBwaW5nXG4vLyBieSBkaXN0YW5jZSBmcm9tIGEgZ2l2ZW4gc3RhcnQgcG9zaXRpb24uIEkuZS4gZm9yIFswLCA0XSwgd2l0aFxuLy8gc3RhcnQgb2YgMiwgdGhpcyB3aWxsIGl0ZXJhdGUgMiwgMywgMSwgNCwgMC5cbmV4cG9ydCBkZWZhdWx0IGZ1bmN0aW9uKHN0YXJ0LCBtaW5MaW5lLCBtYXhMaW5lKSB7XG4gIGxldCB3YW50Rm9yd2FyZCA9IHRydWUsXG4gICAgICBiYWNrd2FyZEV4aGF1c3RlZCA9IGZhbHNlLFxuICAgICAgZm9yd2FyZEV4aGF1c3RlZCA9IGZhbHNlLFxuICAgICAgbG9jYWxPZmZzZXQgPSAxO1xuXG4gIHJldHVybiBmdW5jdGlvbiBpdGVyYXRvcigpIHtcbiAgICBpZiAod2FudEZvcndhcmQgJiYgIWZvcndhcmRFeGhhdXN0ZWQpIHtcbiAgICAgIGlmIChiYWNrd2FyZEV4aGF1c3RlZCkge1xuICAgICAgICBsb2NhbE9mZnNldCsrO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgd2FudEZvcndhcmQgPSBmYWxzZTtcbiAgICAgIH1cblxuICAgICAgLy8gQ2hlY2sgaWYgdHJ5aW5nIHRvIGZpdCBiZXlvbmQgdGV4dCBsZW5ndGgsIGFuZCBpZiBub3QsIGNoZWNrIGl0IGZpdHNcbiAgICAgIC8vIGFmdGVyIG9mZnNldCBsb2NhdGlvbiAob3IgZGVzaXJlZCBsb2NhdGlvbiBvbiBmaXJzdCBpdGVyYXRpb24pXG4gICAgICBpZiAoc3RhcnQgKyBsb2NhbE9mZnNldCA8PSBtYXhMaW5lKSB7XG4gICAgICAgIHJldHVybiBsb2NhbE9mZnNldDtcbiAgICAgIH1cblxuICAgICAgZm9yd2FyZEV4aGF1c3RlZCA9IHRydWU7XG4gICAgfVxuXG4gICAgaWYgKCFiYWNrd2FyZEV4aGF1c3RlZCkge1xuICAgICAgaWYgKCFmb3J3YXJkRXhoYXVzdGVkKSB7XG4gICAgICAgIHdhbnRGb3J3YXJkID0gdHJ1ZTtcbiAgICAgIH1cblxuICAgICAgLy8gQ2hlY2sgaWYgdHJ5aW5nIHRvIGZpdCBiZWZvcmUgdGV4dCBiZWdpbm5pbmcsIGFuZCBpZiBub3QsIGNoZWNrIGl0IGZpdHNcbiAgICAgIC8vIGJlZm9yZSBvZmZzZXQgbG9jYXRpb25cbiAgICAgIGlmIChtaW5MaW5lIDw9IHN0YXJ0IC0gbG9jYWxPZmZzZXQpIHtcbiAgICAgICAgcmV0dXJuIC1sb2NhbE9mZnNldCsrO1xuICAgICAgfVxuXG4gICAgICBiYWNrd2FyZEV4aGF1c3RlZCA9IHRydWU7XG4gICAgICByZXR1cm4gaXRlcmF0b3IoKTtcbiAgICB9XG5cbiAgICAvLyBXZSB0cmllZCB0byBmaXQgaHVuayBiZWZvcmUgdGV4dCBiZWdpbm5pbmcgYW5kIGJleW9uZCB0ZXh0IGxlbmd0aCwgdGhlblxuICAgIC8vIGh1bmsgY2FuJ3QgZml0IG9uIHRoZSB0ZXh0LiBSZXR1cm4gdW5kZWZpbmVkXG4gIH07XG59XG4iXX0= + //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy91dGlsL2Rpc3RhbmNlLWl0ZXJhdG9yLmpzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7NENBR2UsVUFBUyxLQUFULEVBQWdCLE9BQWhCLEVBQXlCLE9BQXpCLEVBQWtDO0FBQy9DLE1BQUksY0FBYyxJQUFsQjtBQUFBLE1BQ0ksb0JBQW9CLEtBRHhCO0FBQUEsTUFFSSxtQkFBbUIsS0FGdkI7QUFBQSxNQUdJLGNBQWMsQ0FIbEI7O0FBS0EsU0FBTyxTQUFTLFFBQVQsR0FBb0I7QUFDekIsUUFBSSxlQUFlLENBQUMsZ0JBQXBCLEVBQXNDO0FBQ3BDLFVBQUksaUJBQUosRUFBdUI7QUFDckI7QUFDRCxPQUZELE1BRU87QUFDTCxzQkFBYyxLQUFkO0FBQ0Q7Ozs7QUFJRCxVQUFJLFFBQVEsV0FBUixJQUF1QixPQUEzQixFQUFvQztBQUNsQyxlQUFPLFdBQVA7QUFDRDs7QUFFRCx5QkFBbUIsSUFBbkI7QUFDRDs7QUFFRCxRQUFJLENBQUMsaUJBQUwsRUFBd0I7QUFDdEIsVUFBSSxDQUFDLGdCQUFMLEVBQXVCO0FBQ3JCLHNCQUFjLElBQWQ7QUFDRDs7OztBQUlELFVBQUksV0FBVyxRQUFRLFdBQXZCLEVBQW9DO0FBQ2xDLGVBQU8sQ0FBQyxhQUFSO0FBQ0Q7O0FBRUQsMEJBQW9CLElBQXBCO0FBQ0EsYUFBTyxVQUFQO0FBQ0Q7Ozs7QUFJRixHQWxDRDtBQW1DRCxDIiwiZmlsZSI6ImRpc3RhbmNlLWl0ZXJhdG9yLmpzIiwic291cmNlc0NvbnRlbnQiOlsiLy8gSXRlcmF0b3IgdGhhdCB0cmF2ZXJzZXMgaW4gdGhlIHJhbmdlIG9mIFttaW4sIG1heF0sIHN0ZXBwaW5nXG4vLyBieSBkaXN0YW5jZSBmcm9tIGEgZ2l2ZW4gc3RhcnQgcG9zaXRpb24uIEkuZS4gZm9yIFswLCA0XSwgd2l0aFxuLy8gc3RhcnQgb2YgMiwgdGhpcyB3aWxsIGl0ZXJhdGUgMiwgMywgMSwgNCwgMC5cbmV4cG9ydCBkZWZhdWx0IGZ1bmN0aW9uKHN0YXJ0LCBtaW5MaW5lLCBtYXhMaW5lKSB7XG4gIGxldCB3YW50Rm9yd2FyZCA9IHRydWUsXG4gICAgICBiYWNrd2FyZEV4aGF1c3RlZCA9IGZhbHNlLFxuICAgICAgZm9yd2FyZEV4aGF1c3RlZCA9IGZhbHNlLFxuICAgICAgbG9jYWxPZmZzZXQgPSAxO1xuXG4gIHJldHVybiBmdW5jdGlvbiBpdGVyYXRvcigpIHtcbiAgICBpZiAod2FudEZvcndhcmQgJiYgIWZvcndhcmRFeGhhdXN0ZWQpIHtcbiAgICAgIGlmIChiYWNrd2FyZEV4aGF1c3RlZCkge1xuICAgICAgICBsb2NhbE9mZnNldCsrO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgd2FudEZvcndhcmQgPSBmYWxzZTtcbiAgICAgIH1cblxuICAgICAgLy8gQ2hlY2sgaWYgdHJ5aW5nIHRvIGZpdCBiZXlvbmQgdGV4dCBsZW5ndGgsIGFuZCBpZiBub3QsIGNoZWNrIGl0IGZpdHNcbiAgICAgIC8vIGFmdGVyIG9mZnNldCBsb2NhdGlvbiAob3IgZGVzaXJlZCBsb2NhdGlvbiBvbiBmaXJzdCBpdGVyYXRpb24pXG4gICAgICBpZiAoc3RhcnQgKyBsb2NhbE9mZnNldCA8PSBtYXhMaW5lKSB7XG4gICAgICAgIHJldHVybiBsb2NhbE9mZnNldDtcbiAgICAgIH1cblxuICAgICAgZm9yd2FyZEV4aGF1c3RlZCA9IHRydWU7XG4gICAgfVxuXG4gICAgaWYgKCFiYWNrd2FyZEV4aGF1c3RlZCkge1xuICAgICAgaWYgKCFmb3J3YXJkRXhoYXVzdGVkKSB7XG4gICAgICAgIHdhbnRGb3J3YXJkID0gdHJ1ZTtcbiAgICAgIH1cblxuICAgICAgLy8gQ2hlY2sgaWYgdHJ5aW5nIHRvIGZpdCBiZWZvcmUgdGV4dCBiZWdpbm5pbmcsIGFuZCBpZiBub3QsIGNoZWNrIGl0IGZpdHNcbiAgICAgIC8vIGJlZm9yZSBvZmZzZXQgbG9jYXRpb25cbiAgICAgIGlmIChtaW5MaW5lIDw9IHN0YXJ0IC0gbG9jYWxPZmZzZXQpIHtcbiAgICAgICAgcmV0dXJuIC1sb2NhbE9mZnNldCsrO1xuICAgICAgfVxuXG4gICAgICBiYWNrd2FyZEV4aGF1c3RlZCA9IHRydWU7XG4gICAgICByZXR1cm4gaXRlcmF0b3IoKTtcbiAgICB9XG5cbiAgICAvLyBXZSB0cmllZCB0byBmaXQgaHVuayBiZWZvcmUgdGV4dCBiZWdpbm5pbmcgYW5kIGJleW9uZCB0ZXh0IGxlbmdodCwgdGhlblxuICAgIC8vIGh1bmsgY2FuJ3QgZml0IG9uIHRoZSB0ZXh0LiBSZXR1cm4gdW5kZWZpbmVkXG4gIH07XG59XG4iXX0= -/***/ }), +/***/ }, /* 13 */ -/***/ (function(module, exports, __webpack_require__) { - - /*istanbul ignore start*/'use strict'; - - exports.__esModule = true; - exports. /*istanbul ignore end*/calcLineCount = calcLineCount; - /*istanbul ignore start*/exports. /*istanbul ignore end*/merge = merge; - - var /*istanbul ignore start*/_create = __webpack_require__(14) /*istanbul ignore end*/; - - var /*istanbul ignore start*/_parse = __webpack_require__(11) /*istanbul ignore end*/; - - var /*istanbul ignore start*/_array = __webpack_require__(15) /*istanbul ignore end*/; - - /*istanbul ignore start*/function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } } - - /*istanbul ignore end*/function calcLineCount(hunk) { - /*istanbul ignore start*/var _calcOldNewLineCount = /*istanbul ignore end*/calcOldNewLineCount(hunk.lines), - oldLines = _calcOldNewLineCount.oldLines, - newLines = _calcOldNewLineCount.newLines; - - if (oldLines !== undefined) { - hunk.oldLines = oldLines; - } else { - delete hunk.oldLines; - } - - if (newLines !== undefined) { - hunk.newLines = newLines; - } else { - delete hunk.newLines; - } - } - - function merge(mine, theirs, base) { - mine = loadPatch(mine, base); - theirs = loadPatch(theirs, base); - - var ret = {}; - - // For index we just let it pass through as it doesn't have any necessary meaning. - // Leaving sanity checks on this to the API consumer that may know more about the - // meaning in their own context. - if (mine.index || theirs.index) { - ret.index = mine.index || theirs.index; - } - - if (mine.newFileName || theirs.newFileName) { - if (!fileNameChanged(mine)) { - // No header or no change in ours, use theirs (and ours if theirs does not exist) - ret.oldFileName = theirs.oldFileName || mine.oldFileName; - ret.newFileName = theirs.newFileName || mine.newFileName; - ret.oldHeader = theirs.oldHeader || mine.oldHeader; - ret.newHeader = theirs.newHeader || mine.newHeader; - } else if (!fileNameChanged(theirs)) { - // No header or no change in theirs, use ours - ret.oldFileName = mine.oldFileName; - ret.newFileName = mine.newFileName; - ret.oldHeader = mine.oldHeader; - ret.newHeader = mine.newHeader; - } else { - // Both changed... figure it out - ret.oldFileName = selectField(ret, mine.oldFileName, theirs.oldFileName); - ret.newFileName = selectField(ret, mine.newFileName, theirs.newFileName); - ret.oldHeader = selectField(ret, mine.oldHeader, theirs.oldHeader); - ret.newHeader = selectField(ret, mine.newHeader, theirs.newHeader); - } - } - - ret.hunks = []; - - var mineIndex = 0, - theirsIndex = 0, - mineOffset = 0, - theirsOffset = 0; - - while (mineIndex < mine.hunks.length || theirsIndex < theirs.hunks.length) { - var mineCurrent = mine.hunks[mineIndex] || { oldStart: Infinity }, - theirsCurrent = theirs.hunks[theirsIndex] || { oldStart: Infinity }; - - if (hunkBefore(mineCurrent, theirsCurrent)) { - // This patch does not overlap with any of the others, yay. - ret.hunks.push(cloneHunk(mineCurrent, mineOffset)); - mineIndex++; - theirsOffset += mineCurrent.newLines - mineCurrent.oldLines; - } else if (hunkBefore(theirsCurrent, mineCurrent)) { - // This patch does not overlap with any of the others, yay. - ret.hunks.push(cloneHunk(theirsCurrent, theirsOffset)); - theirsIndex++; - mineOffset += theirsCurrent.newLines - theirsCurrent.oldLines; - } else { - // Overlap, merge as best we can - var mergedHunk = { - oldStart: Math.min(mineCurrent.oldStart, theirsCurrent.oldStart), - oldLines: 0, - newStart: Math.min(mineCurrent.newStart + mineOffset, theirsCurrent.oldStart + theirsOffset), - newLines: 0, - lines: [] - }; - mergeLines(mergedHunk, mineCurrent.oldStart, mineCurrent.lines, theirsCurrent.oldStart, theirsCurrent.lines); - theirsIndex++; - mineIndex++; - - ret.hunks.push(mergedHunk); - } - } - - return ret; - } - - function loadPatch(param, base) { - if (typeof param === 'string') { - if (/^@@/m.test(param) || /^Index:/m.test(param)) { - return (/*istanbul ignore start*/(0, _parse.parsePatch) /*istanbul ignore end*/(param)[0] - ); - } - - if (!base) { - throw new Error('Must provide a base reference or pass in a patch'); - } - return (/*istanbul ignore start*/(0, _create.structuredPatch) /*istanbul ignore end*/(undefined, undefined, base, param) - ); - } - - return param; - } - - function fileNameChanged(patch) { - return patch.newFileName && patch.newFileName !== patch.oldFileName; - } - - function selectField(index, mine, theirs) { - if (mine === theirs) { - return mine; - } else { - index.conflict = true; - return { mine: mine, theirs: theirs }; - } - } - - function hunkBefore(test, check) { - return test.oldStart < check.oldStart && test.oldStart + test.oldLines < check.oldStart; - } - - function cloneHunk(hunk, offset) { - return { - oldStart: hunk.oldStart, oldLines: hunk.oldLines, - newStart: hunk.newStart + offset, newLines: hunk.newLines, - lines: hunk.lines - }; - } - - function mergeLines(hunk, mineOffset, mineLines, theirOffset, theirLines) { - // This will generally result in a conflicted hunk, but there are cases where the context - // is the only overlap where we can successfully merge the content here. - var mine = { offset: mineOffset, lines: mineLines, index: 0 }, - their = { offset: theirOffset, lines: theirLines, index: 0 }; - - // Handle any leading content - insertLeading(hunk, mine, their); - insertLeading(hunk, their, mine); - - // Now in the overlap content. Scan through and select the best changes from each. - while (mine.index < mine.lines.length && their.index < their.lines.length) { - var mineCurrent = mine.lines[mine.index], - theirCurrent = their.lines[their.index]; - - if ((mineCurrent[0] === '-' || mineCurrent[0] === '+') && (theirCurrent[0] === '-' || theirCurrent[0] === '+')) { - // Both modified ... - mutualChange(hunk, mine, their); - } else if (mineCurrent[0] === '+' && theirCurrent[0] === ' ') { - /*istanbul ignore start*/var _hunk$lines; - - /*istanbul ignore end*/ // Mine inserted - /*istanbul ignore start*/(_hunk$lines = /*istanbul ignore end*/hunk.lines).push. /*istanbul ignore start*/apply /*istanbul ignore end*/( /*istanbul ignore start*/_hunk$lines /*istanbul ignore end*/, /*istanbul ignore start*/_toConsumableArray( /*istanbul ignore end*/collectChange(mine))); - } else if (theirCurrent[0] === '+' && mineCurrent[0] === ' ') { - /*istanbul ignore start*/var _hunk$lines2; - - /*istanbul ignore end*/ // Theirs inserted - /*istanbul ignore start*/(_hunk$lines2 = /*istanbul ignore end*/hunk.lines).push. /*istanbul ignore start*/apply /*istanbul ignore end*/( /*istanbul ignore start*/_hunk$lines2 /*istanbul ignore end*/, /*istanbul ignore start*/_toConsumableArray( /*istanbul ignore end*/collectChange(their))); - } else if (mineCurrent[0] === '-' && theirCurrent[0] === ' ') { - // Mine removed or edited - removal(hunk, mine, their); - } else if (theirCurrent[0] === '-' && mineCurrent[0] === ' ') { - // Their removed or edited - removal(hunk, their, mine, true); - } else if (mineCurrent === theirCurrent) { - // Context identity - hunk.lines.push(mineCurrent); - mine.index++; - their.index++; - } else { - // Context mismatch - conflict(hunk, collectChange(mine), collectChange(their)); - } - } - - // Now push anything that may be remaining - insertTrailing(hunk, mine); - insertTrailing(hunk, their); - - calcLineCount(hunk); - } - - function mutualChange(hunk, mine, their) { - var myChanges = collectChange(mine), - theirChanges = collectChange(their); - - if (allRemoves(myChanges) && allRemoves(theirChanges)) { - // Special case for remove changes that are supersets of one another - if ( /*istanbul ignore start*/(0, _array.arrayStartsWith) /*istanbul ignore end*/(myChanges, theirChanges) && skipRemoveSuperset(their, myChanges, myChanges.length - theirChanges.length)) { - /*istanbul ignore start*/var _hunk$lines3; - - /*istanbul ignore end*/ /*istanbul ignore start*/(_hunk$lines3 = /*istanbul ignore end*/hunk.lines).push. /*istanbul ignore start*/apply /*istanbul ignore end*/( /*istanbul ignore start*/_hunk$lines3 /*istanbul ignore end*/, /*istanbul ignore start*/_toConsumableArray( /*istanbul ignore end*/myChanges)); - return; - } else if ( /*istanbul ignore start*/(0, _array.arrayStartsWith) /*istanbul ignore end*/(theirChanges, myChanges) && skipRemoveSuperset(mine, theirChanges, theirChanges.length - myChanges.length)) { - /*istanbul ignore start*/var _hunk$lines4; - - /*istanbul ignore end*/ /*istanbul ignore start*/(_hunk$lines4 = /*istanbul ignore end*/hunk.lines).push. /*istanbul ignore start*/apply /*istanbul ignore end*/( /*istanbul ignore start*/_hunk$lines4 /*istanbul ignore end*/, /*istanbul ignore start*/_toConsumableArray( /*istanbul ignore end*/theirChanges)); - return; - } - } else if ( /*istanbul ignore start*/(0, _array.arrayEqual) /*istanbul ignore end*/(myChanges, theirChanges)) { - /*istanbul ignore start*/var _hunk$lines5; - - /*istanbul ignore end*/ /*istanbul ignore start*/(_hunk$lines5 = /*istanbul ignore end*/hunk.lines).push. /*istanbul ignore start*/apply /*istanbul ignore end*/( /*istanbul ignore start*/_hunk$lines5 /*istanbul ignore end*/, /*istanbul ignore start*/_toConsumableArray( /*istanbul ignore end*/myChanges)); - return; - } - - conflict(hunk, myChanges, theirChanges); - } - - function removal(hunk, mine, their, swap) { - var myChanges = collectChange(mine), - theirChanges = collectContext(their, myChanges); - if (theirChanges.merged) { - /*istanbul ignore start*/var _hunk$lines6; - - /*istanbul ignore end*/ /*istanbul ignore start*/(_hunk$lines6 = /*istanbul ignore end*/hunk.lines).push. /*istanbul ignore start*/apply /*istanbul ignore end*/( /*istanbul ignore start*/_hunk$lines6 /*istanbul ignore end*/, /*istanbul ignore start*/_toConsumableArray( /*istanbul ignore end*/theirChanges.merged)); - } else { - conflict(hunk, swap ? theirChanges : myChanges, swap ? myChanges : theirChanges); - } - } - - function conflict(hunk, mine, their) { - hunk.conflict = true; - hunk.lines.push({ - conflict: true, - mine: mine, - theirs: their - }); - } - - function insertLeading(hunk, insert, their) { - while (insert.offset < their.offset && insert.index < insert.lines.length) { - var line = insert.lines[insert.index++]; - hunk.lines.push(line); - insert.offset++; - } - } - function insertTrailing(hunk, insert) { - while (insert.index < insert.lines.length) { - var line = insert.lines[insert.index++]; - hunk.lines.push(line); - } - } - - function collectChange(state) { - var ret = [], - operation = state.lines[state.index][0]; - while (state.index < state.lines.length) { - var line = state.lines[state.index]; - - // Group additions that are immediately after subtractions and treat them as one "atomic" modify change. - if (operation === '-' && line[0] === '+') { - operation = '+'; - } - - if (operation === line[0]) { - ret.push(line); - state.index++; - } else { - break; - } - } - - return ret; - } - function collectContext(state, matchChanges) { - var changes = [], - merged = [], - matchIndex = 0, - contextChanges = false, - conflicted = false; - while (matchIndex < matchChanges.length && state.index < state.lines.length) { - var change = state.lines[state.index], - match = matchChanges[matchIndex]; - - // Once we've hit our add, then we are done - if (match[0] === '+') { - break; - } - - contextChanges = contextChanges || change[0] !== ' '; - - merged.push(match); - matchIndex++; - - // Consume any additions in the other block as a conflict to attempt - // to pull in the remaining context after this - if (change[0] === '+') { - conflicted = true; - - while (change[0] === '+') { - changes.push(change); - change = state.lines[++state.index]; - } - } - - if (match.substr(1) === change.substr(1)) { - changes.push(change); - state.index++; - } else { - conflicted = true; - } - } - - if ((matchChanges[matchIndex] || '')[0] === '+' && contextChanges) { - conflicted = true; - } - - if (conflicted) { - return changes; - } - - while (matchIndex < matchChanges.length) { - merged.push(matchChanges[matchIndex++]); - } - - return { - merged: merged, - changes: changes - }; - } - - function allRemoves(changes) { - return changes.reduce(function (prev, change) { - return prev && change[0] === '-'; - }, true); - } - function skipRemoveSuperset(state, removeChanges, delta) { - for (var i = 0; i < delta; i++) { - var changeContent = removeChanges[removeChanges.length - delta + i].substr(1); - if (state.lines[state.index + i] !== ' ' + changeContent) { - return false; - } - } - - state.index += delta; - return true; - } - - function calcOldNewLineCount(lines) { - var oldLines = 0; - var newLines = 0; - - lines.forEach(function (line) { - if (typeof line !== 'string') { - var myCount = calcOldNewLineCount(line.mine); - var theirCount = calcOldNewLineCount(line.theirs); - - if (oldLines !== undefined) { - if (myCount.oldLines === theirCount.oldLines) { - oldLines += myCount.oldLines; - } else { - oldLines = undefined; - } - } - - if (newLines !== undefined) { - if (myCount.newLines === theirCount.newLines) { - newLines += myCount.newLines; - } else { - newLines = undefined; - } - } - } else { - if (newLines !== undefined && (line[0] === '+' || line[0] === ' ')) { - newLines++; - } - if (oldLines !== undefined && (line[0] === '-' || line[0] === ' ')) { - oldLines++; - } - } - }); - - return { oldLines: oldLines, newLines: newLines }; - } - //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9wYXRjaC9tZXJnZS5qcyJdLCJuYW1lcyI6WyJjYWxjTGluZUNvdW50IiwibWVyZ2UiLCJodW5rIiwiY2FsY09sZE5ld0xpbmVDb3VudCIsImxpbmVzIiwib2xkTGluZXMiLCJuZXdMaW5lcyIsInVuZGVmaW5lZCIsIm1pbmUiLCJ0aGVpcnMiLCJiYXNlIiwibG9hZFBhdGNoIiwicmV0IiwiaW5kZXgiLCJuZXdGaWxlTmFtZSIsImZpbGVOYW1lQ2hhbmdlZCIsIm9sZEZpbGVOYW1lIiwib2xkSGVhZGVyIiwibmV3SGVhZGVyIiwic2VsZWN0RmllbGQiLCJodW5rcyIsIm1pbmVJbmRleCIsInRoZWlyc0luZGV4IiwibWluZU9mZnNldCIsInRoZWlyc09mZnNldCIsImxlbmd0aCIsIm1pbmVDdXJyZW50Iiwib2xkU3RhcnQiLCJJbmZpbml0eSIsInRoZWlyc0N1cnJlbnQiLCJodW5rQmVmb3JlIiwicHVzaCIsImNsb25lSHVuayIsIm1lcmdlZEh1bmsiLCJNYXRoIiwibWluIiwibmV3U3RhcnQiLCJtZXJnZUxpbmVzIiwicGFyYW0iLCJ0ZXN0IiwiRXJyb3IiLCJwYXRjaCIsImNvbmZsaWN0IiwiY2hlY2siLCJvZmZzZXQiLCJtaW5lTGluZXMiLCJ0aGVpck9mZnNldCIsInRoZWlyTGluZXMiLCJ0aGVpciIsImluc2VydExlYWRpbmciLCJ0aGVpckN1cnJlbnQiLCJtdXR1YWxDaGFuZ2UiLCJjb2xsZWN0Q2hhbmdlIiwicmVtb3ZhbCIsImluc2VydFRyYWlsaW5nIiwibXlDaGFuZ2VzIiwidGhlaXJDaGFuZ2VzIiwiYWxsUmVtb3ZlcyIsInNraXBSZW1vdmVTdXBlcnNldCIsInN3YXAiLCJjb2xsZWN0Q29udGV4dCIsIm1lcmdlZCIsImluc2VydCIsImxpbmUiLCJzdGF0ZSIsIm9wZXJhdGlvbiIsIm1hdGNoQ2hhbmdlcyIsImNoYW5nZXMiLCJtYXRjaEluZGV4IiwiY29udGV4dENoYW5nZXMiLCJjb25mbGljdGVkIiwiY2hhbmdlIiwibWF0Y2giLCJzdWJzdHIiLCJyZWR1Y2UiLCJwcmV2IiwicmVtb3ZlQ2hhbmdlcyIsImRlbHRhIiwiaSIsImNoYW5nZUNvbnRlbnQiLCJmb3JFYWNoIiwibXlDb3VudCIsInRoZWlyQ291bnQiXSwibWFwcGluZ3MiOiI7OztnQ0FLZ0JBLGEsR0FBQUEsYTt5REFnQkFDLEssR0FBQUEsSzs7QUFyQmhCOztBQUNBOztBQUVBOzs7O3VCQUVPLFNBQVNELGFBQVQsQ0FBdUJFLElBQXZCLEVBQTZCO0FBQUEsNkVBQ0xDLG9CQUFvQkQsS0FBS0UsS0FBekIsQ0FESztBQUFBLE1BQzNCQyxRQUQyQix3QkFDM0JBLFFBRDJCO0FBQUEsTUFDakJDLFFBRGlCLHdCQUNqQkEsUUFEaUI7O0FBR2xDLE1BQUlELGFBQWFFLFNBQWpCLEVBQTRCO0FBQzFCTCxTQUFLRyxRQUFMLEdBQWdCQSxRQUFoQjtBQUNELEdBRkQsTUFFTztBQUNMLFdBQU9ILEtBQUtHLFFBQVo7QUFDRDs7QUFFRCxNQUFJQyxhQUFhQyxTQUFqQixFQUE0QjtBQUMxQkwsU0FBS0ksUUFBTCxHQUFnQkEsUUFBaEI7QUFDRCxHQUZELE1BRU87QUFDTCxXQUFPSixLQUFLSSxRQUFaO0FBQ0Q7QUFDRjs7QUFFTSxTQUFTTCxLQUFULENBQWVPLElBQWYsRUFBcUJDLE1BQXJCLEVBQTZCQyxJQUE3QixFQUFtQztBQUN4Q0YsU0FBT0csVUFBVUgsSUFBVixFQUFnQkUsSUFBaEIsQ0FBUDtBQUNBRCxXQUFTRSxVQUFVRixNQUFWLEVBQWtCQyxJQUFsQixDQUFUOztBQUVBLE1BQUlFLE1BQU0sRUFBVjs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxNQUFJSixLQUFLSyxLQUFMLElBQWNKLE9BQU9JLEtBQXpCLEVBQWdDO0FBQzlCRCxRQUFJQyxLQUFKLEdBQVlMLEtBQUtLLEtBQUwsSUFBY0osT0FBT0ksS0FBakM7QUFDRDs7QUFFRCxNQUFJTCxLQUFLTSxXQUFMLElBQW9CTCxPQUFPSyxXQUEvQixFQUE0QztBQUMxQyxRQUFJLENBQUNDLGdCQUFnQlAsSUFBaEIsQ0FBTCxF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Q0Q7QUFDRjs7QUFFRCxVQUFJRCxhQUFhQyxTQUFqQixFQUE0QjtBQUMxQixZQUFJMEUsUUFBUTNFLFFBQVIsS0FBcUI0RSxXQUFXNUUsUUFBcEMsRUFBOEM7QUFDNUNBLHNCQUFZMkUsUUFBUTNFLFFBQXBCO0FBQ0QsU0FGRCxNQUVPO0FBQ0xBLHFCQUFXQyxTQUFYO0FBQ0Q7QUFDRjtBQUNGLEtBbkJELE1BbUJPO0FBQ0wsVUFBSUQsYUFBYUMsU0FBYixLQUEyQndELEtBQUssQ0FBTCxNQUFZLEdBQVosSUFBbUJBLEtBQUssQ0FBTCxNQUFZLEdBQTFELENBQUosRUFBb0U7QUFDbEV6RDtBQUNEO0FBQ0QsVUFBSUQsYUFBYUUsU0FBYixLQUEyQndELEtBQUssQ0FBTCxNQUFZLEdBQVosSUFBbUJBLEtBQUssQ0FBTCxNQUFZLEdBQTFELENBQUosRUFBb0U7QUFDbEUxRDtBQUNEO0FBQ0Y7QUFDRixHQTVCRDs7QUE4QkEsU0FBTyxFQUFDQSxrQkFBRCxFQUFXQyxrQkFBWCxFQUFQO0FBQ0QiLCJmaWxlIjoibWVyZ2UuanMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge3N0cnVjdHVyZWRQYXRjaH0gZnJvbSAnLi9jcmVhdGUnO1xuaW1wb3J0IHtwYXJzZVBhdGNofSBmcm9tICcuL3BhcnNlJztcblxuaW1wb3J0IHthcnJheUVxdWFsLCBhcnJheVN0YXJ0c1dpdGh9IGZyb20gJy4uL3V0aWwvYXJyYXknO1xuXG5leHBvcnQgZnVuY3Rpb24gY2FsY0xpbmVDb3VudChodW5rKSB7XG4gIGNvbnN0IHtvbGRMaW5lcywgbmV3TGluZXN9ID0gY2FsY09sZE5ld0xpbmVDb3VudChodW5rLmxpbmVzKTtcblxuICBpZiAob2xkTGluZXMgIT09IHVuZGVmaW5lZCkge1xuICAgIGh1bmsub2xkTGluZXMgPSBvbGRMaW5lcztcbiAgfSBlbHNlIHtcbiAgICBkZWxldGUgaHVuay5vbGRMaW5lcztcbiAgfVxuXG4gIGlmIChuZXdMaW5lcyAhPT0gdW5kZWZpbmVkKSB7XG4gICAgaHVuay5uZXdMaW5lcyA9IG5ld0xpbmVzO1xuICB9IGVsc2Uge1xuICAgIGRlbGV0ZSBodW5rLm5ld0xpbmVzO1xuICB9XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBtZXJnZShtaW5lLCB0aGVpcnMsIGJhc2UpIHtcbiAgbWluZSA9IGxvYWRQYXRjaChtaW5lLCBiYXNlKTtcbiAgdGhlaXJzID0gbG9hZFBhdGNoKHRoZWlycywgYmFzZSk7XG5cbiAgbGV0IHJldCA9IHt9O1xuXG4gIC8vIEZvciBpbmRleCB3ZSBqdXN0IGxldCBpdCBwYXNzIHRocm91Z2ggYXMgaXQgZG9lc24ndCBoYXZlIGFueSBuZWNlc3NhcnkgbWVhbmluZy5cbiAgLy8gTGVhdmluZyBzYW5pdHkgY2hlY2tzIG9uIHRoaXMgdG8gdGhlIEFQSSBjb25zdW1lciB0aGF0IG1heSBrbm93IG1vcmUgYWJvdXQgdGhlXG4gIC8vIG1lYW5pbmcgaW4gdGhlaXIgb3duIGNvbnRleHQuXG4gIGlmIChtaW5lLmluZGV4IHx8IHRoZWlycy5pbmRleCkge1xuICAgIHJldC5pbmRleCA9IG1pbmUuaW5kZXggfHwgdGhlaXJzLmluZGV4O1xuICB9XG5cbiAgaWYgKG1pbmUubmV3RmlsZU5hbWUgfHwgdGhlaXJzLm5ld0ZpbGVOYW1lKSB7XG4gICAgaWYgKCFmaWxlTmFtZUNoYW5nZWQobWluZSkpIHtcbiAgICAgIC8vIE5vIGhlYWRlciBvciBubyBjaGFuZ2UgaW4gb3VycywgdXNlIHRoZWlycyAoYW5kIG91cnMgaWYgdGhlaXJzIGRvZXMgbm90IGV4aXN0KVxuICAgICAgcmV0Lm9sZEZpbGVOYW1lID0gdGhlaXJzLm9sZEZpbGVOYW1lIHx8IG1pbmUub2xkRmlsZU5hbWU7XG4gICAgICByZXQubmV3RmlsZU5hbWUgPSB0aGVpcnMubmV3RmlsZU5hbWUgfHwgbWluZS5uZXdGaWxlTmFtZTtcbiAgICAgIHJldC5vbGRIZWFkZXIgPSB0aGVpcnMub2xkSGVhZGVyIHx8IG1pbmUub2xkSGVhZGVyO1xuICAgICAgcmV0Lm5ld0hlYWRlciA9IHRoZWlycy5uZXdIZWFkZXIgfHwgbWluZS5uZXdIZWFkZXI7XG4gICAgfSBlbHNlIGlmICghZmlsZU5hbWVDaGFuZ2VkKHRoZWlycykpIHtcbiAgICAgIC8vIE5vIGhlYWRlciBvciBubyBjaGFuZ2UgaW4gdGhlaXJzLCB1c2Ugb3Vyc1xuICAgICAgcmV0Lm9sZEZpbGVOYW1lID0gbWluZS5vbGRGaWxlTmFtZTtcbiAgICAgIHJldC5uZXdGaWxlTmFtZSA9IG1pbmUubmV3RmlsZU5hbWU7XG4gICAgICByZXQub2xkSGVhZGVyID0gbWluZS5vbGRIZWFkZXI7XG4gICAgICByZXQubmV3SGVhZGVyID0gbWluZS5uZXdIZWFkZXI7XG4gICAgfSBlbHNlIHtcbiAgICAgIC8vIEJvdGggY2hhbmdlZC4uLiBmaWd1cmUgaXQgb3V0XG4gICAgICByZXQub2xkRmlsZU5hbWUgPSBzZWxlY3RGaWVsZChyZXQsIG1pbmUub2xkRmlsZU5hbWUsIHRoZWlycy5vbGRGaWxlTmFtZSk7XG4gICAgICByZXQubmV3RmlsZU5hbWUgPSBzZWxlY3RGaWVsZChyZXQsIG1pbmUubmV3RmlsZU5hbWUsIHRoZWlycy5uZXdGaWxlTmFtZSk7XG4gICAgICByZXQub2xkSGVhZGVyID0gc2VsZWN0RmllbGQocmV0LCBtaW5lLm9sZEhlYWRlciwgdGhlaXJzLm9sZEhlYWRlcik7XG4gICAgICByZXQubmV3SGVhZGVyID0gc2VsZWN0RmllbGQocmV0LCBtaW5lLm5ld0hlYWRlciwgdGhlaXJzLm5ld0hlYWRlcik7XG4gICAgfVxuICB9XG5cbiAgcmV0Lmh1bmtzID0gW107XG5cbiAgbGV0IG1pbmVJbmRleCA9IDAsXG4gICAgICB0aGVpcnNJbmRleCA9IDAsXG4gICAgICBtaW5lT2Zmc2V0ID0gMCxcbiAgICAgIHRoZWlyc09mZnNldCA9IDA7XG5cbiAgd2hpbGUgKG1pbmVJbmRleCA8IG1pbmUuaHVua3MubGVuZ3RoIHx8IHRoZWlyc0luZGV4IDwgdGhlaXJzLmh1bmtzLmxlbmd0aCkge1xuICAgIGxldCBtaW5lQ3VycmVudCA9IG1pbmUuaHVua3NbbWluZUluZGV4XSB8fCB7b2xkU3RhcnQ6IEluZmluaXR5fSxcbiAgICAgICAgdGhlaXJzQ3VycmVudCA9IHRoZWlycy5odW5rc1t0aGVpcnNJbmRleF0gfHwge29sZFN0YXJ0OiBJbmZpbml0eX07XG5cbiAgICBpZiAoaHVua0JlZm9yZShtaW5lQ3VycmVudCwgdGhlaXJzQ3VycmVudCkpIHtcbiAgICAgIC8vIFRoaXMgcGF0Y2ggZG9lcyBub3Qgb3ZlcmxhcCB3aXRoIGFueSBvZiB0aGUgb3RoZXJzLCB5YXkuXG4gICAgICByZXQuaHVua3MucHVzaChjbG9uZUh1bmsobWluZUN1cnJlbnQsIG1pbmVPZmZzZXQpKTtcbiAgICAgIG1pbmVJbmRleCsrO1xuICAgICAgdGhlaXJzT2Zmc2V0ICs9IG1pbmVDdXJyZW50Lm5ld0xpbmVzIC0gbWluZUN1cnJlbnQub2xkTGluZXM7XG4gICAgfSBlbHNlIGlmIChodW5rQmVmb3JlKHRoZWlyc0N1cnJlbnQsIG1pbmVDdXJyZW50KSkge1xuICAgICAgLy8gVGhpcyBwYXRjaCBkb2VzIG5vdCBvdmVybGFwIHdpdGggYW55IG9mIHRoZSBvdGhlcnMsIHlheS5cbiAgICAgIHJldC5odW5rcy5wdXNoKGNsb25lSHVuayh0aGVpcnNDdXJyZW50LCB0aGVpcnNPZmZzZXQpKTtcbiAgICAgIHRoZWlyc0luZGV4Kys7XG4gICAgICBtaW5lT2Zmc2V0ICs9IHRoZWlyc0N1cnJlbnQubmV3TGluZXMgLSB0aGVpcnNDdXJyZW50Lm9sZExpbmVzO1xuICAgIH0gZWxzZSB7XG4gICAgICAvLyBPdmVybGFwLCBtZXJnZSBhcyBiZXN0IHdlIGNhblxuICAgICAgbGV0IG1lcmdlZEh1bmsgPSB7XG4gICAgICAgIG9sZFN0YXJ0OiBNYXRoLm1pbihtaW5lQ3VycmVudC5vbGRTdGFydCwgdGhlaXJzQ3VycmVudC5vbGRTdGFydCksXG4gICAgICAgIG9sZExpbmVzOiAwLFxuICAgICAgICBuZXdTdGFydDogTWF0aC5taW4obWluZUN1cnJlbnQubmV3U3RhcnQgKyBtaW5lT2Zmc2V0LCB0aGVpcnNDdXJyZW50Lm9sZFN0YXJ0ICsgdGhlaXJzT2Zmc2V0KSxcbiAgICAgICAgbmV3TGluZXM6IDAsXG4gICAgICAgIGxpbmVzOiBbXVxuICAgICAgfTtcbiAgICAgIG1lcmdlTGluZXMobWVyZ2VkSHVuaywgbWluZUN1cnJlbnQub2xkU3RhcnQsIG1pbmVDdXJyZW50LmxpbmVzLCB0aGVpcnNDdXJyZW50Lm9sZFN0YXJ0LCB0aGVpcnNDdXJyZW50LmxpbmVzKTtcbiAgICAgIHRoZWlyc0luZGV4Kys7XG4gICAgICBtaW5lSW5kZXgrKztcblxuICAgICAgcmV0Lmh1bmtzLnB1c2gobWVyZ2VkSHVuayk7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHJldDtcbn1cblxuZnVuY3Rpb24gbG9hZFBhdGNoKHBhcmFtLCBiYXNlKSB7XG4gIGlmICh0eXBlb2YgcGFyYW0gPT09ICdzdHJpbmcnKSB7XG4gICAgaWYgKC9eQEAvbS50ZXN0KHBhcmFtKSB8fCAoL15JbmRleDovbS50ZXN0KHBhcmFtKSkpIHtcbiAgICAgIHJldHVybiBwYXJzZVBhdGNoKHBhcmFtKVswXTtcbiAgICB9XG5cbiAgICBpZiAoIWJhc2UpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignTXVzdCBwcm92aWRlIGEgYmFzZSByZWZlcmVuY2Ugb3IgcGFzcyBpbiBhIHBhdGNoJyk7XG4gICAgfVxuICAgIHJldHVybiBzdHJ1Y3R1cmVkUGF0Y2godW5kZWZpbmVkLCB1bmRlZmluZWQsIGJhc2UsIHBhcmFtKTtcbiAgfVxuXG4gIHJldHVybiBwYXJhbTtcbn1cblxuZnVuY3Rpb24gZmlsZU5hbWVDaGFuZ2VkKHBhdGNoKSB7XG4gIHJldHVybiBwYXRjaC5uZXdGaWxlTmFtZSAmJiBwYXRjaC5uZXdGaWxlTmFtZSAhPT0gcGF0Y2gub2xkRmlsZU5hbWU7XG59XG5cbmZ1bmN0aW9uIHNlbGVjdEZpZWxkKGluZGV4LCBtaW5lLCB0aGVpcnMpIHtcbiAgaWYgKG1pbmUgPT09IHRoZWlycykge1xuICAgIHJldHVybiBtaW5lO1xuICB9IGVsc2Uge1xuICAgIGluZGV4LmNvbmZsaWN0ID0gdHJ1ZTtcbiAgICByZXR1cm4ge21pbmUsIHRoZWlyc307XG4gIH1cbn1cblxuZnVuY3Rpb24gaHVua0JlZm9yZSh0ZXN0LCBjaGVjaykge1xuICByZXR1cm4gdGVzdC5vbGRTdGFydCA8IGNoZWNrLm9sZFN0YXJ0XG4gICAgJiYgKHRlc3Qub2xkU3RhcnQgKyB0ZXN0Lm9sZExpbmVzKSA8IGNoZWNrLm9sZFN0YXJ0O1xufVxuXG5mdW5jdGlvbiBjbG9uZUh1bmsoaHVuaywgb2Zmc2V0KSB7XG4gIHJldHVybiB7XG4gICAgb2xkU3RhcnQ6IGh1bmsub2xkU3RhcnQsIG9sZExpbmVzOiBodW5rLm9sZExpbmVzLFxuICAgIG5ld1N0YXJ0OiBodW5rLm5ld1N0YXJ0ICsgb2Zmc2V0LCBuZXdMaW5lczogaHVuay5uZXdMaW5lcyxcbiAgICBsaW5lczogaHVuay5saW5lc1xuICB9O1xufVxuXG5mdW5jdGlvbiBtZXJnZUxpbmVzKGh1bmssIG1pbmVPZmZzZXQsIG1pbmVMaW5lcywgdGhlaXJPZmZzZXQsIHRoZWlyTGluZXMpIHtcbiAgLy8gVGhpcyB3aWxsIGdlbmVyYWxseSByZXN1bHQgaW4gYSBjb25mbGljdGVkIGh1bmssIGJ1dCB0aGVyZSBhcmUgY2FzZXMgd2hlcmUgdGhlIGNvbnRleHRcbiAgLy8gaXMgdGhlIG9ubHkgb3ZlcmxhcCB3aGVyZSB3ZSBjYW4gc3VjY2Vzc2Z1bGx5IG1lcmdlIHRoZSBjb250ZW50IGhlcmUuXG4gIGxldCBtaW5lID0ge29mZnNldDogbWluZU9mZnNldCwgbGluZXM6IG1pbmVMaW5lcywgaW5kZXg6IDB9LFxuICAgICAgdGhlaXIgPSB7b2Zmc2V0OiB0aGVpck9mZnNldCwgbGluZXM6IHRoZWlyTGluZXMsIGluZGV4OiAwfTtcblxuICAvLyBIYW5kbGUgYW55IGxlYWRpbmcgY29udGVudFxuICBpbnNlcnRMZWFkaW5nKGh1bmssIG1pbmUsIHRoZWlyKTtcbiAgaW5zZXJ0TGVhZGluZyhodW5rLCB0aGVpciwgbWluZSk7XG5cbiAgLy8gTm93IGluIHRoZSBvdmVybGFwIGNvbnRlbnQuIFNjYW4gdGhyb3VnaCBhbmQgc2VsZWN0IHRoZSBiZXN0IGNoYW5nZXMgZnJvbSBlYWNoLlxuICB3aGlsZSAobWluZS5pbmRleCA8IG1pbmUubGluZXMubGVuZ3RoICYmIHRoZWlyLmluZGV4IDwgdGhlaXIubGluZXMubGVuZ3RoKSB7XG4gICAgbGV0IG1pbmVDdXJyZW50ID0gbWluZS5saW5lc1ttaW5lLmluZGV4XSxcbiAgICAgICAgdGhlaXJDdXJyZW50ID0gdGhlaXIubGluZXNbdGhlaXIuaW5kZXhdO1xuXG4gICAgaWYgKChtaW5lQ3VycmVudFswXSA9PT0gJy0nIHx8IG1pbmVDdXJyZW50WzBdID09PSAnKycpXG4gICAgICAgICYmICh0aGVpckN1cnJlbnRbMF0gPT09ICctJyB8fCB0aGVpckN1cnJlbnRbMF0gPT09ICcrJykpIHtcbiAgICAgIC8vIEJvdGggbW9kaWZpZWQgLi4uXG4gICAgICBtdXR1YWxDaGFuZ2UoaHVuaywgbWluZSwgdGhlaXIpO1xuICAgIH0gZWxzZSBpZiAobWluZUN1cnJlbnRbMF0gPT09ICcrJyAmJiB0aGVpckN1cnJlbnRbMF0gPT09ICcgJykge1xuICAgICAgLy8gTWluZSBpbnNlcnRlZFxuICAgICAgaHVuay5saW5lcy5wdXNoKC4uLiBjb2xsZWN0Q2hhbmdlKG1pbmUpKTtcbiAgICB9IGVsc2UgaWYgKHRoZWlyQ3VycmVudFswXSA9PT0gJysnICYmIG1pbmVDdXJyZW50WzBdID09PSAnICcpIHtcbiAgICAgIC8vIFRoZWlycyBpbnNlcnRlZFxuICAgICAgaHVuay5saW5lcy5wdXNoKC4uLiBjb2xsZWN0Q2hhbmdlKHRoZWlyKSk7XG4gICAgfSBlbHNlIGlmIChtaW5lQ3VycmVudFswXSA9PT0gJy0nICYmIHRoZWlyQ3VycmVudFswXSA9PT0gJyAnKSB7XG4gICAgICAvLyBNaW5lIHJlbW92ZWQgb3IgZWRpdGVkXG4gICAgICByZW1vdmFsKGh1bmssIG1pbmUsIHRoZWlyKTtcbiAgICB9IGVsc2UgaWYgKHRoZWlyQ3VycmVudFswXSA9PT0gJy0nICYmIG1pbmVDdXJyZW50WzBdID09PSAnICcpIHtcbiAgICAgIC8vIFRoZWlyIHJlbW92ZWQgb3IgZWRpdGVkXG4gICAgICByZW1vdmFsKGh1bmssIHRoZWlyLCBtaW5lLCB0cnVlKTtcbiAgICB9IGVsc2UgaWYgKG1pbmVDdXJyZW50ID09PSB0aGVpckN1cnJlbnQpIHtcbiAgICAgIC8vIENvbnRleHQgaWRlbnRpdHlcbiAgICAgIGh1bmsubGluZXMucHVzaChtaW5lQ3VycmVudCk7XG4gICAgICBtaW5lLmluZGV4Kys7XG4gICAgICB0aGVpci5pbmRleCsrO1xuICAgIH0gZWxzZSB7XG4gICAgICAvLyBDb250ZXh0IG1pc21hdGNoXG4gICAgICBjb25mbGljdChodW5rLCBjb2xsZWN0Q2hhbmdlKG1pbmUpLCBjb2xsZWN0Q2hhbmdlKHRoZWlyKSk7XG4gICAgfVxuICB9XG5cbiAgLy8gTm93IHB1c2ggYW55dGhpbmcgdGhhdCBtYXkgYmUgcmVtYWluaW5nXG4gIGluc2VydFRyYWlsaW5nKGh1bmssIG1pbmUpO1xuICBpbnNlcnRUcmFpbGluZyhodW5rLCB0aGVpcik7XG5cbiAgY2FsY0xpbmVDb3VudChodW5rKTtcbn1cblxuZnVuY3Rpb24gbXV0dWFsQ2hhbmdlKGh1bmssIG1pbmUsIHRoZWlyKSB7XG4gIGxldCBteUNoYW5nZXMgPSBjb2xsZWN0Q2hhbmdlKG1pbmUpLFxuICAgICAgdGhlaXJDaGFuZ2VzID0gY29sbGVjdENoYW5nZSh0aGVpcik7XG5cbiAgaWYgKGFsbFJlbW92ZXMobXlDaGFuZ2VzKSAmJiBhbGxSZW1vdmVzKHRoZWlyQ2hhbmdlcykpIHtcbiAgICAvLyBTcGVjaWFsIGNhc2UgZm9yIHJlbW92ZSBjaGFuZ2VzIHRoYXQgYXJlIHN1cGVyc2V0cyBvZiBvbmUgYW5vdGhlclxuICAgIGlmIChhcnJheVN0YXJ0c1dpdGgobXlDaGFuZ2VzLCB0aGVpckNoYW5nZXMpXG4gICAgICAgICYmIHNraXBSZW1vdmVTdXBlcnNldCh0aGVpciwgbXlDaGFuZ2VzLCBteUNoYW5nZXMubGVuZ3RoIC0gdGhlaXJDaGFuZ2VzLmxlbmd0aCkpIHtcbiAgICAgIGh1bmsubGluZXMucHVzaCguLi4gbXlDaGFuZ2VzKTtcbiAgICAgIHJldHVybjtcbiAgICB9IGVsc2UgaWYgKGFycmF5U3RhcnRzV2l0aCh0aGVpckNoYW5nZXMsIG15Q2hhbmdlcylcbiAgICAgICAgJiYgc2tpcFJlbW92ZVN1cGVyc2V0KG1pbmUsIHRoZWlyQ2hhbmdlcywgdGhlaXJDaGFuZ2VzLmxlbmd0aCAtIG15Q2hhbmdlcy5sZW5ndGgpKSB7XG4gICAgICBodW5rLmxpbmVzLnB1c2goLi4uIHRoZWlyQ2hhbmdlcyk7XG4gICAgICByZXR1cm47XG4gICAgfVxuICB9IGVsc2UgaWYgKGFycmF5RXF1YWwobXlDaGFuZ2VzLCB0aGVpckNoYW5nZXMpKSB7XG4gICAgaHVuay5saW5lcy5wdXNoKC4uLiBteUNoYW5nZXMpO1xuICAgIHJldHVybjtcbiAgfVxuXG4gIGNvbmZsaWN0KGh1bmssIG15Q2hhbmdlcywgdGhlaXJDaGFuZ2VzKTtcbn1cblxuZnVuY3Rpb24gcmVtb3ZhbChodW5rLCBtaW5lLCB0aGVpciwgc3dhcCkge1xuICBsZXQgbXlDaGFuZ2VzID0gY29sbGVjdENoYW5nZShtaW5lKSxcbiAgICAgIHRoZWlyQ2hhbmdlcyA9IGNvbGxlY3RDb250ZXh0KHRoZWlyLCBteUNoYW5nZXMpO1xuICBpZiAodGhlaXJDaGFuZ2VzLm1lcmdlZCkge1xuICAgIGh1bmsubGluZXMucHVzaCguLi4gdGhlaXJDaGFuZ2VzLm1lcmdlZCk7XG4gIH0gZWxzZSB7XG4gICAgY29uZmxpY3QoaHVuaywgc3dhcCA/IHRoZWlyQ2hhbmdlcyA6IG15Q2hhbmdlcywgc3dhcCA/IG15Q2hhbmdlcyA6IHRoZWlyQ2hhbmdlcyk7XG4gIH1cbn1cblxuZnVuY3Rpb24gY29uZmxpY3QoaHVuaywgbWluZSwgdGhlaXIpIHtcbiAgaHVuay5jb25mbGljdCA9IHRydWU7XG4gIGh1bmsubGluZXMucHVzaCh7XG4gICAgY29uZmxpY3Q6IHRydWUsXG4gICAgbWluZTogbWluZSxcbiAgICB0aGVpcnM6IHRoZWlyXG4gIH0pO1xufVxuXG5mdW5jdGlvbiBpbnNlcnRMZWFkaW5nKGh1bmssIGluc2VydCwgdGhlaXIpIHtcbiAgd2hpbGUgKGluc2VydC5vZmZzZXQgPCB0aGVpci5vZmZzZXQgJiYgaW5zZXJ0LmluZGV4IDwgaW5zZXJ0LmxpbmVzLmxlbmd0aCkge1xuICAgIGxldCBsaW5lID0gaW5zZXJ0LmxpbmVzW2luc2VydC5pbmRleCsrXTtcbiAgICBodW5rLmxpbmVzLnB1c2gobGluZSk7XG4gICAgaW5zZXJ0Lm9mZnNldCsrO1xuICB9XG59XG5mdW5jdGlvbiBpbnNlcnRUcmFpbGluZyhodW5rLCBpbnNlcnQpIHtcbiAgd2hpbGUgKGluc2VydC5pbmRleCA8IGluc2VydC5saW5lcy5sZW5ndGgpIHtcbiAgICBsZXQgbGluZSA9IGluc2VydC5saW5lc1tpbnNlcnQuaW5kZXgrK107XG4gICAgaHVuay5saW5lcy5wdXNoKGxpbmUpO1xuICB9XG59XG5cbmZ1bmN0aW9uIGNvbGxlY3RDaGFuZ2Uoc3RhdGUpIHtcbiAgbGV0IHJldCA9IFtdLFxuICAgICAgb3BlcmF0aW9uID0gc3RhdGUubGluZXNbc3RhdGUuaW5kZXhdWzBdO1xuICB3aGlsZSAoc3RhdGUuaW5kZXggPCBzdGF0ZS5saW5lcy5sZW5ndGgpIHtcbiAgICBsZXQgbGluZSA9IHN0YXRlLmxpbmVzW3N0YXRlLmluZGV4XTtcblxuICAgIC8vIEdyb3VwIGFkZGl0aW9ucyB0aGF0IGFyZSBpbW1lZGlhdGVseSBhZnRlciBzdWJ0cmFjdGlvbnMgYW5kIHRyZWF0IHRoZW0gYXMgb25lIFwiYXRvbWljXCIgbW9kaWZ5IGNoYW5nZS5cbiAgICBpZiAob3BlcmF0aW9uID09PSAnLScgJiYgbGluZVswXSA9PT0gJysnKSB7XG4gICAgICBvcGVyYXRpb24gPSAnKyc7XG4gICAgfVxuXG4gICAgaWYgKG9wZXJhdGlvbiA9PT0gbGluZVswXSkge1xuICAgICAgcmV0LnB1c2gobGluZSk7XG4gICAgICBzdGF0ZS5pbmRleCsrO1xuICAgIH0gZWxzZSB7XG4gICAgICBicmVhaztcbiAgICB9XG4gIH1cblxuICByZXR1cm4gcmV0O1xufVxuZnVuY3Rpb24gY29sbGVjdENvbnRleHQoc3RhdGUsIG1hdGNoQ2hhbmdlcykge1xuICBsZXQgY2hhbmdlcyA9IFtdLFxuICAgICAgbWVyZ2VkID0gW10sXG4gICAgICBtYXRjaEluZGV4ID0gMCxcbiAgICAgIGNvbnRleHRDaGFuZ2VzID0gZmFsc2UsXG4gICAgICBjb25mbGljdGVkID0gZmFsc2U7XG4gIHdoaWxlIChtYXRjaEluZGV4IDwgbWF0Y2hDaGFuZ2VzLmxlbmd0aFxuICAgICAgICAmJiBzdGF0ZS5pbmRleCA8IHN0YXRlLmxpbmVzLmxlbmd0aCkge1xuICAgIGxldCBjaGFuZ2UgPSBzdGF0ZS5saW5lc1tzdGF0ZS5pbmRleF0sXG4gICAgICAgIG1hdGNoID0gbWF0Y2hDaGFuZ2VzW21hdGNoSW5kZXhdO1xuXG4gICAgLy8gT25jZSB3ZSd2ZSBoaXQgb3VyIGFkZCwgdGhlbiB3ZSBhcmUgZG9uZVxuICAgIGlmIChtYXRjaFswXSA9PT0gJysnKSB7XG4gICAgICBicmVhaztcbiAgICB9XG5cbiAgICBjb250ZXh0Q2hhbmdlcyA9IGNvbnRleHRDaGFuZ2VzIHx8IGNoYW5nZVswXSAhPT0gJyAnO1xuXG4gICAgbWVyZ2VkLnB1c2gobWF0Y2gpO1xuICAgIG1hdGNoSW5kZXgrKztcblxuICAgIC8vIENvbnN1bWUgYW55IGFkZGl0aW9ucyBpbiB0aGUgb3RoZXIgYmxvY2sgYXMgYSBjb25mbGljdCB0byBhdHRlbXB0XG4gICAgLy8gdG8gcHVsbCBpbiB0aGUgcmVtYWluaW5nIGNvbnRleHQgYWZ0ZXIgdGhpc1xuICAgIGlmIChjaGFuZ2VbMF0gPT09ICcrJykge1xuICAgICAgY29uZmxpY3RlZCA9IHRydWU7XG5cbiAgICAgIHdoaWxlIChjaGFuZ2VbMF0gPT09ICcrJykge1xuICAgICAgICBjaGFuZ2VzLnB1c2goY2hhbmdlKTtcbiAgICAgICAgY2hhbmdlID0gc3RhdGUubGluZXNbKytzdGF0ZS5pbmRleF07XG4gICAgICB9XG4gICAgfVxuXG4gICAgaWYgKG1hdGNoLnN1YnN0cigxKSA9PT0gY2hhbmdlLnN1YnN0cigxKSkge1xuICAgICAgY2hhbmdlcy5wdXNoKGNoYW5nZSk7XG4gICAgICBzdGF0ZS5pbmRleCsrO1xuICAgIH0gZWxzZSB7XG4gICAgICBjb25mbGljdGVkID0gdHJ1ZTtcbiAgICB9XG4gIH1cblxuICBpZiAoKG1hdGNoQ2hhbmdlc1ttYXRjaEluZGV4XSB8fCAnJylbMF0gPT09ICcrJ1xuICAgICAgJiYgY29udGV4dENoYW5nZXMpIHtcbiAgICBjb25mbGljdGVkID0gdHJ1ZTtcbiAgfVxuXG4gIGlmIChjb25mbGljdGVkKSB7XG4gICAgcmV0dXJuIGNoYW5nZXM7XG4gIH1cblxuICB3aGlsZSAobWF0Y2hJbmRleCA8IG1hdGNoQ2hhbmdlcy5sZW5ndGgpIHtcbiAgICBtZXJnZWQucHVzaChtYXRjaENoYW5nZXNbbWF0Y2hJbmRleCsrXSk7XG4gIH1cblxuICByZXR1cm4ge1xuICAgIG1lcmdlZCxcbiAgICBjaGFuZ2VzXG4gIH07XG59XG5cbmZ1bmN0aW9uIGFsbFJlbW92ZXMoY2hhbmdlcykge1xuICByZXR1cm4gY2hhbmdlcy5yZWR1Y2UoZnVuY3Rpb24ocHJldiwgY2hhbmdlKSB7XG4gICAgcmV0dXJuIHByZXYgJiYgY2hhbmdlWzBdID09PSAnLSc7XG4gIH0sIHRydWUpO1xufVxuZnVuY3Rpb24gc2tpcFJlbW92ZVN1cGVyc2V0KHN0YXRlLCByZW1vdmVDaGFuZ2VzLCBkZWx0YSkge1xuICBmb3IgKGxldCBpID0gMDsgaSA8IGRlbHRhOyBpKyspIHtcbiAgICBsZXQgY2hhbmdlQ29udGVudCA9IHJlbW92ZUNoYW5nZXNbcmVtb3ZlQ2hhbmdlcy5sZW5ndGggLSBkZWx0YSArIGldLnN1YnN0cigxKTtcbiAgICBpZiAoc3RhdGUubGluZXNbc3RhdGUuaW5kZXggKyBpXSAhPT0gJyAnICsgY2hhbmdlQ29udGVudCkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgfVxuXG4gIHN0YXRlLmluZGV4ICs9IGRlbHRhO1xuICByZXR1cm4gdHJ1ZTtcbn1cblxuZnVuY3Rpb24gY2FsY09sZE5ld0xpbmVDb3VudChsaW5lcykge1xuICBsZXQgb2xkTGluZXMgPSAwO1xuICBsZXQgbmV3TGluZXMgPSAwO1xuXG4gIGxpbmVzLmZvckVhY2goZnVuY3Rpb24obGluZSkge1xuICAgIGlmICh0eXBlb2YgbGluZSAhPT0gJ3N0cmluZycpIHtcbiAgICAgIGxldCBteUNvdW50ID0gY2FsY09sZE5ld0xpbmVDb3VudChsaW5lLm1pbmUpO1xuICAgICAgbGV0IHRoZWlyQ291bnQgPSBjYWxjT2xkTmV3TGluZUNvdW50KGxpbmUudGhlaXJzKTtcblxuICAgICAgaWYgKG9sZExpbmVzICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgaWYgKG15Q291bnQub2xkTGluZXMgPT09IHRoZWlyQ291bnQub2xkTGluZXMpIHtcbiAgICAgICAgICBvbGRMaW5lcyArPSBteUNvdW50Lm9sZExpbmVzO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIG9sZExpbmVzID0gdW5kZWZpbmVkO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIGlmIChuZXdMaW5lcyAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIGlmIChteUNvdW50Lm5ld0xpbmVzID09PSB0aGVpckNvdW50Lm5ld0xpbmVzKSB7XG4gICAgICAgICAgbmV3TGluZXMgKz0gbXlDb3VudC5uZXdMaW5lcztcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBuZXdMaW5lcyA9IHVuZGVmaW5lZDtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICBpZiAobmV3TGluZXMgIT09IHVuZGVmaW5lZCAmJiAobGluZVswXSA9PT0gJysnIHx8IGxpbmVbMF0gPT09ICcgJykpIHtcbiAgICAgICAgbmV3TGluZXMrKztcbiAgICAgIH1cbiAgICAgIGlmIChvbGRMaW5lcyAhPT0gdW5kZWZpbmVkICYmIChsaW5lWzBdID09PSAnLScgfHwgbGluZVswXSA9PT0gJyAnKSkge1xuICAgICAgICBvbGRMaW5lcysrO1xuICAgICAgfVxuICAgIH1cbiAgfSk7XG5cbiAgcmV0dXJuIHtvbGRMaW5lcywgbmV3TGluZXN9O1xufVxuIl19 - - -/***/ }), -/* 14 */ -/***/ (function(module, exports, __webpack_require__) { +/***/ function(module, exports, __webpack_require__) { /*istanbul ignore start*/'use strict'; @@ -4939,7 +4533,8 @@ return /******/ (function(modules) { // webpackBootstrap var /*istanbul ignore start*/_line = __webpack_require__(5) /*istanbul ignore end*/; - /*istanbul ignore start*/function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } } + /*istanbul ignore start*/ + function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } } /*istanbul ignore end*/function structuredPatch(oldFileName, newFileName, oldStr, newStr, oldHeader, newHeader, options) { if (!options) { @@ -4964,16 +4559,18 @@ return /******/ (function(modules) { // webpackBootstrap curRange = [], oldLine = 1, newLine = 1; - - /*istanbul ignore start*/var _loop = function _loop( /*istanbul ignore end*/i) { + /*istanbul ignore start*/ + var _loop = function _loop( /*istanbul ignore end*/i) { var current = diff[i], lines = current.lines || current.value.replace(/\n$/, '').split('\n'); current.lines = lines; if (current.added || current.removed) { - /*istanbul ignore start*/var _curRange; + /*istanbul ignore start*/ + var _curRange; - /*istanbul ignore end*/ // If we have previous context, start with that + /*istanbul ignore end*/ + // If we have previous context, start with that if (!oldRangeStart) { var prev = diff[i - 1]; oldRangeStart = oldLine; @@ -5002,14 +4599,18 @@ return /******/ (function(modules) { // webpackBootstrap if (oldRangeStart) { // Close out any changes that have been output (or join overlapping) if (lines.length <= options.context * 2 && i < diff.length - 2) { - /*istanbul ignore start*/var _curRange2; + /*istanbul ignore start*/ + var _curRange2; - /*istanbul ignore end*/ // Overlapping + /*istanbul ignore end*/ + // Overlapping /*istanbul ignore start*/(_curRange2 = /*istanbul ignore end*/curRange).push. /*istanbul ignore start*/apply /*istanbul ignore end*/( /*istanbul ignore start*/_curRange2 /*istanbul ignore end*/, /*istanbul ignore start*/_toConsumableArray( /*istanbul ignore end*/contextLines(lines))); } else { - /*istanbul ignore start*/var _curRange3; + /*istanbul ignore start*/ + var _curRange3; - /*istanbul ignore end*/ // end the range and output + /*istanbul ignore end*/ + // end the range and output var contextSize = Math.min(lines.length, options.context); /*istanbul ignore start*/(_curRange3 = /*istanbul ignore end*/curRange).push. /*istanbul ignore start*/apply /*istanbul ignore end*/( /*istanbul ignore start*/_curRange3 /*istanbul ignore end*/, /*istanbul ignore start*/_toConsumableArray( /*istanbul ignore end*/contextLines(lines.slice(0, contextSize)))); @@ -5044,7 +4645,8 @@ return /******/ (function(modules) { // webpackBootstrap }; for (var i = 0; i < diff.length; i++) { - /*istanbul ignore start*/_loop( /*istanbul ignore end*/i); + /*istanbul ignore start*/ + _loop( /*istanbul ignore end*/i); } return { @@ -5077,45 +4679,12 @@ return /******/ (function(modules) { // webpackBootstrap function createPatch(fileName, oldStr, newStr, oldHeader, newHeader, options) { return createTwoFilesPatch(fileName, fileName, oldStr, newStr, oldHeader, newHeader, options); } - //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9wYXRjaC9jcmVhdGUuanMiXSwibmFtZXMiOlsic3RydWN0dXJlZFBhdGNoIiwiY3JlYXRlVHdvRmlsZXNQYXRjaCIsImNyZWF0ZVBhdGNoIiwib2xkRmlsZU5hbWUiLCJuZXdGaWxlTmFtZSIsIm9sZFN0ciIsIm5ld1N0ciIsIm9sZEhlYWRlciIsIm5ld0hlYWRlciIsIm9wdGlvbnMiLCJjb250ZXh0IiwiZGlmZiIsInB1c2giLCJ2YWx1ZSIsImxpbmVzIiwiY29udGV4dExpbmVzIiwibWFwIiwiZW50cnkiLCJodW5rcyIsIm9sZFJhbmdlU3RhcnQiLCJuZXdSYW5nZVN0YXJ0IiwiY3VyUmFuZ2UiLCJvbGRMaW5lIiwibmV3TGluZSIsImkiLCJjdXJyZW50IiwicmVwbGFjZSIsInNwbGl0IiwiYWRkZWQiLCJyZW1vdmVkIiwicHJldiIsInNsaWNlIiwibGVuZ3RoIiwiY29udGV4dFNpemUiLCJNYXRoIiwibWluIiwiaHVuayIsIm9sZFN0YXJ0Iiwib2xkTGluZXMiLCJuZXdTdGFydCIsIm5ld0xpbmVzIiwib2xkRU9GTmV3bGluZSIsInRlc3QiLCJuZXdFT0ZOZXdsaW5lIiwic3BsaWNlIiwicmV0IiwiYXBwbHkiLCJqb2luIiwiZmlsZU5hbWUiXSwibWFwcGluZ3MiOiI7OztnQ0FFZ0JBLGUsR0FBQUEsZTt5REFpR0FDLG1CLEdBQUFBLG1CO3lEQXdCQUMsVyxHQUFBQSxXOztBQTNIaEI7Ozs7dUJBRU8sU0FBU0YsZUFBVCxDQUF5QkcsV0FBekIsRUFBc0NDLFdBQXRDLEVBQW1EQyxNQUFuRCxFQUEyREMsTUFBM0QsRUFBbUVDLFNBQW5FLEVBQThFQyxTQUE5RSxFQUF5RkMsT0FBekYsRUFBa0c7QUFDdkcsTUFBSSxDQUFDQSxPQUFMLEVBQWM7QUFDWkEsY0FBVSxFQUFWO0FBQ0Q7QUFDRCxNQUFJLE9BQU9BLFFBQVFDLE9BQWYsS0FBMkIsV0FBL0IsRUFBNEM7QUFDMUNELFlBQVFDLE9BQVIsR0FBa0IsQ0FBbEI7QUFDRDs7QUFFRCxN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QUEvQyxFQUEwREMsU0FBMUQsRUFBcUVDLE9BQXJFLEVBQThFO0FBQ25GLFNBQU9SLG9CQUFvQitDLFFBQXBCLEVBQThCQSxRQUE5QixFQUF3QzNDLE1BQXhDLEVBQWdEQyxNQUFoRCxFQUF3REMsU0FBeEQsRUFBbUVDLFNBQW5FLEVBQThFQyxPQUE5RSxDQUFQO0FBQ0QiLCJmaWxlIjoiY3JlYXRlLmpzIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtkaWZmTGluZXN9IGZyb20gJy4uL2RpZmYvbGluZSc7XG5cbmV4cG9ydCBmdW5jdGlvbiBzdHJ1Y3R1cmVkUGF0Y2gob2xkRmlsZU5hbWUsIG5ld0ZpbGVOYW1lLCBvbGRTdHIsIG5ld1N0ciwgb2xkSGVhZGVyLCBuZXdIZWFkZXIsIG9wdGlvbnMpIHtcbiAgaWYgKCFvcHRpb25zKSB7XG4gICAgb3B0aW9ucyA9IHt9O1xuICB9XG4gIGlmICh0eXBlb2Ygb3B0aW9ucy5jb250ZXh0ID09PSAndW5kZWZpbmVkJykge1xuICAgIG9wdGlvbnMuY29udGV4dCA9IDQ7XG4gIH1cblxuICBjb25zdCBkaWZmID0gZGlmZkxpbmVzKG9sZFN0ciwgbmV3U3RyLCBvcHRpb25zKTtcbiAgZGlmZi5wdXNoKHt2YWx1ZTogJycsIGxpbmVzOiBbXX0pOyAgIC8vIEFwcGVuZCBhbiBlbXB0eSB2YWx1ZSB0byBtYWtlIGNsZWFudXAgZWFzaWVyXG5cbiAgZnVuY3Rpb24gY29udGV4dExpbmVzKGxpbmVzKSB7XG4gICAgcmV0dXJuIGxpbmVzLm1hcChmdW5jdGlvbihlbnRyeSkgeyByZXR1cm4gJyAnICsgZW50cnk7IH0pO1xuICB9XG5cbiAgbGV0IGh1bmtzID0gW107XG4gIGxldCBvbGRSYW5nZVN0YXJ0ID0gMCwgbmV3UmFuZ2VTdGFydCA9IDAsIGN1clJhbmdlID0gW10sXG4gICAgICBvbGRMaW5lID0gMSwgbmV3TGluZSA9IDE7XG4gIGZvciAobGV0IGkgPSAwOyBpIDwgZGlmZi5sZW5ndGg7IGkrKykge1xuICAgIGNvbnN0IGN1cnJlbnQgPSBkaWZmW2ldLFxuICAgICAgICAgIGxpbmVzID0gY3VycmVudC5saW5lcyB8fCBjdXJyZW50LnZhbHVlLnJlcGxhY2UoL1xcbiQvLCAnJykuc3BsaXQoJ1xcbicpO1xuICAgIGN1cnJlbnQubGluZXMgPSBsaW5lcztcblxuICAgIGlmIChjdXJyZW50LmFkZGVkIHx8IGN1cnJlbnQucmVtb3ZlZCkge1xuICAgICAgLy8gSWYgd2UgaGF2ZSBwcmV2aW91cyBjb250ZXh0LCBzdGFydCB3aXRoIHRoYXRcbiAgICAgIGlmICghb2xkUmFuZ2VTdGFydCkge1xuICAgICAgICBjb25zdCBwcmV2ID0gZGlmZltpIC0gMV07XG4gICAgICAgIG9sZFJhbmdlU3RhcnQgPSBvbGRMaW5lO1xuICAgICAgICBuZXdSYW5nZVN0YXJ0ID0gbmV3TGluZTtcblxuICAgICAgICBpZiAocHJldikge1xuICAgICAgICAgIGN1clJhbmdlID0gb3B0aW9ucy5jb250ZXh0ID4gMCA/IGNvbnRleHRMaW5lcyhwcmV2LmxpbmVzLnNsaWNlKC1vcHRpb25zLmNvbnRleHQpKSA6IFtdO1xuICAgICAgICAgIG9sZFJhbmdlU3RhcnQgLT0gY3VyUmFuZ2UubGVuZ3RoO1xuICAgICAgICAgIG5ld1JhbmdlU3RhcnQgLT0gY3VyUmFuZ2UubGVuZ3RoO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIC8vIE91dHB1dCBvdXIgY2hhbmdlc1xuICAgICAgY3VyUmFuZ2UucHVzaCguLi4gbGluZXMubWFwKGZ1bmN0aW9uKGVudHJ5KSB7XG4gICAgICAgIHJldHVybiAoY3VycmVudC5hZGRlZCA/ICcrJyA6ICctJykgKyBlbnRyeTtcbiAgICAgIH0pKTtcblxuICAgICAgLy8gVHJhY2sgdGhlIHVwZGF0ZWQgZmlsZSBwb3NpdGlvblxuICAgICAgaWYgKGN1cnJlbnQuYWRkZWQpIHtcbiAgICAgICAgbmV3TGluZSArPSBsaW5lcy5sZW5ndGg7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBvbGRMaW5lICs9IGxpbmVzLmxlbmd0aDtcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgLy8gSWRlbnRpY2FsIGNvbnRleHQgbGluZXMuIFRyYWNrIGxpbmUgY2hhbmdlc1xuICAgICAgaWYgKG9sZFJhbmdlU3RhcnQpIHtcbiAgICAgICAgLy8gQ2xvc2Ugb3V0IGFueSBjaGFuZ2VzIHRoYXQgaGF2ZSBiZWVuIG91dHB1dCAob3Igam9pbiBvdmVybGFwcGluZylcbiAgICAgICAgaWYgKGxpbmVzLmxlbmd0aCA8PSBvcHRpb25zLmNvbnRleHQgKiAyICYmIGkgPCBkaWZmLmxlbmd0aCAtIDIpIHtcbiAgICAgICAgICAvLyBPdmVybGFwcGluZ1xuICAgICAgICAgIGN1clJhbmdlLnB1c2goLi4uIGNvbnRleHRMaW5lcyhsaW5lcykpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIC8vIGVuZCB0aGUgcmFuZ2UgYW5kIG91dHB1dFxuICAgICAgICAgIGxldCBjb250ZXh0U2l6ZSA9IE1hdGgubWluKGxpbmVzLmxlbmd0aCwgb3B0aW9ucy5jb250ZXh0KTtcbiAgICAgICAgICBjdXJSYW5nZS5wdXNoKC4uLiBjb250ZXh0TGluZXMobGluZXMuc2xpY2UoMCwgY29udGV4dFNpemUpKSk7XG5cbiAgICAgICAgICBsZXQgaHVuayA9IHtcbiAgICAgICAgICAgIG9sZFN0YXJ0OiBvbGRSYW5nZVN0YXJ0LFxuICAgICAgICAgICAgb2xkTGluZXM6IChvbGRMaW5lIC0gb2xkUmFuZ2VTdGFydCArIGNvbnRleHRTaXplKSxcbiAgICAgICAgICAgIG5ld1N0YXJ0OiBuZXdSYW5nZVN0YXJ0LFxuICAgICAgICAgICAgbmV3TGluZXM6IChuZXdMaW5lIC0gbmV3UmFuZ2VTdGFydCArIGNvbnRleHRTaXplKSxcbiAgICAgICAgICAgIGxpbmVzOiBjdXJSYW5nZVxuICAgICAgICAgIH07XG4gICAgICAgICAgaWYgKGkgPj0gZGlmZi5sZW5ndGggLSAyICYmIGxpbmVzLmxlbmd0aCA8PSBvcHRpb25zLmNvbnRleHQpIHtcbiAgICAgICAgICAgIC8vIEVPRiBpcyBpbnNpZGUgdGhpcyBodW5rXG4gICAgICAgICAgICBsZXQgb2xkRU9GTmV3bGluZSA9ICgvXFxuJC8udGVzdChvbGRTdHIpKTtcbiAgICAgICAgICAgIGxldCBuZXdFT0ZOZXdsaW5lID0gKC9cXG4kLy50ZXN0KG5ld1N0cikpO1xuICAgICAgICAgICAgaWYgKGxpbmVzLmxlbmd0aCA9PSAwICYmICFvbGRFT0ZOZXdsaW5lKSB7XG4gICAgICAgICAgICAgIC8vIHNwZWNpYWwgY2FzZTogb2xkIGhhcyBubyBlb2wgYW5kIG5vIHRyYWlsaW5nIGNvbnRleHQ7IG5vLW5sIGNhbiBlbmQgdXAgYmVmb3JlIGFkZHNcbiAgICAgICAgICAgICAgY3VyUmFuZ2Uuc3BsaWNlKGh1bmsub2xkTGluZXMsIDAsICdcXFxcIE5vIG5ld2xpbmUgYXQgZW5kIG9mIGZpbGUnKTtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoIW9sZEVPRk5ld2xpbmUgfHwgIW5ld0VPRk5ld2xpbmUpIHtcbiAgICAgICAgICAgICAgY3VyUmFuZ2UucHVzaCgnXFxcXCBObyBuZXdsaW5lIGF0IGVuZCBvZiBmaWxlJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICAgIGh1bmtzLnB1c2goaHVuayk7XG5cbiAgICAgICAgICBvbGRSYW5nZVN0YXJ0ID0gMDtcbiAgICAgICAgICBuZXdSYW5nZVN0YXJ0ID0gMDtcbiAgICAgICAgICBjdXJSYW5nZSA9IFtdO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICBvbGRMaW5lICs9IGxpbmVzLmxlbmd0aDtcbiAgICAgIG5ld0xpbmUgKz0gbGluZXMubGVuZ3RoO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiB7XG4gICAgb2xkRmlsZU5hbWU6IG9sZEZpbGVOYW1lLCBuZXdGaWxlTmFtZTogbmV3RmlsZU5hbWUsXG4gICAgb2xkSGVhZGVyOiBvbGRIZWFkZXIsIG5ld0hlYWRlcjogbmV3SGVhZGVyLFxuICAgIGh1bmtzOiBodW5rc1xuICB9O1xufVxuXG5leHBvcnQgZnVuY3Rpb24gY3JlYXRlVHdvRmlsZXNQYXRjaChvbGRGaWxlTmFtZSwgbmV3RmlsZU5hbWUsIG9sZFN0ciwgbmV3U3RyLCBvbGRIZWFkZXIsIG5ld0hlYWRlciwgb3B0aW9ucykge1xuICBjb25zdCBkaWZmID0gc3RydWN0dXJlZFBhdGNoKG9sZEZpbGVOYW1lLCBuZXdGaWxlTmFtZSwgb2xkU3RyLCBuZXdTdHIsIG9sZEhlYWRlciwgbmV3SGVhZGVyLCBvcHRpb25zKTtcblxuICBjb25zdCByZXQgPSBbXTtcbiAgaWYgKG9sZEZpbGVOYW1lID09IG5ld0ZpbGVOYW1lKSB7XG4gICAgcmV0LnB1c2goJ0luZGV4OiAnICsgb2xkRmlsZU5hbWUpO1xuICB9XG4gIHJldC5wdXNoKCc9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09Jyk7XG4gIHJldC5wdXNoKCctLS0gJyArIGRpZmYub2xkRmlsZU5hbWUgKyAodHlwZW9mIGRpZmYub2xkSGVhZGVyID09PSAndW5kZWZpbmVkJyA/ICcnIDogJ1xcdCcgKyBkaWZmLm9sZEhlYWRlcikpO1xuICByZXQucHVzaCgnKysrICcgKyBkaWZmLm5ld0ZpbGVOYW1lICsgKHR5cGVvZiBkaWZmLm5ld0hlYWRlciA9PT0gJ3VuZGVmaW5lZCcgPyAnJyA6ICdcXHQnICsgZGlmZi5uZXdIZWFkZXIpKTtcblxuICBmb3IgKGxldCBpID0gMDsgaSA8IGRpZmYuaHVua3MubGVuZ3RoOyBpKyspIHtcbiAgICBjb25zdCBodW5rID0gZGlmZi5odW5rc1tpXTtcbiAgICByZXQucHVzaChcbiAgICAgICdAQCAtJyArIGh1bmsub2xkU3RhcnQgKyAnLCcgKyBodW5rLm9sZExpbmVzXG4gICAgICArICcgKycgKyBodW5rLm5ld1N0YXJ0ICsgJywnICsgaHVuay5uZXdMaW5lc1xuICAgICAgKyAnIEBAJ1xuICAgICk7XG4gICAgcmV0LnB1c2guYXBwbHkocmV0LCBodW5rLmxpbmVzKTtcbiAgfVxuXG4gIHJldHVybiByZXQuam9pbignXFxuJykgKyAnXFxuJztcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGNyZWF0ZVBhdGNoKGZpbGVOYW1lLCBvbGRTdHIsIG5ld1N0ciwgb2xkSGVhZGVyLCBuZXdIZWFkZXIsIG9wdGlvbnMpIHtcbiAgcmV0dXJuIGNyZWF0ZVR3b0ZpbGVzUGF0Y2goZmlsZU5hbWUsIGZpbGVOYW1lLCBvbGRTdHIsIG5ld1N0ciwgb2xkSGVhZGVyLCBuZXdIZWFkZXIsIG9wdGlvbnMpO1xufVxuIl19 - - -/***/ }), -/* 15 */ -/***/ (function(module, exports) { - - /*istanbul ignore start*/"use strict"; - - exports.__esModule = true; - exports. /*istanbul ignore end*/arrayEqual = arrayEqual; - /*istanbul ignore start*/exports. /*istanbul ignore end*/arrayStartsWith = arrayStartsWith; - function arrayEqual(a, b) { - if (a.length !== b.length) { - return false; - } + //# sourceMappingURL=data:application/json;base64,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QixHQUR6QixHQUMrQixLQUFLLFFBRHBDLEdBRUUsS0FISjtBQUtBLFFBQUksSUFBSixDQUFTLEtBQVQsQ0FBZSxHQUFmLEVBQW9CLEtBQUssS0FBekI7QUFDRDs7QUFFRCxTQUFPLElBQUksSUFBSixDQUFTLElBQVQsSUFBaUIsSUFBeEI7QUFDRDs7QUFFTSxTQUFTLFdBQVQsQ0FBcUIsUUFBckIsRUFBK0IsTUFBL0IsRUFBdUMsTUFBdkMsRUFBK0MsU0FBL0MsRUFBMEQsU0FBMUQsRUFBcUUsT0FBckUsRUFBOEU7QUFDbkYsU0FBTyxvQkFBb0IsUUFBcEIsRUFBOEIsUUFBOUIsRUFBd0MsTUFBeEMsRUFBZ0QsTUFBaEQsRUFBd0QsU0FBeEQsRUFBbUUsU0FBbkUsRUFBOEUsT0FBOUUsQ0FBUDtBQUNEIiwiZmlsZSI6ImNyZWF0ZS5qcyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7ZGlmZkxpbmVzfSBmcm9tICcuLi9kaWZmL2xpbmUnO1xuXG5leHBvcnQgZnVuY3Rpb24gc3RydWN0dXJlZFBhdGNoKG9sZEZpbGVOYW1lLCBuZXdGaWxlTmFtZSwgb2xkU3RyLCBuZXdTdHIsIG9sZEhlYWRlciwgbmV3SGVhZGVyLCBvcHRpb25zKSB7XG4gIGlmICghb3B0aW9ucykge1xuICAgIG9wdGlvbnMgPSB7fTtcbiAgfVxuICBpZiAodHlwZW9mIG9wdGlvbnMuY29udGV4dCA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICBvcHRpb25zLmNvbnRleHQgPSA0O1xuICB9XG5cbiAgY29uc3QgZGlmZiA9IGRpZmZMaW5lcyhvbGRTdHIsIG5ld1N0ciwgb3B0aW9ucyk7XG4gIGRpZmYucHVzaCh7dmFsdWU6ICcnLCBsaW5lczogW119KTsgICAvLyBBcHBlbmQgYW4gZW1wdHkgdmFsdWUgdG8gbWFrZSBjbGVhbnVwIGVhc2llclxuXG4gIGZ1bmN0aW9uIGNvbnRleHRMaW5lcyhsaW5lcykge1xuICAgIHJldHVybiBsaW5lcy5tYXAoZnVuY3Rpb24oZW50cnkpIHsgcmV0dXJuICcgJyArIGVudHJ5OyB9KTtcbiAgfVxuXG4gIGxldCBodW5rcyA9IFtdO1xuICBsZXQgb2xkUmFuZ2VTdGFydCA9IDAsIG5ld1JhbmdlU3RhcnQgPSAwLCBjdXJSYW5nZSA9IFtdLFxuICAgICAgb2xkTGluZSA9IDEsIG5ld0xpbmUgPSAxO1xuICBmb3IgKGxldCBpID0gMDsgaSA8IGRpZmYubGVuZ3RoOyBpKyspIHtcbiAgICBjb25zdCBjdXJyZW50ID0gZGlmZltpXSxcbiAgICAgICAgICBsaW5lcyA9IGN1cnJlbnQubGluZXMgfHwgY3VycmVudC52YWx1ZS5yZXBsYWNlKC9cXG4kLywgJycpLnNwbGl0KCdcXG4nKTtcbiAgICBjdXJyZW50LmxpbmVzID0gbGluZXM7XG5cbiAgICBpZiAoY3VycmVudC5hZGRlZCB8fCBjdXJyZW50LnJlbW92ZWQpIHtcbiAgICAgIC8vIElmIHdlIGhhdmUgcHJldmlvdXMgY29udGV4dCwgc3RhcnQgd2l0aCB0aGF0XG4gICAgICBpZiAoIW9sZFJhbmdlU3RhcnQpIHtcbiAgICAgICAgY29uc3QgcHJldiA9IGRpZmZbaSAtIDFdO1xuICAgICAgICBvbGRSYW5nZVN0YXJ0ID0gb2xkTGluZTtcbiAgICAgICAgbmV3UmFuZ2VTdGFydCA9IG5ld0xpbmU7XG5cbiAgICAgICAgaWYgKHByZXYpIHtcbiAgICAgICAgICBjdXJSYW5nZSA9IG9wdGlvbnMuY29udGV4dCA+IDAgPyBjb250ZXh0TGluZXMocHJldi5saW5lcy5zbGljZSgtb3B0aW9ucy5jb250ZXh0KSkgOiBbXTtcbiAgICAgICAgICBvbGRSYW5nZVN0YXJ0IC09IGN1clJhbmdlLmxlbmd0aDtcbiAgICAgICAgICBuZXdSYW5nZVN0YXJ0IC09IGN1clJhbmdlLmxlbmd0aDtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICAvLyBPdXRwdXQgb3VyIGNoYW5nZXNcbiAgICAgIGN1clJhbmdlLnB1c2goLi4uIGxpbmVzLm1hcChmdW5jdGlvbihlbnRyeSkge1xuICAgICAgICByZXR1cm4gKGN1cnJlbnQuYWRkZWQgPyAnKycgOiAnLScpICsgZW50cnk7XG4gICAgICB9KSk7XG5cbiAgICAgIC8vIFRyYWNrIHRoZSB1cGRhdGVkIGZpbGUgcG9zaXRpb25cbiAgICAgIGlmIChjdXJyZW50LmFkZGVkKSB7XG4gICAgICAgIG5ld0xpbmUgKz0gbGluZXMubGVuZ3RoO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgb2xkTGluZSArPSBsaW5lcy5sZW5ndGg7XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIC8vIElkZW50aWNhbCBjb250ZXh0IGxpbmVzLiBUcmFjayBsaW5lIGNoYW5nZXNcbiAgICAgIGlmIChvbGRSYW5nZVN0YXJ0KSB7XG4gICAgICAgIC8vIENsb3NlIG91dCBhbnkgY2hhbmdlcyB0aGF0IGhhdmUgYmVlbiBvdXRwdXQgKG9yIGpvaW4gb3ZlcmxhcHBpbmcpXG4gICAgICAgIGlmIChsaW5lcy5sZW5ndGggPD0gb3B0aW9ucy5jb250ZXh0ICogMiAmJiBpIDwgZGlmZi5sZW5ndGggLSAyKSB7XG4gICAgICAgICAgLy8gT3ZlcmxhcHBpbmdcbiAgICAgICAgICBjdXJSYW5nZS5wdXNoKC4uLiBjb250ZXh0TGluZXMobGluZXMpKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAvLyBlbmQgdGhlIHJhbmdlIGFuZCBvdXRwdXRcbiAgICAgICAgICBsZXQgY29udGV4dFNpemUgPSBNYXRoLm1pbihsaW5lcy5sZW5ndGgsIG9wdGlvbnMuY29udGV4dCk7XG4gICAgICAgICAgY3VyUmFuZ2UucHVzaCguLi4gY29udGV4dExpbmVzKGxpbmVzLnNsaWNlKDAsIGNvbnRleHRTaXplKSkpO1xuXG4gICAgICAgICAgbGV0IGh1bmsgPSB7XG4gICAgICAgICAgICBvbGRTdGFydDogb2xkUmFuZ2VTdGFydCxcbiAgICAgICAgICAgIG9sZExpbmVzOiAob2xkTGluZSAtIG9sZFJhbmdlU3RhcnQgKyBjb250ZXh0U2l6ZSksXG4gICAgICAgICAgICBuZXdTdGFydDogbmV3UmFuZ2VTdGFydCxcbiAgICAgICAgICAgIG5ld0xpbmVzOiAobmV3TGluZSAtIG5ld1JhbmdlU3RhcnQgKyBjb250ZXh0U2l6ZSksXG4gICAgICAgICAgICBsaW5lczogY3VyUmFuZ2VcbiAgICAgICAgICB9O1xuICAgICAgICAgIGlmIChpID49IGRpZmYubGVuZ3RoIC0gMiAmJiBsaW5lcy5sZW5ndGggPD0gb3B0aW9ucy5jb250ZXh0KSB7XG4gICAgICAgICAgICAvLyBFT0YgaXMgaW5zaWRlIHRoaXMgaHVua1xuICAgICAgICAgICAgbGV0IG9sZEVPRk5ld2xpbmUgPSAoL1xcbiQvLnRlc3Qob2xkU3RyKSk7XG4gICAgICAgICAgICBsZXQgbmV3RU9GTmV3bGluZSA9ICgvXFxuJC8udGVzdChuZXdTdHIpKTtcbiAgICAgICAgICAgIGlmIChsaW5lcy5sZW5ndGggPT0gMCAmJiAhb2xkRU9GTmV3bGluZSkge1xuICAgICAgICAgICAgICAvLyBzcGVjaWFsIGNhc2U6IG9sZCBoYXMgbm8gZW9sIGFuZCBubyB0cmFpbGluZyBjb250ZXh0OyBuby1ubCBjYW4gZW5kIHVwIGJlZm9yZSBhZGRzXG4gICAgICAgICAgICAgIGN1clJhbmdlLnNwbGljZShodW5rLm9sZExpbmVzLCAwLCAnXFxcXCBObyBuZXdsaW5lIGF0IGVuZCBvZiBmaWxlJyk7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKCFvbGRFT0ZOZXdsaW5lIHx8ICFuZXdFT0ZOZXdsaW5lKSB7XG4gICAgICAgICAgICAgIGN1clJhbmdlLnB1c2goJ1xcXFwgTm8gbmV3bGluZSBhdCBlbmQgb2YgZmlsZScpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgICBodW5rcy5wdXNoKGh1bmspO1xuXG4gICAgICAgICAgb2xkUmFuZ2VTdGFydCA9IDA7XG4gICAgICAgICAgbmV3UmFuZ2VTdGFydCA9IDA7XG4gICAgICAgICAgY3VyUmFuZ2UgPSBbXTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgb2xkTGluZSArPSBsaW5lcy5sZW5ndGg7XG4gICAgICBuZXdMaW5lICs9IGxpbmVzLmxlbmd0aDtcbiAgICB9XG4gIH1cblxuICByZXR1cm4ge1xuICAgIG9sZEZpbGVOYW1lOiBvbGRGaWxlTmFtZSwgbmV3RmlsZU5hbWU6IG5ld0ZpbGVOYW1lLFxuICAgIG9sZEhlYWRlcjogb2xkSGVhZGVyLCBuZXdIZWFkZXI6IG5ld0hlYWRlcixcbiAgICBodW5rczogaHVua3NcbiAgfTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGNyZWF0ZVR3b0ZpbGVzUGF0Y2gob2xkRmlsZU5hbWUsIG5ld0ZpbGVOYW1lLCBvbGRTdHIsIG5ld1N0ciwgb2xkSGVhZGVyLCBuZXdIZWFkZXIsIG9wdGlvbnMpIHtcbiAgY29uc3QgZGlmZiA9IHN0cnVjdHVyZWRQYXRjaChvbGRGaWxlTmFtZSwgbmV3RmlsZU5hbWUsIG9sZFN0ciwgbmV3U3RyLCBvbGRIZWFkZXIsIG5ld0hlYWRlciwgb3B0aW9ucyk7XG5cbiAgY29uc3QgcmV0ID0gW107XG4gIGlmIChvbGRGaWxlTmFtZSA9PSBuZXdGaWxlTmFtZSkge1xuICAgIHJldC5wdXNoKCdJbmRleDogJyArIG9sZEZpbGVOYW1lKTtcbiAgfVxuICByZXQucHVzaCgnPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PScpO1xuICByZXQucHVzaCgnLS0tICcgKyBkaWZmLm9sZEZpbGVOYW1lICsgKHR5cGVvZiBkaWZmLm9sZEhlYWRlciA9PT0gJ3VuZGVmaW5lZCcgPyAnJyA6ICdcXHQnICsgZGlmZi5vbGRIZWFkZXIpKTtcbiAgcmV0LnB1c2goJysrKyAnICsgZGlmZi5uZXdGaWxlTmFtZSArICh0eXBlb2YgZGlmZi5uZXdIZWFkZXIgPT09ICd1bmRlZmluZWQnID8gJycgOiAnXFx0JyArIGRpZmYubmV3SGVhZGVyKSk7XG5cbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBkaWZmLmh1bmtzLmxlbmd0aDsgaSsrKSB7XG4gICAgY29uc3QgaHVuayA9IGRpZmYuaHVua3NbaV07XG4gICAgcmV0LnB1c2goXG4gICAgICAnQEAgLScgKyBodW5rLm9sZFN0YXJ0ICsgJywnICsgaHVuay5vbGRMaW5lc1xuICAgICAgKyAnICsnICsgaHVuay5uZXdTdGFydCArICcsJyArIGh1bmsubmV3TGluZXNcbiAgICAgICsgJyBAQCdcbiAgICApO1xuICAgIHJldC5wdXNoLmFwcGx5KHJldCwgaHVuay5saW5lcyk7XG4gIH1cblxuICByZXR1cm4gcmV0LmpvaW4oJ1xcbicpICsgJ1xcbic7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBjcmVhdGVQYXRjaChmaWxlTmFtZSwgb2xkU3RyLCBuZXdTdHIsIG9sZEhlYWRlciwgbmV3SGVhZGVyLCBvcHRpb25zKSB7XG4gIHJldHVybiBjcmVhdGVUd29GaWxlc1BhdGNoKGZpbGVOYW1lLCBmaWxlTmFtZSwgb2xkU3RyLCBuZXdTdHIsIG9sZEhlYWRlciwgbmV3SGVhZGVyLCBvcHRpb25zKTtcbn1cbiJdfQ== - return arrayStartsWith(a, b); - } - function arrayStartsWith(array, start) { - if (start.length > array.length) { - return false; - } - - for (var i = 0; i < start.length; i++) { - if (start[i] !== array[i]) { - return false; - } - } - - return true; - } - //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy91dGlsL2FycmF5LmpzIl0sIm5hbWVzIjpbImFycmF5RXF1YWwiLCJhcnJheVN0YXJ0c1dpdGgiLCJhIiwiYiIsImxlbmd0aCIsImFycmF5Iiwic3RhcnQiLCJpIl0sIm1hcHBpbmdzIjoiOzs7Z0NBQWdCQSxVLEdBQUFBLFU7eURBUUFDLGUsR0FBQUEsZTtBQVJULFNBQVNELFVBQVQsQ0FBb0JFLENBQXBCLEVBQXVCQyxDQUF2QixFQUEwQjtBQUMvQixNQUFJRCxFQUFFRSxNQUFGLEtBQWFELEVBQUVDLE1BQW5CLEVBQTJCO0FBQ3pCLFdBQU8sS0FBUDtBQUNEOztBQUVELFNBQU9ILGdCQUFnQkMsQ0FBaEIsRUFBbUJDLENBQW5CLENBQVA7QUFDRDs7QUFFTSxTQUFTRixlQUFULENBQXlCSSxLQUF6QixFQUFnQ0MsS0FBaEMsRUFBdUM7QUFDNUMsTUFBSUEsTUFBTUYsTUFBTixHQUFlQyxNQUFNRCxNQUF6QixFQUFpQztBQUMvQixXQUFPLEtBQVA7QUFDRDs7QUFFRCxPQUFLLElBQUlHLElBQUksQ0FBYixFQUFnQkEsSUFBSUQsTUFBTUYsTUFBMUIsRUFBa0NHLEdBQWxDLEVBQXVDO0FBQ3JDLFFBQUlELE1BQU1DLENBQU4sTUFBYUYsTUFBTUUsQ0FBTixDQUFqQixFQUEyQjtBQUN6QixhQUFPLEtBQVA7QUFDRDtBQUNGOztBQUVELFNBQU8sSUFBUDtBQUNEIiwiZmlsZSI6ImFycmF5LmpzIiwic291cmNlc0NvbnRlbnQiOlsiZXhwb3J0IGZ1bmN0aW9uIGFycmF5RXF1YWwoYSwgYikge1xuICBpZiAoYS5sZW5ndGggIT09IGIubGVuZ3RoKSB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG5cbiAgcmV0dXJuIGFycmF5U3RhcnRzV2l0aChhLCBiKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGFycmF5U3RhcnRzV2l0aChhcnJheSwgc3RhcnQpIHtcbiAgaWYgKHN0YXJ0Lmxlbmd0aCA+IGFycmF5Lmxlbmd0aCkge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuXG4gIGZvciAobGV0IGkgPSAwOyBpIDwgc3RhcnQubGVuZ3RoOyBpKyspIHtcbiAgICBpZiAoc3RhcnRbaV0gIT09IGFycmF5W2ldKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHRydWU7XG59XG4iXX0= - - -/***/ }), -/* 16 */ -/***/ (function(module, exports) { +/***/ }, +/* 14 */ +/***/ function(module, exports) { /*istanbul ignore start*/"use strict"; @@ -5140,12 +4709,12 @@ return /******/ (function(modules) { // webpackBootstrap } return ret; } - //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9jb252ZXJ0L2RtcC5qcyJdLCJuYW1lcyI6WyJjb252ZXJ0Q2hhbmdlc1RvRE1QIiwiY2hhbmdlcyIsInJldCIsImNoYW5nZSIsIm9wZXJhdGlvbiIsImkiLCJsZW5ndGgiLCJhZGRlZCIsInJlbW92ZWQiLCJwdXNoIiwidmFsdWUiXSwibWFwcGluZ3MiOiI7OztnQ0FDZ0JBLG1CLEdBQUFBLG1CO0FBRGhCO0FBQ08sU0FBU0EsbUJBQVQsQ0FBNkJDLE9BQTdCLEVBQXNDO0FBQzNDLE1BQUlDLE1BQU0sRUFBVjtBQUFBLE1BQ0lDLHdDQURKO0FBQUEsTUFFSUMsMkNBRko7QUFHQSxPQUFLLElBQUlDLElBQUksQ0FBYixFQUFnQkEsSUFBSUosUUFBUUssTUFBNUIsRUFBb0NELEdBQXBDLEVBQXlDO0FBQ3ZDRixhQUFTRixRQUFRSSxDQUFSLENBQVQ7QUFDQSxRQUFJRixPQUFPSSxLQUFYLEVBQWtCO0FBQ2hCSCxrQkFBWSxDQUFaO0FBQ0QsS0FGRCxNQUVPLElBQUlELE9BQU9LLE9BQVgsRUFBb0I7QUFDekJKLGtCQUFZLENBQUMsQ0FBYjtBQUNELEtBRk0sTUFFQTtBQUNMQSxrQkFBWSxDQUFaO0FBQ0Q7O0FBRURGLFFBQUlPLElBQUosQ0FBUyxDQUFDTCxTQUFELEVBQVlELE9BQU9PLEtBQW5CLENBQVQ7QUFDRDtBQUNELFNBQU9SLEdBQVA7QUFDRCIsImZpbGUiOiJkbXAuanMiLCJzb3VyY2VzQ29udGVudCI6WyIvLyBTZWU6IGh0dHA6Ly9jb2RlLmdvb2dsZS5jb20vcC9nb29nbGUtZGlmZi1tYXRjaC1wYXRjaC93aWtpL0FQSVxuZXhwb3J0IGZ1bmN0aW9uIGNvbnZlcnRDaGFuZ2VzVG9ETVAoY2hhbmdlcykge1xuICBsZXQgcmV0ID0gW10sXG4gICAgICBjaGFuZ2UsXG4gICAgICBvcGVyYXRpb247XG4gIGZvciAobGV0IGkgPSAwOyBpIDwgY2hhbmdlcy5sZW5ndGg7IGkrKykge1xuICAgIGNoYW5nZSA9IGNoYW5nZXNbaV07XG4gICAgaWYgKGNoYW5nZS5hZGRlZCkge1xuICAgICAgb3BlcmF0aW9uID0gMTtcbiAgICB9IGVsc2UgaWYgKGNoYW5nZS5yZW1vdmVkKSB7XG4gICAgICBvcGVyYXRpb24gPSAtMTtcbiAgICB9IGVsc2Uge1xuICAgICAgb3BlcmF0aW9uID0gMDtcbiAgICB9XG5cbiAgICByZXQucHVzaChbb3BlcmF0aW9uLCBjaGFuZ2UudmFsdWVdKTtcbiAgfVxuICByZXR1cm4gcmV0O1xufVxuIl19 + //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9jb252ZXJ0L2RtcC5qcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Z0NBQ2dCLG1CLEdBQUEsbUI7O0FBQVQsU0FBUyxtQkFBVCxDQUE2QixPQUE3QixFQUFzQztBQUMzQyxNQUFJLE1BQU0sRUFBVjtBQUFBLE1BQ0ksUyx5QkFBQSxNLHdCQURKO0FBQUEsTUFFSSxZLHlCQUFBLE0sd0JBRko7QUFHQSxPQUFLLElBQUksSUFBSSxDQUFiLEVBQWdCLElBQUksUUFBUSxNQUE1QixFQUFvQyxHQUFwQyxFQUF5QztBQUN2QyxhQUFTLFFBQVEsQ0FBUixDQUFUO0FBQ0EsUUFBSSxPQUFPLEtBQVgsRUFBa0I7QUFDaEIsa0JBQVksQ0FBWjtBQUNELEtBRkQsTUFFTyxJQUFJLE9BQU8sT0FBWCxFQUFvQjtBQUN6QixrQkFBWSxDQUFDLENBQWI7QUFDRCxLQUZNLE1BRUE7QUFDTCxrQkFBWSxDQUFaO0FBQ0Q7O0FBRUQsUUFBSSxJQUFKLENBQVMsQ0FBQyxTQUFELEVBQVksT0FBTyxLQUFuQixDQUFUO0FBQ0Q7QUFDRCxTQUFPLEdBQVA7QUFDRCIsImZpbGUiOiJkbXAuanMiLCJzb3VyY2VzQ29udGVudCI6WyIvLyBTZWU6IGh0dHA6Ly9jb2RlLmdvb2dsZS5jb20vcC9nb29nbGUtZGlmZi1tYXRjaC1wYXRjaC93aWtpL0FQSVxuZXhwb3J0IGZ1bmN0aW9uIGNvbnZlcnRDaGFuZ2VzVG9ETVAoY2hhbmdlcykge1xuICBsZXQgcmV0ID0gW10sXG4gICAgICBjaGFuZ2UsXG4gICAgICBvcGVyYXRpb247XG4gIGZvciAobGV0IGkgPSAwOyBpIDwgY2hhbmdlcy5sZW5ndGg7IGkrKykge1xuICAgIGNoYW5nZSA9IGNoYW5nZXNbaV07XG4gICAgaWYgKGNoYW5nZS5hZGRlZCkge1xuICAgICAgb3BlcmF0aW9uID0gMTtcbiAgICB9IGVsc2UgaWYgKGNoYW5nZS5yZW1vdmVkKSB7XG4gICAgICBvcGVyYXRpb24gPSAtMTtcbiAgICB9IGVsc2Uge1xuICAgICAgb3BlcmF0aW9uID0gMDtcbiAgICB9XG5cbiAgICByZXQucHVzaChbb3BlcmF0aW9uLCBjaGFuZ2UudmFsdWVdKTtcbiAgfVxuICByZXR1cm4gcmV0O1xufVxuIl19 -/***/ }), -/* 17 */ -/***/ (function(module, exports) { +/***/ }, +/* 15 */ +/***/ function(module, exports) { /*istanbul ignore start*/'use strict'; @@ -5181,10 +4750,10 @@ return /******/ (function(modules) { // webpackBootstrap return n; } - //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9jb252ZXJ0L3htbC5qcyJdLCJuYW1lcyI6WyJjb252ZXJ0Q2hhbmdlc1RvWE1MIiwiY2hhbmdlcyIsInJldCIsImkiLCJsZW5ndGgiLCJjaGFuZ2UiLCJhZGRlZCIsInB1c2giLCJyZW1vdmVkIiwiZXNjYXBlSFRNTCIsInZhbHVlIiwiam9pbiIsInMiLCJuIiwicmVwbGFjZSJdLCJtYXBwaW5ncyI6Ijs7O2dDQUFnQkEsbUIsR0FBQUEsbUI7QUFBVCxTQUFTQSxtQkFBVCxDQUE2QkMsT0FBN0IsRUFBc0M7QUFDM0MsTUFBSUMsTUFBTSxFQUFWO0FBQ0EsT0FBSyxJQUFJQyxJQUFJLENBQWIsRUFBZ0JBLElBQUlGLFFBQVFHLE1BQTVCLEVBQW9DRCxHQUFwQyxFQUF5QztBQUN2QyxRQUFJRSxTQUFTSixRQUFRRSxDQUFSLENBQWI7QUFDQSxRQUFJRSxPQUFPQyxLQUFYLEVBQWtCO0FBQ2hCSixVQUFJSyxJQUFKLENBQVMsT0FBVDtBQUNELEtBRkQsTUFFTyxJQUFJRixPQUFPRyxPQUFYLEVBQW9CO0FBQ3pCTixVQUFJSyxJQUFKLENBQVMsT0FBVDtBQUNEOztBQUVETCxRQUFJSyxJQUFKLENBQVNFLFdBQVdKLE9BQU9LLEtBQWxCLENBQVQ7O0FBRUEsUUFBSUwsT0FBT0MsS0FBWCxFQUFrQjtBQUNoQkosVUFBSUssSUFBSixDQUFTLFFBQVQ7QUFDRCxLQUZELE1BRU8sSUFBSUYsT0FBT0csT0FBWCxFQUFvQjtBQUN6Qk4sVUFBSUssSUFBSixDQUFTLFFBQVQ7QUFDRDtBQUNGO0FBQ0QsU0FBT0wsSUFBSVMsSUFBSixDQUFTLEVBQVQsQ0FBUDtBQUNEOztBQUVELFNBQVNGLFVBQVQsQ0FBb0JHLENBQXBCLEVBQXVCO0FBQ3JCLE1BQUlDLElBQUlELENBQVI7QUFDQUMsTUFBSUEsRUFBRUMsT0FBRixDQUFVLElBQVYsRUFBZ0IsT0FBaEIsQ0FBSjtBQUNBRCxNQUFJQSxFQUFFQyxPQUFGLENBQVUsSUFBVixFQUFnQixNQUFoQixDQUFKO0FBQ0FELE1BQUlBLEVBQUVDLE9BQUYsQ0FBVSxJQUFWLEVBQWdCLE1BQWhCLENBQUo7QUFDQUQsTUFBSUEsRUFBRUMsT0FBRixDQUFVLElBQVYsRUFBZ0IsUUFBaEIsQ0FBSjs7QUFFQSxTQUFPRCxDQUFQO0FBQ0QiLCJmaWxlIjoieG1sLmpzIiwic291cmNlc0NvbnRlbnQiOlsiZXhwb3J0IGZ1bmN0aW9uIGNvbnZlcnRDaGFuZ2VzVG9YTUwoY2hhbmdlcykge1xuICBsZXQgcmV0ID0gW107XG4gIGZvciAobGV0IGkgPSAwOyBpIDwgY2hhbmdlcy5sZW5ndGg7IGkrKykge1xuICAgIGxldCBjaGFuZ2UgPSBjaGFuZ2VzW2ldO1xuICAgIGlmIChjaGFuZ2UuYWRkZWQpIHtcbiAgICAgIHJldC5wdXNoKCc8aW5zPicpO1xuICAgIH0gZWxzZSBpZiAoY2hhbmdlLnJlbW92ZWQpIHtcbiAgICAgIHJldC5wdXNoKCc8ZGVsPicpO1xuICAgIH1cblxuICAgIHJldC5wdXNoKGVzY2FwZUhUTUwoY2hhbmdlLnZhbHVlKSk7XG5cbiAgICBpZiAoY2hhbmdlLmFkZGVkKSB7XG4gICAgICByZXQucHVzaCgnPC9pbnM+Jyk7XG4gICAgfSBlbHNlIGlmIChjaGFuZ2UucmVtb3ZlZCkge1xuICAgICAgcmV0LnB1c2goJzwvZGVsPicpO1xuICAgIH1cbiAgfVxuICByZXR1cm4gcmV0LmpvaW4oJycpO1xufVxuXG5mdW5jdGlvbiBlc2NhcGVIVE1MKHMpIHtcbiAgbGV0IG4gPSBzO1xuICBuID0gbi5yZXBsYWNlKC8mL2csICcmYW1wOycpO1xuICBuID0gbi5yZXBsYWNlKC88L2csICcmbHQ7Jyk7XG4gIG4gPSBuLnJlcGxhY2UoLz4vZywgJyZndDsnKTtcbiAgbiA9IG4ucmVwbGFjZSgvXCIvZywgJyZxdW90OycpO1xuXG4gIHJldHVybiBuO1xufVxuIl19 + //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9jb252ZXJ0L3htbC5qcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Z0NBQWdCLG1CLEdBQUEsbUI7QUFBVCxTQUFTLG1CQUFULENBQTZCLE9BQTdCLEVBQXNDO0FBQzNDLE1BQUksTUFBTSxFQUFWO0FBQ0EsT0FBSyxJQUFJLElBQUksQ0FBYixFQUFnQixJQUFJLFFBQVEsTUFBNUIsRUFBb0MsR0FBcEMsRUFBeUM7QUFDdkMsUUFBSSxTQUFTLFFBQVEsQ0FBUixDQUFiO0FBQ0EsUUFBSSxPQUFPLEtBQVgsRUFBa0I7QUFDaEIsVUFBSSxJQUFKLENBQVMsT0FBVDtBQUNELEtBRkQsTUFFTyxJQUFJLE9BQU8sT0FBWCxFQUFvQjtBQUN6QixVQUFJLElBQUosQ0FBUyxPQUFUO0FBQ0Q7O0FBRUQsUUFBSSxJQUFKLENBQVMsV0FBVyxPQUFPLEtBQWxCLENBQVQ7O0FBRUEsUUFBSSxPQUFPLEtBQVgsRUFBa0I7QUFDaEIsVUFBSSxJQUFKLENBQVMsUUFBVDtBQUNELEtBRkQsTUFFTyxJQUFJLE9BQU8sT0FBWCxFQUFvQjtBQUN6QixVQUFJLElBQUosQ0FBUyxRQUFUO0FBQ0Q7QUFDRjtBQUNELFNBQU8sSUFBSSxJQUFKLENBQVMsRUFBVCxDQUFQO0FBQ0Q7O0FBRUQsU0FBUyxVQUFULENBQW9CLENBQXBCLEVBQXVCO0FBQ3JCLE1BQUksSUFBSSxDQUFSO0FBQ0EsTUFBSSxFQUFFLE9BQUYsQ0FBVSxJQUFWLEVBQWdCLE9BQWhCLENBQUo7QUFDQSxNQUFJLEVBQUUsT0FBRixDQUFVLElBQVYsRUFBZ0IsTUFBaEIsQ0FBSjtBQUNBLE1BQUksRUFBRSxPQUFGLENBQVUsSUFBVixFQUFnQixNQUFoQixDQUFKO0FBQ0EsTUFBSSxFQUFFLE9BQUYsQ0FBVSxJQUFWLEVBQWdCLFFBQWhCLENBQUo7O0FBRUEsU0FBTyxDQUFQO0FBQ0QiLCJmaWxlIjoieG1sLmpzIiwic291cmNlc0NvbnRlbnQiOlsiZXhwb3J0IGZ1bmN0aW9uIGNvbnZlcnRDaGFuZ2VzVG9YTUwoY2hhbmdlcykge1xuICBsZXQgcmV0ID0gW107XG4gIGZvciAobGV0IGkgPSAwOyBpIDwgY2hhbmdlcy5sZW5ndGg7IGkrKykge1xuICAgIGxldCBjaGFuZ2UgPSBjaGFuZ2VzW2ldO1xuICAgIGlmIChjaGFuZ2UuYWRkZWQpIHtcbiAgICAgIHJldC5wdXNoKCc8aW5zPicpO1xuICAgIH0gZWxzZSBpZiAoY2hhbmdlLnJlbW92ZWQpIHtcbiAgICAgIHJldC5wdXNoKCc8ZGVsPicpO1xuICAgIH1cblxuICAgIHJldC5wdXNoKGVzY2FwZUhUTUwoY2hhbmdlLnZhbHVlKSk7XG5cbiAgICBpZiAoY2hhbmdlLmFkZGVkKSB7XG4gICAgICByZXQucHVzaCgnPC9pbnM+Jyk7XG4gICAgfSBlbHNlIGlmIChjaGFuZ2UucmVtb3ZlZCkge1xuICAgICAgcmV0LnB1c2goJzwvZGVsPicpO1xuICAgIH1cbiAgfVxuICByZXR1cm4gcmV0LmpvaW4oJycpO1xufVxuXG5mdW5jdGlvbiBlc2NhcGVIVE1MKHMpIHtcbiAgbGV0IG4gPSBzO1xuICBuID0gbi5yZXBsYWNlKC8mL2csICcmYW1wOycpO1xuICBuID0gbi5yZXBsYWNlKC88L2csICcmbHQ7Jyk7XG4gIG4gPSBuLnJlcGxhY2UoLz4vZywgJyZndDsnKTtcbiAgbiA9IG4ucmVwbGFjZSgvXCIvZywgJyZxdW90OycpO1xuXG4gIHJldHVybiBuO1xufVxuIl19 -/***/ }) +/***/ } /******/ ]) }); ; @@ -27196,7 +26765,8 @@ define('vellum/mugs',[ icon: 'fa fa-retweet', possibleDataParent: 'limited', controlNodeChildren: function ($node) { - return $node.children('repeat').children(); + var repeatChildren = $node.children('repeat').children(); + return repeatChildren.not('jr\\:addEmptyCaption, jr\\:addCaption'); }, getExtraDataAttributes: function (mug) { return {"jr:template": ""}; @@ -27212,10 +26782,13 @@ define('vellum/mugs',[ getAppearanceAttribute: function () {}, form: mug.form, p: { - rawControlAttributes: attrs + rawControlAttributes: attrs, + addEmptyCaptionItext: mug.p.addEmptyCaptionItext, + addCaptionItext: mug.p.addCaptionItext, }, options: { tagName: 'repeat', + writeRepeatItexts: mug.options.customRepeatButtonText, writeControlLabel: false, writeControlHint: false, writeControlHelp: false, @@ -28926,6 +28499,9 @@ define('vellum/writer',[ if (opts.writeControlAlert) { createAlert(xmlWriter, mug); } + if (opts.writeRepeatItexts) { + createRepeatButtonItexts(xmlWriter, mug); + } // Write custom attributes first var attributes = mug.p.rawControlAttributes; for (var k in attributes) { @@ -29013,6 +28589,24 @@ define('vellum/writer',[ } } + function createRepeatButtonItexts(xmlWriter, mug) { + var addEmptyCaptionItext = mug.p.addEmptyCaptionItext; + if (addEmptyCaptionItext && !addEmptyCaptionItext.isEmpty()) { + xmlWriter.writeStartElement('jr:addEmptyCaption'); + var addEmptyCaptionRef = "jr:itext('" + addEmptyCaptionItext.id + "')"; + xmlWriter.writeAttributeString('ref', addEmptyCaptionRef); + xmlWriter.writeEndElement(); + } + var addCaptionItext = mug.p.addCaptionItext; + if (addCaptionItext && !addCaptionItext.isEmpty()) { + xmlWriter.writeStartElement('jr:addCaption'); + var addCaptionRef = "jr:itext('" + addCaptionItext.id + "')"; + xmlWriter.writeAttributeString('ref', addCaptionRef); + xmlWriter.writeEndElement(); + } + } + + return { createXForm: createXForm }; @@ -29167,8 +28761,12 @@ define('vellum/exporter',[ "Required", "Hint Text", "Help Text", - "Comment" + "Comment", ]); + const formContainsRepeatGroup = Boolean(form.getMugList().find(mug => mug.options.isRepeat)); + if (formContainsRepeatGroup && form.vellum.opts().features.use_custom_repeat_button_text) { + columnOrder = columnOrder.concat(["'Add New' Button Text", "'Add Another' Button Text"]); + } var mugToExportRow = function (mug) { var row = {}, @@ -29221,6 +28819,10 @@ define('vellum/exporter',[ row["Hint Text"] = defaultOrNothing(mug.p.hintItext, defaultLanguage, 'default'); row["Help Text"] = defaultOrNothing(mug.p.helpItext, defaultLanguage, 'default'); + if (formContainsRepeatGroup && mug.options.customRepeatButtonText) { + row["'Add New' Button Text"] = defaultOrNothing(mug.p.addEmptyCaptionItext, defaultLanguage, 'default'); + row["'Add Another' Button Text"] = defaultOrNothing(mug.p.addCaptionItext, defaultLanguage, 'default'); + } row.Comment = richText.sanitizeInput(mug.p.comment); // make sure there aren't any null values @@ -31780,7 +31382,9 @@ define('vellum/javaRosa/util',[ 'labelItext', 'hintItext', 'helpItext', - 'constraintMsgItext' + 'constraintMsgItext', + 'addEmptyCaptionItext', + 'addCaptionItext', ]; var getDefaultItextRoot = function(mug) { @@ -49456,7 +49060,7 @@ define('vellum/core',[ title: gettext("Advanced"), text: gettext("These are advanced settings and are not needed for most applications. " + "Please only change these if you have a specific need!"), - link: "https://dimagi.atlassian.net/wiki/spaces/commcarepublic/pages/2143946283/Application+Development" + link: "https://confluence.dimagi.com/display/commcarepublic/Application+Building" } } ]; @@ -51869,6 +51473,14 @@ define('vellum/javaRosa/itext',[ if (!mug.p.helpItext && mug.getPresence("helpItext") !== "notallowed") { mug.p.helpItext = this.createItem(); } + if (mug.options.isRepeat && mug.options.customRepeatButtonText) { + if (!mug.p.addEmptyCaptionItext) { + mug.p.addEmptyCaptionItext = this.createItem(); + } + if (!mug.p.addCaptionItext) { + mug.p.addCaptionItext = this.createItem(); + } + } } if (!mug.options.isControlOnly) { // set constraint msg if legal and not there @@ -51964,7 +51576,7 @@ define('vellum/javaRosa/itextWidget',[ currentValue = null; function autoGenerateId() { - return jrUtil.getDefaultItextId(mug, widget.path); + return jrUtil.getDefaultItextId(mug, widget.path.replace(/Itext$/, "")); } function updateAutoId() { @@ -53101,6 +52713,21 @@ define('vellum/javaRosa/plugin',[ mug.p.constraintMsgAttr = null; } } + + function parseRepeatItexts(mug, controlElement) { + var repeatEl = controlElement.children('repeat'); + var addEmptyCaptionEl = repeatEl.children('jr\\:addEmptyCaption'), + addCaptionEl = repeatEl.children('jr\\:addCaption'); + if (addEmptyCaptionEl.length) { + mug.p.addEmptyCaptionItext = parseItextRef(addEmptyCaptionEl, "addEmptyCaption"); + } + if (addCaptionEl.length) { + mug.p.addCaptionItext = parseItextRef(addCaptionEl, "addCaption"); + } + } + if (mug.options.isRepeat && mug.options.customRepeatButtonText) { + parseRepeatItexts(mug, controlElement); + } }, handleMugParseFinish: function (mug) { this.__callOld(); @@ -53563,13 +53190,13 @@ define('vellum/javaRosa/plugin',[ lstring: gettext("Help Message"), widget: trackLogicRefs(function (mug, options) { var block = itextBlock.label(mug, $.extend(options, { - itextType: "help", - messagesPath: "helpItext", - getItextByMug: function (mug) { - return mug.p.helpItext; - }, - displayName: gettext("Help Message") - })); + itextType: "help", + messagesPath: "helpItext", + getItextByMug: function (mug) { + return mug.p.helpItext; + }, + displayName: gettext("Help Message"), + })); return block; }), @@ -53583,6 +53210,60 @@ define('vellum/javaRosa/plugin',[ widgetValuePath: "helpItext" }; + control.addEmptyCaptionItext = addSerializer({ + visibility: 'visible', + presence: function (mug) { + return mug.options.isRepeat && mug.options.customRepeatButtonText ? 'optional' : 'notallowed'; + }, + lstring: gettext("Add New Item Button Text"), + widget: trackLogicRefs(function (mug, options) { + var block = itextBlock.label(mug, $.extend(options, { + itextType: "addEmptyCaption", + messagesPath: "addEmptyCaptionItext", + getItextByMug: function (mug) { + return mug.p.addEmptyCaptionItext; + }, + displayName: gettext("Add New Item Button Text"), + })); + return block; + }), + validationFunc: itextValidator("addEmptyCaptionItext", gettext("Add New Item Button Text")), + }); + // virtual property used to get a widget + control.addEmptyCaptionItextID = { + visibility: 'addEmptyCaptionItext', + lstring: gettext("Add New Itext ID"), + widget: itextWidget.id, + widgetValuePath: "addEmptyCaptionItext", + }; + + control.addCaptionItext = addSerializer({ + visibility: 'visible', + presence: function (mug) { + return mug.options.isRepeat && mug.options.customRepeatButtonText ? 'optional' : 'notallowed'; + }, + lstring: gettext("Add Another Item Button Text"), + widget: trackLogicRefs(function (mug, options) { + var block = itextBlock.label(mug, $.extend(options, { + itextType: "addCaption", + messagesPath: "addCaptionItext", + getItextByMug: function (mug) { + return mug.p.addCaptionItext; + }, + displayName: gettext("Add Another Item Button Text"), + })); + return block; + }), + validationFunc: itextValidator("addCaptionItext", gettext("Add Another Item Button Text")), + }); + // virtual property used to get a widget + control.addCaptionItextID = { + visibility: 'addCaptionItext', + lstring: gettext("Add Another Itext ID"), + widget: itextWidget.id, + widgetValuePath: "addCaptionItext", + }; + // virtual property used to get a widget control.otherItext = function (mugOptions) { return mugOptions.isSpecialGroup ? undefined : { @@ -53669,6 +53350,10 @@ define('vellum/javaRosa/plugin',[ 'hintItext', 'helpItextID', 'helpItext', + 'addEmptyCaptionItextID', + 'addEmptyCaptionItext', + 'addCaptionItextID', + 'addCaptionItext', 'helpMediaIText', ]); @@ -54791,6 +54476,7 @@ define('vellum/modeliteration',[ modelRepeatMugOptions = { //typeName: 'Model Repeat', supportsDataNodeRole: true, + isRepeat: true, getPathName: function (mug, name) { if (mug.p.dataSource.idsQuery) { name += "/item"; @@ -54858,6 +54544,7 @@ define('vellum/modeliteration',[ mug.p.originalPath = null; mug.p.dataSource = {}; mug.p.dataSourceChanged = false; + mug.options.customRepeatButtonText = form.vellum.opts().features.use_custom_repeat_button_text; }, spec: { nodeID: { @@ -56034,38520 +55721,79 @@ __p+='\n
\n
\n
\n
\n \n
\n
\n
\n
\n \n
\n
\n \n
\n
\n
\n'; -} -return __p; -}; }); - - -define('tpl/tpl!vellum/templates/multimedia_upload_trigger', ['underscore'], function (_) { return function(obj){ -var __t,__p='',__j=Array.prototype.join,print=function(){__p+=__j.call(arguments,'');}; -with(obj||{}){ -__p+='\n '+ -((__t=( multimediaExists ? gettext("Replace") : gettext("Upload") ))==null?'':_.escape(__t))+ -' '+ -((__t=(mediaType))==null?'':__t)+ -'\n\n'; -} -return __p; -}; }); - - -define('text/text!vellum/templates/multimedia_queue.html',[],function () { return '
\n
\n <%= file_name %> [<%= file_size %> MB]\n
\n
\n
\n
\n
\n

\n <%\n var msg = gettext("Ready to upload. Click {btn} below to start."),\n btn = "" + gettext("Begin Upload") + "";\n print(msg.replace(/\\{btn\\}/g, btn));\n %>\n

\n

\n <%-gettext("There were errors.")%>\n

\n \n <%-gettext("Cancel Upload")%>\n \n
\n
\n
\n';}); - - -define('text/text!vellum/templates/multimedia_errors.html',[],function () { return '<% if (errors.length > 0) { %>\n
\n
<%-gettext("Errors found")%>
\n <% for (var e = 0; e < errors.length; e++) {\n var error = errors[e]; %>\n

<%- error %>

\n <% } %>\n
\n<% } %>\n';}); - - -define('text/text!vellum/templates/multimedia_existing_image.html',[],function () { return '

\n uploaded image\n "><%-gettext("View Full Size")%>\n

\n

\n <%-gettext("New Image Uploaded Successfully")%>\n

\n';}); - - -define('text/text!vellum/templates/multimedia_existing_audio.html',[],function () { return '

\n "><%-gettext("Open Audio")%>\n

\n

\n <%-gettext("New Audio Uploaded Successfully")%>\n

\n';}); - - -define('text/text!vellum/templates/multimedia_existing_video.html',[],function () { return '

\n "><%-gettext("Open Video")%>\n

\n

\n <%-gettext("New Video Uploaded Successfully")%>\n

\n';}); - - -define('text/text!vellum/templates/multimedia_existing_text.html',[],function () { return '

\n "><%-gettext("Open HTML")%>\n

\n

\n <%-gettext("New HTML Document Uploaded Successfully")%>\n

\n';}); - - -define('tpl/tpl!vellum/templates/multimedia_nomedia', ['underscore'], function (_) { return function(obj){ -var __t,__p='',__j=Array.prototype.join,print=function(){__p+=__j.call(arguments,'');}; -with(obj||{}){ -__p+='

\n \n '+ -((__t=(gettext("No Reference")))==null?'':_.escape(__t))+ -'\n

\n'; -} -return __p; -}; }); - - -define('tpl/tpl!vellum/templates/multimedia_block', ['underscore'], function (_) { return function(obj){ -var __t,__p='',__j=Array.prototype.join,print=function(){__p+=__j.call(arguments,'');}; -with(obj||{}){ -__p+='
\n
\n \n
\n
\n
\n
\n
\n \n
\n
\n
\n'; -} -return __p; -}; }); - -/* -YUI 3.16.0 (build 76f0e08) -Copyright 2014 Yahoo! Inc. All rights reserved. -Licensed under the BSD License. -http://yuilibrary.com/license/ -*/ - -/** -The YUI module contains the components required for building the YUI seed file. -This includes the script loading mechanism, a simple queue, and the core -utilities for the library. - -@module yui -@main yui -@submodule yui-base -**/ - -/*jshint eqeqeq: false*/ -if (typeof YUI != 'undefined') { - YUI._YUI = YUI; -} - -/** -The YUI global namespace object. This is the constructor for all YUI instances. - -This is a self-instantiable factory function, meaning you don't need to precede -it with the `new` operator. You can invoke it directly like this: - - YUI().use('*', function (Y) { - // Y is a new YUI instance. - }); - -But it also works like this: - - var Y = YUI(); - -The `YUI` constructor accepts an optional config object, like this: - - YUI({ - debug: true, - combine: false - }).use('node', function (Y) { - // Y.Node is ready to use. - }); - -See the API docs for the Config class for the complete -list of supported configuration properties accepted by the YUI constuctor. - -If a global `YUI` object is already defined, the existing YUI object will not be -overwritten, to ensure that defined namespaces are preserved. - -Each YUI instance has full custom event support, but only if the event system is -available. - -@class YUI -@uses EventTarget -@constructor -@global -@param {Object} [config]* Zero or more optional configuration objects. Config - values are stored in the `Y.config` property. See the - Config docs for the list of supported properties. -**/ - - /*global YUI*/ - /*global YUI_config*/ - var YUI = function() { - var i = 0, - Y = this, - args = arguments, - l = args.length, - instanceOf = function(o, type) { - return (o && o.hasOwnProperty && (o instanceof type)); - }, - gconf = (typeof YUI_config !== 'undefined') && YUI_config; - - if (!(instanceOf(Y, YUI))) { - Y = new YUI(); - } else { - // set up the core environment - Y._init(); - - /** - Master configuration that might span multiple contexts in a non- - browser environment. It is applied first to all instances in all - contexts. - - @example - - YUI.GlobalConfig = { - filter: 'debug' - }; - - YUI().use('node', function (Y) { - // debug files used here - }); - - YUI({ - filter: 'min' - }).use('node', function (Y) { - // min files used here - }); - - @property {Object} GlobalConfig - @global - @static - **/ - if (YUI.GlobalConfig) { - Y.applyConfig(YUI.GlobalConfig); - } - - /** - Page-level config applied to all YUI instances created on the - current page. This is applied after `YUI.GlobalConfig` and before - any instance-level configuration. - - @example - - // Single global var to include before YUI seed file - YUI_config = { - filter: 'debug' - }; - - YUI().use('node', function (Y) { - // debug files used here - }); - - YUI({ - filter: 'min' - }).use('node', function (Y) { - // min files used here - }); - - @property {Object} YUI_config - @global - **/ - if (gconf) { - Y.applyConfig(gconf); - } - - // bind the specified additional modules for this instance - if (!l) { - Y._setup(); - } - } - - if (l) { - // Each instance can accept one or more configuration objects. - // These are applied after YUI.GlobalConfig and YUI_Config, - // overriding values set in those config files if there is a - // matching property. - for (; i < l; i++) { - Y.applyConfig(args[i]); - } - - Y._setup(); - } - - Y.instanceOf = instanceOf; - - return Y; - }; - -(function() { - - var proto, prop, - VERSION = '3.16.0', - PERIOD = '.', - BASE = 'http://yui.yahooapis.com/', - /* - These CSS class names can't be generated by - getClassName since it is not available at the - time they are being used. - */ - DOC_LABEL = 'yui3-js-enabled', - CSS_STAMP_EL = 'yui3-css-stamp', - NOOP = function() {}, - SLICE = Array.prototype.slice, - APPLY_TO_AUTH = { 'io.xdrReady': 1, // the functions applyTo - 'io.xdrResponse': 1, // can call. this should - 'SWF.eventHandler': 1 }, // be done at build time - hasWin = (typeof window != 'undefined'), - win = (hasWin) ? window : null, - doc = (hasWin) ? win.document : null, - docEl = doc && doc.documentElement, - docClass = docEl && docEl.className, - instances = {}, - time = new Date().getTime(), - add = function(el, type, fn, capture) { - if (el && el.addEventListener) { - el.addEventListener(type, fn, capture); - } else if (el && el.attachEvent) { - el.attachEvent('on' + type, fn); - } - }, - remove = function(el, type, fn, capture) { - if (el && el.removeEventListener) { - // this can throw an uncaught exception in FF - try { - el.removeEventListener(type, fn, capture); - } catch (ex) {} - } else if (el && el.detachEvent) { - el.detachEvent('on' + type, fn); - } - }, - handleReady = function() { - YUI.Env.DOMReady = true; - if (hasWin) { - remove(doc, 'DOMContentLoaded', handleReady); - } - }, - handleLoad = function() { - YUI.Env.windowLoaded = true; - YUI.Env.DOMReady = true; - if (hasWin) { - remove(window, 'load', handleLoad); - } - }, - getLoader = function(Y, o) { - var loader = Y.Env._loader, - lCore = [ 'loader-base' ], - G_ENV = YUI.Env, - mods = G_ENV.mods; - - if (loader) { - //loader._config(Y.config); - loader.ignoreRegistered = false; - loader.onEnd = null; - loader.data = null; - loader.required = []; - loader.loadType = null; - } else { - loader = new Y.Loader(Y.config); - Y.Env._loader = loader; - } - if (mods && mods.loader) { - lCore = [].concat(lCore, YUI.Env.loaderExtras); - } - YUI.Env.core = Y.Array.dedupe([].concat(YUI.Env.core, lCore)); - - return loader; - }, - - clobber = function(r, s) { - for (var i in s) { - if (s.hasOwnProperty(i)) { - r[i] = s[i]; - } - } - }, - - ALREADY_DONE = { success: true }; - -// Stamp the documentElement (HTML) with a class of "yui-loaded" to -// enable styles that need to key off of JS being enabled. -if (docEl && docClass.indexOf(DOC_LABEL) == -1) { - if (docClass) { - docClass += ' '; - } - docClass += DOC_LABEL; - docEl.className = docClass; -} - -if (VERSION.indexOf('@') > -1) { - VERSION = '3.5.0'; // dev time hack for cdn test -} - -proto = { - /** - Applies a new configuration object to the config of this YUI instance. This - will merge new group/module definitions, and will also update the loader - cache if necessary. Updating `Y.config` directly will not update the cache. - - @method applyConfig - @param {Object} o the configuration object. - @since 3.2.0 - **/ - applyConfig: function(o) { - - o = o || NOOP; - - var attr, - name, - // detail, - config = this.config, - mods = config.modules, - groups = config.groups, - aliases = config.aliases, - loader = this.Env._loader; - - for (name in o) { - if (o.hasOwnProperty(name)) { - attr = o[name]; - if (mods && name == 'modules') { - clobber(mods, attr); - } else if (aliases && name == 'aliases') { - clobber(aliases, attr); - } else if (groups && name == 'groups') { - clobber(groups, attr); - } else if (name == 'win') { - config[name] = (attr && attr.contentWindow) || attr; - config.doc = config[name] ? config[name].document : null; - } else if (name == '_yuid') { - // preserve the guid - } else { - config[name] = attr; - } - } - } - - if (loader) { - loader._config(o); - } - - }, - - /** - Old way to apply a config to this instance (calls `applyConfig` under the - hood). - - @private - @method _config - @param {Object} o The config to apply - **/ - _config: function(o) { - this.applyConfig(o); - }, - - /** - Initializes this YUI instance. - - @private - @method _init - **/ - _init: function() { - var filter, el, - Y = this, - G_ENV = YUI.Env, - Env = Y.Env, - prop; - - /** - The version number of this YUI instance. - - This value is typically updated by a script when a YUI release is built, - so it may not reflect the correct version number when YUI is run from - the development source tree. - - @property {String} version - **/ - Y.version = VERSION; - - if (!Env) { - Y.Env = { - core: ['get', 'features', 'intl-base', 'yui-log', 'yui-later'], - loaderExtras: ['loader-rollup', 'loader-yui3'], - mods: {}, // flat module map - versions: {}, // version module map - base: BASE, - cdn: BASE + VERSION + '/build/', - // bootstrapped: false, - _idx: 0, - _used: {}, - _attached: {}, - _exported: {}, - _missed: [], - _yidx: 0, - _uidx: 0, - _guidp: 'y', - _loaded: {}, - // serviced: {}, - // Regex in English: - // I'll start at the \b(yui). - // 1. Look in the test string for "yui" or - // "yui-base" or "yui-davglass" or "yui-foobar" that comes after a word break. That is, it - // can't match "foyui" or "i_heart_yui". This can be anywhere in the string. - // 2. After #1 must come a forward slash followed by the string matched in #1, so - // "yui-base/yui-base" or "yui-pants/yui-pants". - // 3. The second occurence of the #1 token can optionally be followed by "-debug" or "-min", - // so "yui/yui-min", "yui/yui-debug", "yui-base/yui-base-debug". NOT "yui/yui-tshirt". - // 4. This is followed by ".js", so "yui/yui.js". - // 0. Going back to the beginning, now. If all that stuff in 1-4 comes after a "?" in the string, - // then capture the junk between the LAST "&" and the string in 1-4. So - // "blah?foo/yui/yui.js" will capture "foo/" and "blah?some/thing.js&3.3.0/build/yui-davglass/yui-davglass.js" - // will capture "3.3.0/build/" - // - // Regex Exploded: - // (?:\? Find a ? - // (?:[^&]*&) followed by 0..n characters followed by an & - // * in fact, find as many sets of characters followed by a & as you can - // ([^&]*) capture the stuff after the last & in \1 - // )? but it's ok if all this ?junk&more_junk stuff isn't even there - // \b( after a word break find either the string - // yui(?:-\w+)? "yui" optionally followed by a -, then more characters - // ) and store the yui-* string in \2 - // \/\2 then comes a / followed by the yui-* string in \2 - // (?:-(min|debug))? optionally followed by "-min" or "-debug" - // .js and ending in ".js" - _BASE_RE: /(?:\?(?:[^&]*&)*([^&]*))?\b(yui(?:-\w+)?)\/\2(?:-(min|debug))?\.js/, - parseBasePath: function(src, pattern) { - var match = src.match(pattern), - path, filter; - - if (match) { - path = RegExp.leftContext || src.slice(0, src.indexOf(match[0])); - - // this is to set up the path to the loader. The file - // filter for loader should match the yui include. - filter = match[3]; - - // extract correct path for mixed combo urls - // http://yuilibrary.com/projects/yui3/ticket/2528423 - if (match[1]) { - path += '?' + match[1]; - } - path = { - filter: filter, - path: path - }; - } - return path; - }, - getBase: G_ENV && G_ENV.getBase || - function(pattern) { - var nodes = (doc && doc.getElementsByTagName('script')) || [], - path = Env.cdn, parsed, - i, len, src; - - for (i = 0, len = nodes.length; i < len; ++i) { - src = nodes[i].src; - if (src) { - parsed = Y.Env.parseBasePath(src, pattern); - if (parsed) { - filter = parsed.filter; - path = parsed.path; - break; - } - } - } - - // use CDN default - return path; - } - - }; - - Env = Y.Env; - - Env._loaded[VERSION] = {}; - - if (G_ENV && Y !== YUI) { - Env._yidx = ++G_ENV._yidx; - Env._guidp = ('yui_' + VERSION + '_' + - Env._yidx + '_' + time).replace(/[^a-z0-9_]+/g, '_'); - } else if (YUI._YUI) { - - G_ENV = YUI._YUI.Env; - Env._yidx += G_ENV._yidx; - Env._uidx += G_ENV._uidx; - - for (prop in G_ENV) { - if (!(prop in Env)) { - Env[prop] = G_ENV[prop]; - } - } - - delete YUI._YUI; - } - - Y.id = Y.stamp(Y); - instances[Y.id] = Y; - - } - - Y.constructor = YUI; - - // configuration defaults - Y.config = Y.config || { - bootstrap: true, - cacheUse: true, - debug: true, - doc: doc, - fetchCSS: true, - throwFail: true, - useBrowserConsole: true, - useNativeES5: true, - win: win, - global: Function('return this')() - }; - - //Register the CSS stamp element - if (doc && !doc.getElementById(CSS_STAMP_EL)) { - el = doc.createElement('div'); - el.innerHTML = '
'; - YUI.Env.cssStampEl = el.firstChild; - if (doc.body) { - doc.body.appendChild(YUI.Env.cssStampEl); - } else { - docEl.insertBefore(YUI.Env.cssStampEl, docEl.firstChild); - } - } else if (doc && doc.getElementById(CSS_STAMP_EL) && !YUI.Env.cssStampEl) { - YUI.Env.cssStampEl = doc.getElementById(CSS_STAMP_EL); - } - - Y.config.lang = Y.config.lang || 'en-US'; - - Y.config.base = YUI.config.base || Y.Env.getBase(Y.Env._BASE_RE); - - if (!filter || (!('mindebug').indexOf(filter))) { - filter = 'min'; - } - filter = (filter) ? '-' + filter : filter; - Y.config.loaderPath = YUI.config.loaderPath || 'loader/loader' + filter + '.js'; - - }, - - /** - Finishes the instance setup. Attaches whatever YUI modules were defined - at the time that this instance was created. - - @method _setup - @private - **/ - _setup: function() { - var i, Y = this, - core = [], - mods = YUI.Env.mods, - extras = Y.config.core || [].concat(YUI.Env.core); //Clone it.. - - for (i = 0; i < extras.length; i++) { - if (mods[extras[i]]) { - core.push(extras[i]); - } - } - - Y._attach(['yui-base']); - Y._attach(core); - - if (Y.Loader) { - getLoader(Y); - } - - }, - - /** - Executes the named method on the specified YUI instance if that method is - whitelisted. - - @method applyTo - @param {String} id YUI instance id. - @param {String} method Name of the method to execute. For example: - 'Object.keys'. - @param {Array} args Arguments to apply to the method. - @return {Mixed} Return value from the applied method, or `null` if the - specified instance was not found or the method was not whitelisted. - **/ - applyTo: function(id, method, args) { - if (!(method in APPLY_TO_AUTH)) { - this.log(method + ': applyTo not allowed', 'warn', 'yui'); - return null; - } - - var instance = instances[id], nest, m, i; - if (instance) { - nest = method.split('.'); - m = instance; - for (i = 0; i < nest.length; i = i + 1) { - m = m[nest[i]]; - if (!m) { - this.log('applyTo not found: ' + method, 'warn', 'yui'); - } - } - return m && m.apply(instance, args); - } - - return null; - }, - -/** -Registers a YUI module and makes it available for use in a `YUI().use()` call or -as a dependency for other modules. - -The easiest way to create a first-class YUI module is to use -Shifter, the YUI component build -tool. - -Shifter will automatically wrap your module code in a `YUI.add()` call along -with any configuration info required for the module. - -@example - - YUI.add('davglass', function (Y) { - Y.davglass = function () { - }; - }, '3.4.0', { - requires: ['harley-davidson', 'mt-dew'] - }); - -@method add -@param {String} name Module name. -@param {Function} fn Function containing module code. This function will be - executed whenever the module is attached to a specific YUI instance. - - @param {YUI} fn.Y The YUI instance to which this module is attached. - @param {String} fn.name Name of the module - -@param {String} version Module version number. This is currently used only for - informational purposes, and is not used internally by YUI. - -@param {Object} [config] Module config. - @param {Array} [config.requires] Array of other module names that must be - attached before this module can be attached. - @param {Array} [config.optional] Array of optional module names that should - be attached before this module is attached if they've already been - loaded. If the `loadOptional` YUI option is `true`, optional modules - that have not yet been loaded will be loaded just as if they were hard - requirements. - @param {Array} [config.use] Array of module names that are included within - or otherwise provided by this module, and which should be attached - automatically when this module is attached. This makes it possible to - create "virtual rollup" modules that simply attach a collection of other - modules or submodules. - -@return {YUI} This YUI instance. -**/ - add: function(name, fn, version, details) { - details = details || {}; - var env = YUI.Env, - mod = { - name: name, - fn: fn, - version: version, - details: details - }, - //Instance hash so we don't apply it to the same instance twice - applied = {}, - loader, inst, modInfo, - i, versions = env.versions; - - env.mods[name] = mod; - versions[version] = versions[version] || {}; - versions[version][name] = mod; - - for (i in instances) { - if (instances.hasOwnProperty(i)) { - inst = instances[i]; - if (!applied[inst.id]) { - applied[inst.id] = true; - loader = inst.Env._loader; - if (loader) { - modInfo = loader.getModuleInfo(name); - if (!modInfo || modInfo.temp) { - loader.addModule(details, name); - } - } - } - } - } - - return this; - }, - - /** - Executes the callback function associated with each required module, - attaching the module to this YUI instance. - - @method _attach - @param {Array} r The array of modules to attach - @param {Boolean} [moot=false] If `true`, don't throw a warning if the module - is not attached. - @private - **/ - _attach: function(r, moot) { - var i, name, mod, details, req, use, after, - mods = YUI.Env.mods, - aliases = YUI.Env.aliases, - Y = this, j, - cache = YUI.Env._renderedMods, - loader = Y.Env._loader, - done = Y.Env._attached, - exported = Y.Env._exported, - len = r.length, loader, def, go, - c = [], - modArgs, esCompat, reqlen, modInfo, - condition, - __exports__, __imports__; - - //Check for conditional modules (in a second+ instance) and add their requirements - //TODO I hate this entire method, it needs to be fixed ASAP (3.5.0) ^davglass - for (i = 0; i < len; i++) { - name = r[i]; - mod = mods[name]; - c.push(name); - if (loader && loader.conditions[name]) { - for (j in loader.conditions[name]) { - if (loader.conditions[name].hasOwnProperty(j)) { - def = loader.conditions[name][j]; - go = def && ((def.ua && Y.UA[def.ua]) || (def.test && def.test(Y))); - if (go) { - c.push(def.name); - } - } - } - } - } - r = c; - len = r.length; - - for (i = 0; i < len; i++) { - if (!done[r[i]]) { - name = r[i]; - mod = mods[name]; - - if (aliases && aliases[name] && !mod) { - Y._attach(aliases[name]); - continue; - } - if (!mod) { - modInfo = loader && loader.getModuleInfo(name); - if (modInfo) { - mod = modInfo; - moot = true; - } - - - //if (!loader || !loader.moduleInfo[name]) { - //if ((!loader || !loader.moduleInfo[name]) && !moot) { - if (!moot && name) { - if ((name.indexOf('skin-') === -1) && (name.indexOf('css') === -1)) { - Y.Env._missed.push(name); - Y.Env._missed = Y.Array.dedupe(Y.Env._missed); - Y.message('NOT loaded: ' + name, 'warn', 'yui'); - } - } - } else { - done[name] = true; - //Don't like this, but in case a mod was asked for once, then we fetch it - //We need to remove it from the missed list ^davglass - for (j = 0; j < Y.Env._missed.length; j++) { - if (Y.Env._missed[j] === name) { - Y.message('Found: ' + name + ' (was reported as missing earlier)', 'warn', 'yui'); - Y.Env._missed.splice(j, 1); - } - } - /* - If it's a temp module, we need to redo it's requirements if it's already loaded - since it may have been loaded by another instance and it's dependencies might - have been redefined inside the fetched file. - */ - if (loader && cache && cache[name] && cache[name].temp) { - loader.getRequires(cache[name]); - req = []; - modInfo = loader.getModuleInfo(name); - for (j in modInfo.expanded_map) { - if (modInfo.expanded_map.hasOwnProperty(j)) { - req.push(j); - } - } - Y._attach(req); - } - - details = mod.details; - req = details.requires; - esCompat = details.es; - use = details.use; - after = details.after; - //Force Intl load if there is a language (Loader logic) @todo fix this shit - if (details.lang) { - req = req || []; - req.unshift('intl'); - } - - if (req) { - reqlen = req.length; - for (j = 0; j < reqlen; j++) { - if (!done[req[j]]) { - if (!Y._attach(req)) { - return false; - } - break; - } - } - } - - if (after) { - for (j = 0; j < after.length; j++) { - if (!done[after[j]]) { - if (!Y._attach(after, true)) { - return false; - } - break; - } - } - } - - if (mod.fn) { - modArgs = [Y, name]; - if (esCompat) { - __imports__ = {}; - __exports__ = {}; - // passing `exports` and `imports` onto the module function - modArgs.push(__imports__, __exports__); - if (req) { - reqlen = req.length; - for (j = 0; j < reqlen; j++) { - __imports__[req[j]] = exported.hasOwnProperty(req[j]) ? exported[req[j]] : Y; - } - } - } - if (Y.config.throwFail) { - __exports__ = mod.fn.apply(esCompat ? undefined : mod, modArgs); - } else { - try { - __exports__ = mod.fn.apply(esCompat ? undefined : mod, modArgs); - } catch (e) { - Y.error('Attach error: ' + name, e, name); - return false; - } - } - if (esCompat) { - // store the `exports` in case others `es` modules requires it - exported[name] = __exports__; - - // If an ES module is conditionally loaded and set - // to be used "instead" another module, replace the - // trigger module's content with the conditionally - // loaded one so the values returned by require() - // still makes sense - condition = mod.details.condition; - if (condition && condition.when === 'instead') { - exported[condition.trigger] = __exports__; - } - } - } - - if (use) { - for (j = 0; j < use.length; j++) { - if (!done[use[j]]) { - if (!Y._attach(use)) { - return false; - } - break; - } - } - } - - - - } - } - } - - return true; - }, - - /** - Delays the `use` callback until another event has taken place such as - `window.onload`, `domready`, `contentready`, or `available`. - - @private - @method _delayCallback - @param {Function} cb The original `use` callback. - @param {String|Object} until Either an event name ('load', 'domready', etc.) - or an object containing event/args keys for contentready/available. - @return {Function} - **/ - _delayCallback: function(cb, until) { - - var Y = this, - mod = ['event-base']; - - until = (Y.Lang.isObject(until) ? until : { event: until }); - - if (until.event === 'load') { - mod.push('event-synthetic'); - } - - return function() { - var args = arguments; - Y._use(mod, function() { - Y.on(until.event, function() { - args[1].delayUntil = until.event; - cb.apply(Y, args); - }, until.args); - }); - }; - }, - - /** - Attaches one or more modules to this YUI instance. When this is executed, - the requirements of the desired modules are analyzed, and one of several - things can happen: - - - * All required modules have already been loaded, and just need to be - attached to this YUI instance. In this case, the `use()` callback will - be executed synchronously after the modules are attached. - - * One or more modules have not yet been loaded, or the Get utility is not - available, or the `bootstrap` config option is `false`. In this case, - a warning is issued indicating that modules are missing, but all - available modules will still be attached and the `use()` callback will - be executed synchronously. - - * One or more modules are missing and the Loader is not available but the - Get utility is, and `bootstrap` is not `false`. In this case, the Get - utility will be used to load the Loader, and we will then proceed to - the following state: - - * One or more modules are missing and the Loader is available. In this - case, the Loader will be used to resolve the dependency tree for the - missing modules and load them and their dependencies. When the Loader is - finished loading modules, the `use()` callback will be executed - asynchronously. - - @example - - // Loads and attaches dd and its dependencies. - YUI().use('dd', function (Y) { - // ... - }); - - // Loads and attaches dd and node as well as all of their dependencies. - YUI().use(['dd', 'node'], function (Y) { - // ... - }); - - // Attaches all modules that have already been loaded. - YUI().use('*', function (Y) { - // ... - }); - - // Attaches a gallery module. - YUI().use('gallery-yql', function (Y) { - // ... - }); - - // Attaches a YUI 2in3 module. - YUI().use('yui2-datatable', function (Y) { - // ... - }); - - @method use - @param {String|Array} modules* One or more module names to attach. - @param {Function} [callback] Callback function to be executed once all - specified modules and their dependencies have been attached. - @param {YUI} callback.Y The YUI instance created for this sandbox. - @param {Object} callback.status Object containing `success`, `msg` and - `data` properties. - @chainable - **/ - use: function() { - var args = SLICE.call(arguments, 0), - callback = args[args.length - 1], - Y = this, - i = 0, - name, - Env = Y.Env, - provisioned = true; - - // The last argument supplied to use can be a load complete callback - if (Y.Lang.isFunction(callback)) { - args.pop(); - if (Y.config.delayUntil) { - callback = Y._delayCallback(callback, Y.config.delayUntil); - } - } else { - callback = null; - } - if (Y.Lang.isArray(args[0])) { - args = args[0]; - } - - if (Y.config.cacheUse) { - while ((name = args[i++])) { - if (!Env._attached[name]) { - provisioned = false; - break; - } - } - - if (provisioned) { - if (args.length) { - } - Y._notify(callback, ALREADY_DONE, args); - return Y; - } - } - - if (Y._loading) { - Y._useQueue = Y._useQueue || new Y.Queue(); - Y._useQueue.add([args, callback]); - } else { - Y._use(args, function(Y, response) { - Y._notify(callback, response, args); - }); - } - - return Y; - }, - - /** - Sugar for loading both legacy and ES6-based YUI modules. - - @method require - @param {String} [modules*] List of module names to import or a single - module name. - @param {Function} callback Callback that gets called once all the modules - were loaded. Each parameter of the callback is the export value of the - corresponding module in the list. If the module is a legacy YUI module, - the YUI instance is used instead of the module exports. - @example - ``` - YUI().require(['es6-set'], function (Y, imports) { - var Set = imports.Set, - set = new Set(); - }); - ``` - **/ - require: function () { - var args = SLICE.call(arguments), - callback; - - if (typeof args[args.length - 1] === 'function') { - callback = args.pop(); - - // only add the callback if one was provided - // YUI().require('foo'); is valid - args.push(function (Y) { - var i, length = args.length, - exported = Y.Env._exported, - __imports__ = {}; - - // Get only the imports requested as arguments - for (i = 0; i < length; i++) { - if (exported.hasOwnProperty(args[i])) { - __imports__[args[i]] = exported[args[i]]; - } - } - - // Using `undefined` because: - // - Using `Y.config.global` would force the value of `this` to be - // the global object even in strict mode - // - Using `Y` goes against the goal of moving away from a shared - // object and start thinking in terms of imported and exported - // objects - callback.call(undefined, Y, __imports__); - }); - } - // Do not return the Y object. This makes it hard to follow this - // traditional pattern: - // var Y = YUI().use(...); - // This is a good idea in the light of ES6 modules, to avoid working - // in the global scope. - // This also leaves the door open for returning a promise, once the - // YUI loader is based on the ES6 loader which uses - // loader.import(...).then(...) - this.use.apply(this, args); - }, - - /** - Handles Loader notifications about attachment/load errors. - - @method _notify - @param {Function} callback Callback to pass to `Y.config.loadErrorFn`. - @param {Object} response Response returned from Loader. - @param {Array} args Arguments passed from Loader. - @private - **/ - _notify: function(callback, response, args) { - if (!response.success && this.config.loadErrorFn) { - this.config.loadErrorFn.call(this, this, callback, response, args); - } else if (callback) { - if (this.Env._missed && this.Env._missed.length) { - response.msg = 'Missing modules: ' + this.Env._missed.join(); - response.success = false; - } - if (this.config.throwFail) { - callback(this, response); - } else { - try { - callback(this, response); - } catch (e) { - this.error('use callback error', e, args); - } - } - } - }, - - /** - Called from the `use` method queue to ensure that only one set of loading - logic is performed at a time. - - @method _use - @param {String} args* One or more modules to attach. - @param {Function} [callback] Function to call once all required modules have - been attached. - @private - **/ - _use: function(args, callback) { - - if (!this.Array) { - this._attach(['yui-base']); - } - - var len, loader, handleBoot, - Y = this, - G_ENV = YUI.Env, - mods = G_ENV.mods, - Env = Y.Env, - used = Env._used, - aliases = G_ENV.aliases, - queue = G_ENV._loaderQueue, - firstArg = args[0], - YArray = Y.Array, - config = Y.config, - boot = config.bootstrap, - missing = [], - i, - r = [], - ret = true, - fetchCSS = config.fetchCSS, - process = function(names, skip) { - - var i = 0, a = [], name, len, m, req, use; - - if (!names.length) { - return; - } - - if (aliases) { - len = names.length; - for (i = 0; i < len; i++) { - if (aliases[names[i]] && !mods[names[i]]) { - a = [].concat(a, aliases[names[i]]); - } else { - a.push(names[i]); - } - } - names = a; - } - - len = names.length; - - for (i = 0; i < len; i++) { - name = names[i]; - if (!skip) { - r.push(name); - } - - // only attach a module once - if (used[name]) { - continue; - } - - m = mods[name]; - req = null; - use = null; - - if (m) { - used[name] = true; - req = m.details.requires; - use = m.details.use; - } else { - // CSS files don't register themselves, see if it has - // been loaded - if (!G_ENV._loaded[VERSION][name]) { - missing.push(name); - } else { - used[name] = true; // probably css - } - } - - // make sure requirements are attached - if (req && req.length) { - process(req); - } - - // make sure we grab the submodule dependencies too - if (use && use.length) { - process(use, 1); - } - } - - }, - - handleLoader = function(fromLoader) { - var response = fromLoader || { - success: true, - msg: 'not dynamic' - }, - redo, origMissing, - ret = true, - data = response.data; - - Y._loading = false; - - if (data) { - origMissing = missing; - missing = []; - r = []; - process(data); - redo = missing.length; - if (redo) { - if ([].concat(missing).sort().join() == - origMissing.sort().join()) { - redo = false; - } - } - } - - if (redo && data) { - Y._loading = true; - Y._use(missing, function() { - if (Y._attach(data)) { - Y._notify(callback, response, data); - } - }); - } else { - if (data) { - ret = Y._attach(data); - } - if (ret) { - Y._notify(callback, response, args); - } - } - - if (Y._useQueue && Y._useQueue.size() && !Y._loading) { - Y._use.apply(Y, Y._useQueue.next()); - } - - }; - - - // YUI().use('*'); // bind everything available - if (firstArg === '*') { - args = []; - for (i in mods) { - if (mods.hasOwnProperty(i)) { - args.push(i); - } - } - ret = Y._attach(args); - if (ret) { - handleLoader(); - } - return Y; - } - - if ((mods.loader || mods['loader-base']) && !Y.Loader) { - Y._attach(['loader' + ((!mods.loader) ? '-base' : '')]); - } - - - // use loader to expand dependencies and sort the - // requirements if it is available. - if (boot && Y.Loader && args.length) { - loader = getLoader(Y); - loader.require(args); - loader.ignoreRegistered = true; - loader._boot = true; - loader.calculate(null, (fetchCSS) ? null : 'js'); - args = loader.sorted; - loader._boot = false; - } - - process(args); - - len = missing.length; - - - if (len) { - missing = YArray.dedupe(missing); - len = missing.length; - } - - - // dynamic load - if (boot && len && Y.Loader) { - Y._loading = true; - loader = getLoader(Y); - loader.onEnd = handleLoader; - loader.context = Y; - loader.data = args; - loader.ignoreRegistered = false; - loader.require(missing); - loader.insert(null, (fetchCSS) ? null : 'js'); - - } else if (boot && len && Y.Get && !Env.bootstrapped) { - - Y._loading = true; - - handleBoot = function() { - Y._loading = false; - queue.running = false; - Env.bootstrapped = true; - G_ENV._bootstrapping = false; - if (Y._attach(['loader'])) { - Y._use(args, callback); - } - }; - - if (G_ENV._bootstrapping) { - queue.add(handleBoot); - } else { - G_ENV._bootstrapping = true; - Y.Get.script(config.base + config.loaderPath, { - onEnd: handleBoot - }); - } - - } else { - ret = Y._attach(args); - if (ret) { - handleLoader(); - } - } - - return Y; - }, - - - /** - Utility method for safely creating namespaces if they don't already exist. - May be called statically on the YUI global object or as a method on a YUI - instance. - - When called statically, a namespace will be created on the YUI global - object: - - // Create `YUI.your.namespace.here` as nested objects, preserving any - // objects that already exist instead of overwriting them. - YUI.namespace('your.namespace.here'); - - When called as a method on a YUI instance, a namespace will be created on - that instance: - - // Creates `Y.property.package`. - Y.namespace('property.package'); - - Dots in the input string cause `namespace` to create nested objects for each - token. If any part of the requested namespace already exists, the current - object will be left in place and will not be overwritten. This allows - multiple calls to `namespace` to preserve existing namespaced properties. - - If the first token in the namespace string is "YAHOO", that token is - discarded. This is legacy behavior for backwards compatibility with YUI 2. - - Be careful with namespace tokens. Reserved words may work in some browsers - and not others. For instance, the following will fail in some browsers - because the supported version of JavaScript reserves the word "long": - - Y.namespace('really.long.nested.namespace'); - - Note: If you pass multiple arguments to create multiple namespaces, only the - last one created is returned from this function. - - @method namespace - @param {String} namespace* One or more namespaces to create. - @return {Object} Reference to the last namespace object created. - **/ - namespace: function() { - var a = arguments, o, i = 0, j, d, arg; - - for (; i < a.length; i++) { - o = this; //Reset base object per argument or it will get reused from the last - arg = a[i]; - if (arg.indexOf(PERIOD) > -1) { //Skip this if no "." is present - d = arg.split(PERIOD); - for (j = (d[0] == 'YAHOO') ? 1 : 0; j < d.length; j++) { - o[d[j]] = o[d[j]] || {}; - o = o[d[j]]; - } - } else { - o[arg] = o[arg] || {}; - o = o[arg]; //Reset base object to the new object so it's returned - } - } - return o; - }, - - // this is replaced if the log module is included - log: NOOP, - message: NOOP, - // this is replaced if the dump module is included - dump: function (o) { return ''+o; }, - - /** - Reports an error. - - The reporting mechanism is controlled by the `throwFail` configuration - attribute. If `throwFail` is falsy, the message is logged. If `throwFail` is - truthy, a JS exception is thrown. - - If an `errorFn` is specified in the config it must return `true` to indicate - that the exception was handled and keep it from being thrown. - - @method error - @param {String} msg Error message. - @param {Error|String} [e] JavaScript error object or an error string. - @param {String} [src] Source of the error (such as the name of the module in - which the error occurred). - @chainable - **/ - error: function(msg, e, src) { - //TODO Add check for window.onerror here - - var Y = this, ret; - - if (Y.config.errorFn) { - ret = Y.config.errorFn.apply(Y, arguments); - } - - if (!ret) { - throw (e || new Error(msg)); - } else { - Y.message(msg, 'error', ''+src); // don't scrub this one - } - - return Y; - }, - - /** - Generates an id string that is unique among all YUI instances in this - execution context. - - @method guid - @param {String} [pre] Prefix. - @return {String} Unique id. - **/ - guid: function(pre) { - var id = this.Env._guidp + '_' + (++this.Env._uidx); - return (pre) ? (pre + id) : id; - }, - - /** - Returns a unique id associated with the given object and (if *readOnly* is - falsy) stamps the object with that id so it can be identified in the future. - - Stamping an object involves adding a `_yuid` property to it that contains - the object's id. One exception to this is that in Internet Explorer, DOM - nodes have a `uniqueID` property that contains a browser-generated unique - id, which will be used instead of a YUI-generated id when available. - - @method stamp - @param {Object} o Object to stamp. - @param {Boolean} readOnly If truthy and the given object has not already - been stamped, the object will not be modified and `null` will be - returned. - @return {String} Object's unique id, or `null` if *readOnly* was truthy and - the given object was not already stamped. - **/ - stamp: function(o, readOnly) { - var uid; - if (!o) { - return o; - } - - // IE generates its own unique ID for dom nodes - // The uniqueID property of a document node returns a new ID - if (o.uniqueID && o.nodeType && o.nodeType !== 9) { - uid = o.uniqueID; - } else { - uid = (typeof o === 'string') ? o : o._yuid; - } - - if (!uid) { - uid = this.guid(); - if (!readOnly) { - try { - o._yuid = uid; - } catch (e) { - uid = null; - } - } - } - return uid; - }, - - /** - Destroys this YUI instance. - - @method destroy - @since 3.3.0 - **/ - destroy: function() { - var Y = this; - if (Y.Event) { - Y.Event._unload(); - } - delete instances[Y.id]; - delete Y.Env; - delete Y.config; - } - - /** - Safe `instanceof` wrapper that works around a memory leak in IE when the - object being tested is `window` or `document`. - - Unless you are testing objects that may be `window` or `document`, you - should use the native `instanceof` operator instead of this method. - - @method instanceOf - @param {Object} o Object to check. - @param {Object} type Class to check against. - @since 3.3.0 - **/ -}; - - YUI.prototype = proto; - - // inheritance utilities are not available yet - for (prop in proto) { - if (proto.hasOwnProperty(prop)) { - YUI[prop] = proto[prop]; - } - } - - /** - Applies a configuration to all YUI instances in this execution context. - - The main use case for this method is in "mashups" where several third-party - scripts need to write to a global YUI config, but cannot share a single - centrally-managed config object. This way they can all call - `YUI.applyConfig({})` instead of overwriting the single global config. - - @example - - YUI.applyConfig({ - modules: { - davglass: { - fullpath: './davglass.js' - } - } - }); - - YUI.applyConfig({ - modules: { - foo: { - fullpath: './foo.js' - } - } - }); - - YUI().use('davglass', function (Y) { - // Module davglass will be available here. - }); - - @method applyConfig - @param {Object} o Configuration object to apply. - @static - @since 3.5.0 - **/ - YUI.applyConfig = function(o) { - if (!o) { - return; - } - //If there is a GlobalConfig, apply it first to set the defaults - if (YUI.GlobalConfig) { - this.prototype.applyConfig.call(this, YUI.GlobalConfig); - } - //Apply this config to it - this.prototype.applyConfig.call(this, o); - //Reset GlobalConfig to the combined config - YUI.GlobalConfig = this.config; - }; - - // set up the environment - YUI._init(); - - if (hasWin) { - add(doc, 'DOMContentLoaded', handleReady); - - // add a window load event at load time so we can capture - // the case where it fires before dynamic loading is - // complete. - add(window, 'load', handleLoad); - } else { - handleReady(); - handleLoad(); - } - - YUI.Env.add = add; - YUI.Env.remove = remove; - - /*global exports*/ - // Support the CommonJS method for exporting our single global - if (typeof exports == 'object') { - exports.YUI = YUI; - /** - * Set a method to be called when `Get.script` is called in Node.js - * `Get` will open the file, then pass it's content and it's path - * to this method before attaching it. Commonly used for code coverage - * instrumentation. Calling this multiple times will only - * attach the last hook method. This method is only - * available in Node.js. - * @method setLoadHook - * @static - * @param {Function} fn The function to set - * @param {String} fn.data The content of the file - * @param {String} fn.path The file path of the file - */ - YUI.setLoadHook = function(fn) { - YUI._getLoadHook = fn; - }; - /** - * Load hook for `Y.Get.script` in Node.js, see `YUI.setLoadHook` - * @method _getLoadHook - * @private - * @param {String} data The content of the file - * @param {String} path The file path of the file - */ - YUI._getLoadHook = null; - } - - YUI.Env[VERSION] = {}; -}()); - - -/** -Config object that contains all of the configuration options for -this `YUI` instance. - -This object is supplied by the implementer when instantiating YUI. Some -properties have default values if they are not supplied by the implementer. - -This object should not be updated directly because some values are cached. Use -`applyConfig()` to update the config object on a YUI instance that has already -been configured. - -@class config -@static -**/ - -/** -If `true` (the default), YUI will "bootstrap" the YUI Loader and module metadata -if they're needed to load additional dependencies and aren't already available. - -Setting this to `false` will prevent YUI from automatically loading the Loader -and module metadata, so you will need to manually ensure that they're available -or handle dependency resolution yourself. - -@property {Boolean} bootstrap -@default true -**/ - -/** - -@property {Object} filters -**/ - -/** -If `true`, YUI will use a combo handler to load multiple modules in as few -requests as possible. - -The YUI CDN (which YUI uses by default) supports combo handling, but other -servers may not. If the server from which you're loading YUI does not support -combo handling, set this to `false`. - -Providing a value for the `base` config property will cause `combine` to default -to `false` instead of `true`. - -@property {Boolean} combine -@default true -*/ - -/** -Array of module names that should never be dynamically loaded. - -@property {String[]} ignore -**/ - -/** -Array of module names that should always be loaded when required, even if -already present on the page. - -@property {String[]} force -**/ - -/** -DOM element or id that should be used as the insertion point for dynamically -added `', 'script'); - } -}); - -if (!testFeature('innerhtml', 'table')) { - // TODO: thead/tfoot with nested tbody - // IE adds TBODY when creating TABLE elements (which may share this impl) - creators.tbody = function(html, doc) { - var frag = Y_DOM.create(TABLE_OPEN + html + TABLE_CLOSE, doc), - tb = Y.DOM._children(frag, 'tbody')[0]; - - if (frag.children.length > 1 && tb && !re_tbody.test(html)) { - tb.parentNode.removeChild(tb); // strip extraneous tbody - } - return frag; - }; -} - -if (!testFeature('innerhtml-div', 'script')) { - creators.script = function(html, doc) { - var frag = doc.createElement('div'); - - frag.innerHTML = '-' + html; - frag.removeChild(frag.firstChild); - return frag; - }; - - creators.link = creators.style = creators.script; -} - -if (!testFeature('innerhtml-div', 'tr')) { - Y.mix(creators, { - option: function(html, doc) { - return Y_DOM.create('', doc); - }, - - tr: function(html, doc) { - return Y_DOM.create('' + html + '', doc); - }, - - td: function(html, doc) { - return Y_DOM.create('' + html + '', doc); - }, - - col: function(html, doc) { - return Y_DOM.create('' + html + '', doc); - }, - - tbody: 'table' - }); - - Y.mix(creators, { - legend: 'fieldset', - th: creators.td, - thead: creators.tbody, - tfoot: creators.tbody, - caption: creators.tbody, - colgroup: creators.tbody, - optgroup: creators.option - }); -} - -Y_DOM.creators = creators; -Y.mix(Y.DOM, { - /** - * Sets the width of the element to the given size, regardless - * of box model, border, padding, etc. - * @method setWidth - * @param {HTMLElement} element The DOM element. - * @param {String|Number} size The pixel height to size to - */ - - setWidth: function(node, size) { - Y.DOM._setSize(node, 'width', size); - }, - - /** - * Sets the height of the element to the given size, regardless - * of box model, border, padding, etc. - * @method setHeight - * @param {HTMLElement} element The DOM element. - * @param {String|Number} size The pixel height to size to - */ - - setHeight: function(node, size) { - Y.DOM._setSize(node, 'height', size); - }, - - _setSize: function(node, prop, val) { - val = (val > 0) ? val : 0; - var size = 0; - - node.style[prop] = val + 'px'; - size = (prop === 'height') ? node.offsetHeight : node.offsetWidth; - - if (size > val) { - val = val - (size - val); - - if (val < 0) { - val = 0; - } - - node.style[prop] = val + 'px'; - } - } -}); - - -}, '3.16.0', {"requires": ["dom-core"]}); -/* -YUI 3.16.0 (build 76f0e08) -Copyright 2014 Yahoo! Inc. All rights reserved. -Licensed under the BSD License. -http://yuilibrary.com/license/ -*/ - -YUI.add('selector-native', function (Y, NAME) { - -(function(Y) { -/** - * The selector-native module provides support for native querySelector - * @module dom - * @submodule selector-native - * @for Selector - */ - -/** - * Provides support for using CSS selectors to query the DOM - * @class Selector - * @static - * @for Selector - */ - -Y.namespace('Selector'); // allow native module to standalone - -var COMPARE_DOCUMENT_POSITION = 'compareDocumentPosition', - OWNER_DOCUMENT = 'ownerDocument'; - -var Selector = { - _types: { - esc: { - token: '\uE000', - re: /\\[:\[\]\(\)#\.\'\>+~"]/gi - }, - - attr: { - token: '\uE001', - re: /(\[[^\]]*\])/g - }, - - pseudo: { - token: '\uE002', - re: /(\([^\)]*\))/g - } - }, - - /** - * Use the native version of `querySelectorAll`, if it exists. - * - * @property useNative - * @default true - * @static - */ - useNative: true, - - _escapeId: function(id) { - if (id) { - id = id.replace(/([:\[\]\(\)#\.'<>+~"])/g,'\\$1'); - } - return id; - }, - - _compare: ('sourceIndex' in Y.config.doc.documentElement) ? - function(nodeA, nodeB) { - var a = nodeA.sourceIndex, - b = nodeB.sourceIndex; - - if (a === b) { - return 0; - } else if (a > b) { - return 1; - } - - return -1; - - } : (Y.config.doc.documentElement[COMPARE_DOCUMENT_POSITION] ? - function(nodeA, nodeB) { - if (nodeA[COMPARE_DOCUMENT_POSITION](nodeB) & 4) { - return -1; - } else { - return 1; - } - } : - function(nodeA, nodeB) { - var rangeA, rangeB, compare; - if (nodeA && nodeB) { - rangeA = nodeA[OWNER_DOCUMENT].createRange(); - rangeA.setStart(nodeA, 0); - rangeB = nodeB[OWNER_DOCUMENT].createRange(); - rangeB.setStart(nodeB, 0); - compare = rangeA.compareBoundaryPoints(1, rangeB); // 1 === Range.START_TO_END - } - - return compare; - - }), - - _sort: function(nodes) { - if (nodes) { - nodes = Y.Array(nodes, 0, true); - if (nodes.sort) { - nodes.sort(Selector._compare); - } - } - - return nodes; - }, - - _deDupe: function(nodes) { - var ret = [], - i, node; - - for (i = 0; (node = nodes[i++]);) { - if (!node._found) { - ret[ret.length] = node; - node._found = true; - } - } - - for (i = 0; (node = ret[i++]);) { - node._found = null; - node.removeAttribute('_found'); - } - - return ret; - }, - - /** - * Retrieves a set of nodes based on a given CSS selector. - * @method query - * - * @param {String} selector A CSS selector. - * @param {HTMLElement} root optional A node to start the query from. Defaults to `Y.config.doc`. - * @param {Boolean} firstOnly optional Whether or not to return only the first match. - * @return {HTMLElement[]} The array of nodes that matched the given selector. - * @static - */ - query: function(selector, root, firstOnly, skipNative) { - root = root || Y.config.doc; - var ret = [], - useNative = (Y.Selector.useNative && Y.config.doc.querySelector && !skipNative), - queries = [[selector, root]], - query, - result, - i, - fn = (useNative) ? Y.Selector._nativeQuery : Y.Selector._bruteQuery; - - if (selector && fn) { - // split group into seperate queries - if (!skipNative && // already done if skipping - (!useNative || root.tagName)) { // split native when element scoping is needed - queries = Selector._splitQueries(selector, root); - } - - for (i = 0; (query = queries[i++]);) { - result = fn(query[0], query[1], firstOnly); - if (!firstOnly) { // coerce DOM Collection to Array - result = Y.Array(result, 0, true); - } - if (result) { - ret = ret.concat(result); - } - } - - if (queries.length > 1) { // remove dupes and sort by doc order - ret = Selector._sort(Selector._deDupe(ret)); - } - } - - return (firstOnly) ? (ret[0] || null) : ret; - - }, - - _replaceSelector: function(selector) { - var esc = Y.Selector._parse('esc', selector), // pull escaped colon, brackets, etc. - attrs, - pseudos; - - // first replace escaped chars, which could be present in attrs or pseudos - selector = Y.Selector._replace('esc', selector); - - // then replace pseudos before attrs to avoid replacing :not([foo]) - pseudos = Y.Selector._parse('pseudo', selector); - selector = Selector._replace('pseudo', selector); - - attrs = Y.Selector._parse('attr', selector); - selector = Y.Selector._replace('attr', selector); - - return { - esc: esc, - attrs: attrs, - pseudos: pseudos, - selector: selector - }; - }, - - _restoreSelector: function(replaced) { - var selector = replaced.selector; - selector = Y.Selector._restore('attr', selector, replaced.attrs); - selector = Y.Selector._restore('pseudo', selector, replaced.pseudos); - selector = Y.Selector._restore('esc', selector, replaced.esc); - return selector; - }, - - _replaceCommas: function(selector) { - var replaced = Y.Selector._replaceSelector(selector), - selector = replaced.selector; - - if (selector) { - selector = selector.replace(/,/g, '\uE007'); - replaced.selector = selector; - selector = Y.Selector._restoreSelector(replaced); - } - return selector; - }, - - // allows element scoped queries to begin with combinator - // e.g. query('> p', document.body) === query('body > p') - _splitQueries: function(selector, node) { - if (selector.indexOf(',') > -1) { - selector = Y.Selector._replaceCommas(selector); - } - - var groups = selector.split('\uE007'), // split on replaced comma token - queries = [], - prefix = '', - id, - i, - len; - - if (node) { - // enforce for element scoping - if (node.nodeType === 1) { // Elements only - id = Y.Selector._escapeId(Y.DOM.getId(node)); - - if (!id) { - id = Y.guid(); - Y.DOM.setId(node, id); - } - - prefix = '[id="' + id + '"] '; - } - - for (i = 0, len = groups.length; i < len; ++i) { - selector = prefix + groups[i]; - queries.push([selector, node]); - } - } - - return queries; - }, - - _nativeQuery: function(selector, root, one) { - if ( - (Y.UA.webkit || Y.UA.opera) && // webkit (chrome, safari) and Opera - selector.indexOf(':checked') > -1 && // fail to pick up "selected" with ":checked" - (Y.Selector.pseudos && Y.Selector.pseudos.checked) - ) { - return Y.Selector.query(selector, root, one, true); // redo with skipNative true to try brute query - } - try { - return root['querySelector' + (one ? '' : 'All')](selector); - } catch(e) { // fallback to brute if available - return Y.Selector.query(selector, root, one, true); // redo with skipNative true - } - }, - - /** - * Filters out nodes that do not match the given CSS selector. - * @method filter - * - * @param {HTMLElement[]} nodes An array of nodes. - * @param {String} selector A CSS selector to test each node against. - * @return {HTMLElement[]} The nodes that matched the given CSS selector. - * @static - */ - filter: function(nodes, selector) { - var ret = [], - i, node; - - if (nodes && selector) { - for (i = 0; (node = nodes[i++]);) { - if (Y.Selector.test(node, selector)) { - ret[ret.length] = node; - } - } - } else { - } - - return ret; - }, - - /** - * Determines whether or not the given node matches the given CSS selector. - * @method test - * - * @param {HTMLElement} node A node to test. - * @param {String} selector A CSS selector to test the node against. - * @param {HTMLElement} root optional A node to start the query from. Defaults to the parent document of the node. - * @return {Boolean} Whether or not the given node matched the given CSS selector. - * @static - */ - test: function(node, selector, root) { - var ret = false, - useFrag = false, - groups, - parent, - item, - items, - frag, - id, - i, j, group; - - if (node && node.tagName) { // only test HTMLElements - - if (typeof selector == 'function') { // test with function - ret = selector.call(node, node); - } else { // test with query - // we need a root if off-doc - groups = selector.split(','); - if (!root && !Y.DOM.inDoc(node)) { - parent = node.parentNode; - if (parent) { - root = parent; - } else { // only use frag when no parent to query - frag = node[OWNER_DOCUMENT].createDocumentFragment(); - frag.appendChild(node); - root = frag; - useFrag = true; - } - } - root = root || node[OWNER_DOCUMENT]; - - id = Y.Selector._escapeId(Y.DOM.getId(node)); - if (!id) { - id = Y.guid(); - Y.DOM.setId(node, id); - } - - for (i = 0; (group = groups[i++]);) { // TODO: off-dom test - group += '[id="' + id + '"]'; - items = Y.Selector.query(group, root); - - for (j = 0; item = items[j++];) { - if (item === node) { - ret = true; - break; - } - } - if (ret) { - break; - } - } - - if (useFrag) { // cleanup - frag.removeChild(node); - } - }; - } - - return ret; - }, - - /** - * A convenience method to emulate Y.Node's aNode.ancestor(selector). - * @method ancestor - * - * @param {HTMLElement} node A node to start the query from. - * @param {String} selector A CSS selector to test the node against. - * @param {Boolean} testSelf optional Whether or not to include the node in the scan. - * @return {HTMLElement} The ancestor node matching the selector, or null. - * @static - */ - ancestor: function (node, selector, testSelf) { - return Y.DOM.ancestor(node, function(n) { - return Y.Selector.test(n, selector); - }, testSelf); - }, - - _parse: function(name, selector) { - return selector.match(Y.Selector._types[name].re); - }, - - _replace: function(name, selector) { - var o = Y.Selector._types[name]; - return selector.replace(o.re, o.token); - }, - - _restore: function(name, selector, items) { - if (items) { - var token = Y.Selector._types[name].token, - i, len; - for (i = 0, len = items.length; i < len; ++i) { - selector = selector.replace(token, items[i]); - } - } - return selector; - } -}; - -Y.mix(Y.Selector, Selector, true); - -})(Y); - - -}, '3.16.0', {"requires": ["dom-base"]}); -/* -YUI 3.16.0 (build 76f0e08) -Copyright 2014 Yahoo! Inc. All rights reserved. -Licensed under the BSD License. -http://yuilibrary.com/license/ -*/ - -YUI.add('selector', function (Y, NAME) { - - - -}, '3.16.0', {"requires": ["selector-native"]}); -/* -YUI 3.16.0 (build 76f0e08) -Copyright 2014 Yahoo! Inc. All rights reserved. -Licensed under the BSD License. -http://yuilibrary.com/license/ -*/ - -YUI.add('node-core', function (Y, NAME) { - -/** - * The Node Utility provides a DOM-like interface for interacting with DOM nodes. - * @module node - * @main node - * @submodule node-core - */ - -/** - * The Node class provides a wrapper for manipulating DOM Nodes. - * Node properties can be accessed via the set/get methods. - * Use `Y.one()` to retrieve Node instances. - * - * NOTE: Node properties are accessed using - * the set and get methods. - * - * @class Node - * @constructor - * @param {HTMLElement} node the DOM node to be mapped to the Node instance. - * @uses EventTarget - */ - -// "globals" -var DOT = '.', - NODE_NAME = 'nodeName', - NODE_TYPE = 'nodeType', - OWNER_DOCUMENT = 'ownerDocument', - TAG_NAME = 'tagName', - UID = '_yuid', - EMPTY_OBJ = {}, - - _slice = Array.prototype.slice, - - Y_DOM = Y.DOM, - - Y_Node = function(node) { - if (!this.getDOMNode) { // support optional "new" - return new Y_Node(node); - } - - if (typeof node == 'string') { - node = Y_Node._fromString(node); - if (!node) { - return null; // NOTE: return - } - } - - var uid = (node.nodeType !== 9) ? node.uniqueID : node[UID]; - - if (uid && Y_Node._instances[uid] && Y_Node._instances[uid]._node !== node) { - node[UID] = null; // unset existing uid to prevent collision (via clone or hack) - } - - uid = uid || Y.stamp(node); - if (!uid) { // stamp failed; likely IE non-HTMLElement - uid = Y.guid(); - } - - this[UID] = uid; - - /** - * The underlying DOM node bound to the Y.Node instance - * @property _node - * @type HTMLElement - * @private - */ - this._node = node; - - this._stateProxy = node; // when augmented with Attribute - - if (this._initPlugins) { // when augmented with Plugin.Host - this._initPlugins(); - } - }, - - // used with previous/next/ancestor tests - _wrapFn = function(fn) { - var ret = null; - if (fn) { - ret = (typeof fn == 'string') ? - function(n) { - return Y.Selector.test(n, fn); - } : - function(n) { - return fn(Y.one(n)); - }; - } - - return ret; - }; -// end "globals" - -Y_Node.ATTRS = {}; -Y_Node.DOM_EVENTS = {}; - -Y_Node._fromString = function(node) { - if (node) { - if (node.indexOf('doc') === 0) { // doc OR document - node = Y.config.doc; - } else if (node.indexOf('win') === 0) { // win OR window - node = Y.config.win; - } else { - node = Y.Selector.query(node, null, true); - } - } - - return node || null; -}; - -/** - * The name of the component - * @static - * @type String - * @property NAME - */ -Y_Node.NAME = 'node'; - -/* - * The pattern used to identify ARIA attributes - */ -Y_Node.re_aria = /^(?:role$|aria-)/; - -Y_Node.SHOW_TRANSITION = 'fadeIn'; -Y_Node.HIDE_TRANSITION = 'fadeOut'; - -/** - * A list of Node instances that have been created - * @private - * @type Object - * @property _instances - * @static - * - */ -Y_Node._instances = {}; - -/** - * Retrieves the DOM node bound to a Node instance - * @method getDOMNode - * @static - * - * @param {Node|HTMLElement} node The Node instance or an HTMLElement - * @return {HTMLElement} The DOM node bound to the Node instance. If a DOM node is passed - * as the node argument, it is simply returned. - */ -Y_Node.getDOMNode = function(node) { - if (node) { - return (node.nodeType) ? node : node._node || null; - } - return null; -}; - -/** - * Checks Node return values and wraps DOM Nodes as Y.Node instances - * and DOM Collections / Arrays as Y.NodeList instances. - * Other return values just pass thru. If undefined is returned (e.g. no return) - * then the Node instance is returned for chainability. - * @method scrubVal - * @static - * - * @param {HTMLElement|HTMLElement[]|Node} node The Node instance or an HTMLElement - * @return {Node | NodeList | Any} Depends on what is returned from the DOM node. - */ -Y_Node.scrubVal = function(val, node) { - if (val) { // only truthy values are risky - if (typeof val == 'object' || typeof val == 'function') { // safari nodeList === function - if (NODE_TYPE in val || Y_DOM.isWindow(val)) {// node || window - val = Y.one(val); - } else if ((val.item && !val._nodes) || // dom collection or Node instance - (val[0] && val[0][NODE_TYPE])) { // array of DOM Nodes - val = Y.all(val); - } - } - } else if (typeof val === 'undefined') { - val = node; // for chaining - } else if (val === null) { - val = null; // IE: DOM null not the same as null - } - - return val; -}; - -/** - * Adds methods to the Y.Node prototype, routing through scrubVal. - * @method addMethod - * @static - * - * @param {String} name The name of the method to add - * @param {Function} fn The function that becomes the method - * @param {Object} context An optional context to call the method with - * (defaults to the Node instance) - * @return {any} Depends on what is returned from the DOM node. - */ -Y_Node.addMethod = function(name, fn, context) { - if (name && fn && typeof fn == 'function') { - Y_Node.prototype[name] = function() { - var args = _slice.call(arguments), - node = this, - ret; - - if (args[0] && args[0]._node) { - args[0] = args[0]._node; - } - - if (args[1] && args[1]._node) { - args[1] = args[1]._node; - } - args.unshift(node._node); - - ret = fn.apply(context || node, args); - - if (ret) { // scrub truthy - ret = Y_Node.scrubVal(ret, node); - } - - (typeof ret != 'undefined') || (ret = node); - return ret; - }; - } else { - } -}; - -/** - * Imports utility methods to be added as Y.Node methods. - * @method importMethod - * @static - * - * @param {Object} host The object that contains the method to import. - * @param {String} name The name of the method to import - * @param {String} altName An optional name to use in place of the host name - * @param {Object} context An optional context to call the method with - */ -Y_Node.importMethod = function(host, name, altName) { - if (typeof name == 'string') { - altName = altName || name; - Y_Node.addMethod(altName, host[name], host); - } else { - Y.Array.each(name, function(n) { - Y_Node.importMethod(host, n); - }); - } -}; - -/** - * Retrieves a NodeList based on the given CSS selector. - * @method all - * - * @param {string} selector The CSS selector to test against. - * @return {NodeList} A NodeList instance for the matching HTMLCollection/Array. - * @for YUI - */ - -/** - * Returns a single Node instance bound to the node or the - * first element matching the given selector. Returns null if no match found. - * Note: For chaining purposes you may want to - * use Y.all, which returns a NodeList when no match is found. - * @method one - * @param {String | HTMLElement} node a node or Selector - * @return {Node | null} a Node instance or null if no match found. - * @for YUI - */ - -/** - * Returns a single Node instance bound to the node or the - * first element matching the given selector. Returns null if no match found. - * Note: For chaining purposes you may want to - * use Y.all, which returns a NodeList when no match is found. - * @method one - * @static - * @param {String | HTMLElement} node a node or Selector - * @return {Node | null} a Node instance or null if no match found. - * @for Node - */ -Y_Node.one = function(node) { - var instance = null, - cachedNode, - uid; - - if (node) { - if (typeof node == 'string') { - node = Y_Node._fromString(node); - if (!node) { - return null; // NOTE: return - } - } else if (node.getDOMNode) { - return node; // NOTE: return - } - - if (node.nodeType || Y.DOM.isWindow(node)) { // avoid bad input (numbers, boolean, etc) - uid = (node.uniqueID && node.nodeType !== 9) ? node.uniqueID : node._yuid; - instance = Y_Node._instances[uid]; // reuse exising instances - cachedNode = instance ? instance._node : null; - if (!instance || (cachedNode && node !== cachedNode)) { // new Node when nodes don't match - instance = new Y_Node(node); - if (node.nodeType != 11) { // dont cache document fragment - Y_Node._instances[instance[UID]] = instance; // cache node - } - } - } - } - - return instance; -}; - -/** - * The default setter for DOM properties - * Called with instance context (this === the Node instance) - * @method DEFAULT_SETTER - * @static - * @param {String} name The attribute/property being set - * @param {any} val The value to be set - * @return {any} The value - */ -Y_Node.DEFAULT_SETTER = function(name, val) { - var node = this._stateProxy, - strPath; - - if (name.indexOf(DOT) > -1) { - strPath = name; - name = name.split(DOT); - // only allow when defined on node - Y.Object.setValue(node, name, val); - } else if (typeof node[name] != 'undefined') { // pass thru DOM properties - node[name] = val; - } - - return val; -}; - -/** - * The default getter for DOM properties - * Called with instance context (this === the Node instance) - * @method DEFAULT_GETTER - * @static - * @param {String} name The attribute/property to look up - * @return {any} The current value - */ -Y_Node.DEFAULT_GETTER = function(name) { - var node = this._stateProxy, - val; - - if (name.indexOf && name.indexOf(DOT) > -1) { - val = Y.Object.getValue(node, name.split(DOT)); - } else if (typeof node[name] != 'undefined') { // pass thru from DOM - val = node[name]; - } - - return val; -}; - -Y.mix(Y_Node.prototype, { - DATA_PREFIX: 'data-', - - /** - * The method called when outputting Node instances as strings - * @method toString - * @return {String} A string representation of the Node instance - */ - toString: function() { - var str = this[UID] + ': not bound to a node', - node = this._node, - attrs, id, className; - - if (node) { - attrs = node.attributes; - id = (attrs && attrs.id) ? node.getAttribute('id') : null; - className = (attrs && attrs.className) ? node.getAttribute('className') : null; - str = node[NODE_NAME]; - - if (id) { - str += '#' + id; - } - - if (className) { - str += '.' + className.replace(' ', '.'); - } - - // TODO: add yuid? - str += ' ' + this[UID]; - } - return str; - }, - - /** - * Returns an attribute value on the Node instance. - * Unless pre-configured (via `Node.ATTRS`), get hands - * off to the underlying DOM node. Only valid - * attributes/properties for the node will be queried. - * @method get - * @param {String} attr The attribute - * @return {any} The current value of the attribute - */ - get: function(attr) { - var val; - - if (this._getAttr) { // use Attribute imple - val = this._getAttr(attr); - } else { - val = this._get(attr); - } - - if (val) { - val = Y_Node.scrubVal(val, this); - } else if (val === null) { - val = null; // IE: DOM null is not true null (even though they ===) - } - return val; - }, - - /** - * Helper method for get. - * @method _get - * @private - * @param {String} attr The attribute - * @return {any} The current value of the attribute - */ - _get: function(attr) { - var attrConfig = Y_Node.ATTRS[attr], - val; - - if (attrConfig && attrConfig.getter) { - val = attrConfig.getter.call(this); - } else if (Y_Node.re_aria.test(attr)) { - val = this._node.getAttribute(attr, 2); - } else { - val = Y_Node.DEFAULT_GETTER.apply(this, arguments); - } - - return val; - }, - - /** - * Sets an attribute on the Node instance. - * Unless pre-configured (via Node.ATTRS), set hands - * off to the underlying DOM node. Only valid - * attributes/properties for the node will be set. - * To set custom attributes use setAttribute. - * @method set - * @param {String} attr The attribute to be set. - * @param {any} val The value to set the attribute to. - * @chainable - */ - set: function(attr, val) { - var attrConfig = Y_Node.ATTRS[attr]; - - if (this._setAttr) { // use Attribute imple - this._setAttr.apply(this, arguments); - } else { // use setters inline - if (attrConfig && attrConfig.setter) { - attrConfig.setter.call(this, val, attr); - } else if (Y_Node.re_aria.test(attr)) { // special case Aria - this._node.setAttribute(attr, val); - } else { - Y_Node.DEFAULT_SETTER.apply(this, arguments); - } - } - - return this; - }, - - /** - * Sets multiple attributes. - * @method setAttrs - * @param {Object} attrMap an object of name/value pairs to set - * @chainable - */ - setAttrs: function(attrMap) { - if (this._setAttrs) { // use Attribute imple - this._setAttrs(attrMap); - } else { // use setters inline - Y.Object.each(attrMap, function(v, n) { - this.set(n, v); - }, this); - } - - return this; - }, - - /** - * Returns an object containing the values for the requested attributes. - * @method getAttrs - * @param {Array} attrs an array of attributes to get values - * @return {Object} An object with attribute name/value pairs. - */ - getAttrs: function(attrs) { - var ret = {}; - if (this._getAttrs) { // use Attribute imple - this._getAttrs(attrs); - } else { // use setters inline - Y.Array.each(attrs, function(v, n) { - ret[v] = this.get(v); - }, this); - } - - return ret; - }, - - /** - * Compares nodes to determine if they match. - * Node instances can be compared to each other and/or HTMLElements. - * @method compareTo - * @param {HTMLElement | Node} refNode The reference node to compare to the node. - * @return {Boolean} True if the nodes match, false if they do not. - */ - compareTo: function(refNode) { - var node = this._node; - - if (refNode && refNode._node) { - refNode = refNode._node; - } - return node === refNode; - }, - - /** - * Determines whether the node is appended to the document. - * @method inDoc - * @param {Node|HTMLElement} doc optional An optional document to check against. - * Defaults to current document. - * @return {Boolean} Whether or not this node is appended to the document. - */ - inDoc: function(doc) { - var node = this._node; - - if (node) { - doc = (doc) ? doc._node || doc : node[OWNER_DOCUMENT]; - if (doc.documentElement) { - return Y_DOM.contains(doc.documentElement, node); - } - } - - return false; - }, - - getById: function(id) { - var node = this._node, - ret = Y_DOM.byId(id, node[OWNER_DOCUMENT]); - if (ret && Y_DOM.contains(node, ret)) { - ret = Y.one(ret); - } else { - ret = null; - } - return ret; - }, - - /** - * Returns the nearest ancestor that passes the test applied by supplied boolean method. - * @method ancestor - * @param {String | Function} fn A selector string or boolean method for testing elements. - * If a function is used, it receives the current node being tested as the only argument. - * If fn is not passed as an argument, the parent node will be returned. - * @param {Boolean} testSelf optional Whether or not to include the element in the scan - * @param {String | Function} stopFn optional A selector string or boolean - * method to indicate when the search should stop. The search bails when the function - * returns true or the selector matches. - * If a function is used, it receives the current node being tested as the only argument. - * @return {Node} The matching Node instance or null if not found - */ - ancestor: function(fn, testSelf, stopFn) { - // testSelf is optional, check for stopFn as 2nd arg - if (arguments.length === 2 && - (typeof testSelf == 'string' || typeof testSelf == 'function')) { - stopFn = testSelf; - } - - return Y.one(Y_DOM.ancestor(this._node, _wrapFn(fn), testSelf, _wrapFn(stopFn))); - }, - - /** - * Returns the ancestors that pass the test applied by supplied boolean method. - * @method ancestors - * @param {String | Function} fn A selector string or boolean method for testing elements. - * @param {Boolean} testSelf optional Whether or not to include the element in the scan - * If a function is used, it receives the current node being tested as the only argument. - * @return {NodeList} A NodeList instance containing the matching elements - */ - ancestors: function(fn, testSelf, stopFn) { - if (arguments.length === 2 && - (typeof testSelf == 'string' || typeof testSelf == 'function')) { - stopFn = testSelf; - } - return Y.all(Y_DOM.ancestors(this._node, _wrapFn(fn), testSelf, _wrapFn(stopFn))); - }, - - /** - * Returns the previous matching sibling. - * Returns the nearest element node sibling if no method provided. - * @method previous - * @param {String | Function} fn A selector or boolean method for testing elements. - * If a function is used, it receives the current node being tested as the only argument. - * @param {Boolean} [all] Whether text nodes as well as element nodes should be returned, or - * just element nodes will be returned(default) - * @return {Node} Node instance or null if not found - */ - previous: function(fn, all) { - return Y.one(Y_DOM.elementByAxis(this._node, 'previousSibling', _wrapFn(fn), all)); - }, - - /** - * Returns the next matching sibling. - * Returns the nearest element node sibling if no method provided. - * @method next - * @param {String | Function} fn A selector or boolean method for testing elements. - * If a function is used, it receives the current node being tested as the only argument. - * @param {Boolean} [all] Whether text nodes as well as element nodes should be returned, or - * just element nodes will be returned(default) - * @return {Node} Node instance or null if not found - */ - next: function(fn, all) { - return Y.one(Y_DOM.elementByAxis(this._node, 'nextSibling', _wrapFn(fn), all)); - }, - - /** - * Returns all matching siblings. - * Returns all siblings if no method provided. - * @method siblings - * @param {String | Function} fn A selector or boolean method for testing elements. - * If a function is used, it receives the current node being tested as the only argument. - * @return {NodeList} NodeList instance bound to found siblings - */ - siblings: function(fn) { - return Y.all(Y_DOM.siblings(this._node, _wrapFn(fn))); - }, - - /** - * Retrieves a single Node instance, the first element matching the given - * CSS selector. - * Returns null if no match found. - * @method one - * - * @param {string} selector The CSS selector to test against. - * @return {Node | null} A Node instance for the matching HTMLElement or null - * if no match found. - */ - one: function(selector) { - return Y.one(Y.Selector.query(selector, this._node, true)); - }, - - /** - * Retrieves a NodeList based on the given CSS selector. - * @method all - * - * @param {string} selector The CSS selector to test against. - * @return {NodeList} A NodeList instance for the matching HTMLCollection/Array. - */ - all: function(selector) { - var nodelist; - - if (this._node) { - nodelist = Y.all(Y.Selector.query(selector, this._node)); - nodelist._query = selector; - nodelist._queryRoot = this._node; - } - - return nodelist || Y.all([]); - }, - - // TODO: allow fn test - /** - * Test if the supplied node matches the supplied selector. - * @method test - * - * @param {string} selector The CSS selector to test against. - * @return {boolean} Whether or not the node matches the selector. - */ - test: function(selector) { - return Y.Selector.test(this._node, selector); - }, - - /** - * Removes the node from its parent. - * Shortcut for myNode.get('parentNode').removeChild(myNode); - * @method remove - * @param {Boolean} destroy whether or not to call destroy() on the node - * after removal. - * @chainable - * - */ - remove: function(destroy) { - var node = this._node; - - if (node && node.parentNode) { - node.parentNode.removeChild(node); - } - - if (destroy) { - this.destroy(); - } - - return this; - }, - - /** - * Replace the node with the other node. This is a DOM update only - * and does not change the node bound to the Node instance. - * Shortcut for myNode.get('parentNode').replaceChild(newNode, myNode); - * @method replace - * @param {Node | HTMLElement} newNode Node to be inserted - * @chainable - * - */ - replace: function(newNode) { - var node = this._node; - if (typeof newNode == 'string') { - newNode = Y_Node.create(newNode); - } - node.parentNode.replaceChild(Y_Node.getDOMNode(newNode), node); - return this; - }, - - /** - * @method replaceChild - * @for Node - * @param {String | HTMLElement | Node} node Node to be inserted - * @param {HTMLElement | Node} refNode Node to be replaced - * @return {Node} The replaced node - */ - replaceChild: function(node, refNode) { - if (typeof node == 'string') { - node = Y_DOM.create(node); - } - - return Y.one(this._node.replaceChild(Y_Node.getDOMNode(node), Y_Node.getDOMNode(refNode))); - }, - - /** - * Nulls internal node references, removes any plugins and event listeners. - * Note that destroy() will not remove the node from its parent or from the DOM. For that - * functionality, call remove(true). - * @method destroy - * @param {Boolean} recursivePurge (optional) Whether or not to remove listeners from the - * node's subtree (default is false) - * - */ - destroy: function(recursive) { - var UID = Y.config.doc.uniqueID ? 'uniqueID' : '_yuid', - instance; - - this.purge(); // TODO: only remove events add via this Node - - if (this.unplug) { // may not be a PluginHost - this.unplug(); - } - - this.clearData(); - - if (recursive) { - Y.NodeList.each(this.all('*'), function(node) { - instance = Y_Node._instances[node[UID]]; - if (instance) { - instance.destroy(); - } else { // purge in case added by other means - Y.Event.purgeElement(node); - } - }); - } - - this._node = null; - this._stateProxy = null; - - delete Y_Node._instances[this._yuid]; - }, - - /** - * Invokes a method on the Node instance - * @method invoke - * @param {String} method The name of the method to invoke - * @param {any} [args*] Arguments to invoke the method with. - * @return {any} Whatever the underly method returns. - * DOM Nodes and Collections return values - * are converted to Node/NodeList instances. - * - */ - invoke: function(method, a, b, c, d, e) { - var node = this._node, - ret; - - if (a && a._node) { - a = a._node; - } - - if (b && b._node) { - b = b._node; - } - - ret = node[method](a, b, c, d, e); - return Y_Node.scrubVal(ret, this); - }, - - /** - * @method swap - * @description Swap DOM locations with the given node. - * This does not change which DOM node each Node instance refers to. - * @param {Node} otherNode The node to swap with - * @chainable - */ - swap: Y.config.doc.documentElement.swapNode ? - function(otherNode) { - this._node.swapNode(Y_Node.getDOMNode(otherNode)); - } : - function(otherNode) { - otherNode = Y_Node.getDOMNode(otherNode); - var node = this._node, - parent = otherNode.parentNode, - nextSibling = otherNode.nextSibling; - - if (nextSibling === node) { - parent.insertBefore(node, otherNode); - } else if (otherNode === node.nextSibling) { - parent.insertBefore(otherNode, node); - } else { - node.parentNode.replaceChild(otherNode, node); - Y_DOM.addHTML(parent, node, nextSibling); - } - return this; - }, - - - hasMethod: function(method) { - var node = this._node; - return !!(node && method in node && - typeof node[method] != 'unknown' && - (typeof node[method] == 'function' || - String(node[method]).indexOf('function') === 1)); // IE reports as object, prepends space - }, - - isFragment: function() { - return (this.get('nodeType') === 11); - }, - - /** - * Removes and destroys all of the nodes within the node. - * @method empty - * @chainable - */ - empty: function() { - this.get('childNodes').remove().destroy(true); - return this; - }, - - /** - * Returns the DOM node bound to the Node instance - * @method getDOMNode - * @return {HTMLElement} - */ - getDOMNode: function() { - return this._node; - } -}, true); - -Y.Node = Y_Node; -Y.one = Y_Node.one; -/** - * The NodeList module provides support for managing collections of Nodes. - * @module node - * @submodule node-core - */ - -/** - * The NodeList class provides a wrapper for manipulating DOM NodeLists. - * NodeList properties can be accessed via the set/get methods. - * Use Y.all() to retrieve NodeList instances. - * - * @class NodeList - * @constructor - * @param nodes {String|element|Node|Array} A selector, DOM element, Node, list of DOM elements, or list of Nodes with which to populate this NodeList. - */ - -var NodeList = function(nodes) { - var tmp = []; - - if (nodes) { - if (typeof nodes === 'string') { // selector query - this._query = nodes; - nodes = Y.Selector.query(nodes); - } else if (nodes.nodeType || Y_DOM.isWindow(nodes)) { // domNode || window - nodes = [nodes]; - } else if (nodes._node) { // Y.Node - nodes = [nodes._node]; - } else if (nodes[0] && nodes[0]._node) { // allow array of Y.Nodes - Y.Array.each(nodes, function(node) { - if (node._node) { - tmp.push(node._node); - } - }); - nodes = tmp; - } else { // array of domNodes or domNodeList (no mixed array of Y.Node/domNodes) - nodes = Y.Array(nodes, 0, true); - } - } - - /** - * The underlying array of DOM nodes bound to the Y.NodeList instance - * @property _nodes - * @private - */ - this._nodes = nodes || []; -}; - -NodeList.NAME = 'NodeList'; - -/** - * Retrieves the DOM nodes bound to a NodeList instance - * @method getDOMNodes - * @static - * - * @param {NodeList} nodelist The NodeList instance - * @return {Array} The array of DOM nodes bound to the NodeList - */ -NodeList.getDOMNodes = function(nodelist) { - return (nodelist && nodelist._nodes) ? nodelist._nodes : nodelist; -}; - -NodeList.each = function(instance, fn, context) { - var nodes = instance._nodes; - if (nodes && nodes.length) { - Y.Array.each(nodes, fn, context || instance); - } else { - } -}; - -NodeList.addMethod = function(name, fn, context) { - if (name && fn) { - NodeList.prototype[name] = function() { - var ret = [], - args = arguments; - - Y.Array.each(this._nodes, function(node) { - var UID = (node.uniqueID && node.nodeType !== 9 ) ? 'uniqueID' : '_yuid', - instance = Y.Node._instances[node[UID]], - ctx, - result; - - if (!instance) { - instance = NodeList._getTempNode(node); - } - ctx = context || instance; - result = fn.apply(ctx, args); - if (result !== undefined && result !== instance) { - ret[ret.length] = result; - } - }); - - // TODO: remove tmp pointer - return ret.length ? ret : this; - }; - } else { - } -}; - -NodeList.importMethod = function(host, name, altName) { - if (typeof name === 'string') { - altName = altName || name; - NodeList.addMethod(name, host[name]); - } else { - Y.Array.each(name, function(n) { - NodeList.importMethod(host, n); - }); - } -}; - -NodeList._getTempNode = function(node) { - var tmp = NodeList._tempNode; - if (!tmp) { - tmp = Y.Node.create('
'); - NodeList._tempNode = tmp; - } - - tmp._node = node; - tmp._stateProxy = node; - return tmp; -}; - -Y.mix(NodeList.prototype, { - _invoke: function(method, args, getter) { - var ret = (getter) ? [] : this; - - this.each(function(node) { - var val = node[method].apply(node, args); - if (getter) { - ret.push(val); - } - }); - - return ret; - }, - - /** - * Retrieves the Node instance at the given index. - * @method item - * - * @param {Number} index The index of the target Node. - * @return {Node} The Node instance at the given index. - */ - item: function(index) { - return Y.one((this._nodes || [])[index]); - }, - - /** - * Applies the given function to each Node in the NodeList. - * @method each - * @param {Function} fn The function to apply. It receives 3 arguments: - * the current node instance, the node's index, and the NodeList instance - * @param {Object} context optional An optional context to apply the function with - * Default context is the current Node instance - * @chainable - */ - each: function(fn, context) { - var instance = this; - Y.Array.each(this._nodes, function(node, index) { - node = Y.one(node); - return fn.call(context || node, node, index, instance); - }); - return instance; - }, - - batch: function(fn, context) { - var nodelist = this; - - Y.Array.each(this._nodes, function(node, index) { - var instance = Y.Node._instances[node[UID]]; - if (!instance) { - instance = NodeList._getTempNode(node); - } - - return fn.call(context || instance, instance, index, nodelist); - }); - return nodelist; - }, - - /** - * Executes the function once for each node until a true value is returned. - * @method some - * @param {Function} fn The function to apply. It receives 3 arguments: - * the current node instance, the node's index, and the NodeList instance - * @param {Object} context optional An optional context to execute the function from. - * Default context is the current Node instance - * @return {Boolean} Whether or not the function returned true for any node. - */ - some: function(fn, context) { - var instance = this; - return Y.Array.some(this._nodes, function(node, index) { - node = Y.one(node); - context = context || node; - return fn.call(context, node, index, instance); - }); - }, - - /** - * Creates a documenFragment from the nodes bound to the NodeList instance - * @method toFrag - * @return {Node} a Node instance bound to the documentFragment - */ - toFrag: function() { - return Y.one(Y.DOM._nl2frag(this._nodes)); - }, - - /** - * Returns the index of the node in the NodeList instance - * or -1 if the node isn't found. - * @method indexOf - * @param {Node | HTMLElement} node the node to search for - * @return {Number} the index of the node value or -1 if not found - */ - indexOf: function(node) { - return Y.Array.indexOf(this._nodes, Y.Node.getDOMNode(node)); - }, - - /** - * Filters the NodeList instance down to only nodes matching the given selector. - * @method filter - * @param {String} selector The selector to filter against - * @return {NodeList} NodeList containing the updated collection - * @see Selector - */ - filter: function(selector) { - return Y.all(Y.Selector.filter(this._nodes, selector)); - }, - - - /** - * Creates a new NodeList containing all nodes at every n indices, where - * remainder n % index equals r. - * (zero-based index). - * @method modulus - * @param {Number} n The offset to use (return every nth node) - * @param {Number} r An optional remainder to use with the modulus operation (defaults to zero) - * @return {NodeList} NodeList containing the updated collection - */ - modulus: function(n, r) { - r = r || 0; - var nodes = []; - NodeList.each(this, function(node, i) { - if (i % n === r) { - nodes.push(node); - } - }); - - return Y.all(nodes); - }, - - /** - * Creates a new NodeList containing all nodes at odd indices - * (zero-based index). - * @method odd - * @return {NodeList} NodeList containing the updated collection - */ - odd: function() { - return this.modulus(2, 1); - }, - - /** - * Creates a new NodeList containing all nodes at even indices - * (zero-based index), including zero. - * @method even - * @return {NodeList} NodeList containing the updated collection - */ - even: function() { - return this.modulus(2); - }, - - destructor: function() { - }, - - /** - * Reruns the initial query, when created using a selector query - * @method refresh - * @chainable - */ - refresh: function() { - var doc, - nodes = this._nodes, - query = this._query, - root = this._queryRoot; - - if (query) { - if (!root) { - if (nodes && nodes[0] && nodes[0].ownerDocument) { - root = nodes[0].ownerDocument; - } - } - - this._nodes = Y.Selector.query(query, root); - } - - return this; - }, - - /** - * Returns the current number of items in the NodeList. - * @method size - * @return {Number} The number of items in the NodeList. - */ - size: function() { - return this._nodes.length; - }, - - /** - * Determines if the instance is bound to any nodes - * @method isEmpty - * @return {Boolean} Whether or not the NodeList is bound to any nodes - */ - isEmpty: function() { - return this._nodes.length < 1; - }, - - toString: function() { - var str = '', - errorMsg = this[UID] + ': not bound to any nodes', - nodes = this._nodes, - node; - - if (nodes && nodes[0]) { - node = nodes[0]; - str += node[NODE_NAME]; - if (node.id) { - str += '#' + node.id; - } - - if (node.className) { - str += '.' + node.className.replace(' ', '.'); - } - - if (nodes.length > 1) { - str += '...[' + nodes.length + ' items]'; - } - } - return str || errorMsg; - }, - - /** - * Returns the DOM node bound to the Node instance - * @method getDOMNodes - * @return {Array} - */ - getDOMNodes: function() { - return this._nodes; - } -}, true); - -NodeList.importMethod(Y.Node.prototype, [ - /** - * Called on each Node instance. Nulls internal node references, - * removes any plugins and event listeners - * @method destroy - * @param {Boolean} recursivePurge (optional) Whether or not to - * remove listeners from the node's subtree (default is false) - * @see Node.destroy - */ - 'destroy', - - /** - * Called on each Node instance. Removes and destroys all of the nodes - * within the node - * @method empty - * @chainable - * @see Node.empty - */ - 'empty', - - /** - * Called on each Node instance. Removes the node from its parent. - * Shortcut for myNode.get('parentNode').removeChild(myNode); - * @method remove - * @param {Boolean} destroy whether or not to call destroy() on the node - * after removal. - * @chainable - * @see Node.remove - */ - 'remove', - - /** - * Called on each Node instance. Sets an attribute on the Node instance. - * Unless pre-configured (via Node.ATTRS), set hands - * off to the underlying DOM node. Only valid - * attributes/properties for the node will be set. - * To set custom attributes use setAttribute. - * @method set - * @param {String} attr The attribute to be set. - * @param {any} val The value to set the attribute to. - * @chainable - * @see Node.set - */ - 'set' -]); - -// one-off implementation to convert array of Nodes to NodeList -// e.g. Y.all('input').get('parentNode'); - -/** Called on each Node instance - * @method get - * @see Node - */ -NodeList.prototype.get = function(attr) { - var ret = [], - nodes = this._nodes, - isNodeList = false, - getTemp = NodeList._getTempNode, - instance, - val; - - if (nodes[0]) { - instance = Y.Node._instances[nodes[0]._yuid] || getTemp(nodes[0]); - val = instance._get(attr); - if (val && val.nodeType) { - isNodeList = true; - } - } - - Y.Array.each(nodes, function(node) { - instance = Y.Node._instances[node._yuid]; - - if (!instance) { - instance = getTemp(node); - } - - val = instance._get(attr); - if (!isNodeList) { // convert array of Nodes to NodeList - val = Y.Node.scrubVal(val, instance); - } - - ret.push(val); - }); - - return (isNodeList) ? Y.all(ret) : ret; -}; - -Y.NodeList = NodeList; - -Y.all = function(nodes) { - return new NodeList(nodes); -}; - -Y.Node.all = Y.all; -/** - * @module node - * @submodule node-core - */ - -var Y_NodeList = Y.NodeList, - ArrayProto = Array.prototype, - ArrayMethods = { - /** Returns a new NodeList combining the given NodeList(s) - * @for NodeList - * @method concat - * @param {NodeList | Array} valueN Arrays/NodeLists and/or values to - * concatenate to the resulting NodeList - * @return {NodeList} A new NodeList comprised of this NodeList joined with the input. - */ - 'concat': 1, - /** Removes the last from the NodeList and returns it. - * @for NodeList - * @method pop - * @return {Node | null} The last item in the NodeList, or null if the list is empty. - */ - 'pop': 0, - /** Adds the given Node(s) to the end of the NodeList. - * @for NodeList - * @method push - * @param {Node | HTMLElement} nodes One or more nodes to add to the end of the NodeList. - */ - 'push': 0, - /** Removes the first item from the NodeList and returns it. - * @for NodeList - * @method shift - * @return {Node | null} The first item in the NodeList, or null if the NodeList is empty. - */ - 'shift': 0, - /** Returns a new NodeList comprising the Nodes in the given range. - * @for NodeList - * @method slice - * @param {Number} begin Zero-based index at which to begin extraction. - As a negative index, start indicates an offset from the end of the sequence. slice(-2) extracts the second-to-last element and the last element in the sequence. - * @param {Number} end Zero-based index at which to end extraction. slice extracts up to but not including end. - slice(1,4) extracts the second element through the fourth element (elements indexed 1, 2, and 3). - As a negative index, end indicates an offset from the end of the sequence. slice(2,-1) extracts the third element through the second-to-last element in the sequence. - If end is omitted, slice extracts to the end of the sequence. - * @return {NodeList} A new NodeList comprised of this NodeList joined with the input. - */ - 'slice': 1, - /** Changes the content of the NodeList, adding new elements while removing old elements. - * @for NodeList - * @method splice - * @param {Number} index Index at which to start changing the array. If negative, will begin that many elements from the end. - * @param {Number} howMany An integer indicating the number of old array elements to remove. If howMany is 0, no elements are removed. In this case, you should specify at least one new element. If no howMany parameter is specified (second syntax above, which is a SpiderMonkey extension), all elements after index are removed. - * {Node | HTMLElement| element1, ..., elementN - The elements to add to the array. If you don't specify any elements, splice simply removes elements from the array. - * @return {NodeList} The element(s) removed. - */ - 'splice': 1, - /** Adds the given Node(s) to the beginning of the NodeList. - * @for NodeList - * @method unshift - * @param {Node | HTMLElement} nodes One or more nodes to add to the NodeList. - */ - 'unshift': 0 - }; - - -Y.Object.each(ArrayMethods, function(returnNodeList, name) { - Y_NodeList.prototype[name] = function() { - var args = [], - i = 0, - arg, - ret; - - while (typeof (arg = arguments[i++]) != 'undefined') { // use DOM nodes/nodeLists - args.push(arg._node || arg._nodes || arg); - } - - ret = ArrayProto[name].apply(this._nodes, args); - - if (returnNodeList) { - ret = Y.all(ret); - } else { - ret = Y.Node.scrubVal(ret); - } - - return ret; - }; -}); -/** - * @module node - * @submodule node-core - */ - -Y.Array.each([ - /** - * Passes through to DOM method. - * @for Node - * @method removeChild - * @param {HTMLElement | Node} node Node to be removed - * @return {Node} The removed node - */ - 'removeChild', - - /** - * Passes through to DOM method. - * @method hasChildNodes - * @return {Boolean} Whether or not the node has any childNodes - */ - 'hasChildNodes', - - /** - * Passes through to DOM method. - * @method cloneNode - * @param {Boolean} deep Whether or not to perform a deep clone, which includes - * subtree and attributes - * @return {Node} The clone - */ - 'cloneNode', - - /** - * Passes through to DOM method. - * @method hasAttribute - * @param {String} attribute The attribute to test for - * @return {Boolean} Whether or not the attribute is present - */ - 'hasAttribute', - - /** - * Passes through to DOM method. - * @method scrollIntoView - * @chainable - */ - 'scrollIntoView', - - /** - * Passes through to DOM method. - * @method getElementsByTagName - * @param {String} tagName The tagName to collect - * @return {NodeList} A NodeList representing the HTMLCollection - */ - 'getElementsByTagName', - - /** - * Passes through to DOM method. - * @method focus - * @chainable - */ - 'focus', - - /** - * Passes through to DOM method. - * @method blur - * @chainable - */ - 'blur', - - /** - * Passes through to DOM method. - * Only valid on FORM elements - * @method submit - * @chainable - */ - 'submit', - - /** - * Passes through to DOM method. - * Only valid on FORM elements - * @method reset - * @chainable - */ - 'reset', - - /** - * Passes through to DOM method. - * @method select - * @chainable - */ - 'select', - - /** - * Passes through to DOM method. - * Only valid on TABLE elements - * @method createCaption - * @chainable - */ - 'createCaption' - -], function(method) { - Y.Node.prototype[method] = function(arg1, arg2, arg3) { - var ret = this.invoke(method, arg1, arg2, arg3); - return ret; - }; -}); - -/** - * Passes through to DOM method. - * @method removeAttribute - * @param {String} attribute The attribute to be removed - * @chainable - */ - // one-off implementation due to IE returning boolean, breaking chaining -Y.Node.prototype.removeAttribute = function(attr) { - var node = this._node; - if (node) { - node.removeAttribute(attr, 0); // comma zero for IE < 8 to force case-insensitive - } - - return this; -}; - -Y.Node.importMethod(Y.DOM, [ - /** - * Determines whether the node is an ancestor of another HTML element in the DOM hierarchy. - * @method contains - * @param {Node | HTMLElement} needle The possible node or descendent - * @return {Boolean} Whether or not this node is the needle its ancestor - */ - 'contains', - /** - * Allows setting attributes on DOM nodes, normalizing in some cases. - * This passes through to the DOM node, allowing for custom attributes. - * @method setAttribute - * @for Node - * @chainable - * @param {string} name The attribute name - * @param {string} value The value to set - */ - 'setAttribute', - /** - * Allows getting attributes on DOM nodes, normalizing in some cases. - * This passes through to the DOM node, allowing for custom attributes. - * @method getAttribute - * @for Node - * @param {string} name The attribute name - * @return {string} The attribute value - */ - 'getAttribute', - - /** - * Wraps the given HTML around the node. - * @method wrap - * @param {String} html The markup to wrap around the node. - * @chainable - * @for Node - */ - 'wrap', - - /** - * Removes the node's parent node. - * @method unwrap - * @chainable - */ - 'unwrap', - - /** - * Applies a unique ID to the node if none exists - * @method generateID - * @return {String} The existing or generated ID - */ - 'generateID' -]); - -Y.NodeList.importMethod(Y.Node.prototype, [ -/** - * Allows getting attributes on DOM nodes, normalizing in some cases. - * This passes through to the DOM node, allowing for custom attributes. - * @method getAttribute - * @see Node - * @for NodeList - * @param {string} name The attribute name - * @return {string} The attribute value - */ - - 'getAttribute', -/** - * Allows setting attributes on DOM nodes, normalizing in some cases. - * This passes through to the DOM node, allowing for custom attributes. - * @method setAttribute - * @see Node - * @for NodeList - * @chainable - * @param {string} name The attribute name - * @param {string} value The value to set - */ - 'setAttribute', - -/** - * Allows for removing attributes on DOM nodes. - * This passes through to the DOM node, allowing for custom attributes. - * @method removeAttribute - * @see Node - * @for NodeList - * @param {string} name The attribute to remove - */ - 'removeAttribute', -/** - * Removes the parent node from node in the list. - * @method unwrap - * @chainable - */ - 'unwrap', -/** - * Wraps the given HTML around each node. - * @method wrap - * @param {String} html The markup to wrap around the node. - * @chainable - */ - 'wrap', - -/** - * Applies a unique ID to each node if none exists - * @method generateID - * @return {String} The existing or generated ID - */ - 'generateID' -]); - - -}, '3.16.0', {"requires": ["dom-core", "selector"]}); -/* -YUI 3.16.0 (build 76f0e08) -Copyright 2014 Yahoo! Inc. All rights reserved. -Licensed under the BSD License. -http://yuilibrary.com/license/ -*/ - -YUI.add('color-base', function (Y, NAME) { - -/** -Color provides static methods for color conversion. - - Y.Color.toRGB('f00'); // rgb(255, 0, 0) - - Y.Color.toHex('rgb(255, 255, 0)'); // #ffff00 - -@module color -@submodule color-base -@class Color -@since 3.8.0 -**/ - -var REGEX_HEX = /^#?([\da-fA-F]{2})([\da-fA-F]{2})([\da-fA-F]{2})(\ufffe)?/, - REGEX_HEX3 = /^#?([\da-fA-F]{1})([\da-fA-F]{1})([\da-fA-F]{1})(\ufffe)?/, - REGEX_RGB = /rgba?\(([\d]{1,3}), ?([\d]{1,3}), ?([\d]{1,3}),? ?([.\d]*)?\)/, - TYPES = { 'HEX': 'hex', 'RGB': 'rgb', 'RGBA': 'rgba' }, - CONVERTS = { 'hex': 'toHex', 'rgb': 'toRGB', 'rgba': 'toRGBA' }; - - -Y.Color = { - /** - @static - @property KEYWORDS - @type Object - @since 3.8.0 - **/ - KEYWORDS: { - 'black': '000', 'silver': 'c0c0c0', 'gray': '808080', 'white': 'fff', - 'maroon': '800000', 'red': 'f00', 'purple': '800080', 'fuchsia': 'f0f', - 'green': '008000', 'lime': '0f0', 'olive': '808000', 'yellow': 'ff0', - 'navy': '000080', 'blue': '00f', 'teal': '008080', 'aqua': '0ff' - }, - - /** - NOTE: `(\ufffe)?` is added to the Regular Expression to carve out a - place for the alpha channel that is returned from toArray - without compromising any usage of the Regular Expression - - @static - @property REGEX_HEX - @type RegExp - @default /^#?([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})(\ufffe)?/ - @since 3.8.0 - **/ - REGEX_HEX: REGEX_HEX, - - /** - NOTE: `(\ufffe)?` is added to the Regular Expression to carve out a - place for the alpha channel that is returned from toArray - without compromising any usage of the Regular Expression - - @static - @property REGEX_HEX3 - @type RegExp - @default /^#?([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})(\ufffe)?/ - @since 3.8.0 - **/ - REGEX_HEX3: REGEX_HEX3, - - /** - @static - @property REGEX_RGB - @type RegExp - @default /rgba?\(([0-9]{1,3}), ?([0-9]{1,3}), ?([0-9]{1,3}),? ?([.0-9]{1,3})?\)/ - @since 3.8.0 - **/ - REGEX_RGB: REGEX_RGB, - - re_RGB: REGEX_RGB, - - re_hex: REGEX_HEX, - - re_hex3: REGEX_HEX3, - - /** - @static - @property STR_HEX - @type String - @default #{*}{*}{*} - @since 3.8.0 - **/ - STR_HEX: '#{*}{*}{*}', - - /** - @static - @property STR_RGB - @type String - @default rgb({*}, {*}, {*}) - @since 3.8.0 - **/ - STR_RGB: 'rgb({*}, {*}, {*})', - - /** - @static - @property STR_RGBA - @type String - @default rgba({*}, {*}, {*}, {*}) - @since 3.8.0 - **/ - STR_RGBA: 'rgba({*}, {*}, {*}, {*})', - - /** - @static - @property TYPES - @type Object - @default {'rgb':'rgb', 'rgba':'rgba'} - @since 3.8.0 - **/ - TYPES: TYPES, - - /** - @static - @property CONVERTS - @type Object - @default {} - @since 3.8.0 - **/ - CONVERTS: CONVERTS, - - /** - Converts the provided string to the provided type. - You can use the `Y.Color.TYPES` to get a valid `to` type. - If the color cannot be converted, the original color will be returned. - - @public - @method convert - @param {String} str - @param {String} to - @return {String} - @since 3.8.0 - **/ - convert: function (str, to) { - var convert = Y.Color.CONVERTS[to.toLowerCase()], - clr = str; - - if (convert && Y.Color[convert]) { - clr = Y.Color[convert](str); - } - - return clr; - }, - - /** - Converts provided color value to a hex value string - - @public - @method toHex - @param {String} str Hex or RGB value string - @return {String} returns array of values or CSS string if options.css is true - @since 3.8.0 - **/ - toHex: function (str) { - var clr = Y.Color._convertTo(str, 'hex'), - isTransparent = clr.toLowerCase() === 'transparent'; - - if (clr.charAt(0) !== '#' && !isTransparent) { - clr = '#' + clr; - } - - return isTransparent ? clr.toLowerCase() : clr.toUpperCase(); - }, - - /** - Converts provided color value to an RGB value string - @public - @method toRGB - @param {String} str Hex or RGB value string - @return {String} - @since 3.8.0 - **/ - toRGB: function (str) { - var clr = Y.Color._convertTo(str, 'rgb'); - return clr.toLowerCase(); - }, - - /** - Converts provided color value to an RGB value string - @public - @method toRGBA - @param {String} str Hex or RGB value string - @return {String} - @since 3.8.0 - **/ - toRGBA: function (str) { - var clr = Y.Color._convertTo(str, 'rgba' ); - return clr.toLowerCase(); - }, - - /** - Converts the provided color string to an array of values where the - last value is the alpha value. Will return an empty array if - the provided string is not able to be parsed. - - NOTE: `(\ufffe)?` is added to `HEX` and `HEX3` Regular Expressions to - carve out a place for the alpha channel that is returned from - toArray without compromising any usage of the Regular Expression - - Y.Color.toArray('fff'); // ['ff', 'ff', 'ff', 1] - Y.Color.toArray('rgb(0, 0, 0)'); // ['0', '0', '0', 1] - Y.Color.toArray('rgba(0, 0, 0, 0)'); // ['0', '0', '0', 1] - - - - @public - @method toArray - @param {String} str - @return {Array} - @since 3.8.0 - **/ - toArray: function(str) { - // parse with regex and return "matches" array - var type = Y.Color.findType(str).toUpperCase(), - regex, - arr, - length, - lastItem; - - if (type === 'HEX' && str.length < 5) { - type = 'HEX3'; - } - - if (type.charAt(type.length - 1) === 'A') { - type = type.slice(0, -1); - } - - regex = Y.Color['REGEX_' + type]; - - if (regex) { - arr = regex.exec(str) || []; - length = arr.length; - - if (length) { - - arr.shift(); - length--; - - if (type === 'HEX3') { - arr[0] += arr[0]; - arr[1] += arr[1]; - arr[2] += arr[2]; - } - - lastItem = arr[length - 1]; - if (!lastItem) { - arr[length - 1] = 1; - } - } - } - - return arr; - - }, - - /** - Converts the array of values to a string based on the provided template. - @public - @method fromArray - @param {Array} arr - @param {String} template - @return {String} - @since 3.8.0 - **/ - fromArray: function(arr, template) { - arr = arr.concat(); - - if (typeof template === 'undefined') { - return arr.join(', '); - } - - var replace = '{*}'; - - template = Y.Color['STR_' + template.toUpperCase()]; - - if (arr.length === 3 && template.match(/\{\*\}/g).length === 4) { - arr.push(1); - } - - while ( template.indexOf(replace) >= 0 && arr.length > 0) { - template = template.replace(replace, arr.shift()); - } - - return template; - }, - - /** - Finds the value type based on the str value provided. - @public - @method findType - @param {String} str - @return {String} - @since 3.8.0 - **/ - findType: function (str) { - if (Y.Color.KEYWORDS[str]) { - return 'keyword'; - } - - var index = str.indexOf('('), - key; - - if (index > 0) { - key = str.substr(0, index); - } - - if (key && Y.Color.TYPES[key.toUpperCase()]) { - return Y.Color.TYPES[key.toUpperCase()]; - } - - return 'hex'; - - }, // return 'keyword', 'hex', 'rgb' - - /** - Retrives the alpha channel from the provided string. If no alpha - channel is present, `1` will be returned. - @protected - @method _getAlpha - @param {String} clr - @return {Number} - @since 3.8.0 - **/ - _getAlpha: function (clr) { - var alpha, - arr = Y.Color.toArray(clr); - - if (arr.length > 3) { - alpha = arr.pop(); - } - - return +alpha || 1; - }, - - /** - Returns the hex value string if found in the KEYWORDS object - @protected - @method _keywordToHex - @param {String} clr - @return {String} - @since 3.8.0 - **/ - _keywordToHex: function (clr) { - var keyword = Y.Color.KEYWORDS[clr]; - - if (keyword) { - return keyword; - } - }, - - /** - Converts the provided color string to the value type provided as `to` - @protected - @method _convertTo - @param {String} clr - @param {String} to - @return {String} - @since 3.8.0 - **/ - _convertTo: function(clr, to) { - - if (clr === 'transparent') { - return clr; - } - - var from = Y.Color.findType(clr), - originalTo = to, - needsAlpha, - alpha, - method, - ucTo; - - if (from === 'keyword') { - clr = Y.Color._keywordToHex(clr); - from = 'hex'; - } - - if (from === 'hex' && clr.length < 5) { - if (clr.charAt(0) === '#') { - clr = clr.substr(1); - } - - clr = '#' + clr.charAt(0) + clr.charAt(0) + - clr.charAt(1) + clr.charAt(1) + - clr.charAt(2) + clr.charAt(2); - } - - if (from === to) { - return clr; - } - - if (from.charAt(from.length - 1) === 'a') { - from = from.slice(0, -1); - } - - needsAlpha = (to.charAt(to.length - 1) === 'a'); - if (needsAlpha) { - to = to.slice(0, -1); - alpha = Y.Color._getAlpha(clr); - } - - ucTo = to.charAt(0).toUpperCase() + to.substr(1).toLowerCase(); - method = Y.Color['_' + from + 'To' + ucTo ]; - - // check to see if need conversion to rgb first - // check to see if there is a direct conversion method - // convertions are: hex <-> rgb <-> hsl - if (!method) { - if (from !== 'rgb' && to !== 'rgb') { - clr = Y.Color['_' + from + 'ToRgb'](clr); - from = 'rgb'; - method = Y.Color['_' + from + 'To' + ucTo ]; - } - } - - if (method) { - clr = ((method)(clr, needsAlpha)); - } - - // process clr from arrays to strings after conversions if alpha is needed - if (needsAlpha) { - if (!Y.Lang.isArray(clr)) { - clr = Y.Color.toArray(clr); - } - clr.push(alpha); - clr = Y.Color.fromArray(clr, originalTo.toUpperCase()); - } - - return clr; - }, - - /** - Processes the hex string into r, g, b values. Will return values as - an array, or as an rgb string. - @protected - @method _hexToRgb - @param {String} str - @param {Boolean} [toArray] - @return {String|Array} - @since 3.8.0 - **/ - _hexToRgb: function (str, toArray) { - var r, g, b; - - /*jshint bitwise:false*/ - if (str.charAt(0) === '#') { - str = str.substr(1); - } - - str = parseInt(str, 16); - - r = str >> 16; - g = str >> 8 & 0xFF; - b = str & 0xFF; - - if (toArray) { - return [r, g, b]; - } - - return 'rgb(' + r + ', ' + g + ', ' + b + ')'; - }, - - /** - Processes the rgb string into r, g, b values. Will return values as - an array, or as a hex string. - @protected - @method _rgbToHex - @param {String} str - @param {Boolean} [toArray] - @return {String|Array} - @since 3.8.0 - **/ - _rgbToHex: function (str) { - /*jshint bitwise:false*/ - var rgb = Y.Color.toArray(str), - hex = rgb[2] | (rgb[1] << 8) | (rgb[0] << 16); - - hex = (+hex).toString(16); - - while (hex.length < 6) { - hex = '0' + hex; - } - - return '#' + hex; - } - -}; - - - -}, '3.16.0', {"requires": ["yui-base"]}); -/* -YUI 3.16.0 (build 76f0e08) -Copyright 2014 Yahoo! Inc. All rights reserved. -Licensed under the BSD License. -http://yuilibrary.com/license/ -*/ - -YUI.add('dom-style', function (Y, NAME) { - -/** - * Add style management functionality to DOM. - * @module dom - * @submodule dom-style - * @for DOM - */ - -var DOCUMENT_ELEMENT = 'documentElement', - DEFAULT_VIEW = 'defaultView', - OWNER_DOCUMENT = 'ownerDocument', - STYLE = 'style', - FLOAT = 'float', - CSS_FLOAT = 'cssFloat', - STYLE_FLOAT = 'styleFloat', - TRANSPARENT = 'transparent', - GET_COMPUTED_STYLE = 'getComputedStyle', - GET_BOUNDING_CLIENT_RECT = 'getBoundingClientRect', - - DOCUMENT = Y.config.doc, - - Y_DOM = Y.DOM, - - TRANSFORM = 'transform', - TRANSFORMORIGIN = 'transformOrigin', - VENDOR_TRANSFORM = [ - 'WebkitTransform', - 'MozTransform', - 'OTransform', - 'msTransform' - ], - - re_color = /color$/i, - re_unit = /width|height|top|left|right|bottom|margin|padding/i; - -Y.Array.each(VENDOR_TRANSFORM, function(val) { - if (val in DOCUMENT[DOCUMENT_ELEMENT].style) { - TRANSFORM = val; - TRANSFORMORIGIN = val + "Origin"; - } -}); - -Y.mix(Y_DOM, { - DEFAULT_UNIT: 'px', - - CUSTOM_STYLES: { - }, - - - /** - * Sets a style property for a given element. - * @method setStyle - * @param {HTMLElement} node The HTMLElement to apply the style to. - * @param {String} att The style property to set. - * @param {String|Number} val The value. - * @param {Object} [style] The style node. Defaults to `node.style`. - */ - setStyle: function(node, att, val, style) { - style = style || node.style; - var CUSTOM_STYLES = Y_DOM.CUSTOM_STYLES; - - if (style) { - if (val === null || val === '') { // normalize unsetting - val = ''; - } else if (!isNaN(Number(val)) && re_unit.test(att)) { // number values may need a unit - val += Y_DOM.DEFAULT_UNIT; - } - - if (att in CUSTOM_STYLES) { - if (CUSTOM_STYLES[att].set) { - CUSTOM_STYLES[att].set(node, val, style); - return; // NOTE: return - } else if (typeof CUSTOM_STYLES[att] === 'string') { - att = CUSTOM_STYLES[att]; - } - } else if (att === '') { // unset inline styles - att = 'cssText'; - val = ''; - } - style[att] = val; - } - }, - - /** - * Returns the current style value for the given property. - * @method getStyle - * @param {HTMLElement} node The HTMLElement to get the style from. - * @param {String} att The style property to get. - * @param {Object} [style] The style node. Defaults to `node.style`. - */ - getStyle: function(node, att, style) { - style = style || node.style; - var CUSTOM_STYLES = Y_DOM.CUSTOM_STYLES, - val = ''; - - if (style) { - if (att in CUSTOM_STYLES) { - if (CUSTOM_STYLES[att].get) { - return CUSTOM_STYLES[att].get(node, att, style); // NOTE: return - } else if (typeof CUSTOM_STYLES[att] === 'string') { - att = CUSTOM_STYLES[att]; - } - } - val = style[att]; - if (val === '') { // TODO: is empty string sufficient? - val = Y_DOM[GET_COMPUTED_STYLE](node, att); - } - } - - return val; - }, - - /** - * Sets multiple style properties. - * @method setStyles - * @param {HTMLElement} node The HTMLElement to apply the styles to. - * @param {Object} hash An object literal of property:value pairs. - */ - setStyles: function(node, hash) { - var style = node.style; - Y.each(hash, function(v, n) { - Y_DOM.setStyle(node, n, v, style); - }, Y_DOM); - }, - - /** - * Returns the computed style for the given node. - * @method getComputedStyle - * @param {HTMLElement} node The HTMLElement to get the style from. - * @param {String} att The style property to get. - * @return {String} The computed value of the style property. - */ - getComputedStyle: function(node, att) { - var val = '', - doc = node[OWNER_DOCUMENT], - computed; - - if (node[STYLE] && doc[DEFAULT_VIEW] && doc[DEFAULT_VIEW][GET_COMPUTED_STYLE]) { - computed = doc[DEFAULT_VIEW][GET_COMPUTED_STYLE](node, null); - if (computed) { // FF may be null in some cases (ticket #2530548) - val = computed[att]; - } - } - return val; - } -}); - -// normalize reserved word float alternatives ("cssFloat" or "styleFloat") -if (DOCUMENT[DOCUMENT_ELEMENT][STYLE][CSS_FLOAT] !== undefined) { - Y_DOM.CUSTOM_STYLES[FLOAT] = CSS_FLOAT; -} else if (DOCUMENT[DOCUMENT_ELEMENT][STYLE][STYLE_FLOAT] !== undefined) { - Y_DOM.CUSTOM_STYLES[FLOAT] = STYLE_FLOAT; -} - -// fix opera computedStyle default color unit (convert to rgb) -if (Y.UA.opera) { - Y_DOM[GET_COMPUTED_STYLE] = function(node, att) { - var view = node[OWNER_DOCUMENT][DEFAULT_VIEW], - val = view[GET_COMPUTED_STYLE](node, '')[att]; - - if (re_color.test(att)) { - val = Y.Color.toRGB(val); - } - - return val; - }; - -} - -// safari converts transparent to rgba(), others use "transparent" -if (Y.UA.webkit) { - Y_DOM[GET_COMPUTED_STYLE] = function(node, att) { - var view = node[OWNER_DOCUMENT][DEFAULT_VIEW], - val = view[GET_COMPUTED_STYLE](node, '')[att]; - - if (val === 'rgba(0, 0, 0, 0)') { - val = TRANSPARENT; - } - - return val; - }; - -} - -Y.DOM._getAttrOffset = function(node, attr) { - var val = Y.DOM[GET_COMPUTED_STYLE](node, attr), - offsetParent = node.offsetParent, - position, - parentOffset, - offset; - - if (val === 'auto') { - position = Y.DOM.getStyle(node, 'position'); - if (position === 'static' || position === 'relative') { - val = 0; - } else if (offsetParent && offsetParent[GET_BOUNDING_CLIENT_RECT]) { - parentOffset = offsetParent[GET_BOUNDING_CLIENT_RECT]()[attr]; - offset = node[GET_BOUNDING_CLIENT_RECT]()[attr]; - if (attr === 'left' || attr === 'top') { - val = offset - parentOffset; - } else { - val = parentOffset - node[GET_BOUNDING_CLIENT_RECT]()[attr]; - } - } - } - - return val; -}; - -Y.DOM._getOffset = function(node) { - var pos, - xy = null; - - if (node) { - pos = Y_DOM.getStyle(node, 'position'); - xy = [ - parseInt(Y_DOM[GET_COMPUTED_STYLE](node, 'left'), 10), - parseInt(Y_DOM[GET_COMPUTED_STYLE](node, 'top'), 10) - ]; - - if ( isNaN(xy[0]) ) { // in case of 'auto' - xy[0] = parseInt(Y_DOM.getStyle(node, 'left'), 10); // try inline - if ( isNaN(xy[0]) ) { // default to offset value - xy[0] = (pos === 'relative') ? 0 : node.offsetLeft || 0; - } - } - - if ( isNaN(xy[1]) ) { // in case of 'auto' - xy[1] = parseInt(Y_DOM.getStyle(node, 'top'), 10); // try inline - if ( isNaN(xy[1]) ) { // default to offset value - xy[1] = (pos === 'relative') ? 0 : node.offsetTop || 0; - } - } - } - - return xy; - -}; - -Y_DOM.CUSTOM_STYLES.transform = { - set: function(node, val, style) { - style[TRANSFORM] = val; - }, - - get: function(node) { - return Y_DOM[GET_COMPUTED_STYLE](node, TRANSFORM); - } -}; - -Y_DOM.CUSTOM_STYLES.transformOrigin = { - set: function(node, val, style) { - style[TRANSFORMORIGIN] = val; - }, - - get: function(node) { - return Y_DOM[GET_COMPUTED_STYLE](node, TRANSFORMORIGIN); - } -}; - - -}, '3.16.0', {"requires": ["dom-base", "color-base"]}); -/* -YUI 3.16.0 (build 76f0e08) -Copyright 2014 Yahoo! Inc. All rights reserved. -Licensed under the BSD License. -http://yuilibrary.com/license/ -*/ - -YUI.add('node-base', function (Y, NAME) { - -/** - * @module node - * @submodule node-base - */ - -var methods = [ -/** - * Determines whether the node has the given className. - * @method hasClass - * @for Node - * @param {String} className the class name to search for - * @return {Boolean} Whether or not the node has the specified class - */ - 'hasClass', - -/** - * Adds a class name to the node. - * @method addClass - * @param {String} className the class name to add to the node's class attribute - * @chainable - */ - 'addClass', - -/** - * Removes a class name from the node. - * @method removeClass - * @param {String} className the class name to remove from the node's class attribute - * @chainable - */ - 'removeClass', - -/** - * Replace a class with another class on the node. - * If no oldClassName is present, the newClassName is simply added. - * @method replaceClass - * @param {String} oldClassName the class name to be replaced - * @param {String} newClassName the class name that will be replacing the old class name - * @chainable - */ - 'replaceClass', - -/** - * If the className exists on the node it is removed, if it doesn't exist it is added. - * @method toggleClass - * @param {String} className the class name to be toggled - * @param {Boolean} force Option to force adding or removing the class. - * @chainable - */ - 'toggleClass' -]; - -Y.Node.importMethod(Y.DOM, methods); -/** - * Determines whether each node has the given className. - * @method hasClass - * @see Node.hasClass - * @for NodeList - * @param {String} className the class name to search for - * @return {Array} An array of booleans for each node bound to the NodeList. - */ - -/** - * Adds a class name to each node. - * @method addClass - * @see Node.addClass - * @param {String} className the class name to add to each node's class attribute - * @chainable - */ - -/** - * Removes a class name from each node. - * @method removeClass - * @see Node.removeClass - * @param {String} className the class name to remove from each node's class attribute - * @chainable - */ - -/** - * Replace a class with another class for each node. - * If no oldClassName is present, the newClassName is simply added. - * @method replaceClass - * @see Node.replaceClass - * @param {String} oldClassName the class name to be replaced - * @param {String} newClassName the class name that will be replacing the old class name - * @chainable - */ - -/** - * For each node, if the className exists on the node it is removed, if it doesn't exist it is added. - * @method toggleClass - * @see Node.toggleClass - * @param {String} className the class name to be toggled - * @chainable - */ -Y.NodeList.importMethod(Y.Node.prototype, methods); -/** - * @module node - * @submodule node-base - */ - -var Y_Node = Y.Node, - Y_DOM = Y.DOM; - -/** - * Returns a new dom node using the provided markup string. - * @method create - * @static - * @param {String} html The markup used to create the element. - * Use `Y.Escape.html()` - * to escape html content. - * @param {HTMLDocument} doc An optional document context - * @return {Node} A Node instance bound to a DOM node or fragment - * @for Node - */ -Y_Node.create = function(html, doc) { - if (doc && doc._node) { - doc = doc._node; - } - return Y.one(Y_DOM.create(html, doc)); -}; - -Y.mix(Y_Node.prototype, { - /** - * Creates a new Node using the provided markup string. - * @method create - * @param {String} html The markup used to create the element. - * Use `Y.Escape.html()` - * to escape html content. - * @param {HTMLDocument} doc An optional document context - * @return {Node} A Node instance bound to a DOM node or fragment - */ - create: Y_Node.create, - - /** - * Inserts the content before the reference node. - * @method insert - * @param {String | Node | HTMLElement | NodeList | HTMLCollection} content The content to insert. - * Use `Y.Escape.html()` - * to escape html content. - * @param {Int | Node | HTMLElement | String} where The position to insert at. - * Possible "where" arguments - *
- *
Y.Node
- *
The Node to insert before
- *
HTMLElement
- *
The element to insert before
- *
Int
- *
The index of the child element to insert before
- *
"replace"
- *
Replaces the existing HTML
- *
"before"
- *
Inserts before the existing HTML
- *
"before"
- *
Inserts content before the node
- *
"after"
- *
Inserts content after the node
- *
- * @chainable - */ - insert: function(content, where) { - this._insert(content, where); - return this; - }, - - _insert: function(content, where) { - var node = this._node, - ret = null; - - if (typeof where == 'number') { // allow index - where = this._node.childNodes[where]; - } else if (where && where._node) { // Node - where = where._node; - } - - if (content && typeof content != 'string') { // allow Node or NodeList/Array instances - content = content._node || content._nodes || content; - } - ret = Y_DOM.addHTML(node, content, where); - - return ret; - }, - - /** - * Inserts the content as the firstChild of the node. - * @method prepend - * @param {String | Node | HTMLElement} content The content to insert. - * Use `Y.Escape.html()` - * to escape html content. - * @chainable - */ - prepend: function(content) { - return this.insert(content, 0); - }, - - /** - * Inserts the content as the lastChild of the node. - * @method append - * @param {String | Node | HTMLElement} content The content to insert. - * Use `Y.Escape.html()` - * to escape html content. - * @chainable - */ - append: function(content) { - return this.insert(content, null); - }, - - /** - * @method appendChild - * @param {String | HTMLElement | Node} node Node to be appended. - * Use `Y.Escape.html()` - * to escape html content. - * @return {Node} The appended node - */ - appendChild: function(node) { - return Y_Node.scrubVal(this._insert(node)); - }, - - /** - * @method insertBefore - * @param {String | HTMLElement | Node} newNode Node to be appended - * @param {HTMLElement | Node} refNode Node to be inserted before. - * Use `Y.Escape.html()` - * to escape html content. - * @return {Node} The inserted node - */ - insertBefore: function(newNode, refNode) { - return Y.Node.scrubVal(this._insert(newNode, refNode)); - }, - - /** - * Appends the node to the given node. - * @example - * // appendTo returns the node that has been created beforehand - * Y.Node.create('

').appendTo('body').set('text', 'hello world!'); - * @method appendTo - * @param {Node | HTMLElement | String} node The node to append to. - * If `node` is a string it will be considered as a css selector and only the first matching node will be used. - * @chainable - */ - appendTo: function(node) { - Y.one(node).append(this); - return this; - }, - - // This method is deprecated, and is intentionally left undocumented. - // Use `setHTML` instead. - setContent: function(content) { - this._insert(content, 'replace'); - return this; - }, - - // This method is deprecated, and is intentionally left undocumented. - // Use `getHTML` instead. - getContent: function() { - var node = this; - - if (node._node.nodeType === 11) { // 11 === Node.DOCUMENT_FRAGMENT_NODE - // "this", when it is a document fragment, must be cloned because - // the nodes contained in the fragment actually disappear once - // the fragment is appended anywhere - node = node.create("
").append(node.cloneNode(true)); - } - - return node.get("innerHTML"); - } -}); - -/** - * Replaces the node's current html content with the content provided. - * Note that this passes to innerHTML and is not escaped. - * Use `Y.Escape.html()` - * to escape html content or `set('text')` to add as text. - * @method setHTML - * @param {String | Node | HTMLElement | NodeList | HTMLCollection} content The content to insert - * @chainable - */ -Y.Node.prototype.setHTML = Y.Node.prototype.setContent; - -/** - * Returns the node's current html content (e.g. innerHTML) - * @method getHTML - * @return {String} The html content - */ -Y.Node.prototype.getHTML = Y.Node.prototype.getContent; - -Y.NodeList.importMethod(Y.Node.prototype, [ - /** - * Called on each Node instance - * @for NodeList - * @method append - * @see Node.append - */ - 'append', - - /** - * Called on each Node instance - * @for NodeList - * @method insert - * @see Node.insert - */ - 'insert', - - /** - * Called on each Node instance - * @for NodeList - * @method appendChild - * @see Node.appendChild - */ - 'appendChild', - - /** - * Called on each Node instance - * @for NodeList - * @method insertBefore - * @see Node.insertBefore - */ - 'insertBefore', - - /** - * Called on each Node instance - * @for NodeList - * @method prepend - * @see Node.prepend - */ - 'prepend', - - 'setContent', - - 'getContent', - - /** - * Called on each Node instance - * Note that this passes to innerHTML and is not escaped. - * Use `Y.Escape.html()` - * to escape html content or `set('text')` to add as text. - * @for NodeList - * @method setHTML - * @see Node.setHTML - */ - 'setHTML', - - /** - * Called on each Node instance - * @for NodeList - * @method getHTML - * @see Node.getHTML - */ - 'getHTML' -]); -/** - * @module node - * @submodule node-base - */ - -var Y_Node = Y.Node, - Y_DOM = Y.DOM; - -/** - * Static collection of configuration attributes for special handling - * @property ATTRS - * @static - * @type object - */ -Y_Node.ATTRS = { - /** - * Allows for getting and setting the text of an element. - * Formatting is preserved and special characters are treated literally. - * @config text - * @type String - */ - text: { - getter: function() { - return Y_DOM.getText(this._node); - }, - - setter: function(content) { - Y_DOM.setText(this._node, content); - return content; - } - }, - - /** - * Allows for getting and setting the text of an element. - * Formatting is preserved and special characters are treated literally. - * @config for - * @type String - */ - 'for': { - getter: function() { - return Y_DOM.getAttribute(this._node, 'for'); - }, - - setter: function(val) { - Y_DOM.setAttribute(this._node, 'for', val); - return val; - } - }, - - 'options': { - getter: function() { - return this._node.getElementsByTagName('option'); - } - }, - - /** - * Returns a NodeList instance of all HTMLElement children. - * @readOnly - * @config children - * @type NodeList - */ - 'children': { - getter: function() { - var node = this._node, - children = node.children, - childNodes, i, len; - - if (!children) { - childNodes = node.childNodes; - children = []; - - for (i = 0, len = childNodes.length; i < len; ++i) { - if (childNodes[i].tagName) { - children[children.length] = childNodes[i]; - } - } - } - return Y.all(children); - } - }, - - value: { - getter: function() { - return Y_DOM.getValue(this._node); - }, - - setter: function(val) { - Y_DOM.setValue(this._node, val); - return val; - } - } -}; - -Y.Node.importMethod(Y.DOM, [ - /** - * Allows setting attributes on DOM nodes, normalizing in some cases. - * This passes through to the DOM node, allowing for custom attributes. - * @method setAttribute - * @for Node - * @for NodeList - * @chainable - * @param {string} name The attribute name - * @param {string} value The value to set - */ - 'setAttribute', - /** - * Allows getting attributes on DOM nodes, normalizing in some cases. - * This passes through to the DOM node, allowing for custom attributes. - * @method getAttribute - * @for Node - * @for NodeList - * @param {string} name The attribute name - * @return {string} The attribute value - */ - 'getAttribute' - -]); -/** - * @module node - * @submodule node-base - */ - -var Y_Node = Y.Node; -var Y_NodeList = Y.NodeList; -/** - * List of events that route to DOM events - * @static - * @property DOM_EVENTS - * @for Node - */ - -Y_Node.DOM_EVENTS = { - abort: 1, - beforeunload: 1, - blur: 1, - change: 1, - click: 1, - close: 1, - command: 1, - contextmenu: 1, - copy: 1, - cut: 1, - dblclick: 1, - DOMMouseScroll: 1, - drag: 1, - dragstart: 1, - dragenter: 1, - dragover: 1, - dragleave: 1, - dragend: 1, - drop: 1, - error: 1, - focus: 1, - key: 1, - keydown: 1, - keypress: 1, - keyup: 1, - load: 1, - message: 1, - mousedown: 1, - mouseenter: 1, - mouseleave: 1, - mousemove: 1, - mousemultiwheel: 1, - mouseout: 1, - mouseover: 1, - mouseup: 1, - mousewheel: 1, - orientationchange: 1, - paste: 1, - reset: 1, - resize: 1, - select: 1, - selectstart: 1, - submit: 1, - scroll: 1, - textInput: 1, - unload: 1 -}; - -// Add custom event adaptors to this list. This will make it so -// that delegate, key, available, contentready, etc all will -// be available through Node.on -Y.mix(Y_Node.DOM_EVENTS, Y.Env.evt.plugins); - -Y.augment(Y_Node, Y.EventTarget); - -Y.mix(Y_Node.prototype, { - /** - * Removes event listeners from the node and (optionally) its subtree - * @method purge - * @param {Boolean} recurse (optional) Whether or not to remove listeners from the - * node's subtree - * @param {String} type (optional) Only remove listeners of the specified type - * @chainable - * - */ - purge: function(recurse, type) { - Y.Event.purgeElement(this._node, recurse, type); - return this; - } - -}); - -Y.mix(Y.NodeList.prototype, { - _prepEvtArgs: function(type, fn, context) { - // map to Y.on/after signature (type, fn, nodes, context, arg1, arg2, etc) - var args = Y.Array(arguments, 0, true); - - if (args.length < 2) { // type only (event hash) just add nodes - args[2] = this._nodes; - } else { - args.splice(2, 0, this._nodes); - } - - args[3] = context || this; // default to NodeList instance as context - - return args; - }, - - /** - Subscribe a callback function for each `Node` in the collection to execute - in response to a DOM event. - - NOTE: Generally, the `on()` method should be avoided on `NodeLists`, in - favor of using event delegation from a parent Node. See the Event user - guide for details. - - Most DOM events are associated with a preventable default behavior, such as - link clicks navigating to a new page. Callbacks are passed a - `DOMEventFacade` object as their first argument (usually called `e`) that - can be used to prevent this default behavior with `e.preventDefault()`. See - the `DOMEventFacade` API for all available properties and methods on the - object. - - By default, the `this` object will be the `NodeList` that the subscription - came from, not the `Node` that received the event. Use - `e.currentTarget` to refer to the `Node`. - - Returning `false` from a callback is supported as an alternative to calling - `e.preventDefault(); e.stopPropagation();`. However, it is recommended to - use the event methods. - - @example - - Y.all(".sku").on("keydown", function (e) { - if (e.keyCode === 13) { - e.preventDefault(); - - // Use e.currentTarget to refer to the individual Node - var item = Y.MyApp.searchInventory( e.currentTarget.get('value') ); - // etc ... - } - }); - - @method on - @param {String} type The name of the event - @param {Function} fn The callback to execute in response to the event - @param {Object} [context] Override `this` object in callback - @param {Any} [arg*] 0..n additional arguments to supply to the subscriber - @return {EventHandle} A subscription handle capable of detaching that - subscription - @for NodeList - **/ - on: function(type, fn, context) { - return Y.on.apply(Y, this._prepEvtArgs.apply(this, arguments)); - }, - - /** - * Applies an one-time event listener to each Node bound to the NodeList. - * @method once - * @param {String} type The event being listened for - * @param {Function} fn The handler to call when the event fires - * @param {Object} context The context to call the handler with. - * Default is the NodeList instance. - * @return {EventHandle} A subscription handle capable of detaching that - * subscription - * @for NodeList - */ - once: function(type, fn, context) { - return Y.once.apply(Y, this._prepEvtArgs.apply(this, arguments)); - }, - - /** - * Applies an event listener to each Node bound to the NodeList. - * The handler is called only after all on() handlers are called - * and the event is not prevented. - * @method after - * @param {String} type The event being listened for - * @param {Function} fn The handler to call when the event fires - * @param {Object} context The context to call the handler with. - * Default is the NodeList instance. - * @return {EventHandle} A subscription handle capable of detaching that - * subscription - * @for NodeList - */ - after: function(type, fn, context) { - return Y.after.apply(Y, this._prepEvtArgs.apply(this, arguments)); - }, - - /** - * Applies an one-time event listener to each Node bound to the NodeList - * that will be called only after all on() handlers are called and the - * event is not prevented. - * - * @method onceAfter - * @param {String} type The event being listened for - * @param {Function} fn The handler to call when the event fires - * @param {Object} context The context to call the handler with. - * Default is the NodeList instance. - * @return {EventHandle} A subscription handle capable of detaching that - * subscription - * @for NodeList - */ - onceAfter: function(type, fn, context) { - return Y.onceAfter.apply(Y, this._prepEvtArgs.apply(this, arguments)); - } -}); - -Y_NodeList.importMethod(Y.Node.prototype, [ - /** - * Called on each Node instance - * @method detach - * @see Node.detach - * @for NodeList - */ - 'detach', - - /** Called on each Node instance - * @method detachAll - * @see Node.detachAll - * @for NodeList - */ - 'detachAll' -]); - -/** -Subscribe a callback function to execute in response to a DOM event or custom -event. - -Most DOM events are associated with a preventable default behavior such as -link clicks navigating to a new page. Callbacks are passed a `DOMEventFacade` -object as their first argument (usually called `e`) that can be used to -prevent this default behavior with `e.preventDefault()`. See the -`DOMEventFacade` API for all available properties and methods on the object. - -If the event name passed as the first parameter is not a whitelisted DOM event, -it will be treated as a custom event subscriptions, allowing -`node.fire('customEventName')` later in the code. Refer to the Event user guide -for the full DOM event whitelist. - -By default, the `this` object in the callback will refer to the subscribed -`Node`. - -Returning `false` from a callback is supported as an alternative to calling -`e.preventDefault(); e.stopPropagation();`. However, it is recommended to use -the event methods. - -@example - - Y.one("#my-form").on("submit", function (e) { - e.preventDefault(); - - // proceed with ajax form submission instead... - }); - -@method on -@param {String} type The name of the event -@param {Function} fn The callback to execute in response to the event -@param {Object} [context] Override `this` object in callback -@param {Any} [arg*] 0..n additional arguments to supply to the subscriber -@return {EventHandle} A subscription handle capable of detaching that - subscription -@for Node -**/ - -Y.mix(Y.Node.ATTRS, { - offsetHeight: { - setter: function(h) { - Y.DOM.setHeight(this._node, h); - return h; - }, - - getter: function() { - return this._node.offsetHeight; - } - }, - - offsetWidth: { - setter: function(w) { - Y.DOM.setWidth(this._node, w); - return w; - }, - - getter: function() { - return this._node.offsetWidth; - } - } -}); - -Y.mix(Y.Node.prototype, { - sizeTo: function(w, h) { - var node; - if (arguments.length < 2) { - node = Y.one(w); - w = node.get('offsetWidth'); - h = node.get('offsetHeight'); - } - - this.setAttrs({ - offsetWidth: w, - offsetHeight: h - }); - } -}); - -if (!Y.config.doc.documentElement.hasAttribute) { // IE < 8 - Y.Node.prototype.hasAttribute = function(attr) { - if (attr === 'value') { - if (this.get('value') !== "") { // IE < 8 fails to populate specified when set in HTML - return true; - } - } - return !!(this._node.attributes[attr] && - this._node.attributes[attr].specified); - }; -} - -// IE throws an error when calling focus() on an element that's invisible, not -// displayed, or disabled. -Y.Node.prototype.focus = function () { - try { - this._node.focus(); - } catch (e) { - } - - return this; -}; - -// IE throws error when setting input.type = 'hidden', -// input.setAttribute('type', 'hidden') and input.attributes.type.value = 'hidden' -Y.Node.ATTRS.type = { - setter: function(val) { - if (val === 'hidden') { - try { - this._node.type = 'hidden'; - } catch(e) { - this._node.style.display = 'none'; - this._inputType = 'hidden'; - } - } else { - try { // IE errors when changing the type from "hidden' - this._node.type = val; - } catch (e) { - } - } - return val; - }, - - getter: function() { - return this._inputType || this._node.type; - }, - - _bypassProxy: true // don't update DOM when using with Attribute -}; - -if (Y.config.doc.createElement('form').elements.nodeType) { - // IE: elements collection is also FORM node which trips up scrubVal. - Y.Node.ATTRS.elements = { - getter: function() { - return this.all('input, textarea, button, select'); - } - }; -} -/** - * Provides methods for managing custom Node data. - * - * @module node - * @main node - * @submodule node-data - */ - -Y.mix(Y.Node.prototype, { - _initData: function() { - if (! ('_data' in this)) { - this._data = {}; - } - }, - - /** - * @method getData - * @for Node - * @description Retrieves arbitrary data stored on a Node instance. - * If no data is associated with the Node, it will attempt to retrieve - * a value from the corresponding HTML data attribute. (e.g. node.getData('foo') - * will check node.getAttribute('data-foo')). - * @param {string} name Optional name of the data field to retrieve. - * If no name is given, all data is returned. - * @return {any | Object} Whatever is stored at the given field, - * or an object hash of all fields. - */ - getData: function(name) { - this._initData(); - var data = this._data, - ret = data; - - if (arguments.length) { // single field - if (name in data) { - ret = data[name]; - } else { // initialize from HTML attribute - ret = this._getDataAttribute(name); - } - } else if (typeof data == 'object' && data !== null) { // all fields - ret = {}; - Y.Object.each(data, function(v, n) { - ret[n] = v; - }); - - ret = this._getDataAttributes(ret); - } - - return ret; - - }, - - _getDataAttributes: function(ret) { - ret = ret || {}; - var i = 0, - attrs = this._node.attributes, - len = attrs.length, - prefix = this.DATA_PREFIX, - prefixLength = prefix.length, - name; - - while (i < len) { - name = attrs[i].name; - if (name.indexOf(prefix) === 0) { - name = name.substr(prefixLength); - if (!(name in ret)) { // only merge if not already stored - ret[name] = this._getDataAttribute(name); - } - } - - i += 1; - } - - return ret; - }, - - _getDataAttribute: function(name) { - name = this.DATA_PREFIX + name; - - var node = this._node, - attrs = node.attributes, - data = attrs && attrs[name] && attrs[name].value; - - return data; - }, - - /** - * @method setData - * @for Node - * @description Stores arbitrary data on a Node instance. - * This is not stored with the DOM node. - * @param {string} name The name of the field to set. If no val - * is given, name is treated as the data and overrides any existing data. - * @param {any} val The value to be assigned to the field. - * @chainable - */ - setData: function(name, val) { - this._initData(); - if (arguments.length > 1) { - this._data[name] = val; - } else { - this._data = name; - } - - return this; - }, - - /** - * @method clearData - * @for Node - * @description Clears internally stored data. - * @param {string} name The name of the field to clear. If no name - * is given, all data is cleared. - * @chainable - */ - clearData: function(name) { - if ('_data' in this) { - if (typeof name != 'undefined') { - delete this._data[name]; - } else { - delete this._data; - } - } - - return this; - } -}); - -Y.mix(Y.NodeList.prototype, { - /** - * @method getData - * @for NodeList - * @description Retrieves arbitrary data stored on each Node instance - * bound to the NodeList. - * @see Node - * @param {string} name Optional name of the data field to retrieve. - * If no name is given, all data is returned. - * @return {Array} An array containing all of the data for each Node instance. - * or an object hash of all fields. - */ - getData: function(name) { - var args = (arguments.length) ? [name] : []; - return this._invoke('getData', args, true); - }, - - /** - * @method setData - * @for NodeList - * @description Stores arbitrary data on each Node instance bound to the - * NodeList. This is not stored with the DOM node. - * @param {string} name The name of the field to set. If no name - * is given, name is treated as the data and overrides any existing data. - * @param {any} val The value to be assigned to the field. - * @chainable - */ - setData: function(name, val) { - var args = (arguments.length > 1) ? [name, val] : [name]; - return this._invoke('setData', args); - }, - - /** - * @method clearData - * @for NodeList - * @description Clears data on all Node instances bound to the NodeList. - * @param {string} name The name of the field to clear. If no name - * is given, all data is cleared. - * @chainable - */ - clearData: function(name) { - var args = (arguments.length) ? [name] : []; - return this._invoke('clearData', [name]); - } -}); - - -}, '3.16.0', {"requires": ["event-base", "node-core", "dom-base", "dom-style"]}); -/* -YUI 3.16.0 (build 76f0e08) -Copyright 2014 Yahoo! Inc. All rights reserved. -Licensed under the BSD License. -http://yuilibrary.com/license/ -*/ - -YUI.add('event-synthetic', function (Y, NAME) { - -/** - * Define new DOM events that can be subscribed to from Nodes. - * - * @module event - * @submodule event-synthetic - */ -var CustomEvent = Y.CustomEvent, - DOMMap = Y.Env.evt.dom_map, - toArray = Y.Array, - YLang = Y.Lang, - isObject = YLang.isObject, - isString = YLang.isString, - isArray = YLang.isArray, - query = Y.Selector.query, - noop = function () {}; - -/** - *

The triggering mechanism used by SyntheticEvents.

- * - *

Implementers should not instantiate these directly. Use the Notifier - * provided to the event's implemented on(node, sub, notifier) or - * delegate(node, sub, notifier, filter) methods.

- * - * @class SyntheticEvent.Notifier - * @constructor - * @param handle {EventHandle} the detach handle for the subscription to an - * internal custom event used to execute the callback passed to - * on(..) or delegate(..) - * @param emitFacade {Boolean} take steps to ensure the first arg received by - * the subscription callback is an event facade - * @private - * @since 3.2.0 - */ -function Notifier(handle, emitFacade) { - this.handle = handle; - this.emitFacade = emitFacade; -} - -/** - *

Executes the subscription callback, passing the firing arguments as the - * first parameters to that callback. For events that are configured with - * emitFacade=true, it is common practice to pass the triggering DOMEventFacade - * as the first parameter. Barring a proper DOMEventFacade or EventFacade - * (from a CustomEvent), a new EventFacade will be generated. In that case, if - * fire() is called with a simple object, it will be mixed into the facade. - * Otherwise, the facade will be prepended to the callback parameters.

- * - *

For notifiers provided to delegate logic, the first argument should be an - * object with a "currentTarget" property to identify what object to - * default as 'this' in the callback. Typically this is gleaned from the - * DOMEventFacade or EventFacade, but if configured with emitFacade=false, an - * object must be provided. In that case, the object will be removed from the - * callback parameters.

- * - *

Additional arguments passed during event subscription will be - * automatically added after those passed to fire().

- * - * @method fire - * @param {EventFacade|DOMEventFacade|any} e (see description) - * @param {any[]} [arg*] additional arguments received by all subscriptions - * @private - */ -Notifier.prototype.fire = function (e) { - // first arg to delegate notifier should be an object with currentTarget - var args = toArray(arguments, 0, true), - handle = this.handle, - ce = handle.evt, - sub = handle.sub, - thisObj = sub.context, - delegate = sub.filter, - event = e || {}, - ret; - - if (this.emitFacade) { - if (!e || !e.preventDefault) { - event = ce._getFacade(); - - if (isObject(e) && !e.preventDefault) { - Y.mix(event, e, true); - args[0] = event; - } else { - args.unshift(event); - } - } - - event.type = ce.type; - event.details = args.slice(); - - if (delegate) { - event.container = ce.host; - } - } else if (delegate && isObject(e) && e.currentTarget) { - args.shift(); - } - - sub.context = thisObj || event.currentTarget || ce.host; - ret = ce.fire.apply(ce, args); - - // have to handle preventedFn and stoppedFn manually because - // Notifier CustomEvents are forced to emitFacade=false - if (e.prevented && ce.preventedFn) { - ce.preventedFn.apply(ce, args); - } - - if (e.stopped && ce.stoppedFn) { - ce.stoppedFn.apply(ce, args); - } - - sub.context = thisObj; // reset for future firing - - // to capture callbacks that return false to stopPropagation. - // Useful for delegate implementations - return ret; -}; - -/** - * Manager object for synthetic event subscriptions to aggregate multiple synths on the - * same node without colliding with actual DOM subscription entries in the global map of - * DOM subscriptions. Also facilitates proper cleanup on page unload. - * - * @class SynthRegistry - * @constructor - * @param el {HTMLElement} the DOM element - * @param yuid {String} the yuid stamp for the element - * @param key {String} the generated id token used to identify an event type + - * element in the global DOM subscription map. - * @private - */ -function SynthRegistry(el, yuid, key) { - this.handles = []; - this.el = el; - this.key = key; - this.domkey = yuid; -} - -SynthRegistry.prototype = { - constructor: SynthRegistry, - - // A few object properties to fake the CustomEvent interface for page - // unload cleanup. DON'T TOUCH! - type : '_synth', - fn : noop, - capture : false, - - /** - * Adds a subscription from the Notifier registry. - * - * @method register - * @param handle {EventHandle} the subscription - * @since 3.4.0 - */ - register: function (handle) { - handle.evt.registry = this; - this.handles.push(handle); - }, - - /** - * Removes the subscription from the Notifier registry. - * - * @method _unregisterSub - * @param sub {Subscription} the subscription - * @since 3.4.0 - */ - unregister: function (sub) { - var handles = this.handles, - events = DOMMap[this.domkey], - i; - - for (i = handles.length - 1; i >= 0; --i) { - if (handles[i].sub === sub) { - handles.splice(i, 1); - break; - } - } - - // Clean up left over objects when there are no more subscribers. - if (!handles.length) { - delete events[this.key]; - if (!Y.Object.size(events)) { - delete DOMMap[this.domkey]; - } - } - }, - - /** - * Used by the event system's unload cleanup process. When navigating - * away from the page, the event system iterates the global map of element - * subscriptions and detaches everything using detachAll(). Normally, - * the map is populated with custom events, so this object needs to - * at least support the detachAll method to duck type its way to - * cleanliness. - * - * @method detachAll - * @private - * @since 3.4.0 - */ - detachAll : function () { - var handles = this.handles, - i = handles.length; - - while (--i >= 0) { - handles[i].detach(); - } - } -}; - -/** - *

Wrapper class for the integration of new events into the YUI event - * infrastructure. Don't instantiate this object directly, use - * Y.Event.define(type, config). See that method for details.

- * - *

Properties that MAY or SHOULD be specified in the configuration are noted - * below and in the description of Y.Event.define.

- * - * @class SyntheticEvent - * @constructor - * @param cfg {Object} Implementation pieces and configuration - * @since 3.1.0 - * @in event-synthetic - */ -function SyntheticEvent() { - this._init.apply(this, arguments); -} - -Y.mix(SyntheticEvent, { - Notifier: Notifier, - SynthRegistry: SynthRegistry, - - /** - * Returns the array of subscription handles for a node for the given event - * type. Passing true as the third argument will create a registry entry - * in the event system's DOM map to host the array if one doesn't yet exist. - * - * @method getRegistry - * @param node {Node} the node - * @param type {String} the event - * @param create {Boolean} create a registration entry to host a new array - * if one doesn't exist. - * @return {Array} - * @static - * @protected - * @since 3.2.0 - */ - getRegistry: function (node, type, create) { - var el = node._node, - yuid = Y.stamp(el), - key = 'event:' + yuid + type + '_synth', - events = DOMMap[yuid]; - - if (create) { - if (!events) { - events = DOMMap[yuid] = {}; - } - if (!events[key]) { - events[key] = new SynthRegistry(el, yuid, key); - } - } - - return (events && events[key]) || null; - }, - - /** - * Alternate _delete() method for the CustomEvent object - * created to manage SyntheticEvent subscriptions. - * - * @method _deleteSub - * @param sub {Subscription} the subscription to clean up - * @private - * @since 3.2.0 - */ - _deleteSub: function (sub) { - if (sub && sub.fn) { - var synth = this.eventDef, - method = (sub.filter) ? 'detachDelegate' : 'detach'; - - this._subscribers = []; - - if (CustomEvent.keepDeprecatedSubs) { - this.subscribers = {}; - } - - synth[method](sub.node, sub, this.notifier, sub.filter); - this.registry.unregister(sub); - - delete sub.fn; - delete sub.node; - delete sub.context; - } - }, - - prototype: { - constructor: SyntheticEvent, - - /** - * Construction logic for the event. - * - * @method _init - * @protected - */ - _init: function () { - var config = this.publishConfig || (this.publishConfig = {}); - - // The notification mechanism handles facade creation - this.emitFacade = ('emitFacade' in config) ? - config.emitFacade : - true; - config.emitFacade = false; - }, - - /** - *

Implementers MAY provide this method definition.

- * - *

Implement this function if the event supports a different - * subscription signature. This function is used by both - * on() and delegate(). The second parameter - * indicates that the event is being subscribed via - * delegate().

- * - *

Implementations must remove extra arguments from the args list - * before returning. The required args for on() - * subscriptions are

- *
[type, callback, target, context, argN...]
- * - *

The required args for delegate() - * subscriptions are

- * - *
[type, callback, target, filter, context, argN...]
- * - *

The return value from this function will be stored on the - * subscription in the '_extra' property for reference elsewhere.

- * - * @method processArgs - * @param args {Array} parmeters passed to Y.on(..) or Y.delegate(..) - * @param delegate {Boolean} true if the subscription is from Y.delegate - * @return {any} - */ - processArgs: noop, - - /** - *

Implementers MAY override this property.

- * - *

Whether to prevent multiple subscriptions to this event that are - * classified as being the same. By default, this means the subscribed - * callback is the same function. See the subMatch - * method. Setting this to true will impact performance for high volume - * events.

- * - * @property preventDups - * @type {Boolean} - * @default false - */ - //preventDups : false, - - /** - *

Implementers SHOULD provide this method definition.

- * - * Implementation logic for subscriptions done via node.on(type, - * fn) or Y.on(type, fn, target). This - * function should set up the monitor(s) that will eventually fire the - * event. Typically this involves subscribing to at least one DOM - * event. It is recommended to store detach handles from any DOM - * subscriptions to make for easy cleanup in the detach - * method. Typically these handles are added to the sub - * object. Also for SyntheticEvents that leverage a single DOM - * subscription under the hood, it is recommended to pass the DOM event - * object to notifier.fire(e). (The event name on the - * object will be updated). - * - * @method on - * @param node {Node} the node the subscription is being applied to - * @param sub {Subscription} the object to track this subscription - * @param notifier {SyntheticEvent.Notifier} call notifier.fire(..) to - * trigger the execution of the subscribers - */ - on: noop, - - /** - *

Implementers SHOULD provide this method definition.

- * - *

Implementation logic for detaching subscriptions done via - * node.on(type, fn). This function should clean up any - * subscriptions made in the on() phase.

- * - * @method detach - * @param node {Node} the node the subscription was applied to - * @param sub {Subscription} the object tracking this subscription - * @param notifier {SyntheticEvent.Notifier} the Notifier used to - * trigger the execution of the subscribers - */ - detach: noop, - - /** - *

Implementers SHOULD provide this method definition.

- * - *

Implementation logic for subscriptions done via - * node.delegate(type, fn, filter) or - * Y.delegate(type, fn, container, filter). Like with - * on() above, this function should monitor the environment - * for the event being fired, and trigger subscription execution by - * calling notifier.fire(e).

- * - *

This function receives a fourth argument, which is the filter - * used to identify which Node's are of interest to the subscription. - * The filter will be either a boolean function that accepts a target - * Node for each hierarchy level as the event bubbles, or a selector - * string. To translate selector strings into filter functions, use - * Y.delegate.compileFilter(filter).

- * - * @method delegate - * @param node {Node} the node the subscription is being applied to - * @param sub {Subscription} the object to track this subscription - * @param notifier {SyntheticEvent.Notifier} call notifier.fire(..) to - * trigger the execution of the subscribers - * @param filter {String|Function} Selector string or function that - * accepts an event object and returns null, a Node, or an - * array of Nodes matching the criteria for processing. - * @since 3.2.0 - */ - delegate : noop, - - /** - *

Implementers SHOULD provide this method definition.

- * - *

Implementation logic for detaching subscriptions done via - * node.delegate(type, fn, filter) or - * Y.delegate(type, fn, container, filter). This function - * should clean up any subscriptions made in the - * delegate() phase.

- * - * @method detachDelegate - * @param node {Node} the node the subscription was applied to - * @param sub {Subscription} the object tracking this subscription - * @param notifier {SyntheticEvent.Notifier} the Notifier used to - * trigger the execution of the subscribers - * @param filter {String|Function} Selector string or function that - * accepts an event object and returns null, a Node, or an - * array of Nodes matching the criteria for processing. - * @since 3.2.0 - */ - detachDelegate : noop, - - /** - * Sets up the boilerplate for detaching the event and facilitating the - * execution of subscriber callbacks. - * - * @method _on - * @param args {Array} array of arguments passed to - * Y.on(...) or Y.delegate(...) - * @param delegate {Boolean} true if called from - * Y.delegate(...) - * @return {EventHandle} the detach handle for this subscription - * @private - * since 3.2.0 - */ - _on: function (args, delegate) { - var handles = [], - originalArgs = args.slice(), - extra = this.processArgs(args, delegate), - selector = args[2], - method = delegate ? 'delegate' : 'on', - nodes, handle; - - // Can't just use Y.all because it doesn't support window (yet?) - nodes = (isString(selector)) ? - query(selector) : - toArray(selector || Y.one(Y.config.win)); - - if (!nodes.length && isString(selector)) { - handle = Y.on('available', function () { - Y.mix(handle, Y[method].apply(Y, originalArgs), true); - }, selector); - - return handle; - } - - Y.Array.each(nodes, function (node) { - var subArgs = args.slice(), - filter; - - node = Y.one(node); - - if (node) { - if (delegate) { - filter = subArgs.splice(3, 1)[0]; - } - - // (type, fn, el, thisObj, ...) => (fn, thisObj, ...) - subArgs.splice(0, 4, subArgs[1], subArgs[3]); - - if (!this.preventDups || - !this.getSubs(node, args, null, true)) - { - handles.push(this._subscribe(node, method, subArgs, extra, filter)); - } - } - }, this); - - return (handles.length === 1) ? - handles[0] : - new Y.EventHandle(handles); - }, - - /** - * Creates a new Notifier object for use by this event's - * on(...) or delegate(...) implementation - * and register the custom event proxy in the DOM system for cleanup. - * - * @method _subscribe - * @param node {Node} the Node hosting the event - * @param method {String} "on" or "delegate" - * @param args {Array} the subscription arguments passed to either - * Y.on(...) or Y.delegate(...) - * after running through processArgs(args) to - * normalize the argument signature - * @param extra {any} Extra data parsed from - * processArgs(args) - * @param filter {String|Function} the selector string or function - * filter passed to Y.delegate(...) (not - * present when called from Y.on(...)) - * @return {EventHandle} - * @private - * @since 3.2.0 - */ - _subscribe: function (node, method, args, extra, filter) { - var dispatcher = new Y.CustomEvent(this.type, this.publishConfig), - handle = dispatcher.on.apply(dispatcher, args), - notifier = new Notifier(handle, this.emitFacade), - registry = SyntheticEvent.getRegistry(node, this.type, true), - sub = handle.sub; - - sub.node = node; - sub.filter = filter; - if (extra) { - this.applyArgExtras(extra, sub); - } - - Y.mix(dispatcher, { - eventDef : this, - notifier : notifier, - host : node, // I forget what this is for - currentTarget: node, // for generating facades - target : node, // for generating facades - el : node._node, // For category detach - - _delete : SyntheticEvent._deleteSub - }, true); - - handle.notifier = notifier; - - registry.register(handle); - - // Call the implementation's "on" or "delegate" method - this[method](node, sub, notifier, filter); - - return handle; - }, - - /** - *

Implementers MAY provide this method definition.

- * - *

Implement this function if you want extra data extracted during - * processArgs to be propagated to subscriptions on a per-node basis. - * That is to say, if you call Y.on('xyz', fn, xtra, 'div') - * the data returned from processArgs will be shared - * across the subscription objects for all the divs. If you want each - * subscription to receive unique information, do that processing - * here.

- * - *

The default implementation adds the data extracted by processArgs - * to the subscription object as sub._extra.

- * - * @method applyArgExtras - * @param extra {any} Any extra data extracted from processArgs - * @param sub {Subscription} the individual subscription - */ - applyArgExtras: function (extra, sub) { - sub._extra = extra; - }, - - /** - * Removes the subscription(s) from the internal subscription dispatch - * mechanism. See SyntheticEvent._deleteSub. - * - * @method _detach - * @param args {Array} The arguments passed to - * node.detach(...) - * @private - * @since 3.2.0 - */ - _detach: function (args) { - // Can't use Y.all because it doesn't support window (yet?) - // TODO: Does Y.all support window now? - var target = args[2], - els = (isString(target)) ? - query(target) : toArray(target), - node, i, len, handles, j; - - // (type, fn, el, context, filter?) => (type, fn, context, filter?) - args.splice(2, 1); - - for (i = 0, len = els.length; i < len; ++i) { - node = Y.one(els[i]); - - if (node) { - handles = this.getSubs(node, args); - - if (handles) { - for (j = handles.length - 1; j >= 0; --j) { - handles[j].detach(); - } - } - } - } - }, - - /** - * Returns the detach handles of subscriptions on a node that satisfy a - * search/filter function. By default, the filter used is the - * subMatch method. - * - * @method getSubs - * @param node {Node} the node hosting the event - * @param args {Array} the array of original subscription args passed - * to Y.on(...) (before - * processArgs - * @param filter {Function} function used to identify a subscription - * for inclusion in the returned array - * @param first {Boolean} stop after the first match (used to check for - * duplicate subscriptions) - * @return {EventHandle[]} detach handles for the matching subscriptions - */ - getSubs: function (node, args, filter, first) { - var registry = SyntheticEvent.getRegistry(node, this.type), - handles = [], - allHandles, i, len, handle; - - if (registry) { - allHandles = registry.handles; - - if (!filter) { - filter = this.subMatch; - } - - for (i = 0, len = allHandles.length; i < len; ++i) { - handle = allHandles[i]; - if (filter.call(this, handle.sub, args)) { - if (first) { - return handle; - } else { - handles.push(allHandles[i]); - } - } - } - } - - return handles.length && handles; - }, - - /** - *

Implementers MAY override this to define what constitutes a - * "same" subscription. Override implementations should - * consider the lack of a comparator as a match, so calling - * getSubs() with no arguments will return all subs.

- * - *

Compares a set of subscription arguments against a Subscription - * object to determine if they match. The default implementation - * compares the callback function against the second argument passed to - * Y.on(...) or node.detach(...) etc.

- * - * @method subMatch - * @param sub {Subscription} the existing subscription - * @param args {Array} the calling arguments passed to - * Y.on(...) etc. - * @return {Boolean} true if the sub can be described by the args - * present - * @since 3.2.0 - */ - subMatch: function (sub, args) { - // Default detach cares only about the callback matching - return !args[1] || sub.fn === args[1]; - } - } -}, true); - -Y.SyntheticEvent = SyntheticEvent; - -/** - *

Defines a new event in the DOM event system. Implementers are - * responsible for monitoring for a scenario whereby the event is fired. A - * notifier object is provided to the functions identified below. When the - * criteria defining the event are met, call notifier.fire( [args] ); to - * execute event subscribers.

- * - *

The first parameter is the name of the event. The second parameter is a - * configuration object which define the behavior of the event system when the - * new event is subscribed to or detached from. The methods that should be - * defined in this configuration object are on, - * detach, delegate, and detachDelegate. - * You are free to define any other methods or properties needed to define your - * event. Be aware, however, that since the object is used to subclass - * SyntheticEvent, you should avoid method names used by SyntheticEvent unless - * your intention is to override the default behavior.

- * - *

This is a list of properties and methods that you can or should specify - * in the configuration object:

- * - *
- *
on
- *
function (node, subscription, notifier) The - * implementation logic for subscription. Any special setup you need to - * do to create the environment for the event being fired--E.g. native - * DOM event subscriptions. Store subscription related objects and - * state on the subscription object. When the - * criteria have been met to fire the synthetic event, call - * notifier.fire(e). See Notifier's fire() - * method for details about what to pass as parameters.
- * - *
detach
- *
function (node, subscription, notifier) The - * implementation logic for cleaning up a detached subscription. E.g. - * detach any DOM subscriptions added in on.
- * - *
delegate
- *
function (node, subscription, notifier, filter) The - * implementation logic for subscription via Y.delegate or - * node.delegate. The filter is typically either a selector - * string or a function. You can use - * Y.delegate.compileFilter(selectorString) to create a - * filter function from a selector string if needed. The filter function - * expects an event object as input and should output either null, a - * matching Node, or an array of matching Nodes. Otherwise, this acts - * like on DOM event subscriptions. Store subscription - * related objects and information on the subscription - * object. When the criteria have been met to fire the synthetic event, - * call notifier.fire(e) as noted above.
- * - *
detachDelegate
- *
function (node, subscription, notifier) The - * implementation logic for cleaning up a detached delegate subscription. - * E.g. detach any DOM delegate subscriptions added in - * delegate.
- * - *
publishConfig
- *
(Object) The configuration object that will be used to instantiate - * the underlying CustomEvent. See Notifier's fire method - * for details.
- * - *
processArgs
- *

function (argArray, fromDelegate) Optional method - * to extract any additional arguments from the subscription - * signature. Using this allows on or - * delegate signatures like - * node.on("hover", overCallback, - * outCallback).

- *

When processing an atypical argument signature, make sure the - * args array is returned to the normal signature before returning - * from the function. For example, in the "hover" example - * above, the outCallback needs to be spliced - * out of the array. The expected signature of the args array for - * on() subscriptions is:

- *
- *              [type, callback, target, contextOverride, argN...]
- *          
- *

And for delegate():

- *
- *              [type, callback, target, filter, contextOverride, argN...]
- *          
- *

where target is the node the event is being - * subscribed for. You can see these signatures documented for - * Y.on() and Y.delegate() respectively.

- *

Whatever gets returned from the function will be stored on the - * subscription object under - * subscription._extra.

- *
subMatch
- *
- *

function (sub, args) Compares a set of - * subscription arguments against a Subscription object to determine - * if they match. The default implementation compares the callback - * function against the second argument passed to - * Y.on(...) or node.detach(...) etc.

- *
- *
- * - * @method define - * @param type {String} the name of the event - * @param config {Object} the prototype definition for the new event (see above) - * @param force {Boolean} override an existing event (use with caution) - * @return {SyntheticEvent} the subclass implementation instance created to - * handle event subscriptions of this type - * @static - * @for Event - * @since 3.1.0 - * @in event-synthetic - */ -Y.Event.define = function (type, config, force) { - var eventDef, Impl, synth; - - if (type && type.type) { - eventDef = type; - force = config; - } else if (config) { - eventDef = Y.merge({ type: type }, config); - } - - if (eventDef) { - if (force || !Y.Node.DOM_EVENTS[eventDef.type]) { - Impl = function () { - SyntheticEvent.apply(this, arguments); - }; - Y.extend(Impl, SyntheticEvent, eventDef); - synth = new Impl(); - - type = synth.type; - - Y.Node.DOM_EVENTS[type] = Y.Env.evt.plugins[type] = { - eventDef: synth, - - on: function () { - return synth._on(toArray(arguments)); - }, - - delegate: function () { - return synth._on(toArray(arguments), true); - }, - - detach: function () { - return synth._detach(toArray(arguments)); - } - }; - - } - } else if (isString(type) || isArray(type)) { - Y.Array.each(toArray(type), function (t) { - Y.Node.DOM_EVENTS[t] = 1; - }); - } - - return synth; -}; - - -}, '3.16.0', {"requires": ["node-base", "event-custom-complex"]}); - -define("yui-base", (function (global) { - return function () { - var ret, fn; - return ret || global.YUI; - }; -}(this))); - -/* -YUI 3.16.0 (build 76f0e08) -Copyright 2014 Yahoo! Inc. All rights reserved. -Licensed under the BSD License. -http://yuilibrary.com/license/ -*/ - -YUI.add('loader-base', function (Y, NAME) { - -/** - * The YUI loader core - * @module loader - * @submodule loader-base - */ - -(function() { - var VERSION = Y.version, - BUILD = '/build/', - ROOT = VERSION + '/', - CDN_BASE = Y.Env.base, - GALLERY_VERSION = 'gallery-2014.04.02-20-01', - TNT = '2in3', - TNT_VERSION = '4', - YUI2_VERSION = '2.9.0', - COMBO_BASE = CDN_BASE + 'combo?', - META = { - version: VERSION, - root: ROOT, - base: Y.Env.base, - comboBase: COMBO_BASE, - skin: { - defaultSkin: 'sam', - base: 'assets/skins/', - path: 'skin.css', - after: [ - 'cssreset', - 'cssfonts', - 'cssgrids', - 'cssbase', - 'cssreset-context', - 'cssfonts-context' - ] - }, - groups: {}, - patterns: {} - }, - groups = META.groups, - yui2Update = function(tnt, yui2, config) { - var root = TNT + '.' + - (tnt || TNT_VERSION) + '/' + - (yui2 || YUI2_VERSION) + BUILD, - base = (config && config.base) ? config.base : CDN_BASE, - combo = (config && config.comboBase) ? config.comboBase : COMBO_BASE; - - groups.yui2.base = base + root; - groups.yui2.root = root; - groups.yui2.comboBase = combo; - }, - galleryUpdate = function(tag, config) { - var root = (tag || GALLERY_VERSION) + BUILD, - base = (config && config.base) ? config.base : CDN_BASE, - combo = (config && config.comboBase) ? config.comboBase : COMBO_BASE; - - groups.gallery.base = base + root; - groups.gallery.root = root; - groups.gallery.comboBase = combo; - }; - - - groups[VERSION] = {}; - - groups.gallery = { - ext: false, - combine: true, - comboBase: COMBO_BASE, - update: galleryUpdate, - patterns: { - 'gallery-': {}, - 'lang/gallery-': {}, - 'gallerycss-': { - type: 'css' - } - } - }; - - groups.yui2 = { - combine: true, - ext: false, - comboBase: COMBO_BASE, - update: yui2Update, - patterns: { - 'yui2-': { - configFn: function(me) { - if (/-skin|reset|fonts|grids|base/.test(me.name)) { - me.type = 'css'; - me.path = me.path.replace(/\.js/, '.css'); - // this makes skins in builds earlier than - // 2.6.0 work as long as combine is false - me.path = me.path.replace(/\/yui2-skin/, - '/assets/skins/sam/yui2-skin'); - } - } - } - } - }; - - galleryUpdate(); - yui2Update(); - - if (YUI.Env[VERSION]) { - Y.mix(META, YUI.Env[VERSION], false, [ - 'modules', - 'groups', - 'skin' - ], 0, true); - } - - YUI.Env[VERSION] = META; -}()); -/*jslint forin: true, maxlen: 350 */ - -/** - * Loader dynamically loads script and css files. It includes the dependency - * information for the version of the library in use, and will automatically pull in - * dependencies for the modules requested. It can also load the - * files from the Yahoo! CDN, and it can utilize the combo service provided on - * this network to reduce the number of http connections required to download - * YUI files. - * - * @module loader - * @main loader - * @submodule loader-base - */ - -var NOT_FOUND = {}, - NO_REQUIREMENTS = [], - MAX_URL_LENGTH = 1024, - GLOBAL_ENV = YUI.Env, - GLOBAL_LOADED = GLOBAL_ENV._loaded, - CSS = 'css', - JS = 'js', - INTL = 'intl', - DEFAULT_SKIN = 'sam', - VERSION = Y.version, - ROOT_LANG = '', - YObject = Y.Object, - oeach = YObject.each, - yArray = Y.Array, - _queue = GLOBAL_ENV._loaderQueue, - META = GLOBAL_ENV[VERSION], - SKIN_PREFIX = 'skin-', - L = Y.Lang, - ON_PAGE = GLOBAL_ENV.mods, - modulekey, - _path = function(dir, file, type, nomin) { - var path = dir + '/' + file; - if (!nomin) { - path += '-min'; - } - path += '.' + (type || CSS); - - return path; - }; - - - if (!YUI.Env._cssLoaded) { - YUI.Env._cssLoaded = {}; - } - - -/** - * The component metadata is stored in Y.Env.meta. - * Part of the loader module. - * @property meta - * @for YUI - */ -Y.Env.meta = META; - -/** - * Loader dynamically loads script and css files. It includes the dependency - * info for the version of the library in use, and will automatically pull in - * dependencies for the modules requested. It can load the - * files from the Yahoo! CDN, and it can utilize the combo service provided on - * this network to reduce the number of http connections required to download - * YUI files. You can also specify an external, custom combo service to host - * your modules as well. - - var Y = YUI(); - var loader = new Y.Loader({ - filter: 'debug', - base: '../../', - root: 'build/', - combine: true, - require: ['node', 'dd', 'console'] - }); - var out = loader.resolve(true); - - * If the Loader needs to be patched before it is used for the first time, it - * should be done through the `doBeforeLoader` hook. Simply make the patch - * available via configuration before YUI is loaded: - - YUI_config = YUI_config || {}; - YUI_config.doBeforeLoader = function (config) { - var resolve = this.context.Loader.prototype.resolve; - this.context.Loader.prototype.resolve = function () { - // do something here - return resolve.apply(this, arguments); - }; - }; - - * @constructor - * @class Loader - * @param {Object} config an optional set of configuration options. - * @param {String} config.base The base dir which to fetch this module from - * @param {String} config.comboBase The Combo service base path. Ex: `http://yui.yahooapis.com/combo?` - * @param {String} config.root The root path to prepend to module names for the combo service. Ex: `2.5.2/build/` - * @param {String|Object} config.filter A filter to apply to result urls. See filter property - * @param {Object} config.filters Per-component filter specification. If specified for a given component, this overrides the filter config. - * @param {Boolean} config.combine Use a combo service to reduce the number of http connections required to load your dependencies - * @param {Boolean} [config.async=true] Fetch files in async - * @param {Array} config.ignore: A list of modules that should never be dynamically loaded - * @param {Array} config.force A list of modules that should always be loaded when required, even if already present on the page - * @param {HTMLElement|String} config.insertBefore Node or id for a node that should be used as the insertion point for new nodes - * @param {Object} config.jsAttributes Object literal containing attributes to add to script nodes - * @param {Object} config.cssAttributes Object literal containing attributes to add to link nodes - * @param {Number} config.timeout The number of milliseconds before a timeout occurs when dynamically loading nodes. If not set, there is no timeout - * @param {Object} config.context Execution context for all callbacks - * @param {Function} config.onSuccess Callback for the 'success' event - * @param {Function} config.onFailure Callback for the 'failure' event - * @param {Function} config.onTimeout Callback for the 'timeout' event - * @param {Function} config.onProgress Callback executed each time a script or css file is loaded - * @param {Object} config.modules A list of module definitions. See Loader.addModule for the supported module metadata - * @param {Object} config.groups A list of group definitions. Each group can contain specific definitions for `base`, `comboBase`, `combine`, and accepts a list of `modules`. - * @param {String} config.2in3 The version of the YUI 2 in 3 wrapper to use. The intrinsic support for YUI 2 modules in YUI 3 relies on versions of the YUI 2 components inside YUI 3 module wrappers. These wrappers change over time to accomodate the issues that arise from running YUI 2 in a YUI 3 sandbox. - * @param {String} config.yui2 When using the 2in3 project, you can select the version of YUI 2 to use. Valid values are `2.2.2`, `2.3.1`, `2.4.1`, `2.5.2`, `2.6.0`, `2.7.0`, `2.8.0`, `2.8.1` and `2.9.0` [default] -- plus all versions of YUI 2 going forward. - * @param {Function} config.doBeforeLoader An optional hook that allows for the patching of the loader instance. The `Y` instance is available as `this.context` and the only argument to the function is the Loader configuration object. - */ -Y.Loader = function(o) { - - var self = this; - - //Catch no config passed. - o = o || {}; - - modulekey = META.md5; - - /** - * Internal callback to handle multiple internal insert() calls - * so that css is inserted prior to js - * @property _internalCallback - * @private - */ - // self._internalCallback = null; - - /** - * Callback that will be executed when the loader is finished - * with an insert - * @method onSuccess - * @type function - */ - // self.onSuccess = null; - - /** - * Callback that will be executed if there is a failure - * @method onFailure - * @type function - */ - // self.onFailure = null; - - /** - * Callback executed each time a script or css file is loaded - * @method onProgress - * @type function - */ - // self.onProgress = null; - - /** - * Callback that will be executed if a timeout occurs - * @method onTimeout - * @type function - */ - // self.onTimeout = null; - - /** - * The execution context for all callbacks - * @property context - * @default {YUI} the YUI instance - */ - self.context = Y; - - // Hook that allows the patching of loader - if (o.doBeforeLoader) { - o.doBeforeLoader.apply(self, arguments); - } - - /** - * Data that is passed to all callbacks - * @property data - */ - // self.data = null; - - /** - * Node reference or id where new nodes should be inserted before - * @property insertBefore - * @type string|HTMLElement - */ - // self.insertBefore = null; - - /** - * The charset attribute for inserted nodes - * @property charset - * @type string - * @deprecated , use cssAttributes or jsAttributes. - */ - // self.charset = null; - - /** - * An object literal containing attributes to add to link nodes - * @property cssAttributes - * @type object - */ - // self.cssAttributes = null; - - /** - * An object literal containing attributes to add to script nodes - * @property jsAttributes - * @type object - */ - // self.jsAttributes = null; - - /** - * The base directory. - * @property base - * @type string - * @default http://yui.yahooapis.com/[YUI VERSION]/build/ - */ - self.base = Y.Env.meta.base + Y.Env.meta.root; - - /** - * Base path for the combo service - * @property comboBase - * @type string - * @default http://yui.yahooapis.com/combo? - */ - self.comboBase = Y.Env.meta.comboBase; - - /* - * Base path for language packs. - */ - // self.langBase = Y.Env.meta.langBase; - // self.lang = ""; - - /** - * If configured, the loader will attempt to use the combo - * service for YUI resources and configured external resources. - * @property combine - * @type boolean - * @default true if a base dir isn't in the config - */ - self.combine = o.base && - (o.base.indexOf(self.comboBase.substr(0, 20)) > -1); - - /** - * The default seperator to use between files in a combo URL - * @property comboSep - * @type {String} - * @default Ampersand - */ - self.comboSep = '&'; - /** - * Max url length for combo urls. The default is 1024. This is the URL - * limit for the Yahoo! hosted combo servers. If consuming - * a different combo service that has a different URL limit - * it is possible to override this default by supplying - * the maxURLLength config option. The config option will - * only take effect if lower than the default. - * - * @property maxURLLength - * @type int - */ - self.maxURLLength = MAX_URL_LENGTH; - - /** - * Ignore modules registered on the YUI global - * @property ignoreRegistered - * @default false - */ - self.ignoreRegistered = o.ignoreRegistered; - - /** - * Root path to prepend to module path for the combo - * service - * @property root - * @type string - * @default [YUI VERSION]/build/ - */ - self.root = Y.Env.meta.root; - - /** - * Timeout value in milliseconds. If set, self value will be used by - * the get utility. the timeout event will fire if - * a timeout occurs. - * @property timeout - * @type int - */ - self.timeout = 0; - - /** - * A list of modules that should not be loaded, even if - * they turn up in the dependency tree - * @property ignore - * @type string[] - */ - // self.ignore = null; - - /** - * A list of modules that should always be loaded, even - * if they have already been inserted into the page. - * @property force - * @type string[] - */ - // self.force = null; - - self.forceMap = {}; - - /** - * Should we allow rollups - * @property allowRollup - * @type boolean - * @default false - */ - self.allowRollup = false; - - /** - * A filter to apply to result urls. This filter will modify the default - * path for all modules. The default path for the YUI library is the - * minified version of the files (e.g., event-min.js). The filter property - * can be a predefined filter or a custom filter. The valid predefined - * filters are: - *
- *
DEBUG
- *
Selects the debug versions of the library (e.g., event-debug.js). - * This option will automatically include the Logger widget
- *
RAW
- *
Selects the non-minified version of the library (e.g., event.js). - *
- *
- * You can also define a custom filter, which must be an object literal - * containing a search expression and a replace string: - * - * myFilter: { - * 'searchExp': "-min\\.js", - * 'replaceStr': "-debug.js" - * } - * - * @property filter - * @type string| {searchExp: string, replaceStr: string} - */ - // self.filter = null; - - /** - * per-component filter specification. If specified for a given - * component, this overrides the filter config. - * @property filters - * @type object - */ - self.filters = {}; - - /** - * The list of requested modules - * @property required - * @type {string: boolean} - */ - self.required = {}; - - /** - * If a module name is predefined when requested, it is checked againsts - * the patterns provided in this property. If there is a match, the - * module is added with the default configuration. - * - * At the moment only supporting module prefixes, but anticipate - * supporting at least regular expressions. - * @property patterns - * @type Object - */ - // self.patterns = Y.merge(Y.Env.meta.patterns); - self.patterns = {}; - - /** - * Internal loader instance metadata. Use accessor `getModuleInfo()` instead. - */ - self.moduleInfo = {}; - - self.groups = Y.merge(Y.Env.meta.groups); - - /** - * Provides the information used to skin the skinnable components. - * The following skin definition would result in 'skin1' and 'skin2' - * being loaded for calendar (if calendar was requested), and - * 'sam' for all other skinnable components: - * - * skin: { - * // The default skin, which is automatically applied if not - * // overriden by a component-specific skin definition. - * // Change this in to apply a different skin globally - * defaultSkin: 'sam', - * - * // This is combined with the loader base property to get - * // the default root directory for a skin. ex: - * // http://yui.yahooapis.com/2.3.0/build/assets/skins/sam/ - * base: 'assets/skins/', - * - * // Any component-specific overrides can be specified here, - * // making it possible to load different skins for different - * // components. It is possible to load more than one skin - * // for a given component as well. - * overrides: { - * calendar: ['skin1', 'skin2'] - * } - * } - * @property skin - * @type {Object} - */ - self.skin = Y.merge(Y.Env.meta.skin); - - /* - * Map of conditional modules - * @since 3.2.0 - */ - self.conditions = {}; - - // map of modules with a hash of modules that meet the requirement - // self.provides = {}; - - self.config = o; - self._internal = true; - - self._populateConditionsCache(); - - /** - * Set when beginning to compute the dependency tree. - * Composed of what YUI reports to be loaded combined - * with what has been loaded by any instance on the page - * with the version number specified in the metadata. - * @property loaded - * @type {string: boolean} - */ - self.loaded = GLOBAL_LOADED[VERSION]; - - - /** - * Should Loader fetch scripts in `async`, defaults to `true` - * @property async - */ - - self.async = true; - - self._inspectPage(); - - self._internal = false; - - self._config(o); - - self.forceMap = (self.force) ? Y.Array.hash(self.force) : {}; - - self.testresults = null; - - if (Y.config.tests) { - self.testresults = Y.config.tests; - } - - /** - * List of rollup files found in the library metadata - * @property rollups - */ - // self.rollups = null; - - /** - * Whether or not to load optional dependencies for - * the requested modules - * @property loadOptional - * @type boolean - * @default false - */ - // self.loadOptional = false; - - /** - * All of the derived dependencies in sorted order, which - * will be populated when either calculate() or insert() - * is called - * @property sorted - * @type string[] - */ - self.sorted = []; - - /* - * A list of modules to attach to the YUI instance when complete. - * If not supplied, the sorted list of dependencies are applied. - * @property attaching - */ - // self.attaching = null; - - /** - * Flag to indicate the dependency tree needs to be recomputed - * if insert is called again. - * @property dirty - * @type boolean - * @default true - */ - self.dirty = true; - - /** - * List of modules inserted by the utility - * @property inserted - * @type {string: boolean} - */ - self.inserted = {}; - - /** - * List of skipped modules during insert() because the module - * was not defined - * @property skipped - */ - self.skipped = {}; - - // Y.on('yui:load', self.loadNext, self); - - self.tested = {}; - - /* - * Cached sorted calculate results - * @property results - * @since 3.2.0 - */ - //self.results = {}; - - if (self.ignoreRegistered) { - //Clear inpage already processed modules. - self._resetModules(); - } - -}; - -Y.Loader.prototype = { - /** - * Gets the module info from the local moduleInfo hash, or from the - * default metadata and populate the local moduleInfo hash. - * @method getModuleInfo - * @param {string} name of the module - * @public - */ - getModuleInfo: function(name) { - - var m = this.moduleInfo[name], - rawMetaModules, globalRenderedMods, internal, v; - - if (m) { - return m; - } - - rawMetaModules = META.modules; - globalRenderedMods = GLOBAL_ENV._renderedMods; - internal = this._internal; - - /* - The logic here is: - - - if the `moduleInfo[name]` is avilable, - then short circuit - - otherwise, if the module is in the globalCache (cross Y instance), - then port it from the global registry into `moduleInfo[name]` - - otherwise, if the module has raw metadata (from meta modules) - then add it to the global registry and to `moduleInfo[name]` - - */ - if (globalRenderedMods && globalRenderedMods.hasOwnProperty(name) && !this.ignoreRegistered) { - this.moduleInfo[name] = Y.merge(globalRenderedMods[name]); - } else { - if (rawMetaModules.hasOwnProperty(name)) { - this._internal = true; // making sure that modules from raw data are marked as internal - v = this.addModule(rawMetaModules[name], name); - // Inspect the page for the CSS module and mark it as loaded. - if (v && v.type === CSS) { - if (this.isCSSLoaded(v.name, true)) { - this.loaded[v.name] = true; - } - } - this._internal = internal; - } - } - return this.moduleInfo[name]; - }, - /** - * Expand the names that are aliases to other modules. - * @method _expandAliases - * @param {string[]} list a module name or a list of names to be expanded - * @private - * @return {array} - */ - _expandAliases: function(list) { - var expanded = [], - aliases = YUI.Env.aliases, - i, name; - list = Y.Array(list); - for (i = 0; i < list.length; i += 1) { - name = list[i]; - expanded.push.apply(expanded, aliases[name] ? aliases[name] : [name]); - } - return expanded; - }, - /** - * Populate the conditions cache from raw modules, this is necessary - * because no other module will require a conditional module, instead - * the condition has to be executed and then the module is analyzed - * to be included in the final requirement list. Without this cache - * conditional modules will be simply ignored. - * @method _populateConditionsCache - * @private - */ - _populateConditionsCache: function() { - var rawMetaModules = META.modules, - cache = GLOBAL_ENV._conditions, - i, j, t, trigger; - - // if we have conditions in cache and cache is enabled - // we should port them to this loader instance - if (cache && !this.ignoreRegistered) { - for (i in cache) { - if (cache.hasOwnProperty(i)) { - this.conditions[i] = Y.merge(cache[i]); - } - } - } else { - for (i in rawMetaModules) { - if (rawMetaModules.hasOwnProperty(i) && rawMetaModules[i].condition) { - t = this._expandAliases(rawMetaModules[i].condition.trigger); - for (j = 0; j < t.length; j += 1) { - trigger = t[j]; - this.conditions[trigger] = this.conditions[trigger] || {}; - this.conditions[trigger][rawMetaModules[i].name || i] = rawMetaModules[i].condition; - } - } - } - GLOBAL_ENV._conditions = this.conditions; - } - }, - /** - * Reset modules in the module cache to a pre-processed state so additional - * computations with a different skin or language will work as expected. - * @method _resetModules - * @private - */ - _resetModules: function() { - var self = this, i, o, - mod, name, details; - for (i in self.moduleInfo) { - if (self.moduleInfo.hasOwnProperty(i) && self.moduleInfo[i]) { - mod = self.moduleInfo[i]; - name = mod.name; - details = (YUI.Env.mods[name] ? YUI.Env.mods[name].details : null); - - if (details) { - self.moduleInfo[name]._reset = true; - self.moduleInfo[name].requires = details.requires || []; - self.moduleInfo[name].optional = details.optional || []; - self.moduleInfo[name].supersedes = details.supercedes || []; - } - - if (mod.defaults) { - for (o in mod.defaults) { - if (mod.defaults.hasOwnProperty(o)) { - if (mod[o]) { - mod[o] = mod.defaults[o]; - } - } - } - } - mod.langCache = undefined; - mod.skinCache = undefined; - if (mod.skinnable) { - self._addSkin(self.skin.defaultSkin, mod.name); - } - } - } - }, - /** - Regex that matches a CSS URL. Used to guess the file type when it's not - specified. - - @property REGEX_CSS - @type RegExp - @final - @protected - @since 3.5.0 - **/ - REGEX_CSS: /\.css(?:[?;].*)?$/i, - - /** - * Default filters for raw and debug - * @property FILTER_DEFS - * @type Object - * @final - * @protected - */ - FILTER_DEFS: { - RAW: { - 'searchExp': '-min\\.js', - 'replaceStr': '.js' - }, - DEBUG: { - 'searchExp': '-min\\.js', - 'replaceStr': '-debug.js' - }, - COVERAGE: { - 'searchExp': '-min\\.js', - 'replaceStr': '-coverage.js' - } - }, - /* - * Check the pages meta-data and cache the result. - * @method _inspectPage - * @private - */ - _inspectPage: function() { - var self = this, v, m, req, mr, i; - - for (i in ON_PAGE) { - if (ON_PAGE.hasOwnProperty(i)) { - v = ON_PAGE[i]; - if (v.details) { - m = self.getModuleInfo(v.name); - req = v.details.requires; - mr = m && m.requires; - - if (m) { - if (!m._inspected && req && mr.length !== req.length) { - // console.log('deleting ' + m.name); - delete m.expanded; - } - } else { - m = self.addModule(v.details, i); - } - m._inspected = true; - } - } - } - }, - /* - * returns true if b is not loaded, and is required directly or by means of modules it supersedes. - * @private - * @method _requires - * @param {String} mod1 The first module to compare - * @param {String} mod2 The second module to compare - */ - _requires: function(mod1, mod2) { - - var i, rm, after_map, s, - m = this.getModuleInfo(mod1), - other = this.getModuleInfo(mod2); - - if (!m || !other) { - return false; - } - - rm = m.expanded_map; - after_map = m.after_map; - - // check if this module should be sorted after the other - // do this first to short circut circular deps - if (after_map && (mod2 in after_map)) { - return true; - } - - after_map = other.after_map; - - // and vis-versa - if (after_map && (mod1 in after_map)) { - return false; - } - - // check if this module requires one the other supersedes - s = other.supersedes; - if (s) { - for (i = 0; i < s.length; i++) { - if (this._requires(mod1, s[i])) { - return true; - } - } - } - - s = m.supersedes; - if (s) { - for (i = 0; i < s.length; i++) { - if (this._requires(mod2, s[i])) { - return false; - } - } - } - - // check if this module requires the other directly - // if (r && yArray.indexOf(r, mod2) > -1) { - if (rm && (mod2 in rm)) { - return true; - } - - // external css files should be sorted below yui css - if (m.ext && m.type === CSS && !other.ext && other.type === CSS) { - return true; - } - - return false; - }, - /** - * Apply a new config to the Loader instance - * @method _config - * @private - * @param {Object} o The new configuration - */ - _config: function(o) { - var i, j, val, a, f, group, groupName, self = this, - mods = [], mod, modInfo; - // apply config values - if (o) { - for (i in o) { - if (o.hasOwnProperty(i)) { - val = o[i]; - //TODO This should be a case - if (i === 'require') { - self.require(val); - } else if (i === 'skin') { - //If the config.skin is a string, format to the expected object - if (typeof val === 'string') { - self.skin.defaultSkin = o.skin; - val = { - defaultSkin: val - }; - } - - Y.mix(self.skin, val, true); - } else if (i === 'groups') { - for (j in val) { - if (val.hasOwnProperty(j)) { - groupName = j; - group = val[j]; - self.addGroup(group, groupName); - if (group.aliases) { - for (a in group.aliases) { - if (group.aliases.hasOwnProperty(a)) { - self.addAlias(group.aliases[a], a); - } - } - } - } - } - - } else if (i === 'modules') { - // add a hash of module definitions - for (j in val) { - if (val.hasOwnProperty(j)) { - self.addModule(val[j], j); - } - } - } else if (i === 'aliases') { - for (j in val) { - if (val.hasOwnProperty(j)) { - self.addAlias(val[j], j); - } - } - } else if (i === 'gallery') { - if (this.groups.gallery.update) { - this.groups.gallery.update(val, o); - } - } else if (i === 'yui2' || i === '2in3') { - if (this.groups.yui2.update) { - this.groups.yui2.update(o['2in3'], o.yui2, o); - } - } else { - self[i] = val; - } - } - } - } - - // fix filter - f = self.filter; - - if (L.isString(f)) { - f = f.toUpperCase(); - self.filterName = f; - self.filter = self.FILTER_DEFS[f]; - if (f === 'DEBUG') { - self.require('yui-log', 'dump'); - } - } - - if (self.filterName && self.coverage) { - if (self.filterName === 'COVERAGE' && L.isArray(self.coverage) && self.coverage.length) { - for (i = 0; i < self.coverage.length; i++) { - mod = self.coverage[i]; - modInfo = self.getModuleInfo(mod); - if (modInfo && modInfo.use) { - mods = mods.concat(modInfo.use); - } else { - mods.push(mod); - } - } - self.filters = self.filters || {}; - Y.Array.each(mods, function(mod) { - self.filters[mod] = self.FILTER_DEFS.COVERAGE; - }); - self.filterName = 'RAW'; - self.filter = self.FILTER_DEFS[self.filterName]; - } - } - - }, - - /** - * Returns the skin module name for the specified skin name. If a - * module name is supplied, the returned skin module name is - * specific to the module passed in. - * @method formatSkin - * @param {string} skin the name of the skin. - * @param {string} mod optional: the name of a module to skin. - * @return {string} the full skin module name. - */ - formatSkin: function(skin, mod) { - var s = SKIN_PREFIX + skin; - if (mod) { - s = s + '-' + mod; - } - - return s; - }, - - /** - * Adds the skin def to the module info - * @method _addSkin - * @param {string} skin the name of the skin. - * @param {string} mod the name of the module. - * @param {string} parent parent module if this is a skin of a - * submodule or plugin. - * @return {string} the module name for the skin. - * @private - */ - _addSkin: function(skin, mod, parent) { - var pkg, name, nmod, - sinf = this.skin, - mdef = mod && this.getModuleInfo(mod), - ext = mdef && mdef.ext; - - // Add a module definition for the module-specific skin css - if (mod) { - name = this.formatSkin(skin, mod); - if (!this.getModuleInfo(name)) { - pkg = mdef.pkg || mod; - nmod = { - skin: true, - name: name, - group: mdef.group, - type: 'css', - after: sinf.after, - path: (parent || pkg) + '/' + sinf.base + skin + - '/' + mod + '.css', - ext: ext - }; - if (mdef.base) { - nmod.base = mdef.base; - } - if (mdef.configFn) { - nmod.configFn = mdef.configFn; - } - this.addModule(nmod, name); - - } - } - - return name; - }, - /** - * Adds an alias module to the system - * @method addAlias - * @param {Array} use An array of modules that makes up this alias - * @param {String} name The name of the alias - * @example - * var loader = new Y.Loader({}); - * loader.addAlias([ 'node', 'yql' ], 'davglass'); - * loader.require(['davglass']); - * var out = loader.resolve(true); - * - * //out.js will contain Node and YQL modules - */ - addAlias: function(use, name) { - YUI.Env.aliases[name] = use; - this.addModule({ - name: name, - use: use - }); - }, - /** - * Add a new module group - * @method addGroup - * @param {Object} config An object containing the group configuration data - * @param {String} config.name required, the group name - * @param {String} config.base The base directory for this module group - * @param {String} config.root The root path to add to each combo resource path - * @param {Boolean} config.combine Should the request be combined - * @param {String} config.comboBase Combo service base path - * @param {Object} config.modules The group of modules - * @param {String} name the group name. - * @example - * var loader = new Y.Loader({}); - * loader.addGroup({ - * name: 'davglass', - * combine: true, - * comboBase: '/combo?', - * root: '', - * modules: { - * //Module List here - * } - * }, 'davglass'); - */ - addGroup: function(o, name) { - var mods = o.modules, - self = this, i, v; - - name = name || o.name; - o.name = name; - self.groups[name] = o; - - if (o.patterns) { - for (i in o.patterns) { - if (o.patterns.hasOwnProperty(i)) { - o.patterns[i].group = name; - self.patterns[i] = o.patterns[i]; - } - } - } - - if (mods) { - for (i in mods) { - if (mods.hasOwnProperty(i)) { - v = mods[i]; - if (typeof v === 'string') { - v = { name: i, fullpath: v }; - } - v.group = name; - self.addModule(v, i); - } - } - } - }, - - /** - * Add a new module to the component metadata. - * @method addModule - * @param {Object} config An object containing the module data. - * @param {String} config.name Required, the component name - * @param {String} config.type Required, the component type (js or css) - * @param {String} config.path Required, the path to the script from `base` - * @param {Array} config.requires Array of modules required by this component - * @param {Array} [config.optional] Array of optional modules for this component - * @param {Array} [config.supersedes] Array of the modules this component replaces - * @param {Array} [config.after] Array of modules the components which, if present, should be sorted above this one - * @param {Object} [config.after_map] Faster alternative to 'after' -- supply a hash instead of an array - * @param {Number} [config.rollup] The number of superseded modules required for automatic rollup - * @param {String} [config.fullpath] If `fullpath` is specified, this is used instead of the configured `base + path` - * @param {Boolean} [config.skinnable] Flag to determine if skin assets should automatically be pulled in - * @param {Object} [config.submodules] Hash of submodules - * @param {String} [config.group] The group the module belongs to -- this is set automatically when it is added as part of a group configuration. - * @param {Array} [config.lang] Array of BCP 47 language tags of languages for which this module has localized resource bundles, e.g., `["en-GB", "zh-Hans-CN"]` - * @param {Object} [config.condition] Specifies that the module should be loaded automatically if a condition is met. This is an object with up to four fields: - * @param {String} [config.condition.trigger] The name of a module that can trigger the auto-load - * @param {Function} [config.condition.test] A function that returns true when the module is to be loaded. - * @param {String} [config.condition.ua] The UA name of Y.UA object that returns true when the module is to be loaded. e.g., `"ie"`, `"nodejs"`. - * @param {String} [config.condition.when] Specifies the load order of the conditional module - * with regard to the position of the trigger module. - * This should be one of three values: `before`, `after`, or `instead`. The default is `after`. - * @param {Object} [config.testresults] A hash of test results from `Y.Features.all()` - * @param {Function} [config.configFn] A function to exectute when configuring this module - * @param {Object} config.configFn.mod The module config, modifying this object will modify it's config. Returning false will delete the module's config. - * @param {String} [name] The module name, required if not in the module data. - * @return {Object} the module definition or null if the object passed in did not provide all required attributes. - */ - addModule: function(o, name) { - name = name || o.name; - - if (typeof o === 'string') { - o = { name: name, fullpath: o }; - } - - - var subs, i, l, t, sup, s, smod, plugins, plug, - j, langs, packName, supName, flatSup, flatLang, lang, ret, - overrides, skinname, when, g, p, - modInfo = this.moduleInfo[name], - conditions = this.conditions, trigger; - - //Only merge this data if the temp flag is set - //from an earlier pass from a pattern or else - //an override module (YUI_config) can not be used to - //replace a default module. - if (modInfo && modInfo.temp) { - //This catches temp modules loaded via a pattern - // The module will be added twice, once from the pattern and - // Once from the actual add call, this ensures that properties - // that were added to the module the first time around (group: gallery) - // are also added the second time around too. - o = Y.merge(modInfo, o); - } - - o.name = name; - - if (!o || !o.name) { - return null; - } - - if (!o.type) { - //Always assume it's javascript unless the CSS pattern is matched. - o.type = JS; - p = o.path || o.fullpath; - if (p && this.REGEX_CSS.test(p)) { - o.type = CSS; - } - } - - if (!o.path && !o.fullpath) { - o.path = _path(name, name, o.type); - } - o.supersedes = o.supersedes || o.use; - - o.ext = ('ext' in o) ? o.ext : (this._internal) ? false : true; - - // Handle submodule logic - subs = o.submodules; - - this.moduleInfo[name] = o; - - o.requires = o.requires || []; - - /* - Only allowing the cascade of requires information, since - optional and supersedes are far more fine grained than - a blanket requires is. - */ - if (this.requires) { - for (i = 0; i < this.requires.length; i++) { - o.requires.push(this.requires[i]); - } - } - if (o.group && this.groups && this.groups[o.group]) { - g = this.groups[o.group]; - if (g.requires) { - for (i = 0; i < g.requires.length; i++) { - o.requires.push(g.requires[i]); - } - } - } - - - if (!o.defaults) { - o.defaults = { - requires: o.requires ? [].concat(o.requires) : null, - supersedes: o.supersedes ? [].concat(o.supersedes) : null, - optional: o.optional ? [].concat(o.optional) : null - }; - } - - if (o.skinnable && o.ext && o.temp) { - skinname = this._addSkin(this.skin.defaultSkin, name); - o.requires.unshift(skinname); - } - - if (o.requires.length) { - o.requires = this.filterRequires(o.requires) || []; - } - - if (!o.langPack && o.lang) { - langs = yArray(o.lang); - for (j = 0; j < langs.length; j++) { - lang = langs[j]; - packName = this.getLangPackName(lang, name); - smod = this.getModuleInfo(packName); - if (!smod) { - smod = this._addLangPack(lang, o, packName); - } - } - } - - - if (subs) { - sup = o.supersedes || []; - l = 0; - - for (i in subs) { - if (subs.hasOwnProperty(i)) { - s = subs[i]; - - s.path = s.path || _path(name, i, o.type); - s.pkg = name; - s.group = o.group; - - if (s.supersedes) { - sup = sup.concat(s.supersedes); - } - - smod = this.addModule(s, i); - sup.push(i); - - if (smod.skinnable) { - o.skinnable = true; - overrides = this.skin.overrides; - if (overrides && overrides[i]) { - for (j = 0; j < overrides[i].length; j++) { - skinname = this._addSkin(overrides[i][j], - i, name); - sup.push(skinname); - } - } - skinname = this._addSkin(this.skin.defaultSkin, - i, name); - sup.push(skinname); - } - - // looks like we are expected to work out the metadata - // for the parent module language packs from what is - // specified in the child modules. - if (s.lang && s.lang.length) { - - langs = yArray(s.lang); - for (j = 0; j < langs.length; j++) { - lang = langs[j]; - packName = this.getLangPackName(lang, name); - supName = this.getLangPackName(lang, i); - smod = this.getModuleInfo(packName); - - if (!smod) { - smod = this._addLangPack(lang, o, packName); - } - - flatSup = flatSup || yArray.hash(smod.supersedes); - - if (!(supName in flatSup)) { - smod.supersedes.push(supName); - } - - o.lang = o.lang || []; - - flatLang = flatLang || yArray.hash(o.lang); - - if (!(lang in flatLang)) { - o.lang.push(lang); - } - -// Add rollup file, need to add to supersedes list too - - // default packages - packName = this.getLangPackName(ROOT_LANG, name); - supName = this.getLangPackName(ROOT_LANG, i); - - smod = this.getModuleInfo(packName); - - if (!smod) { - smod = this._addLangPack(lang, o, packName); - } - - if (!(supName in flatSup)) { - smod.supersedes.push(supName); - } - -// Add rollup file, need to add to supersedes list too - - } - } - - l++; - } - } - //o.supersedes = YObject.keys(yArray.hash(sup)); - o.supersedes = yArray.dedupe(sup); - if (this.allowRollup) { - o.rollup = (l < 4) ? l : Math.min(l - 1, 4); - } - } - - plugins = o.plugins; - if (plugins) { - for (i in plugins) { - if (plugins.hasOwnProperty(i)) { - plug = plugins[i]; - plug.pkg = name; - plug.path = plug.path || _path(name, i, o.type); - plug.requires = plug.requires || []; - plug.group = o.group; - this.addModule(plug, i); - if (o.skinnable) { - this._addSkin(this.skin.defaultSkin, i, name); - } - - } - } - } - - if (o.condition) { - t = this._expandAliases(o.condition.trigger); - for (i = 0; i < t.length; i++) { - trigger = t[i]; - when = o.condition.when; - conditions[trigger] = conditions[trigger] || {}; - conditions[trigger][name] = o.condition; - // the 'when' attribute can be 'before', 'after', or 'instead' - // the default is after. - if (when && when !== 'after') { - if (when === 'instead') { // replace the trigger - o.supersedes = o.supersedes || []; - o.supersedes.push(trigger); - } - // before the trigger - // the trigger requires the conditional mod, - // so it should appear before the conditional - // mod if we do not intersede. - } else { // after the trigger - o.after = o.after || []; - o.after.push(trigger); - } - } - } - - if (o.supersedes) { - o.supersedes = this.filterRequires(o.supersedes); - } - - if (o.after) { - o.after = this.filterRequires(o.after); - o.after_map = yArray.hash(o.after); - } - - // this.dirty = true; - - if (o.configFn) { - ret = o.configFn(o); - if (ret === false) { - delete this.moduleInfo[name]; - delete GLOBAL_ENV._renderedMods[name]; - o = null; - } - } - //Add to global cache - if (o) { - if (!GLOBAL_ENV._renderedMods) { - GLOBAL_ENV._renderedMods = {}; - } - GLOBAL_ENV._renderedMods[name] = Y.mix(GLOBAL_ENV._renderedMods[name] || {}, o); - GLOBAL_ENV._conditions = conditions; - } - - return o; - }, - - /** - * Add a requirement for one or more module - * @method require - * @param {string[] | string*} what the modules to load. - */ - require: function(what) { - var a = (typeof what === 'string') ? yArray(arguments) : what; - this.dirty = true; - this.required = Y.merge(this.required, yArray.hash(this.filterRequires(a))); - - this._explodeRollups(); - }, - /** - * Grab all the items that were asked for, check to see if the Loader - * meta-data contains a "use" array. If it doesm remove the asked item and replace it with - * the content of the "use". - * This will make asking for: "dd" - * Actually ask for: "dd-ddm-base,dd-ddm,dd-ddm-drop,dd-drag,dd-proxy,dd-constrain,dd-drop,dd-scroll,dd-drop-plugin" - * @private - * @method _explodeRollups - */ - _explodeRollups: function() { - var self = this, m, m2, i, a, v, len, len2, - r = self.required; - - if (!self.allowRollup) { - for (i in r) { - if (r.hasOwnProperty(i)) { - m = self.getModule(i); - if (m && m.use) { - len = m.use.length; - for (a = 0; a < len; a++) { - m2 = self.getModule(m.use[a]); - if (m2 && m2.use) { - len2 = m2.use.length; - for (v = 0; v < len2; v++) { - r[m2.use[v]] = true; - } - } else { - r[m.use[a]] = true; - } - } - } - } - } - self.required = r; - } - - }, - /** - * Explodes the required array to remove aliases and replace them with real modules - * @method filterRequires - * @param {Array} r The original requires array - * @return {Array} The new array of exploded requirements - */ - filterRequires: function(r) { - if (r) { - if (!Y.Lang.isArray(r)) { - r = [r]; - } - r = Y.Array(r); - var c = [], i, mod, o, m; - - for (i = 0; i < r.length; i++) { - mod = this.getModule(r[i]); - if (mod && mod.use) { - for (o = 0; o < mod.use.length; o++) { - //Must walk the other modules in case a module is a rollup of rollups (datatype) - m = this.getModule(mod.use[o]); - if (m && m.use && (m.name !== mod.name)) { - c = Y.Array.dedupe([].concat(c, this.filterRequires(m.use))); - } else { - c.push(mod.use[o]); - } - } - } else { - c.push(r[i]); - } - } - r = c; - } - return r; - }, - /** - * Returns an object containing properties for all modules required - * in order to load the requested module - * @method getRequires - * @param {object} mod The module definition from moduleInfo. - * @return {array} the expanded requirement list. - */ - getRequires: function(mod) { - - if (!mod) { - //console.log('returning no reqs for ' + mod.name); - return NO_REQUIREMENTS; - } - - if (mod._parsed) { - //console.log('returning requires for ' + mod.name, mod.requires); - return mod.expanded || NO_REQUIREMENTS; - } - - //TODO add modue cache here out of scope.. - - var i, m, j, add, packName, lang, testresults = this.testresults, - name = mod.name, cond, - adddef = ON_PAGE[name] && ON_PAGE[name].details, - d, go, def, - r, old_mod, - o, skinmod, skindef, skinpar, skinname, - intl = mod.lang || mod.intl, - ftests = Y.Features && Y.Features.tests.load, - hash, reparse; - - // console.log(name); - - // pattern match leaves module stub that needs to be filled out - if (mod.temp && adddef) { - old_mod = mod; - mod = this.addModule(adddef, name); - mod.group = old_mod.group; - mod.pkg = old_mod.pkg; - delete mod.expanded; - } - - // console.log('cache: ' + mod.langCache + ' == ' + this.lang); - - //If a skin or a lang is different, reparse.. - reparse = !((!this.lang || mod.langCache === this.lang) && (mod.skinCache === this.skin.defaultSkin)); - - if (mod.expanded && !reparse) { - return mod.expanded; - } - - - d = []; - hash = {}; - r = this.filterRequires(mod.requires); - if (mod.lang) { - //If a module has a lang attribute, auto add the intl requirement. - d.unshift('intl'); - r.unshift('intl'); - intl = true; - } - o = this.filterRequires(mod.optional); - - - mod._parsed = true; - mod.langCache = this.lang; - mod.skinCache = this.skin.defaultSkin; - - for (i = 0; i < r.length; i++) { - if (!hash[r[i]]) { - d.push(r[i]); - hash[r[i]] = true; - m = this.getModule(r[i]); - if (m) { - add = this.getRequires(m); - intl = intl || (m.expanded_map && - (INTL in m.expanded_map)); - for (j = 0; j < add.length; j++) { - d.push(add[j]); - } - } - } - } - - // get the requirements from superseded modules, if any - r = this.filterRequires(mod.supersedes); - if (r) { - for (i = 0; i < r.length; i++) { - if (!hash[r[i]]) { - // if this module has submodules, the requirements list is - // expanded to include the submodules. This is so we can - // prevent dups when a submodule is already loaded and the - // parent is requested. - if (mod.submodules) { - d.push(r[i]); - } - - hash[r[i]] = true; - m = this.getModule(r[i]); - - if (m) { - add = this.getRequires(m); - intl = intl || (m.expanded_map && - (INTL in m.expanded_map)); - for (j = 0; j < add.length; j++) { - d.push(add[j]); - } - } - } - } - } - - if (o && this.loadOptional) { - for (i = 0; i < o.length; i++) { - if (!hash[o[i]]) { - d.push(o[i]); - hash[o[i]] = true; - m = this.getModuleInfo(o[i]); - if (m) { - add = this.getRequires(m); - intl = intl || (m.expanded_map && - (INTL in m.expanded_map)); - for (j = 0; j < add.length; j++) { - d.push(add[j]); - } - } - } - } - } - - cond = this.conditions[name]; - - if (cond) { - //Set the module to not parsed since we have conditionals and this could change the dependency tree. - mod._parsed = false; - if (testresults && ftests) { - oeach(testresults, function(result, id) { - var condmod = ftests[id].name; - if (!hash[condmod] && ftests[id].trigger === name) { - if (result && ftests[id]) { - hash[condmod] = true; - d.push(condmod); - } - } - }); - } else { - for (i in cond) { - if (cond.hasOwnProperty(i)) { - if (!hash[i]) { - def = cond[i]; - //first see if they've specfied a ua check - //then see if they've got a test fn & if it returns true - //otherwise just having a condition block is enough - go = def && ((!def.ua && !def.test) || (def.ua && Y.UA[def.ua]) || - (def.test && def.test(Y, r))); - - if (go) { - hash[i] = true; - d.push(i); - m = this.getModule(i); - if (m) { - add = this.getRequires(m); - for (j = 0; j < add.length; j++) { - d.push(add[j]); - } - - } - } - } - } - } - } - } - - // Create skin modules - if (mod.skinnable) { - skindef = this.skin.overrides; - for (i in YUI.Env.aliases) { - if (YUI.Env.aliases.hasOwnProperty(i)) { - if (Y.Array.indexOf(YUI.Env.aliases[i], name) > -1) { - skinpar = i; - } - } - } - if (skindef && (skindef[name] || (skinpar && skindef[skinpar]))) { - skinname = name; - if (skindef[skinpar]) { - skinname = skinpar; - } - for (i = 0; i < skindef[skinname].length; i++) { - skinmod = this._addSkin(skindef[skinname][i], name); - if (!this.isCSSLoaded(skinmod, this._boot)) { - d.push(skinmod); - } - } - } else { - skinmod = this._addSkin(this.skin.defaultSkin, name); - if (!this.isCSSLoaded(skinmod, this._boot)) { - d.push(skinmod); - } - } - } - - mod._parsed = false; - - if (intl) { - - if (mod.lang && !mod.langPack && Y.Intl) { - lang = Y.Intl.lookupBestLang(this.lang || ROOT_LANG, mod.lang); - packName = this.getLangPackName(lang, name); - if (packName) { - d.unshift(packName); - } - } - d.unshift(INTL); - } - - mod.expanded_map = yArray.hash(d); - - mod.expanded = YObject.keys(mod.expanded_map); - - return mod.expanded; - }, - /** - * Check to see if named css module is already loaded on the page - * @method isCSSLoaded - * @param {String} name The name of the css file - * @param {Boolean} skip To skip the short-circuit for ignoreRegister - * @return Boolean - */ - isCSSLoaded: function(name, skip) { - //TODO - Make this call a batching call with name being an array - if (!name || !YUI.Env.cssStampEl || (!skip && this.ignoreRegistered)) { - return false; - } - var el = YUI.Env.cssStampEl, - ret = false, - mod = YUI.Env._cssLoaded[name], - style = el.currentStyle; //IE - - - if (mod !== undefined) { - return mod; - } - - //Add the classname to the element - el.className = name; - - if (!style) { - style = Y.config.doc.defaultView.getComputedStyle(el, null); - } - - if (style && style.display === 'none') { - ret = true; - } - - - el.className = ''; //Reset the classname to '' - - YUI.Env._cssLoaded[name] = ret; - - return ret; - }, - - /** - * Returns a hash of module names the supplied module satisfies. - * @method getProvides - * @param {string} name The name of the module. - * @return {object} what this module provides. - */ - getProvides: function(name) { - var m = this.getModule(name), o, s; - // supmap = this.provides; - - if (!m) { - return NOT_FOUND; - } - - if (m && !m.provides) { - o = {}; - s = m.supersedes; - - if (s) { - yArray.each(s, function(v) { - Y.mix(o, this.getProvides(v)); - }, this); - } - - o[name] = true; - m.provides = o; - - } - - return m.provides; - }, - - /** - * Calculates the dependency tree, the result is stored in the sorted - * property. - * @method calculate - * @param {object} o optional options object. - * @param {string} type optional argument to prune modules. - */ - calculate: function(o, type) { - if (o || type || this.dirty) { - - if (o) { - this._config(o); - } - - if (!this._init) { - this._setup(); - } - - this._explode(); - - if (this.allowRollup) { - this._rollup(); - } else { - this._explodeRollups(); - } - this._reduce(); - this._sort(); - } - }, - /** - * Creates a "psuedo" package for languages provided in the lang array - * @method _addLangPack - * @private - * @param {String} lang The language to create - * @param {Object} m The module definition to create the language pack around - * @param {String} packName The name of the package (e.g: lang/datatype-date-en-US) - * @return {Object} The module definition - */ - _addLangPack: function(lang, m, packName) { - var name = m.name, - packPath, conf, - existing = this.getModuleInfo(packName); - - if (!existing) { - - packPath = _path((m.pkg || name), packName, JS, true); - - conf = { - path: packPath, - intl: true, - langPack: true, - ext: m.ext, - group: m.group, - supersedes: [] - }; - if (m.root) { - conf.root = m.root; - } - if (m.base) { - conf.base = m.base; - } - - if (m.configFn) { - conf.configFn = m.configFn; - } - - this.addModule(conf, packName); - - if (lang) { - Y.Env.lang = Y.Env.lang || {}; - Y.Env.lang[lang] = Y.Env.lang[lang] || {}; - Y.Env.lang[lang][name] = true; - } - } - - return this.getModuleInfo(packName); - }, - - /** - * Investigates the current YUI configuration on the page. By default, - * modules already detected will not be loaded again unless a force - * option is encountered. Called by calculate() - * @method _setup - * @private - */ - _setup: function() { - var info = this.moduleInfo, name, i, j, m, l, - packName; - - for (name in info) { - if (info.hasOwnProperty(name)) { - m = info[name]; - if (m) { - - // remove dups - //m.requires = YObject.keys(yArray.hash(m.requires)); - m.requires = yArray.dedupe(m.requires); - - // Create lang pack modules - //if (m.lang && m.lang.length) { - if (m.lang) { - // Setup root package if the module has lang defined, - // it needs to provide a root language pack - packName = this.getLangPackName(ROOT_LANG, name); - this._addLangPack(null, m, packName); - } - - } - } - } - - - //l = Y.merge(this.inserted); - l = {}; - - // available modules - if (!this.ignoreRegistered) { - Y.mix(l, GLOBAL_ENV.mods); - } - - // add the ignore list to the list of loaded packages - if (this.ignore) { - Y.mix(l, yArray.hash(this.ignore)); - } - - // expand the list to include superseded modules - for (j in l) { - if (l.hasOwnProperty(j)) { - Y.mix(l, this.getProvides(j)); - } - } - - // remove modules on the force list from the loaded list - if (this.force) { - for (i = 0; i < this.force.length; i++) { - if (this.force[i] in l) { - delete l[this.force[i]]; - } - } - } - - Y.mix(this.loaded, l); - - this._init = true; - }, - - /** - * Builds a module name for a language pack - * @method getLangPackName - * @param {string} lang the language code. - * @param {string} mname the module to build it for. - * @return {string} the language pack module name. - */ - getLangPackName: function(lang, mname) { - return ('lang/' + mname + ((lang) ? '_' + lang : '')); - }, - /** - * Inspects the required modules list looking for additional - * dependencies. Expands the required list to include all - * required modules. Called by calculate() - * @method _explode - * @private - */ - _explode: function() { - //TODO Move done out of scope - var r = this.required, m, reqs, done = {}, - self = this, name, expound; - - // the setup phase is over, all modules have been created - self.dirty = false; - - self._explodeRollups(); - r = self.required; - - for (name in r) { - if (r.hasOwnProperty(name)) { - if (!done[name]) { - done[name] = true; - m = self.getModule(name); - if (m) { - expound = m.expound; - - if (expound) { - r[expound] = self.getModule(expound); - reqs = self.getRequires(r[expound]); - Y.mix(r, yArray.hash(reqs)); - } - - reqs = self.getRequires(m); - Y.mix(r, yArray.hash(reqs)); - } - } - } - } - - }, - /** - * The default method used to test a module against a pattern - * @method _patternTest - * @private - * @param {String} mname The module being tested - * @param {String} pname The pattern to match - */ - _patternTest: function(mname, pname) { - return (mname.indexOf(pname) > -1); - }, - /** - * Get's the loader meta data for the requested module - * @method getModule - * @param {String} mname The module name to get - * @return {Object} The module metadata - */ - getModule: function(mname) { - //TODO: Remove name check - it's a quick hack to fix pattern WIP - if (!mname) { - return null; - } - - var p, found, pname, - m = this.getModuleInfo(mname), - patterns = this.patterns; - - // check the patterns library to see if we should automatically add - // the module with defaults - if (!m || (m && m.ext)) { - for (pname in patterns) { - if (patterns.hasOwnProperty(pname)) { - p = patterns[pname]; - - //There is no test method, create a default one that tests - // the pattern against the mod name - if (!p.test) { - p.test = this._patternTest; - } - - if (p.test(mname, pname)) { - // use the metadata supplied for the pattern - // as the module definition. - found = p; - break; - } - } - } - } - - if (!m) { - if (found) { - if (p.action) { - p.action.call(this, mname, pname); - } else { - // ext true or false? - m = this.addModule(Y.merge(found), mname); - if (found.configFn) { - m.configFn = found.configFn; - } - m.temp = true; - } - } - } else { - if (found && m && found.configFn && !m.configFn) { - m.configFn = found.configFn; - m.configFn(m); - } - } - - return m; - }, - - // impl in rollup submodule - _rollup: function() { }, - - /** - * Remove superceded modules and loaded modules. Called by - * calculate() after we have the mega list of all dependencies - * @method _reduce - * @return {object} the reduced dependency hash. - * @private - */ - _reduce: function(r) { - - r = r || this.required; - - var i, j, s, m, type = this.loadType, - ignore = this.ignore ? yArray.hash(this.ignore) : false; - - for (i in r) { - if (r.hasOwnProperty(i)) { - m = this.getModule(i); - // remove if already loaded - if (((this.loaded[i] || ON_PAGE[i]) && - !this.forceMap[i] && !this.ignoreRegistered) || - (type && m && m.type !== type)) { - delete r[i]; - } - if (ignore && ignore[i]) { - delete r[i]; - } - // remove anything this module supersedes - s = m && m.supersedes; - if (s) { - for (j = 0; j < s.length; j++) { - if (s[j] in r) { - delete r[s[j]]; - } - } - } - } - } - - return r; - }, - /** - * Handles the queue when a module has been loaded for all cases - * @method _finish - * @private - * @param {String} msg The message from Loader - * @param {Boolean} success A boolean denoting success or failure - */ - _finish: function(msg, success) { - - _queue.running = false; - - var onEnd = this.onEnd; - if (onEnd) { - onEnd.call(this.context, { - msg: msg, - data: this.data, - success: success - }); - } - this._continue(); - }, - /** - * The default Loader onSuccess handler, calls this.onSuccess with a payload - * @method _onSuccess - * @private - */ - _onSuccess: function() { - var self = this, skipped = Y.merge(self.skipped), fn, - failed = [], rreg = self.requireRegistration, - success, msg, i, mod; - - for (i in skipped) { - if (skipped.hasOwnProperty(i)) { - delete self.inserted[i]; - } - } - - self.skipped = {}; - - for (i in self.inserted) { - if (self.inserted.hasOwnProperty(i)) { - mod = self.getModule(i); - if (mod && rreg && mod.type === JS && !(i in YUI.Env.mods)) { - failed.push(i); - } else { - Y.mix(self.loaded, self.getProvides(i)); - } - } - } - - fn = self.onSuccess; - msg = (failed.length) ? 'notregistered' : 'success'; - success = !(failed.length); - if (fn) { - fn.call(self.context, { - msg: msg, - data: self.data, - success: success, - failed: failed, - skipped: skipped - }); - } - self._finish(msg, success); - }, - /** - * The default Loader onProgress handler, calls this.onProgress with a payload - * @method _onProgress - * @private - */ - _onProgress: function(e) { - var self = this, i; - //set the internal cache to what just came in. - if (e.data && e.data.length) { - for (i = 0; i < e.data.length; i++) { - e.data[i] = self.getModule(e.data[i].name); - } - } - if (self.onProgress) { - self.onProgress.call(self.context, { - name: e.url, - data: e.data - }); - } - }, - /** - * The default Loader onFailure handler, calls this.onFailure with a payload - * @method _onFailure - * @private - */ - _onFailure: function(o) { - var f = this.onFailure, msg = [], i = 0, len = o.errors.length; - - for (i; i < len; i++) { - msg.push(o.errors[i].error); - } - - msg = msg.join(','); - - - if (f) { - f.call(this.context, { - msg: msg, - data: this.data, - success: false - }); - } - - this._finish(msg, false); - - }, - - /** - * The default Loader onTimeout handler, calls this.onTimeout with a payload - * @method _onTimeout - * @param {Get.Transaction} transaction The Transaction object from `Y.Get` - * @private - */ - _onTimeout: function(transaction) { - var f = this.onTimeout; - if (f) { - f.call(this.context, { - msg: 'timeout', - data: this.data, - success: false, - transaction: transaction - }); - } - }, - - /** - * Sorts the dependency tree. The last step of calculate() - * @method _sort - * @private - */ - _sort: function() { - var name, - - // Object containing module names. - required = this.required, - - // Keep track of whether we've visited a module. - visited = {}; - - // Will contain modules names, in the correct order, - // according to dependencies. - this.sorted = []; - - for (name in required) { - if (!visited[name] && required.hasOwnProperty(name)) { - this._visit(name, visited); - } - } - }, - - /** - * Recursively visits the dependencies of the module name - * passed in, and appends each module name to the `sorted` property. - * @param {String} name The name of a module. - * @param {Object} visited Keeps track of whether a module was visited. - * @method _visit - * @private - */ - _visit: function (name, visited) { - var required, condition, moduleInfo, dependency, dependencies, - trigger, isAfter, i, l; - - visited[name] = true; - required = this.required; - moduleInfo = this.moduleInfo[name]; - condition = this.conditions[name] || {}; - - if (moduleInfo) { - // Recurse on each dependency of this module, - // figuring out its dependencies, and so on. - dependencies = moduleInfo.expanded || moduleInfo.requires; - - for (i = 0, l = dependencies.length; i < l; ++i) { - dependency = dependencies[i]; - trigger = condition[dependency]; - - // We cannot process this dependency yet if it must - // appear after our current module. - isAfter = trigger && (!trigger.when || trigger.when === "after"); - - // Is this module name in the required list of modules, - // and have we not already visited it? - if (required[dependency] && !visited[dependency] && !isAfter) { - this._visit(dependency, visited); - } - } - } - - this.sorted.push(name); - }, - - /** - * Handles the actual insertion of script/link tags - * @method _insert - * @private - * @param {Object} source The YUI instance the request came from - * @param {Object} o The metadata to include - * @param {String} type JS or CSS - * @param {Boolean} [skipcalc=false] Do a Loader.calculate on the meta - */ - _insert: function(source, o, type, skipcalc) { - - - // restore the state at the time of the request - if (source) { - this._config(source); - } - - // build the dependency list - // don't include type so we can process CSS and script in - // one pass when the type is not specified. - - var modules = this.resolve(!skipcalc), - self = this, comp = 0, actions = 0, - mods = {}, deps, complete; - - self._refetch = []; - - if (type) { - //Filter out the opposite type and reset the array so the checks later work - modules[((type === JS) ? CSS : JS)] = []; - } - if (!self.fetchCSS) { - modules.css = []; - } - if (modules.js.length) { - comp++; - } - if (modules.css.length) { - comp++; - } - - //console.log('Resolved Modules: ', modules); - - complete = function(d) { - actions++; - var errs = {}, i = 0, o = 0, u = '', fn, - modName, resMods; - - if (d && d.errors) { - for (i = 0; i < d.errors.length; i++) { - if (d.errors[i].request) { - u = d.errors[i].request.url; - } else { - u = d.errors[i]; - } - errs[u] = u; - } - } - - if (d && d.data && d.data.length && (d.type === 'success')) { - for (i = 0; i < d.data.length; i++) { - self.inserted[d.data[i].name] = true; - //If the external module has a skin or a lang, reprocess it - if (d.data[i].lang || d.data[i].skinnable) { - delete self.inserted[d.data[i].name]; - self._refetch.push(d.data[i].name); - } - } - } - - if (actions === comp) { - self._loading = null; - if (self._refetch.length) { - //Get the deps for the new meta-data and reprocess - for (i = 0; i < self._refetch.length; i++) { - deps = self.getRequires(self.getModule(self._refetch[i])); - for (o = 0; o < deps.length; o++) { - if (!self.inserted[deps[o]]) { - //We wouldn't be to this point without the module being here - mods[deps[o]] = deps[o]; - } - } - } - mods = Y.Object.keys(mods); - if (mods.length) { - self.require(mods); - resMods = self.resolve(true); - if (resMods.cssMods.length) { - for (i=0; i < resMods.cssMods.length; i++) { - modName = resMods.cssMods[i].name; - delete YUI.Env._cssLoaded[modName]; - if (self.isCSSLoaded(modName)) { - self.inserted[modName] = true; - delete self.required[modName]; - } - } - self.sorted = []; - self._sort(); - } - d = null; //bail - self._insert(); //insert the new deps - } - } - if (d && d.fn) { - fn = d.fn; - delete d.fn; - fn.call(self, d); - } - } - }; - - this._loading = true; - - if (!modules.js.length && !modules.css.length) { - actions = -1; - complete({ - fn: self._onSuccess - }); - return; - } - - - if (modules.css.length) { //Load CSS first - Y.Get.css(modules.css, { - data: modules.cssMods, - attributes: self.cssAttributes, - insertBefore: self.insertBefore, - charset: self.charset, - timeout: self.timeout, - context: self, - onProgress: function(e) { - self._onProgress.call(self, e); - }, - onTimeout: function(d) { - self._onTimeout.call(self, d); - }, - onSuccess: function(d) { - d.type = 'success'; - d.fn = self._onSuccess; - complete.call(self, d); - }, - onFailure: function(d) { - d.type = 'failure'; - d.fn = self._onFailure; - complete.call(self, d); - } - }); - } - - if (modules.js.length) { - Y.Get.js(modules.js, { - data: modules.jsMods, - insertBefore: self.insertBefore, - attributes: self.jsAttributes, - charset: self.charset, - timeout: self.timeout, - autopurge: false, - context: self, - async: self.async, - onProgress: function(e) { - self._onProgress.call(self, e); - }, - onTimeout: function(d) { - self._onTimeout.call(self, d); - }, - onSuccess: function(d) { - d.type = 'success'; - d.fn = self._onSuccess; - complete.call(self, d); - }, - onFailure: function(d) { - d.type = 'failure'; - d.fn = self._onFailure; - complete.call(self, d); - } - }); - } - }, - /** - * Once a loader operation is completely finished, process any additional queued items. - * @method _continue - * @private - */ - _continue: function() { - if (!(_queue.running) && _queue.size() > 0) { - _queue.running = true; - _queue.next()(); - } - }, - - /** - * inserts the requested modules and their dependencies. - * type can be "js" or "css". Both script and - * css are inserted if type is not provided. - * @method insert - * @param {object} o optional options object. - * @param {string} type the type of dependency to insert. - */ - insert: function(o, type, skipsort) { - var self = this, copy = Y.merge(this); - delete copy.require; - delete copy.dirty; - _queue.add(function() { - self._insert(copy, o, type, skipsort); - }); - this._continue(); - }, - - /** - * Executed every time a module is loaded, and if we are in a load - * cycle, we attempt to load the next script. Public so that it - * is possible to call this if using a method other than - * Y.register to determine when scripts are fully loaded - * @method loadNext - * @deprecated - * @param {string} mname optional the name of the module that has - * been loaded (which is usually why it is time to load the next - * one). - */ - loadNext: function() { - return; - }, - - /** - * Apply filter defined for this instance to a url/path - * @method _filter - * @param {string} u the string to filter. - * @param {string} name the name of the module, if we are processing - * a single module as opposed to a combined url. - * @return {string} the filtered string. - * @private - */ - _filter: function(u, name, group) { - var f = this.filter, - hasFilter = name && (name in this.filters), - modFilter = hasFilter && this.filters[name], - groupName = group || (this.getModuleInfo(name) || {}).group || null; - - if (groupName && this.groups[groupName] && this.groups[groupName].filter) { - modFilter = this.groups[groupName].filter; - hasFilter = true; - } - - if (u) { - if (hasFilter) { - f = (L.isString(modFilter)) ? this.FILTER_DEFS[modFilter.toUpperCase()] || null : modFilter; - } - if (f) { - u = u.replace(new RegExp(f.searchExp, 'g'), f.replaceStr); - } - } - return u; - }, - - /** - * Generates the full url for a module - * @method _url - * @param {string} path the path fragment. - * @param {String} name The name of the module - * @param {String} [base] The base url to use. Defaults to self.base - * @return {string} the full url. - * @private - */ - _url: function(path, name, base) { - return this._filter((base || this.base || '') + path, name); - }, - /** - * Returns an Object hash of file arrays built from `loader.sorted` or from an arbitrary list of sorted modules. - * @method resolve - * @param {Boolean} [calc=false] Perform a loader.calculate() before anything else - * @param {Array} [s] An override for the loader.sorted array. Defaults to - * `loader.sorted`. - * @return {Object} Object hash (js and css) of two arrays of file lists - * @example This method can be used as an off-line dep calculator - * - * var Y = YUI(); - * var loader = new Y.Loader({ - * filter: 'debug', - * base: '../../', - * root: 'build/', - * combine: true, - * require: ['node', 'dd', 'console'] - * }); - * var out = loader.resolve(true); - * - */ - resolve: function(calc, s) { - - var len, i, m, url, group, groupName, j, frag, - comboSource, comboSources, mods, comboBase, - base, urls, u = [], tmpBase, baseLen, resCombos = {}, - self = this, comboSep, maxURLLength, - inserted = (self.ignoreRegistered) ? {} : self.inserted, - resolved = { js: [], jsMods: [], css: [], cssMods: [] }, - type = self.loadType || 'js', addSingle; - - if (self.skin.overrides || self.skin.defaultSkin !== DEFAULT_SKIN || self.ignoreRegistered) { - self._resetModules(); - } - - if (calc) { - self.calculate(); - } - s = s || self.sorted; - - addSingle = function(m) { - - if (m) { - group = (m.group && self.groups[m.group]) || NOT_FOUND; - - //Always assume it's async - if (group.async === false) { - m.async = group.async; - } - - url = (m.fullpath) ? self._filter(m.fullpath, s[i]) : - self._url(m.path, s[i], group.base || m.base); - - if (m.attributes || m.async === false) { - url = { - url: url, - async: m.async - }; - if (m.attributes) { - url.attributes = m.attributes; - } - } - resolved[m.type].push(url); - resolved[m.type + 'Mods'].push(m); - } else { - } - - }; - - len = s.length; - - // the default combo base - comboBase = self.comboBase; - - url = comboBase; - - comboSources = {}; - - for (i = 0; i < len; i++) { - comboSource = comboBase; - m = self.getModule(s[i]); - groupName = m && m.group; - group = self.groups[groupName]; - if (groupName && group) { - - if (!group.combine || m.fullpath) { - //This is not a combo module, skip it and load it singly later. - addSingle(m); - continue; - } - m.combine = true; - if (group.comboBase) { - comboSource = group.comboBase; - } - - if ("root" in group && L.isValue(group.root)) { - m.root = group.root; - } - m.comboSep = group.comboSep || self.comboSep; - m.maxURLLength = group.maxURLLength || self.maxURLLength; - } else { - if (!self.combine) { - //This is not a combo module, skip it and load it singly later. - addSingle(m); - continue; - } - } - - comboSources[comboSource] = comboSources[comboSource] || []; - comboSources[comboSource].push(m); - } - - for (j in comboSources) { - if (comboSources.hasOwnProperty(j)) { - resCombos[j] = resCombos[j] || { js: [], jsMods: [], css: [], cssMods: [] }; - url = j; - mods = comboSources[j]; - len = mods.length; - - if (len) { - for (i = 0; i < len; i++) { - if (inserted[mods[i]]) { - continue; - } - m = mods[i]; - // Do not try to combine non-yui JS unless combo def - // is found - if (m && (m.combine || !m.ext)) { - resCombos[j].comboSep = m.comboSep; - resCombos[j].group = m.group; - resCombos[j].maxURLLength = m.maxURLLength; - frag = ((L.isValue(m.root)) ? m.root : self.root) + (m.path || m.fullpath); - frag = self._filter(frag, m.name); - resCombos[j][m.type].push(frag); - resCombos[j][m.type + 'Mods'].push(m); - } else { - //Add them to the next process.. - if (mods[i]) { - addSingle(mods[i]); - } - } - - } - } - } - } - - - for (j in resCombos) { - if (resCombos.hasOwnProperty(j)) { - base = j; - comboSep = resCombos[base].comboSep || self.comboSep; - maxURLLength = resCombos[base].maxURLLength || self.maxURLLength; - for (type in resCombos[base]) { - if (type === JS || type === CSS) { - urls = resCombos[base][type]; - mods = resCombos[base][type + 'Mods']; - len = urls.length; - tmpBase = base + urls.join(comboSep); - baseLen = tmpBase.length; - if (maxURLLength <= base.length) { - maxURLLength = MAX_URL_LENGTH; - } - - if (len) { - if (baseLen > maxURLLength) { - u = []; - for (s = 0; s < len; s++) { - u.push(urls[s]); - tmpBase = base + u.join(comboSep); - - if (tmpBase.length > maxURLLength) { - m = u.pop(); - tmpBase = base + u.join(comboSep); - resolved[type].push(self._filter(tmpBase, null, resCombos[base].group)); - u = []; - if (m) { - u.push(m); - } - } - } - if (u.length) { - tmpBase = base + u.join(comboSep); - resolved[type].push(self._filter(tmpBase, null, resCombos[base].group)); - } - } else { - resolved[type].push(self._filter(tmpBase, null, resCombos[base].group)); - } - } - resolved[type + 'Mods'] = resolved[type + 'Mods'].concat(mods); - } - } - } - } - - resCombos = null; - - return resolved; - }, - /** - Shortcut to calculate, resolve and load all modules. - - var loader = new Y.Loader({ - ignoreRegistered: true, - modules: { - mod: { - path: 'mod.js' - } - }, - requires: [ 'mod' ] - }); - loader.load(function() { - console.log('All modules have loaded..'); - }); - - - @method load - @param {Function} cb Executed after all load operations are complete - */ - load: function(cb) { - if (!cb) { - return; - } - var self = this, - out = self.resolve(true); - - self.data = out; - - self.onEnd = function() { - cb.apply(self.context || self, arguments); - }; - - self.insert(); - } -}; - - - -}, '@VERSION@', {"requires": ["get", "features"]}); -YUI.add('loader-rollup', function (Y, NAME) { - -/** - * Optional automatic rollup logic for reducing http connections - * when not using a combo service. - * @module loader - * @submodule rollup - */ - -/** - * Look for rollup packages to determine if all of the modules a - * rollup supersedes are required. If so, include the rollup to - * help reduce the total number of connections required. Called - * by calculate(). This is an optional feature, and requires the - * appropriate submodule to function. - * @method _rollup - * @for Loader - * @private - */ -Y.Loader.prototype._rollup = function() { - var i, j, m, s, r = this.required, roll, - info = this.moduleInfo, rolled, c, smod; - - // find and cache rollup modules - if (this.dirty || !this.rollups) { - this.rollups = {}; - for (i in info) { - if (info.hasOwnProperty(i)) { - m = this.getModule(i); - // if (m && m.rollup && m.supersedes) { - if (m && m.rollup) { - this.rollups[i] = m; - } - } - } - } - - // make as many passes as needed to pick up rollup rollups - for (;;) { - rolled = false; - - // go through the rollup candidates - for (i in this.rollups) { - if (this.rollups.hasOwnProperty(i)) { - // there can be only one, unless forced - if (!r[i] && ((!this.loaded[i]) || this.forceMap[i])) { - m = this.getModule(i); - s = m.supersedes || []; - roll = false; - - // @TODO remove continue - if (!m.rollup) { - continue; - } - - c = 0; - - // check the threshold - for (j = 0; j < s.length; j++) { - smod = info[s[j]]; - - // if the superseded module is loaded, we can't - // load the rollup unless it has been forced. - if (this.loaded[s[j]] && !this.forceMap[s[j]]) { - roll = false; - break; - // increment the counter if this module is required. - // if we are beyond the rollup threshold, we will - // use the rollup module - } else if (r[s[j]] && m.type === smod.type) { - c++; - roll = (c >= m.rollup); - if (roll) { - break; - } - } - } - - if (roll) { - // add the rollup - r[i] = true; - rolled = true; - - // expand the rollup's dependencies - this.getRequires(m); - } - } - } - } - - // if we made it here w/o rolling up something, we are done - if (!rolled) { - break; - } - } -}; - - -}, '@VERSION@', {"requires": ["loader-base"]}); -YUI.add('loader-yui3', function (Y, NAME) { - -/* This file is auto-generated by (yogi.js loader --mix --yes) */ - -/*jshint maxlen:900, eqeqeq: false */ - -/** - * YUI 3 module metadata - * @module loader - * @submodule loader-yui3 - */ -YUI.Env[Y.version].modules = YUI.Env[Y.version].modules || {}; -Y.mix(YUI.Env[Y.version].modules, { - "align-plugin": { - "requires": [ - "node-screen", - "node-pluginhost" - ] - }, - "anim": { - "use": [ - "anim-base", - "anim-color", - "anim-curve", - "anim-easing", - "anim-node-plugin", - "anim-scroll", - "anim-xy" - ] - }, - "anim-base": { - "requires": [ - "base-base", - "node-style" - ] - }, - "anim-color": { - "requires": [ - "anim-base" - ] - }, - "anim-curve": { - "requires": [ - "anim-xy" - ] - }, - "anim-easing": { - "requires": [ - "anim-base" - ] - }, - "anim-node-plugin": { - "requires": [ - "node-pluginhost", - "anim-base" - ] - }, - "anim-scroll": { - "requires": [ - "anim-base" - ] - }, - "anim-shape": { - "requires": [ - "anim-base", - "anim-easing", - "anim-color", - "matrix" - ] - }, - "anim-shape-transform": { - "use": [ - "anim-shape" - ] - }, - "anim-xy": { - "requires": [ - "anim-base", - "node-screen" - ] - }, - "app": { - "use": [ - "app-base", - "app-content", - "app-transitions", - "lazy-model-list", - "model", - "model-list", - "model-sync-rest", - "model-sync-local", - "router", - "view", - "view-node-map" - ] - }, - "app-base": { - "requires": [ - "classnamemanager", - "pjax-base", - "router", - "view" - ] - }, - "app-content": { - "requires": [ - "app-base", - "pjax-content" - ] - }, - "app-transitions": { - "requires": [ - "app-base" - ] - }, - "app-transitions-css": { - "type": "css" - }, - "app-transitions-native": { - "condition": { - "name": "app-transitions-native", - "test": function (Y) { - var doc = Y.config.doc, - node = doc ? doc.documentElement : null; - - if (node && node.style) { - return ('MozTransition' in node.style || 'WebkitTransition' in node.style || 'transition' in node.style); - } - - return false; -}, - "trigger": "app-transitions" - }, - "requires": [ - "app-transitions", - "app-transitions-css", - "parallel", - "transition" - ] - }, - "array-extras": { - "requires": [ - "yui-base" - ] - }, - "array-invoke": { - "requires": [ - "yui-base" - ] - }, - "arraylist": { - "requires": [ - "yui-base" - ] - }, - "arraylist-add": { - "requires": [ - "arraylist" - ] - }, - "arraylist-filter": { - "requires": [ - "arraylist" - ] - }, - "arraysort": { - "requires": [ - "yui-base" - ] - }, - "async-queue": { - "requires": [ - "event-custom" - ] - }, - "attribute": { - "use": [ - "attribute-base", - "attribute-complex" - ] - }, - "attribute-base": { - "requires": [ - "attribute-core", - "attribute-observable", - "attribute-extras" - ] - }, - "attribute-complex": { - "requires": [ - "attribute-base" - ] - }, - "attribute-core": { - "requires": [ - "oop" - ] - }, - "attribute-events": { - "use": [ - "attribute-observable" - ] - }, - "attribute-extras": { - "requires": [ - "oop" - ] - }, - "attribute-observable": { - "requires": [ - "event-custom" - ] - }, - "autocomplete": { - "use": [ - "autocomplete-base", - "autocomplete-sources", - "autocomplete-list", - "autocomplete-plugin" - ] - }, - "autocomplete-base": { - "optional": [ - "autocomplete-sources" - ], - "requires": [ - "array-extras", - "base-build", - "escape", - "event-valuechange", - "node-base" - ] - }, - "autocomplete-filters": { - "requires": [ - "array-extras", - "text-wordbreak" - ] - }, - "autocomplete-filters-accentfold": { - "requires": [ - "array-extras", - "text-accentfold", - "text-wordbreak" - ] - }, - "autocomplete-highlighters": { - "requires": [ - "array-extras", - "highlight-base" - ] - }, - "autocomplete-highlighters-accentfold": { - "requires": [ - "array-extras", - "highlight-accentfold" - ] - }, - "autocomplete-list": { - "after": [ - "autocomplete-sources" - ], - "lang": [ - "en", - "es", - "hu", - "it" - ], - "requires": [ - "autocomplete-base", - "event-resize", - "node-screen", - "selector-css3", - "shim-plugin", - "widget", - "widget-position", - "widget-position-align" - ], - "skinnable": true - }, - "autocomplete-list-keys": { - "condition": { - "name": "autocomplete-list-keys", - "test": function (Y) { - // Only add keyboard support to autocomplete-list if this doesn't appear to - // be an iOS or Android-based mobile device. - // - // There's currently no feasible way to actually detect whether a device has - // a hardware keyboard, so this sniff will have to do. It can easily be - // overridden by manually loading the autocomplete-list-keys module. - // - // Worth noting: even though iOS supports bluetooth keyboards, Mobile Safari - // doesn't fire the keyboard events used by AutoCompleteList, so there's - // no point loading the -keys module even when a bluetooth keyboard may be - // available. - return !(Y.UA.ios || Y.UA.android); -}, - "trigger": "autocomplete-list" - }, - "requires": [ - "autocomplete-list", - "base-build" - ] - }, - "autocomplete-plugin": { - "requires": [ - "autocomplete-list", - "node-pluginhost" - ] - }, - "autocomplete-sources": { - "optional": [ - "io-base", - "json-parse", - "jsonp", - "yql" - ], - "requires": [ - "autocomplete-base" - ] - }, - "axes": { - "use": [ - "axis-numeric", - "axis-category", - "axis-time", - "axis-stacked" - ] - }, - "axes-base": { - "use": [ - "axis-numeric-base", - "axis-category-base", - "axis-time-base", - "axis-stacked-base" - ] - }, - "axis": { - "requires": [ - "dom", - "widget", - "widget-position", - "widget-stack", - "graphics", - "axis-base" - ] - }, - "axis-base": { - "requires": [ - "classnamemanager", - "datatype-number", - "datatype-date", - "base", - "event-custom" - ] - }, - "axis-category": { - "requires": [ - "axis", - "axis-category-base" - ] - }, - "axis-category-base": { - "requires": [ - "axis-base" - ] - }, - "axis-numeric": { - "requires": [ - "axis", - "axis-numeric-base" - ] - }, - "axis-numeric-base": { - "requires": [ - "axis-base" - ] - }, - "axis-stacked": { - "requires": [ - "axis-numeric", - "axis-stacked-base" - ] - }, - "axis-stacked-base": { - "requires": [ - "axis-numeric-base" - ] - }, - "axis-time": { - "requires": [ - "axis", - "axis-time-base" - ] - }, - "axis-time-base": { - "requires": [ - "axis-base" - ] - }, - "base": { - "use": [ - "base-base", - "base-pluginhost", - "base-build" - ] - }, - "base-base": { - "requires": [ - "attribute-base", - "base-core", - "base-observable" - ] - }, - "base-build": { - "requires": [ - "base-base" - ] - }, - "base-core": { - "requires": [ - "attribute-core" - ] - }, - "base-observable": { - "requires": [ - "attribute-observable", - "base-core" - ] - }, - "base-pluginhost": { - "requires": [ - "base-base", - "pluginhost" - ] - }, - "button": { - "requires": [ - "button-core", - "cssbutton", - "widget" - ] - }, - "button-core": { - "requires": [ - "attribute-core", - "classnamemanager", - "node-base", - "escape" - ] - }, - "button-group": { - "requires": [ - "button-plugin", - "cssbutton", - "widget" - ] - }, - "button-plugin": { - "requires": [ - "button-core", - "cssbutton", - "node-pluginhost" - ] - }, - "cache": { - "use": [ - "cache-base", - "cache-offline", - "cache-plugin" - ] - }, - "cache-base": { - "requires": [ - "base" - ] - }, - "cache-offline": { - "requires": [ - "cache-base", - "json" - ] - }, - "cache-plugin": { - "requires": [ - "plugin", - "cache-base" - ] - }, - "calendar": { - "requires": [ - "calendar-base", - "calendarnavigator" - ], - "skinnable": true - }, - "calendar-base": { - "lang": [ - "de", - "en", - "es", - "es-AR", - "fr", - "hu", - "it", - "ja", - "nb-NO", - "nl", - "pt-BR", - "ru", - "zh-Hans", - "zh-Hans-CN", - "zh-Hant", - "zh-Hant-HK", - "zh-HANT-TW" - ], - "requires": [ - "widget", - "datatype-date", - "datatype-date-math", - "cssgrids" - ], - "skinnable": true - }, - "calendarnavigator": { - "requires": [ - "plugin", - "classnamemanager", - "datatype-date", - "node" - ], - "skinnable": true - }, - "charts": { - "use": [ - "charts-base" - ] - }, - "charts-base": { - "requires": [ - "dom", - "event-mouseenter", - "event-touch", - "graphics-group", - "axes", - "series-pie", - "series-line", - "series-marker", - "series-area", - "series-spline", - "series-column", - "series-bar", - "series-areaspline", - "series-combo", - "series-combospline", - "series-line-stacked", - "series-marker-stacked", - "series-area-stacked", - "series-spline-stacked", - "series-column-stacked", - "series-bar-stacked", - "series-areaspline-stacked", - "series-combo-stacked", - "series-combospline-stacked" - ] - }, - "charts-legend": { - "requires": [ - "charts-base" - ] - }, - "classnamemanager": { - "requires": [ - "yui-base" - ] - }, - "clickable-rail": { - "requires": [ - "slider-base" - ] - }, - "collection": { - "use": [ - "array-extras", - "arraylist", - "arraylist-add", - "arraylist-filter", - "array-invoke" - ] - }, - "color": { - "use": [ - "color-base", - "color-hsl", - "color-harmony" - ] - }, - "color-base": { - "requires": [ - "yui-base" - ] - }, - "color-harmony": { - "requires": [ - "color-hsl" - ] - }, - "color-hsl": { - "requires": [ - "color-base" - ] - }, - "color-hsv": { - "requires": [ - "color-base" - ] - }, - "console": { - "lang": [ - "en", - "es", - "hu", - "it", - "ja" - ], - "requires": [ - "yui-log", - "widget" - ], - "skinnable": true - }, - "console-filters": { - "requires": [ - "plugin", - "console" - ], - "skinnable": true - }, - "content-editable": { - "requires": [ - "node-base", - "editor-selection", - "stylesheet", - "plugin" - ] - }, - "controller": { - "use": [ - "router" - ] - }, - "cookie": { - "requires": [ - "yui-base" - ] - }, - "createlink-base": { - "requires": [ - "editor-base" - ] - }, - "cssbase": { - "after": [ - "cssreset", - "cssfonts", - "cssgrids", - "cssreset-context", - "cssfonts-context", - "cssgrids-context" - ], - "type": "css" - }, - "cssbase-context": { - "after": [ - "cssreset", - "cssfonts", - "cssgrids", - "cssreset-context", - "cssfonts-context", - "cssgrids-context" - ], - "type": "css" - }, - "cssbutton": { - "type": "css" - }, - "cssfonts": { - "type": "css" - }, - "cssfonts-context": { - "type": "css" - }, - "cssgrids": { - "optional": [ - "cssnormalize" - ], - "type": "css" - }, - "cssgrids-base": { - "optional": [ - "cssnormalize" - ], - "type": "css" - }, - "cssgrids-responsive": { - "optional": [ - "cssnormalize" - ], - "requires": [ - "cssgrids", - "cssgrids-responsive-base" - ], - "type": "css" - }, - "cssgrids-units": { - "optional": [ - "cssnormalize" - ], - "requires": [ - "cssgrids-base" - ], - "type": "css" - }, - "cssnormalize": { - "type": "css" - }, - "cssnormalize-context": { - "type": "css" - }, - "cssreset": { - "type": "css" - }, - "cssreset-context": { - "type": "css" - }, - "dataschema": { - "use": [ - "dataschema-base", - "dataschema-json", - "dataschema-xml", - "dataschema-array", - "dataschema-text" - ] - }, - "dataschema-array": { - "requires": [ - "dataschema-base" - ] - }, - "dataschema-base": { - "requires": [ - "base" - ] - }, - "dataschema-json": { - "requires": [ - "dataschema-base", - "json" - ] - }, - "dataschema-text": { - "requires": [ - "dataschema-base" - ] - }, - "dataschema-xml": { - "requires": [ - "dataschema-base" - ] - }, - "datasource": { - "use": [ - "datasource-local", - "datasource-io", - "datasource-get", - "datasource-function", - "datasource-cache", - "datasource-jsonschema", - "datasource-xmlschema", - "datasource-arrayschema", - "datasource-textschema", - "datasource-polling" - ] - }, - "datasource-arrayschema": { - "requires": [ - "datasource-local", - "plugin", - "dataschema-array" - ] - }, - "datasource-cache": { - "requires": [ - "datasource-local", - "plugin", - "cache-base" - ] - }, - "datasource-function": { - "requires": [ - "datasource-local" - ] - }, - "datasource-get": { - "requires": [ - "datasource-local", - "get" - ] - }, - "datasource-io": { - "requires": [ - "datasource-local", - "io-base" - ] - }, - "datasource-jsonschema": { - "requires": [ - "datasource-local", - "plugin", - "dataschema-json" - ] - }, - "datasource-local": { - "requires": [ - "base" - ] - }, - "datasource-polling": { - "requires": [ - "datasource-local" - ] - }, - "datasource-textschema": { - "requires": [ - "datasource-local", - "plugin", - "dataschema-text" - ] - }, - "datasource-xmlschema": { - "requires": [ - "datasource-local", - "plugin", - "datatype-xml", - "dataschema-xml" - ] - }, - "datatable": { - "use": [ - "datatable-core", - "datatable-table", - "datatable-head", - "datatable-body", - "datatable-base", - "datatable-column-widths", - "datatable-message", - "datatable-mutable", - "datatable-sort", - "datatable-datasource" - ] - }, - "datatable-base": { - "requires": [ - "datatable-core", - "datatable-table", - "datatable-head", - "datatable-body", - "base-build", - "widget" - ], - "skinnable": true - }, - "datatable-body": { - "requires": [ - "datatable-core", - "view", - "classnamemanager" - ] - }, - "datatable-column-widths": { - "requires": [ - "datatable-base" - ] - }, - "datatable-core": { - "requires": [ - "escape", - "model-list", - "node-event-delegate" - ] - }, - "datatable-datasource": { - "requires": [ - "datatable-base", - "plugin", - "datasource-local" - ] - }, - "datatable-foot": { - "requires": [ - "datatable-core", - "view" - ] - }, - "datatable-formatters": { - "requires": [ - "datatable-body", - "datatype-number-format", - "datatype-date-format", - "escape" - ] - }, - "datatable-head": { - "requires": [ - "datatable-core", - "view", - "classnamemanager" - ] - }, - "datatable-highlight": { - "requires": [ - "datatable-base", - "event-hover" - ], - "skinnable": true - }, - "datatable-keynav": { - "requires": [ - "datatable-base" - ] - }, - "datatable-message": { - "lang": [ - "en", - "fr", - "es", - "hu", - "it" - ], - "requires": [ - "datatable-base" - ], - "skinnable": true - }, - "datatable-mutable": { - "requires": [ - "datatable-base" - ] - }, - "datatable-paginator": { - "lang": [ - "en", - "fr" - ], - "requires": [ - "model", - "view", - "paginator-core", - "datatable-foot", - "datatable-paginator-templates" - ], - "skinnable": true - }, - "datatable-paginator-templates": { - "requires": [ - "template" - ] - }, - "datatable-scroll": { - "requires": [ - "datatable-base", - "datatable-column-widths", - "dom-screen" - ], - "skinnable": true - }, - "datatable-sort": { - "lang": [ - "en", - "fr", - "es", - "hu" - ], - "requires": [ - "datatable-base" - ], - "skinnable": true - }, - "datatable-table": { - "requires": [ - "datatable-core", - "datatable-head", - "datatable-body", - "view", - "classnamemanager" - ] - }, - "datatype": { - "use": [ - "datatype-date", - "datatype-number", - "datatype-xml" - ] - }, - "datatype-date": { - "use": [ - "datatype-date-parse", - "datatype-date-format", - "datatype-date-math" - ] - }, - "datatype-date-format": { - "lang": [ - "ar", - "ar-JO", - "ca", - "ca-ES", - "da", - "da-DK", - "de", - "de-AT", - "de-DE", - "el", - "el-GR", - "en", - "en-AU", - "en-CA", - "en-GB", - "en-IE", - "en-IN", - "en-JO", - "en-MY", - "en-NZ", - "en-PH", - "en-SG", - "en-US", - "es", - "es-AR", - "es-BO", - "es-CL", - "es-CO", - "es-EC", - "es-ES", - "es-MX", - "es-PE", - "es-PY", - "es-US", - "es-UY", - "es-VE", - "fi", - "fi-FI", - "fr", - "fr-BE", - "fr-CA", - "fr-FR", - "hi", - "hi-IN", - "hu", - "id", - "id-ID", - "it", - "it-IT", - "ja", - "ja-JP", - "ko", - "ko-KR", - "ms", - "ms-MY", - "nb", - "nb-NO", - "nl", - "nl-BE", - "nl-NL", - "pl", - "pl-PL", - "pt", - "pt-BR", - "ro", - "ro-RO", - "ru", - "ru-RU", - "sv", - "sv-SE", - "th", - "th-TH", - "tr", - "tr-TR", - "vi", - "vi-VN", - "zh-Hans", - "zh-Hans-CN", - "zh-Hant", - "zh-Hant-HK", - "zh-Hant-TW" - ] - }, - "datatype-date-math": { - "requires": [ - "yui-base" - ] - }, - "datatype-date-parse": {}, - "datatype-number": { - "use": [ - "datatype-number-parse", - "datatype-number-format" - ] - }, - "datatype-number-format": {}, - "datatype-number-parse": { - "requires": [ - "escape" - ] - }, - "datatype-xml": { - "use": [ - "datatype-xml-parse", - "datatype-xml-format" - ] - }, - "datatype-xml-format": {}, - "datatype-xml-parse": {}, - "dd": { - "use": [ - "dd-ddm-base", - "dd-ddm", - "dd-ddm-drop", - "dd-drag", - "dd-proxy", - "dd-constrain", - "dd-drop", - "dd-scroll", - "dd-delegate" - ] - }, - "dd-constrain": { - "requires": [ - "dd-drag" - ] - }, - "dd-ddm": { - "requires": [ - "dd-ddm-base", - "event-resize" - ] - }, - "dd-ddm-base": { - "requires": [ - "node", - "base", - "yui-throttle", - "classnamemanager" - ] - }, - "dd-ddm-drop": { - "requires": [ - "dd-ddm" - ] - }, - "dd-delegate": { - "requires": [ - "dd-drag", - "dd-drop-plugin", - "event-mouseenter" - ] - }, - "dd-drag": { - "requires": [ - "dd-ddm-base" - ] - }, - "dd-drop": { - "requires": [ - "dd-drag", - "dd-ddm-drop" - ] - }, - "dd-drop-plugin": { - "requires": [ - "dd-drop" - ] - }, - "dd-gestures": { - "condition": { - "name": "dd-gestures", - "trigger": "dd-drag", - "ua": "touchEnabled" - }, - "requires": [ - "dd-drag", - "event-synthetic", - "event-gestures" - ] - }, - "dd-plugin": { - "optional": [ - "dd-constrain", - "dd-proxy" - ], - "requires": [ - "dd-drag" - ] - }, - "dd-proxy": { - "requires": [ - "dd-drag" - ] - }, - "dd-scroll": { - "requires": [ - "dd-drag" - ] - }, - "dial": { - "lang": [ - "en", - "es", - "hu" - ], - "requires": [ - "widget", - "dd-drag", - "event-mouseenter", - "event-move", - "event-key", - "transition", - "intl" - ], - "skinnable": true - }, - "dom": { - "use": [ - "dom-base", - "dom-screen", - "dom-style", - "selector-native", - "selector" - ] - }, - "dom-base": { - "requires": [ - "dom-core" - ] - }, - "dom-core": { - "requires": [ - "oop", - "features" - ] - }, - "dom-screen": { - "requires": [ - "dom-base", - "dom-style" - ] - }, - "dom-style": { - "requires": [ - "dom-base", - "color-base" - ] - }, - "dom-style-ie": { - "condition": { - "name": "dom-style-ie", - "test": function (Y) { - - var testFeature = Y.Features.test, - addFeature = Y.Features.add, - WINDOW = Y.config.win, - DOCUMENT = Y.config.doc, - DOCUMENT_ELEMENT = 'documentElement', - ret = false; - - addFeature('style', 'computedStyle', { - test: function() { - return WINDOW && 'getComputedStyle' in WINDOW; - } - }); - - addFeature('style', 'opacity', { - test: function() { - return DOCUMENT && 'opacity' in DOCUMENT[DOCUMENT_ELEMENT].style; - } - }); - - ret = (!testFeature('style', 'opacity') && - !testFeature('style', 'computedStyle')); - - return ret; -}, - "trigger": "dom-style" - }, - "requires": [ - "dom-style" - ] - }, - "dump": { - "requires": [ - "yui-base" - ] - }, - "editor": { - "use": [ - "frame", - "editor-selection", - "exec-command", - "editor-base", - "editor-para", - "editor-br", - "editor-bidi", - "editor-tab", - "createlink-base" - ] - }, - "editor-base": { - "requires": [ - "base", - "frame", - "node", - "exec-command", - "editor-selection" - ] - }, - "editor-bidi": { - "requires": [ - "editor-base" - ] - }, - "editor-br": { - "requires": [ - "editor-base" - ] - }, - "editor-inline": { - "requires": [ - "editor-base", - "content-editable" - ] - }, - "editor-lists": { - "requires": [ - "editor-base" - ] - }, - "editor-para": { - "requires": [ - "editor-para-base" - ] - }, - "editor-para-base": { - "requires": [ - "editor-base" - ] - }, - "editor-para-ie": { - "condition": { - "name": "editor-para-ie", - "trigger": "editor-para", - "ua": "ie", - "when": "instead" - }, - "requires": [ - "editor-para-base" - ] - }, - "editor-selection": { - "requires": [ - "node" - ] - }, - "editor-tab": { - "requires": [ - "editor-base" - ] - }, - "escape": { - "requires": [ - "yui-base" - ] - }, - "event": { - "after": [ - "node-base" - ], - "use": [ - "event-base", - "event-delegate", - "event-synthetic", - "event-mousewheel", - "event-mouseenter", - "event-key", - "event-focus", - "event-resize", - "event-hover", - "event-outside", - "event-touch", - "event-move", - "event-flick", - "event-valuechange", - "event-tap" - ] - }, - "event-base": { - "after": [ - "node-base" - ], - "requires": [ - "event-custom-base" - ] - }, - "event-base-ie": { - "after": [ - "event-base" - ], - "condition": { - "name": "event-base-ie", - "test": function(Y) { - var imp = Y.config.doc && Y.config.doc.implementation; - return (imp && (!imp.hasFeature('Events', '2.0'))); -}, - "trigger": "node-base" - }, - "requires": [ - "node-base" - ] - }, - "event-contextmenu": { - "requires": [ - "event-synthetic", - "dom-screen" - ] - }, - "event-custom": { - "use": [ - "event-custom-base", - "event-custom-complex" - ] - }, - "event-custom-base": { - "requires": [ - "oop" - ] - }, - "event-custom-complex": { - "requires": [ - "event-custom-base" - ] - }, - "event-delegate": { - "requires": [ - "node-base" - ] - }, - "event-flick": { - "requires": [ - "node-base", - "event-touch", - "event-synthetic" - ] - }, - "event-focus": { - "requires": [ - "event-synthetic" - ] - }, - "event-gestures": { - "use": [ - "event-flick", - "event-move" - ] - }, - "event-hover": { - "requires": [ - "event-mouseenter" - ] - }, - "event-key": { - "requires": [ - "event-synthetic" - ] - }, - "event-mouseenter": { - "requires": [ - "event-synthetic" - ] - }, - "event-mousewheel": { - "requires": [ - "node-base" - ] - }, - "event-move": { - "requires": [ - "node-base", - "event-touch", - "event-synthetic" - ] - }, - "event-outside": { - "requires": [ - "event-synthetic" - ] - }, - "event-resize": { - "requires": [ - "node-base", - "event-synthetic" - ] - }, - "event-simulate": { - "requires": [ - "event-base" - ] - }, - "event-synthetic": { - "requires": [ - "node-base", - "event-custom-complex" - ] - }, - "event-tap": { - "requires": [ - "node-base", - "event-base", - "event-touch", - "event-synthetic" - ] - }, - "event-touch": { - "requires": [ - "node-base" - ] - }, - "event-valuechange": { - "requires": [ - "event-focus", - "event-synthetic" - ] - }, - "exec-command": { - "requires": [ - "frame" - ] - }, - "features": { - "requires": [ - "yui-base" - ] - }, - "file": { - "requires": [ - "file-flash", - "file-html5" - ] - }, - "file-flash": { - "requires": [ - "base" - ] - }, - "file-html5": { - "requires": [ - "base" - ] - }, - "frame": { - "requires": [ - "base", - "node", - "plugin", - "selector-css3", - "yui-throttle" - ] - }, - "gesture-simulate": { - "requires": [ - "async-queue", - "event-simulate", - "node-screen" - ] - }, - "get": { - "requires": [ - "yui-base" - ] - }, - "graphics": { - "requires": [ - "node", - "event-custom", - "pluginhost", - "matrix", - "classnamemanager" - ] - }, - "graphics-canvas": { - "condition": { - "name": "graphics-canvas", - "test": function(Y) { - var DOCUMENT = Y.config.doc, - useCanvas = Y.config.defaultGraphicEngine && Y.config.defaultGraphicEngine == "canvas", - canvas = DOCUMENT && DOCUMENT.createElement("canvas"), - svg = (DOCUMENT && DOCUMENT.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure", "1.1")); - return (!svg || useCanvas) && (canvas && canvas.getContext && canvas.getContext("2d")); -}, - "trigger": "graphics" - }, - "requires": [ - "graphics" - ] - }, - "graphics-canvas-default": { - "condition": { - "name": "graphics-canvas-default", - "test": function(Y) { - var DOCUMENT = Y.config.doc, - useCanvas = Y.config.defaultGraphicEngine && Y.config.defaultGraphicEngine == "canvas", - canvas = DOCUMENT && DOCUMENT.createElement("canvas"), - svg = (DOCUMENT && DOCUMENT.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure", "1.1")); - return (!svg || useCanvas) && (canvas && canvas.getContext && canvas.getContext("2d")); -}, - "trigger": "graphics" - } - }, - "graphics-group": { - "requires": [ - "graphics" - ] - }, - "graphics-svg": { - "condition": { - "name": "graphics-svg", - "test": function(Y) { - var DOCUMENT = Y.config.doc, - useSVG = !Y.config.defaultGraphicEngine || Y.config.defaultGraphicEngine != "canvas", - canvas = DOCUMENT && DOCUMENT.createElement("canvas"), - svg = (DOCUMENT && DOCUMENT.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure", "1.1")); - - return svg && (useSVG || !canvas); -}, - "trigger": "graphics" - }, - "requires": [ - "graphics" - ] - }, - "graphics-svg-default": { - "condition": { - "name": "graphics-svg-default", - "test": function(Y) { - var DOCUMENT = Y.config.doc, - useSVG = !Y.config.defaultGraphicEngine || Y.config.defaultGraphicEngine != "canvas", - canvas = DOCUMENT && DOCUMENT.createElement("canvas"), - svg = (DOCUMENT && DOCUMENT.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure", "1.1")); - - return svg && (useSVG || !canvas); -}, - "trigger": "graphics" - } - }, - "graphics-vml": { - "condition": { - "name": "graphics-vml", - "test": function(Y) { - var DOCUMENT = Y.config.doc, - canvas = DOCUMENT && DOCUMENT.createElement("canvas"); - return (DOCUMENT && !DOCUMENT.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure", "1.1") && (!canvas || !canvas.getContext || !canvas.getContext("2d"))); -}, - "trigger": "graphics" - }, - "requires": [ - "graphics" - ] - }, - "graphics-vml-default": { - "condition": { - "name": "graphics-vml-default", - "test": function(Y) { - var DOCUMENT = Y.config.doc, - canvas = DOCUMENT && DOCUMENT.createElement("canvas"); - return (DOCUMENT && !DOCUMENT.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure", "1.1") && (!canvas || !canvas.getContext || !canvas.getContext("2d"))); -}, - "trigger": "graphics" - } - }, - "handlebars": { - "use": [ - "handlebars-compiler" - ] - }, - "handlebars-base": { - "requires": [] - }, - "handlebars-compiler": { - "requires": [ - "handlebars-base" - ] - }, - "highlight": { - "use": [ - "highlight-base", - "highlight-accentfold" - ] - }, - "highlight-accentfold": { - "requires": [ - "highlight-base", - "text-accentfold" - ] - }, - "highlight-base": { - "requires": [ - "array-extras", - "classnamemanager", - "escape", - "text-wordbreak" - ] - }, - "history": { - "use": [ - "history-base", - "history-hash", - "history-html5" - ] - }, - "history-base": { - "requires": [ - "event-custom-complex" - ] - }, - "history-hash": { - "after": [ - "history-html5" - ], - "requires": [ - "event-synthetic", - "history-base", - "yui-later" - ] - }, - "history-hash-ie": { - "condition": { - "name": "history-hash-ie", - "test": function (Y) { - var docMode = Y.config.doc && Y.config.doc.documentMode; - - return Y.UA.ie && (!('onhashchange' in Y.config.win) || - !docMode || docMode < 8); -}, - "trigger": "history-hash" - }, - "requires": [ - "history-hash", - "node-base" - ] - }, - "history-html5": { - "optional": [ - "json" - ], - "requires": [ - "event-base", - "history-base", - "node-base" - ] - }, - "imageloader": { - "requires": [ - "base-base", - "node-style", - "node-screen" - ] - }, - "intl": { - "requires": [ - "intl-base", - "event-custom" - ] - }, - "intl-base": { - "requires": [ - "yui-base" - ] - }, - "io": { - "use": [ - "io-base", - "io-xdr", - "io-form", - "io-upload-iframe", - "io-queue" - ] - }, - "io-base": { - "requires": [ - "event-custom-base", - "querystring-stringify-simple" - ] - }, - "io-form": { - "requires": [ - "io-base", - "node-base" - ] - }, - "io-nodejs": { - "condition": { - "name": "io-nodejs", - "trigger": "io-base", - "ua": "nodejs" - }, - "requires": [ - "io-base" - ] - }, - "io-queue": { - "requires": [ - "io-base", - "queue-promote" - ] - }, - "io-upload-iframe": { - "requires": [ - "io-base", - "node-base" - ] - }, - "io-xdr": { - "requires": [ - "io-base", - "datatype-xml-parse" - ] - }, - "json": { - "use": [ - "json-parse", - "json-stringify" - ] - }, - "json-parse": { - "requires": [ - "yui-base" - ] - }, - "json-parse-shim": { - "condition": { - "name": "json-parse-shim", - "test": function (Y) { - var _JSON = Y.config.global.JSON, - Native = Object.prototype.toString.call(_JSON) === '[object JSON]' && _JSON, - nativeSupport = Y.config.useNativeJSONParse !== false && !!Native; - - function workingNative( k, v ) { - return k === "ok" ? true : v; - } - - // Double check basic functionality. This is mainly to catch early broken - // implementations of the JSON API in Firefox 3.1 beta1 and beta2 - if ( nativeSupport ) { - try { - nativeSupport = ( Native.parse( '{"ok":false}', workingNative ) ).ok; - } - catch ( e ) { - nativeSupport = false; - } - } - - return !nativeSupport; -}, - "trigger": "json-parse" - }, - "requires": [ - "json-parse" - ] - }, - "json-stringify": { - "requires": [ - "yui-base" - ] - }, - "json-stringify-shim": { - "condition": { - "name": "json-stringify-shim", - "test": function (Y) { - var _JSON = Y.config.global.JSON, - Native = Object.prototype.toString.call(_JSON) === '[object JSON]' && _JSON, - nativeSupport = Y.config.useNativeJSONStringify !== false && !!Native; - - // Double check basic native functionality. This is primarily to catch broken - // early JSON API implementations in Firefox 3.1 beta1 and beta2. - if ( nativeSupport ) { - try { - nativeSupport = ( '0' === Native.stringify(0) ); - } catch ( e ) { - nativeSupport = false; - } - } - - - return !nativeSupport; -}, - "trigger": "json-stringify" - }, - "requires": [ - "json-stringify" - ] - }, - "jsonp": { - "requires": [ - "get", - "oop" - ] - }, - "jsonp-url": { - "requires": [ - "jsonp" - ] - }, - "lazy-model-list": { - "requires": [ - "model-list" - ] - }, - "loader": { - "use": [ - "loader-base", - "loader-rollup", - "loader-yui3" - ] - }, - "loader-base": { - "requires": [ - "get", - "features" - ] - }, - "loader-rollup": { - "requires": [ - "loader-base" - ] - }, - "loader-yui3": { - "requires": [ - "loader-base" - ] - }, - "matrix": { - "requires": [ - "yui-base" - ] - }, - "model": { - "requires": [ - "base-build", - "escape", - "json-parse" - ] - }, - "model-list": { - "requires": [ - "array-extras", - "array-invoke", - "arraylist", - "base-build", - "escape", - "json-parse", - "model" - ] - }, - "model-sync-local": { - "requires": [ - "model", - "json-stringify" - ] - }, - "model-sync-rest": { - "requires": [ - "model", - "io-base", - "json-stringify" - ] - }, - "node": { - "use": [ - "node-base", - "node-event-delegate", - "node-pluginhost", - "node-screen", - "node-style" - ] - }, - "node-base": { - "requires": [ - "event-base", - "node-core", - "dom-base", - "dom-style" - ] - }, - "node-core": { - "requires": [ - "dom-core", - "selector" - ] - }, - "node-event-delegate": { - "requires": [ - "node-base", - "event-delegate" - ] - }, - "node-event-html5": { - "requires": [ - "node-base" - ] - }, - "node-event-simulate": { - "requires": [ - "node-base", - "event-simulate", - "gesture-simulate" - ] - }, - "node-flick": { - "requires": [ - "classnamemanager", - "transition", - "event-flick", - "plugin" - ], - "skinnable": true - }, - "node-focusmanager": { - "requires": [ - "attribute", - "node", - "plugin", - "node-event-simulate", - "event-key", - "event-focus" - ] - }, - "node-load": { - "requires": [ - "node-base", - "io-base" - ] - }, - "node-menunav": { - "requires": [ - "node", - "classnamemanager", - "plugin", - "node-focusmanager" - ], - "skinnable": true - }, - "node-pluginhost": { - "requires": [ - "node-base", - "pluginhost" - ] - }, - "node-screen": { - "requires": [ - "dom-screen", - "node-base" - ] - }, - "node-scroll-info": { - "requires": [ - "array-extras", - "base-build", - "event-resize", - "node-pluginhost", - "plugin", - "selector" - ] - }, - "node-style": { - "requires": [ - "dom-style", - "node-base" - ] - }, - "oop": { - "requires": [ - "yui-base" - ] - }, - "overlay": { - "requires": [ - "widget", - "widget-stdmod", - "widget-position", - "widget-position-align", - "widget-stack", - "widget-position-constrain" - ], - "skinnable": true - }, - "paginator": { - "requires": [ - "paginator-core" - ] - }, - "paginator-core": { - "requires": [ - "base" - ] - }, - "paginator-url": { - "requires": [ - "paginator" - ] - }, - "panel": { - "requires": [ - "widget", - "widget-autohide", - "widget-buttons", - "widget-modality", - "widget-position", - "widget-position-align", - "widget-position-constrain", - "widget-stack", - "widget-stdmod" - ], - "skinnable": true - }, - "parallel": { - "requires": [ - "yui-base" - ] - }, - "pjax": { - "requires": [ - "pjax-base", - "pjax-content" - ] - }, - "pjax-base": { - "requires": [ - "classnamemanager", - "node-event-delegate", - "router" - ] - }, - "pjax-content": { - "requires": [ - "io-base", - "node-base", - "router" - ] - }, - "pjax-plugin": { - "requires": [ - "node-pluginhost", - "pjax", - "plugin" - ] - }, - "plugin": { - "requires": [ - "base-base" - ] - }, - "pluginhost": { - "use": [ - "pluginhost-base", - "pluginhost-config" - ] - }, - "pluginhost-base": { - "requires": [ - "yui-base" - ] - }, - "pluginhost-config": { - "requires": [ - "pluginhost-base" - ] - }, - "promise": { - "requires": [ - "timers" - ] - }, - "querystring": { - "use": [ - "querystring-parse", - "querystring-stringify" - ] - }, - "querystring-parse": { - "requires": [ - "yui-base", - "array-extras" - ] - }, - "querystring-parse-simple": { - "requires": [ - "yui-base" - ] - }, - "querystring-stringify": { - "requires": [ - "yui-base" - ] - }, - "querystring-stringify-simple": { - "requires": [ - "yui-base" - ] - }, - "queue-promote": { - "requires": [ - "yui-base" - ] - }, - "range-slider": { - "requires": [ - "slider-base", - "slider-value-range", - "clickable-rail" - ] - }, - "recordset": { - "use": [ - "recordset-base", - "recordset-sort", - "recordset-filter", - "recordset-indexer" - ] - }, - "recordset-base": { - "requires": [ - "base", - "arraylist" - ] - }, - "recordset-filter": { - "requires": [ - "recordset-base", - "array-extras", - "plugin" - ] - }, - "recordset-indexer": { - "requires": [ - "recordset-base", - "plugin" - ] - }, - "recordset-sort": { - "requires": [ - "arraysort", - "recordset-base", - "plugin" - ] - }, - "resize": { - "use": [ - "resize-base", - "resize-proxy", - "resize-constrain" - ] - }, - "resize-base": { - "requires": [ - "base", - "widget", - "event", - "oop", - "dd-drag", - "dd-delegate", - "dd-drop" - ], - "skinnable": true - }, - "resize-constrain": { - "requires": [ - "plugin", - "resize-base" - ] - }, - "resize-plugin": { - "optional": [ - "resize-constrain" - ], - "requires": [ - "resize-base", - "plugin" - ] - }, - "resize-proxy": { - "requires": [ - "plugin", - "resize-base" - ] - }, - "router": { - "optional": [ - "querystring-parse" - ], - "requires": [ - "array-extras", - "base-build", - "history" - ] - }, - "scrollview": { - "requires": [ - "scrollview-base", - "scrollview-scrollbars" - ] - }, - "scrollview-base": { - "requires": [ - "widget", - "event-gestures", - "event-mousewheel", - "transition" - ], - "skinnable": true - }, - "scrollview-base-ie": { - "condition": { - "name": "scrollview-base-ie", - "trigger": "scrollview-base", - "ua": "ie" - }, - "requires": [ - "scrollview-base" - ] - }, - "scrollview-list": { - "requires": [ - "plugin", - "classnamemanager" - ], - "skinnable": true - }, - "scrollview-paginator": { - "requires": [ - "plugin", - "classnamemanager" - ] - }, - "scrollview-scrollbars": { - "requires": [ - "classnamemanager", - "transition", - "plugin" - ], - "skinnable": true - }, - "selector": { - "requires": [ - "selector-native" - ] - }, - "selector-css2": { - "condition": { - "name": "selector-css2", - "test": function (Y) { - var DOCUMENT = Y.config.doc, - ret = DOCUMENT && !('querySelectorAll' in DOCUMENT); - - return ret; -}, - "trigger": "selector" - }, - "requires": [ - "selector-native" - ] - }, - "selector-css3": { - "requires": [ - "selector-native", - "selector-css2" - ] - }, - "selector-native": { - "requires": [ - "dom-base" - ] - }, - "series-area": { - "requires": [ - "series-cartesian", - "series-fill-util" - ] - }, - "series-area-stacked": { - "requires": [ - "series-stacked", - "series-area" - ] - }, - "series-areaspline": { - "requires": [ - "series-area", - "series-curve-util" - ] - }, - "series-areaspline-stacked": { - "requires": [ - "series-stacked", - "series-areaspline" - ] - }, - "series-bar": { - "requires": [ - "series-marker", - "series-histogram-base" - ] - }, - "series-bar-stacked": { - "requires": [ - "series-stacked", - "series-bar" - ] - }, - "series-base": { - "requires": [ - "graphics", - "axis-base" - ] - }, - "series-candlestick": { - "requires": [ - "series-range" - ] - }, - "series-cartesian": { - "requires": [ - "series-base" - ] - }, - "series-column": { - "requires": [ - "series-marker", - "series-histogram-base" - ] - }, - "series-column-stacked": { - "requires": [ - "series-stacked", - "series-column" - ] - }, - "series-combo": { - "requires": [ - "series-cartesian", - "series-line-util", - "series-plot-util", - "series-fill-util" - ] - }, - "series-combo-stacked": { - "requires": [ - "series-stacked", - "series-combo" - ] - }, - "series-combospline": { - "requires": [ - "series-combo", - "series-curve-util" - ] - }, - "series-combospline-stacked": { - "requires": [ - "series-combo-stacked", - "series-curve-util" - ] - }, - "series-curve-util": {}, - "series-fill-util": {}, - "series-histogram-base": { - "requires": [ - "series-cartesian", - "series-plot-util" - ] - }, - "series-line": { - "requires": [ - "series-cartesian", - "series-line-util" - ] - }, - "series-line-stacked": { - "requires": [ - "series-stacked", - "series-line" - ] - }, - "series-line-util": {}, - "series-marker": { - "requires": [ - "series-cartesian", - "series-plot-util" - ] - }, - "series-marker-stacked": { - "requires": [ - "series-stacked", - "series-marker" - ] - }, - "series-ohlc": { - "requires": [ - "series-range" - ] - }, - "series-pie": { - "requires": [ - "series-base", - "series-plot-util" - ] - }, - "series-plot-util": {}, - "series-range": { - "requires": [ - "series-cartesian" - ] - }, - "series-spline": { - "requires": [ - "series-line", - "series-curve-util" - ] - }, - "series-spline-stacked": { - "requires": [ - "series-stacked", - "series-spline" - ] - }, - "series-stacked": { - "requires": [ - "axis-stacked" - ] - }, - "shim-plugin": { - "requires": [ - "node-style", - "node-pluginhost" - ] - }, - "slider": { - "use": [ - "slider-base", - "slider-value-range", - "clickable-rail", - "range-slider" - ] - }, - "slider-base": { - "requires": [ - "widget", - "dd-constrain", - "event-key" - ], - "skinnable": true - }, - "slider-value-range": { - "requires": [ - "slider-base" - ] - }, - "sortable": { - "requires": [ - "dd-delegate", - "dd-drop-plugin", - "dd-proxy" - ] - }, - "sortable-scroll": { - "requires": [ - "dd-scroll", - "sortable" - ] - }, - "stylesheet": { - "requires": [ - "yui-base" - ] - }, - "substitute": { - "optional": [ - "dump" - ], - "requires": [ - "yui-base" - ] - }, - "swf": { - "requires": [ - "event-custom", - "node", - "swfdetect", - "escape" - ] - }, - "swfdetect": { - "requires": [ - "yui-base" - ] - }, - "tabview": { - "requires": [ - "widget", - "widget-parent", - "widget-child", - "tabview-base", - "node-pluginhost", - "node-focusmanager" - ], - "skinnable": true - }, - "tabview-base": { - "requires": [ - "node-event-delegate", - "classnamemanager" - ] - }, - "tabview-plugin": { - "requires": [ - "tabview-base" - ] - }, - "template": { - "use": [ - "template-base", - "template-micro" - ] - }, - "template-base": { - "requires": [ - "yui-base" - ] - }, - "template-micro": { - "requires": [ - "escape" - ] - }, - "test": { - "requires": [ - "event-simulate", - "event-custom", - "json-stringify" - ] - }, - "test-console": { - "requires": [ - "console-filters", - "test", - "array-extras" - ], - "skinnable": true - }, - "text": { - "use": [ - "text-accentfold", - "text-wordbreak" - ] - }, - "text-accentfold": { - "requires": [ - "array-extras", - "text-data-accentfold" - ] - }, - "text-data-accentfold": { - "requires": [ - "yui-base" - ] - }, - "text-data-wordbreak": { - "requires": [ - "yui-base" - ] - }, - "text-wordbreak": { - "requires": [ - "array-extras", - "text-data-wordbreak" - ] - }, - "timers": { - "requires": [ - "yui-base" - ] - }, - "transition": { - "requires": [ - "node-style" - ] - }, - "transition-timer": { - "condition": { - "name": "transition-timer", - "test": function (Y) { - var DOCUMENT = Y.config.doc, - node = (DOCUMENT) ? DOCUMENT.documentElement: null, - ret = true; - - if (node && node.style) { - ret = !('MozTransition' in node.style || 'WebkitTransition' in node.style || 'transition' in node.style); - } - - return ret; -}, - "trigger": "transition" - }, - "requires": [ - "transition" - ] - }, - "tree": { - "requires": [ - "base-build", - "tree-node" - ] - }, - "tree-labelable": { - "requires": [ - "tree" - ] - }, - "tree-lazy": { - "requires": [ - "base-pluginhost", - "plugin", - "tree" - ] - }, - "tree-node": {}, - "tree-openable": { - "requires": [ - "tree" - ] - }, - "tree-selectable": { - "requires": [ - "tree" - ] - }, - "tree-sortable": { - "requires": [ - "tree" - ] - }, - "uploader": { - "requires": [ - "uploader-html5", - "uploader-flash" - ] - }, - "uploader-flash": { - "requires": [ - "swfdetect", - "escape", - "widget", - "base", - "cssbutton", - "node", - "event-custom", - "uploader-queue" - ] - }, - "uploader-html5": { - "requires": [ - "widget", - "node-event-simulate", - "file-html5", - "uploader-queue" - ] - }, - "uploader-queue": { - "requires": [ - "base" - ] - }, - "view": { - "requires": [ - "base-build", - "node-event-delegate" - ] - }, - "view-node-map": { - "requires": [ - "view" - ] - }, - "widget": { - "use": [ - "widget-base", - "widget-htmlparser", - "widget-skin", - "widget-uievents" - ] - }, - "widget-anim": { - "requires": [ - "anim-base", - "plugin", - "widget" - ] - }, - "widget-autohide": { - "requires": [ - "base-build", - "event-key", - "event-outside", - "widget" - ] - }, - "widget-base": { - "requires": [ - "attribute", - "base-base", - "base-pluginhost", - "classnamemanager", - "event-focus", - "node-base", - "node-style" - ], - "skinnable": true - }, - "widget-base-ie": { - "condition": { - "name": "widget-base-ie", - "trigger": "widget-base", - "ua": "ie" - }, - "requires": [ - "widget-base" - ] - }, - "widget-buttons": { - "requires": [ - "button-plugin", - "cssbutton", - "widget-stdmod" - ] - }, - "widget-child": { - "requires": [ - "base-build", - "widget" - ] - }, - "widget-htmlparser": { - "requires": [ - "widget-base" - ] - }, - "widget-modality": { - "requires": [ - "base-build", - "event-outside", - "widget" - ], - "skinnable": true - }, - "widget-parent": { - "requires": [ - "arraylist", - "base-build", - "widget" - ] - }, - "widget-position": { - "requires": [ - "base-build", - "node-screen", - "widget" - ] - }, - "widget-position-align": { - "requires": [ - "widget-position" - ] - }, - "widget-position-constrain": { - "requires": [ - "widget-position" - ] - }, - "widget-skin": { - "requires": [ - "widget-base" - ] - }, - "widget-stack": { - "requires": [ - "base-build", - "widget" - ], - "skinnable": true - }, - "widget-stdmod": { - "requires": [ - "base-build", - "widget" - ] - }, - "widget-uievents": { - "requires": [ - "node-event-delegate", - "widget-base" - ] - }, - "yql": { - "requires": [ - "oop" - ] - }, - "yql-jsonp": { - "condition": { - "name": "yql-jsonp", - "test": function (Y) { - /* Only load the JSONP module when not in nodejs or winjs - TODO Make the winjs module a CORS module - */ - return (!Y.UA.nodejs && !Y.UA.winjs); -}, - "trigger": "yql" - }, - "requires": [ - "yql", - "jsonp", - "jsonp-url" - ] - }, - "yql-nodejs": { - "condition": { - "name": "yql-nodejs", - "trigger": "yql", - "ua": "nodejs" - }, - "requires": [ - "yql" - ] - }, - "yql-winjs": { - "condition": { - "name": "yql-winjs", - "trigger": "yql", - "ua": "winjs" - }, - "requires": [ - "yql" - ] - }, - "yui": {}, - "yui-base": {}, - "yui-later": { - "requires": [ - "yui-base" - ] - }, - "yui-log": { - "requires": [ - "yui-base" - ] - }, - "yui-throttle": { - "requires": [ - "yui-base" - ] - } -}); -YUI.Env[Y.version].md5 = 'e61397b06e7b9d3e4298ee7a7a4ea6a1'; - - -}, '@VERSION@', {"requires": ["loader-base"]}); -YUI.add('loader', function (Y, NAME) {}, '@VERSION@', {"use": ["loader-base", "loader-rollup", "loader-yui3"]}); - -define("yui-loader", ["yui-base"], (function (global) { - return function () { - var ret, fn; - return ret || global.YUI; - }; -}(this))); - -/* -YUI 3.16.0 (build 76f0e08) -Copyright 2014 Yahoo! Inc. All rights reserved. -Licensed under the BSD License. -http://yuilibrary.com/license/ -*/ - -YUI.add('event-focus', function (Y, NAME) { - -/** - * Adds bubbling and delegation support to DOM events focus and blur. - * - * @module event - * @submodule event-focus - */ -var Event = Y.Event, - - YLang = Y.Lang, - - isString = YLang.isString, - - arrayIndex = Y.Array.indexOf, - - useActivate = (function() { - - // Changing the structure of this test, so that it doesn't use inline JS in HTML, - // which throws an exception in Win8 packaged apps, due to additional security restrictions: - // http://msdn.microsoft.com/en-us/library/windows/apps/hh465380.aspx#differences - - var supported = false, - doc = Y.config.doc, - p; - - if (doc) { - - p = doc.createElement("p"); - p.setAttribute("onbeforeactivate", ";"); - - // onbeforeactivate is a function in IE8+. - // onbeforeactivate is a string in IE6,7 (unfortunate, otherwise we could have just checked for function below). - // onbeforeactivate is a function in IE10, in a Win8 App environment (no exception running the test). - - // onbeforeactivate is undefined in Webkit/Gecko. - // onbeforeactivate is a function in Webkit/Gecko if it's a supported event (e.g. onclick). - - supported = (p.onbeforeactivate !== undefined); - } - - return supported; - }()); - -function define(type, proxy, directEvent) { - var nodeDataKey = '_' + type + 'Notifiers'; - - Y.Event.define(type, { - - _useActivate : useActivate, - - _attach: function (el, notifier, delegate) { - if (Y.DOM.isWindow(el)) { - return Event._attach([type, function (e) { - notifier.fire(e); - }, el]); - } else { - return Event._attach( - [proxy, this._proxy, el, this, notifier, delegate], - { capture: true }); - } - }, - - _proxy: function (e, notifier, delegate) { - var target = e.target, - currentTarget = e.currentTarget, - notifiers = target.getData(nodeDataKey), - yuid = Y.stamp(currentTarget._node), - defer = (useActivate || target !== currentTarget), - directSub; - - notifier.currentTarget = (delegate) ? target : currentTarget; - notifier.container = (delegate) ? currentTarget : null; - - // Maintain a list to handle subscriptions from nested - // containers div#a>div#b>input #a.on(focus..) #b.on(focus..), - // use one focus or blur subscription that fires notifiers from - // #b then #a to emulate bubble sequence. - if (!notifiers) { - notifiers = {}; - target.setData(nodeDataKey, notifiers); - - // only subscribe to the element's focus if the target is - // not the current target ( - if (defer) { - directSub = Event._attach( - [directEvent, this._notify, target._node]).sub; - directSub.once = true; - } - } else { - // In old IE, defer is always true. In capture-phase browsers, - // The delegate subscriptions will be encountered first, which - // will establish the notifiers data and direct subscription - // on the node. If there is also a direct subscription to the - // node's focus/blur, it should not call _notify because the - // direct subscription from the delegate sub(s) exists, which - // will call _notify. So this avoids _notify being called - // twice, unnecessarily. - defer = true; - } - - if (!notifiers[yuid]) { - notifiers[yuid] = []; - } - - notifiers[yuid].push(notifier); - - if (!defer) { - this._notify(e); - } - }, - - _notify: function (e, container) { - var currentTarget = e.currentTarget, - notifierData = currentTarget.getData(nodeDataKey), - axisNodes = currentTarget.ancestors(), - doc = currentTarget.get('ownerDocument'), - delegates = [], - // Used to escape loops when there are no more - // notifiers to consider - count = notifierData ? - Y.Object.keys(notifierData).length : - 0, - target, notifiers, notifier, yuid, match, tmp, i, len, sub, ret; - - // clear the notifications list (mainly for delegation) - currentTarget.clearData(nodeDataKey); - - // Order the delegate subs by their placement in the parent axis - axisNodes.push(currentTarget); - // document.get('ownerDocument') returns null - // which we'll use to prevent having duplicate Nodes in the list - if (doc) { - axisNodes.unshift(doc); - } - - // ancestors() returns the Nodes from top to bottom - axisNodes._nodes.reverse(); - - if (count) { - // Store the count for step 2 - tmp = count; - axisNodes.some(function (node) { - var yuid = Y.stamp(node), - notifiers = notifierData[yuid], - i, len; - - if (notifiers) { - count--; - for (i = 0, len = notifiers.length; i < len; ++i) { - if (notifiers[i].handle.sub.filter) { - delegates.push(notifiers[i]); - } - } - } - - return !count; - }); - count = tmp; - } - - // Walk up the parent axis, notifying direct subscriptions and - // testing delegate filters. - while (count && (target = axisNodes.shift())) { - yuid = Y.stamp(target); - - notifiers = notifierData[yuid]; - - if (notifiers) { - for (i = 0, len = notifiers.length; i < len; ++i) { - notifier = notifiers[i]; - sub = notifier.handle.sub; - match = true; - - e.currentTarget = target; - - if (sub.filter) { - match = sub.filter.apply(target, - [target, e].concat(sub.args || [])); - - // No longer necessary to test against this - // delegate subscription for the nodes along - // the parent axis. - delegates.splice( - arrayIndex(delegates, notifier), 1); - } - - if (match) { - // undefined for direct subs - e.container = notifier.container; - ret = notifier.fire(e); - } - - if (ret === false || e.stopped === 2) { - break; - } - } - - delete notifiers[yuid]; - count--; - } - - if (e.stopped !== 2) { - // delegates come after subs targeting this specific node - // because they would not normally report until they'd - // bubbled to the container node. - for (i = 0, len = delegates.length; i < len; ++i) { - notifier = delegates[i]; - sub = notifier.handle.sub; - - if (sub.filter.apply(target, - [target, e].concat(sub.args || []))) { - - e.container = notifier.container; - e.currentTarget = target; - ret = notifier.fire(e); - } - - if (ret === false || e.stopped === 2 || - // If e.stopPropagation() is called, notify any - // delegate subs from the same container, but break - // once the container changes. This emulates - // delegate() behavior for events like 'click' which - // won't notify delegates higher up the parent axis. - (e.stopped && delegates[i+1] && - delegates[i+1].container !== notifier.container)) { - break; - } - } - } - - if (e.stopped) { - break; - } - } - }, - - on: function (node, sub, notifier) { - sub.handle = this._attach(node._node, notifier); - }, - - detach: function (node, sub) { - sub.handle.detach(); - }, - - delegate: function (node, sub, notifier, filter) { - if (isString(filter)) { - sub.filter = function (target) { - return Y.Selector.test(target._node, filter, - node === target ? null : node._node); - }; - } - - sub.handle = this._attach(node._node, notifier, true); - }, - - detachDelegate: function (node, sub) { - sub.handle.detach(); - } - }, true); -} - -// For IE, we need to defer to focusin rather than focus because -// `el.focus(); doSomething();` executes el.onbeforeactivate, el.onactivate, -// el.onfocusin, doSomething, then el.onfocus. All others support capture -// phase focus, which executes before doSomething. To guarantee consistent -// behavior for this use case, IE's direct subscriptions are made against -// focusin so subscribers will be notified before js following el.focus() is -// executed. -if (useActivate) { - // name capture phase direct subscription - define("focus", "beforeactivate", "focusin"); - define("blur", "beforedeactivate", "focusout"); -} else { - define("focus", "focus", "focus"); - define("blur", "blur", "blur"); -} - - -}, '3.16.0', {"requires": ["event-synthetic"]}); -/* -YUI 3.16.0 (build 76f0e08) -Copyright 2014 Yahoo! Inc. All rights reserved. -Licensed under the BSD License. -http://yuilibrary.com/license/ -*/ - -YUI.add('node-style', function (Y, NAME) { - -(function(Y) { -/** - * Extended Node interface for managing node styles. - * @module node - * @submodule node-style - */ - -Y.mix(Y.Node.prototype, { - /** - * Sets a style property of the node. - * Use camelCase (e.g. 'backgroundColor') for multi-word properties. - * @method setStyle - * @param {String} attr The style attribute to set. - * @param {String|Number} val The value. - * @chainable - */ - setStyle: function(attr, val) { - Y.DOM.setStyle(this._node, attr, val); - return this; - }, - - /** - * Sets multiple style properties on the node. - * Use camelCase (e.g. 'backgroundColor') for multi-word properties. - * @method setStyles - * @param {Object} hash An object literal of property:value pairs. - * @chainable - */ - setStyles: function(hash) { - Y.DOM.setStyles(this._node, hash); - return this; - }, - - /** - * Returns the style's current value. - * Use camelCase (e.g. 'backgroundColor') for multi-word properties. - * @method getStyle - * @for Node - * @param {String} attr The style attribute to retrieve. - * @return {String} The current value of the style property for the element. - */ - - getStyle: function(attr) { - return Y.DOM.getStyle(this._node, attr); - }, - - /** - * Returns the computed value for the given style property. - * Use camelCase (e.g. 'backgroundColor') for multi-word properties. - * @method getComputedStyle - * @param {String} attr The style attribute to retrieve. - * @return {String} The computed value of the style property for the element. - */ - getComputedStyle: function(attr) { - return Y.DOM.getComputedStyle(this._node, attr); - } -}); - -/** - * Returns an array of values for each node. - * Use camelCase (e.g. 'backgroundColor') for multi-word properties. - * @method getStyle - * @for NodeList - * @see Node.getStyle - * @param {String} attr The style attribute to retrieve. - * @return {Array} The current values of the style property for the element. - */ - -/** - * Returns an array of the computed value for each node. - * Use camelCase (e.g. 'backgroundColor') for multi-word properties. - * @method getComputedStyle - * @see Node.getComputedStyle - * @param {String} attr The style attribute to retrieve. - * @return {Array} The computed values for each node. - */ - -/** - * Sets a style property on each node. - * Use camelCase (e.g. 'backgroundColor') for multi-word properties. - * @method setStyle - * @see Node.setStyle - * @param {String} attr The style attribute to set. - * @param {String|Number} val The value. - * @chainable - */ - -/** - * Sets multiple style properties on each node. - * Use camelCase (e.g. 'backgroundColor') for multi-word properties. - * @method setStyles - * @see Node.setStyles - * @param {Object} hash An object literal of property:value pairs. - * @chainable - */ - -// These are broken out to handle undefined return (avoid false positive for -// chainable) - -Y.NodeList.importMethod(Y.Node.prototype, ['getStyle', 'getComputedStyle', 'setStyle', 'setStyles']); -})(Y); -/** - * @module node - * @submodule node-base - */ - -var Y_Node = Y.Node; - -Y.mix(Y_Node.prototype, { - /** - * Makes the node visible. - * If the "transition" module is loaded, show optionally - * animates the showing of the node using either the default - * transition effect ('fadeIn'), or the given named effect. - * @method show - * @for Node - * @param {String} name A named Transition effect to use as the show effect. - * @param {Object} config Options to use with the transition. - * @param {Function} callback An optional function to run after the transition completes. - * @chainable - */ - show: function(callback) { - callback = arguments[arguments.length - 1]; - this.toggleView(true, callback); - return this; - }, - - /** - * The implementation for showing nodes. - * Default is to remove the hidden attribute and reset the CSS style.display property. - * @method _show - * @protected - * @chainable - */ - _show: function() { - this.removeAttribute('hidden'); - - // For back-compat we need to leave this in for browsers that - // do not visually hide a node via the hidden attribute - // and for users that check visibility based on style display. - this.setStyle('display', ''); - - }, - - /** - Returns whether the node is hidden by YUI or not. The hidden status is - determined by the 'hidden' attribute and the value of the 'display' CSS - property. - - @method _isHidden - @return {Boolean} `true` if the node is hidden. - @private - **/ - _isHidden: function() { - return this.hasAttribute('hidden') || Y.DOM.getComputedStyle(this._node, 'display') === 'none'; - }, - - /** - * Displays or hides the node. - * If the "transition" module is loaded, toggleView optionally - * animates the toggling of the node using given named effect. - * @method toggleView - * @for Node - * @param {Boolean} [on] An optional boolean value to force the node to be shown or hidden - * @param {Function} [callback] An optional function to run after the transition completes. - * @chainable - */ - toggleView: function(on, callback) { - this._toggleView.apply(this, arguments); - return this; - }, - - _toggleView: function(on, callback) { - callback = arguments[arguments.length - 1]; - - // base on current state if not forcing - if (typeof on != 'boolean') { - on = (this._isHidden()) ? 1 : 0; - } - - if (on) { - this._show(); - } else { - this._hide(); - } - - if (typeof callback == 'function') { - callback.call(this); - } - - return this; - }, - - /** - * Hides the node. - * If the "transition" module is loaded, hide optionally - * animates the hiding of the node using either the default - * transition effect ('fadeOut'), or the given named effect. - * @method hide - * @param {String} name A named Transition effect to use as the show effect. - * @param {Object} config Options to use with the transition. - * @param {Function} callback An optional function to run after the transition completes. - * @chainable - */ - hide: function(callback) { - callback = arguments[arguments.length - 1]; - this.toggleView(false, callback); - return this; - }, - - /** - * The implementation for hiding nodes. - * Default is to set the hidden attribute to true and set the CSS style.display to 'none'. - * @method _hide - * @protected - * @chainable - */ - _hide: function() { - this.setAttribute('hidden', 'hidden'); - - // For back-compat we need to leave this in for browsers that - // do not visually hide a node via the hidden attribute - // and for users that check visibility based on style display. - this.setStyle('display', 'none'); - } -}); - -Y.NodeList.importMethod(Y.Node.prototype, [ - /** - * Makes each node visible. - * If the "transition" module is loaded, show optionally - * animates the showing of the node using either the default - * transition effect ('fadeIn'), or the given named effect. - * @method show - * @param {String} name A named Transition effect to use as the show effect. - * @param {Object} config Options to use with the transition. - * @param {Function} callback An optional function to run after the transition completes. - * @for NodeList - * @chainable - */ - 'show', - - /** - * Hides each node. - * If the "transition" module is loaded, hide optionally - * animates the hiding of the node using either the default - * transition effect ('fadeOut'), or the given named effect. - * @method hide - * @param {String} name A named Transition effect to use as the show effect. - * @param {Object} config Options to use with the transition. - * @param {Function} callback An optional function to run after the transition completes. - * @chainable - */ - 'hide', - - /** - * Displays or hides each node. - * If the "transition" module is loaded, toggleView optionally - * animates the toggling of the nodes using given named effect. - * @method toggleView - * @param {Boolean} [on] An optional boolean value to force the nodes to be shown or hidden - * @param {Function} [callback] An optional function to run after the transition completes. - * @chainable - */ - 'toggleView' -]); - - -}, '3.16.0', {"requires": ["dom-style", "node-base"]}); -/* -YUI 3.16.0 (build 76f0e08) -Copyright 2014 Yahoo! Inc. All rights reserved. -Licensed under the BSD License. -http://yuilibrary.com/license/ -*/ - -YUI.add('widget-base', function (Y, NAME) { - -/** - * Provides the base Widget class, with HTML Parser support - * - * @module widget - * @main widget - */ - -/** - * Provides the base Widget class - * - * @module widget - * @submodule widget-base - */ -var L = Y.Lang, - Node = Y.Node, - - ClassNameManager = Y.ClassNameManager, - - _getClassName = ClassNameManager.getClassName, - _getWidgetClassName, - - _toInitialCap = Y.cached(function(str) { - return str.substring(0, 1).toUpperCase() + str.substring(1); - }), - - // K-Weight, IE GC optimizations - CONTENT = "content", - VISIBLE = "visible", - HIDDEN = "hidden", - DISABLED = "disabled", - FOCUSED = "focused", - WIDTH = "width", - HEIGHT = "height", - BOUNDING_BOX = "boundingBox", - CONTENT_BOX = "contentBox", - PARENT_NODE = "parentNode", - OWNER_DOCUMENT = "ownerDocument", - AUTO = "auto", - SRC_NODE = "srcNode", - BODY = "body", - TAB_INDEX = "tabIndex", - ID = "id", - RENDER = "render", - RENDERED = "rendered", - DESTROYED = "destroyed", - STRINGS = "strings", - DIV = "
", - CHANGE = "Change", - LOADING = "loading", - - _UISET = "_uiSet", - - EMPTY_STR = "", - EMPTY_FN = function() {}, - - TRUE = true, - FALSE = false, - - UI, - ATTRS = {}, - UI_ATTRS = [VISIBLE, DISABLED, HEIGHT, WIDTH, FOCUSED, TAB_INDEX], - - WEBKIT = Y.UA.webkit, - - // Widget nodeid-to-instance map. - _instances = {}; - -/** - * A base class for widgets, providing: - *
    - *
  • The render lifecycle method, in addition to the init and destroy - * lifecycle methods provide by Base
  • - *
  • Abstract methods to support consistent MVC structure across - * widgets: renderer, renderUI, bindUI, syncUI
  • - *
  • Support for common widget attributes, such as boundingBox, contentBox, visible, - * disabled, focused, strings
  • - *
- * - * @param config {Object} Object literal specifying widget configuration properties. - * - * @class Widget - * @constructor - * @extends Base - */ -function Widget(config) { - - // kweight - var widget = this, - parentNode, - render, - constructor = widget.constructor; - - widget._strs = {}; - widget._cssPrefix = constructor.CSS_PREFIX || _getClassName(constructor.NAME.toLowerCase()); - - // We need a config for HTML_PARSER to work. - config = config || {}; - - Widget.superclass.constructor.call(widget, config); - - render = widget.get(RENDER); - - if (render) { - // Render could be a node or boolean - if (render !== TRUE) { - parentNode = render; - } - widget.render(parentNode); - } -} - -/** - * Static property provides a string to identify the class. - *

- * Currently used to apply class identifiers to the bounding box - * and to classify events fired by the widget. - *

- * - * @property NAME - * @type String - * @static - */ -Widget.NAME = "widget"; - -/** - * Constant used to identify state changes originating from - * the DOM (as opposed to the JavaScript model). - * - * @property UI_SRC - * @type String - * @static - * @final - */ -UI = Widget.UI_SRC = "ui"; - -/** - * Static property used to define the default attribute - * configuration for the Widget. - * - * @property ATTRS - * @type Object - * @static - */ -Widget.ATTRS = ATTRS; - -// Trying to optimize kweight by setting up attrs this way saves about 0.4K min'd - -/** - * @attribute id - * @writeOnce - * @default Generated using guid() - * @type String - */ - -ATTRS[ID] = { - valueFn: "_guid", - writeOnce: TRUE -}; - -/** - * Flag indicating whether or not this Widget - * has been through the render lifecycle phase. - * - * @attribute rendered - * @readOnly - * @default false - * @type boolean - */ -ATTRS[RENDERED] = { - value:FALSE, - readOnly: TRUE -}; - -/** - * @attribute boundingBox - * @description The outermost DOM node for the Widget, used for sizing and positioning - * of a Widget as well as a containing element for any decorator elements used - * for skinning. - * @type String | Node - * @writeOnce - */ -ATTRS[BOUNDING_BOX] = { - valueFn:"_defaultBB", - setter: "_setBB", - writeOnce: TRUE -}; - -/** - * @attribute contentBox - * @description A DOM node that is a direct descendant of a Widget's bounding box that - * houses its content. - * @type String | Node - * @writeOnce - */ -ATTRS[CONTENT_BOX] = { - valueFn:"_defaultCB", - setter: "_setCB", - writeOnce: TRUE -}; - -/** - * @attribute tabIndex - * @description Number (between -32767 to 32767) indicating the widget's - * position in the default tab flow. The value is used to set the - * "tabIndex" attribute on the widget's bounding box. Negative values allow - * the widget to receive DOM focus programmatically (by calling the focus - * method), while being removed from the default tab flow. A value of - * null removes the "tabIndex" attribute from the widget's bounding box. - * @type Number - * @default null - */ -ATTRS[TAB_INDEX] = { - value: null, - validator: "_validTabIndex" -}; - -/** - * @attribute focused - * @description Boolean indicating if the Widget, or one of its descendants, - * has focus. - * @readOnly - * @default false - * @type boolean - */ -ATTRS[FOCUSED] = { - value: FALSE, - readOnly:TRUE -}; - -/** - * @attribute disabled - * @description Boolean indicating if the Widget should be disabled. The disabled implementation - * is left to the specific classes extending widget. - * @default false - * @type boolean - */ -ATTRS[DISABLED] = { - value: FALSE -}; - -/** - * @attribute visible - * @description Boolean indicating whether or not the Widget is visible. - * @default TRUE - * @type boolean - */ -ATTRS[VISIBLE] = { - value: TRUE -}; - -/** - * @attribute height - * @description String with units, or number, representing the height of the Widget. If a number is provided, - * the default unit, defined by the Widgets DEF_UNIT, property is used. - * @default EMPTY_STR - * @type {String | Number} - */ -ATTRS[HEIGHT] = { - value: EMPTY_STR -}; - -/** - * @attribute width - * @description String with units, or number, representing the width of the Widget. If a number is provided, - * the default unit, defined by the Widgets DEF_UNIT, property is used. - * @default EMPTY_STR - * @type {String | Number} - */ -ATTRS[WIDTH] = { - value: EMPTY_STR -}; - -/** - * @attribute strings - * @description Collection of strings used to label elements of the Widget's UI. - * @default null - * @type Object - */ -ATTRS[STRINGS] = { - value: {}, - setter: "_strSetter", - getter: "_strGetter" -}; - -/** - * Whether or not to render the widget automatically after init, and optionally, to which parent node. - * - * @attribute render - * @type boolean | Node - * @writeOnce - */ -ATTRS[RENDER] = { - value:FALSE, - writeOnce:TRUE -}; - -/** - * The css prefix which the static Widget.getClassName method should use when constructing class names - * - * @property CSS_PREFIX - * @type String - * @default Widget.NAME.toLowerCase() - * @private - * @static - */ -Widget.CSS_PREFIX = _getClassName(Widget.NAME.toLowerCase()); - -/** - * Generate a standard prefixed classname for the Widget, prefixed by the default prefix defined - * by the Y.config.classNamePrefix attribute used by ClassNameManager and - * Widget.NAME.toLowerCase() (e.g. "yui-widget-xxxxx-yyyyy", based on default values for - * the prefix and widget class name). - *

- * The instance based version of this method can be used to generate standard prefixed classnames, - * based on the instances NAME, as opposed to Widget.NAME. This method should be used when you - * need to use a constant class name across different types instances. - *

- * @method getClassName - * @param {String*} args* 0..n strings which should be concatenated, using the default separator defined by ClassNameManager, to create the class name - */ -Widget.getClassName = function() { - // arguments needs to be array'fied to concat - return _getClassName.apply(ClassNameManager, [Widget.CSS_PREFIX].concat(Y.Array(arguments), true)); -}; - -_getWidgetClassName = Widget.getClassName; - -/** - * Returns the widget instance whose bounding box contains, or is, the given node. - *

- * In the case of nested widgets, the nearest bounding box ancestor is used to - * return the widget instance. - *

- * @method getByNode - * @static - * @param node {Node | String} The node for which to return a Widget instance. If a selector - * string is passed in, which selects more than one node, the first node found is used. - * @return {Widget} Widget instance, or null if not found. - */ -Widget.getByNode = function(node) { - var widget, - widgetMarker = _getWidgetClassName(); - - node = Node.one(node); - if (node) { - node = node.ancestor("." + widgetMarker, true); - if (node) { - widget = _instances[Y.stamp(node, true)]; - } - } - - return widget || null; -}; - -Y.extend(Widget, Y.Base, { - - /** - * Returns a class name prefixed with the the value of the - * YUI.config.classNamePrefix attribute + the instances NAME property. - * Uses YUI.config.classNameDelimiter attribute to delimit the provided strings. - * e.g. - * - *
-     *    // returns "yui-slider-foo-bar", for a slider instance
-     *    var scn = slider.getClassName('foo','bar');
-     *
-     *    // returns "yui-overlay-foo-bar", for an overlay instance
-     *    var ocn = overlay.getClassName('foo','bar');
-     * 
- *
- * - * @method getClassName - * @param {String} [classnames*] One or more classname bits to be joined and prefixed - */ - getClassName: function () { - return _getClassName.apply(ClassNameManager, [this._cssPrefix].concat(Y.Array(arguments), true)); - }, - - /** - * Initializer lifecycle implementation for the Widget class. Registers the - * widget instance, and runs through the Widget's HTML_PARSER definition. - * - * @method initializer - * @protected - * @param config {Object} Configuration object literal for the widget - */ - initializer: function(config) { - - var bb = this.get(BOUNDING_BOX); - - if (bb instanceof Node) { - this._mapInstance(Y.stamp(bb)); - } - - /** - * Notification event, which widget implementations can fire, when - * they change the content of the widget. This event has no default - * behavior and cannot be prevented, so the "on" or "after" - * moments are effectively equivalent (with on listeners being invoked before - * after listeners). - * - * @event widget:contentUpdate - * @preventable false - * @param {EventFacade} e The Event Facade - */ - }, - - /** - * Utility method used to add an entry to the boundingBox id to instance map. - * - * This method can be used to populate the instance with lazily created boundingBox Node references. - * - * @method _mapInstance - * @param {String} The boundingBox id - * @protected - */ - _mapInstance : function(id) { - _instances[id] = this; - }, - - /** - * Destructor lifecycle implementation for the Widget class. Purges events attached - * to the bounding box and content box, removes them from the DOM and removes - * the Widget from the list of registered widgets. - * - * @method destructor - * @protected - */ - destructor: function() { - - var boundingBox = this.get(BOUNDING_BOX), - bbGuid; - - if (boundingBox instanceof Node) { - bbGuid = Y.stamp(boundingBox,true); - - if (bbGuid in _instances) { - delete _instances[bbGuid]; - } - - this._destroyBox(); - } - }, - - /** - *

- * Destroy lifecycle method. Fires the destroy - * event, prior to invoking destructors for the - * class hierarchy. - * - * Overrides Base's implementation, to support arguments to destroy - *

- *

- * Subscribers to the destroy - * event can invoke preventDefault on the event object, to prevent destruction - * from proceeding. - *

- * @method destroy - * @param destroyAllNodes {Boolean} If true, all nodes contained within the Widget are - * removed and destroyed. Defaults to false due to potentially high run-time cost. - * @return {Widget} A reference to this object - * @chainable - */ - destroy: function(destroyAllNodes) { - this._destroyAllNodes = destroyAllNodes; - return Widget.superclass.destroy.apply(this); - }, - - /** - * Removes and destroys the widgets rendered boundingBox, contentBox, - * and detaches bound UI events. - * - * @method _destroyBox - * @protected - */ - _destroyBox : function() { - - var boundingBox = this.get(BOUNDING_BOX), - contentBox = this.get(CONTENT_BOX), - deep = this._destroyAllNodes, - same; - - same = boundingBox && boundingBox.compareTo(contentBox); - - if (this.UI_EVENTS) { - this._destroyUIEvents(); - } - - this._unbindUI(boundingBox); - - if (contentBox) { - if (deep) { - contentBox.empty(); - } - contentBox.remove(TRUE); - } - - if (!same) { - if (deep) { - boundingBox.empty(); - } - boundingBox.remove(TRUE); - } - }, - - /** - * Establishes the initial DOM for the widget. Invoking this - * method will lead to the creating of all DOM elements for - * the widget (or the manipulation of existing DOM elements - * for the progressive enhancement use case). - *

- * This method should only be invoked once for an initialized - * widget. - *

- *

- * It delegates to the widget specific renderer method to do - * the actual work. - *

- * - * @method render - * @chainable - * @final - * @param parentNode {Object | String} Optional. The Node under which the - * Widget is to be rendered. This can be a Node instance or a CSS selector string. - *

- * If the selector string returns more than one Node, the first node will be used - * as the parentNode. NOTE: This argument is required if both the boundingBox and contentBox - * are not currently in the document. If it's not provided, the Widget will be rendered - * to the body of the current document in this case. - *

- */ - render: function(parentNode) { - - if (!this.get(DESTROYED) && !this.get(RENDERED)) { - /** - * Lifecycle event for the render phase, fired prior to rendering the UI - * for the widget (prior to invoking the widget's renderer method). - *

- * Subscribers to the "on" moment of this event, will be notified - * before the widget is rendered. - *

- *

- * Subscribers to the "after" moment of this event, will be notified - * after rendering is complete. - *

- * - * @event render - * @preventable _defRenderFn - * @param {EventFacade} e The Event Facade - */ - this.publish(RENDER, { - queuable:FALSE, - fireOnce:TRUE, - defaultTargetOnly:TRUE, - defaultFn: this._defRenderFn - }); - - this.fire(RENDER, {parentNode: (parentNode) ? Node.one(parentNode) : null}); - } - return this; - }, - - /** - * Default render handler - * - * @method _defRenderFn - * @protected - * @param {EventFacade} e The Event object - * @param {Node} parentNode The parent node to render to, if passed in to the render method - */ - _defRenderFn : function(e) { - this._parentNode = e.parentNode; - - this.renderer(); - this._set(RENDERED, TRUE); - - this._removeLoadingClassNames(); - }, - - /** - * Creates DOM (or manipulates DOM for progressive enhancement) - * This method is invoked by render() and is not chained - * automatically for the class hierarchy (unlike initializer, destructor) - * so it should be chained manually for subclasses if required. - * - * @method renderer - * @protected - */ - renderer: function() { - // kweight - var widget = this; - - widget._renderUI(); - widget.renderUI(); - - widget._bindUI(); - widget.bindUI(); - - widget._syncUI(); - widget.syncUI(); - }, - - /** - * Configures/Sets up listeners to bind Widget State to UI/DOM - * - * This method is not called by framework and is not chained - * automatically for the class hierarchy. - * - * @method bindUI - * @protected - */ - bindUI: EMPTY_FN, - - /** - * Adds nodes to the DOM - * - * This method is not called by framework and is not chained - * automatically for the class hierarchy. - * - * @method renderUI - * @protected - */ - renderUI: EMPTY_FN, - - /** - * Refreshes the rendered UI, based on Widget State - * - * This method is not called by framework and is not chained - * automatically for the class hierarchy. - * - * @method syncUI - * @protected - * - */ - syncUI: EMPTY_FN, - - /** - * @method hide - * @description Hides the Widget by setting the "visible" attribute to "false". - * @chainable - */ - hide: function() { - return this.set(VISIBLE, FALSE); - }, - - /** - * @method show - * @description Shows the Widget by setting the "visible" attribute to "true". - * @chainable - */ - show: function() { - return this.set(VISIBLE, TRUE); - }, - - /** - * @method focus - * @description Causes the Widget to receive the focus by setting the "focused" - * attribute to "true". - * @chainable - */ - focus: function () { - return this._set(FOCUSED, TRUE); - }, - - /** - * @method blur - * @description Causes the Widget to lose focus by setting the "focused" attribute - * to "false" - * @chainable - */ - blur: function () { - return this._set(FOCUSED, FALSE); - }, - - /** - * @method enable - * @description Set the Widget's "disabled" attribute to "false". - * @chainable - */ - enable: function() { - return this.set(DISABLED, FALSE); - }, - - /** - * @method disable - * @description Set the Widget's "disabled" attribute to "true". - * @chainable - */ - disable: function() { - return this.set(DISABLED, TRUE); - }, - - /** - * @method _uiSizeCB - * @protected - * @param {boolean} expand - */ - _uiSizeCB : function(expand) { - this.get(CONTENT_BOX).toggleClass(_getWidgetClassName(CONTENT, "expanded"), expand); - }, - - /** - * Helper method to collect the boundingBox and contentBox and append to the provided parentNode, if not - * already a child. The owner document of the boundingBox, or the owner document of the contentBox will be used - * as the document into which the Widget is rendered if a parentNode is node is not provided. If both the boundingBox and - * the contentBox are not currently in the document, and no parentNode is provided, the widget will be rendered - * to the current document's body. - * - * @method _renderBox - * @private - * @param {Node} parentNode The parentNode to render the widget to. If not provided, and both the boundingBox and - * the contentBox are not currently in the document, the widget will be rendered to the current document's body. - */ - _renderBox: function(parentNode) { - - // TODO: Performance Optimization [ More effective algo to reduce Node refs, compares, replaces? ] - - var widget = this, // kweight - contentBox = widget.get(CONTENT_BOX), - boundingBox = widget.get(BOUNDING_BOX), - srcNode = widget.get(SRC_NODE), - defParentNode = widget.DEF_PARENT_NODE, - - doc = (srcNode && srcNode.get(OWNER_DOCUMENT)) || boundingBox.get(OWNER_DOCUMENT) || contentBox.get(OWNER_DOCUMENT); - - // If srcNode (assume it's always in doc), have contentBox take its place (widget render responsible for re-use of srcNode contents) - if (srcNode && !srcNode.compareTo(contentBox) && !contentBox.inDoc(doc)) { - srcNode.replace(contentBox); - } - - if (!boundingBox.compareTo(contentBox.get(PARENT_NODE)) && !boundingBox.compareTo(contentBox)) { - // If contentBox box is already in the document, have boundingBox box take it's place - if (contentBox.inDoc(doc)) { - contentBox.replace(boundingBox); - } - boundingBox.appendChild(contentBox); - } - - parentNode = parentNode || (defParentNode && Node.one(defParentNode)); - - if (parentNode) { - parentNode.appendChild(boundingBox); - } else if (!boundingBox.inDoc(doc)) { - Node.one(BODY).insert(boundingBox, 0); - } - }, - - /** - * Setter for the boundingBox attribute - * - * @method _setBB - * @private - * @param {Node|String} node - * @return Node - */ - _setBB: function(node) { - return this._setBox(this.get(ID), node, this.BOUNDING_TEMPLATE, true); - }, - - /** - * Setter for the contentBox attribute - * - * @method _setCB - * @private - * @param {Node|String} node - * @return Node - */ - _setCB: function(node) { - return (this.CONTENT_TEMPLATE === null) ? this.get(BOUNDING_BOX) : this._setBox(null, node, this.CONTENT_TEMPLATE, false); - }, - - /** - * Returns the default value for the boundingBox attribute. - * - * For the Widget class, this will most commonly be null (resulting in a new - * boundingBox node instance being created), unless a srcNode was provided - * and CONTENT_TEMPLATE is null, in which case it will be srcNode. - * This behavior was introduced in 3.16.0 to accomodate single-box widgets - * whose BB & CB both point to srcNode (e.g. Y.Button). - * - * @method _defaultBB - * @protected - */ - _defaultBB : function() { - var node = this.get(SRC_NODE), - nullCT = (this.CONTENT_TEMPLATE === null); - - return ((node && nullCT) ? node : null); - }, - - /** - * Returns the default value for the contentBox attribute. - * - * For the Widget class, this will be the srcNode if provided, otherwise null (resulting in - * a new contentBox node instance being created) - * - * @method _defaultCB - * @protected - */ - _defaultCB : function(node) { - return this.get(SRC_NODE) || null; - }, - - /** - * Helper method to set the bounding/content box, or create it from - * the provided template if not found. - * - * @method _setBox - * @private - * - * @param {String} id The node's id attribute - * @param {Node|String} node The node reference - * @param {String} template HTML string template for the node - * @param {boolean} isBounding true if this is the boundingBox, false if it's the contentBox - * @return {Node} The node - */ - _setBox : function(id, node, template, isBounding) { - - node = Node.one(node); - - if (!node) { - node = Node.create(template); - - if (isBounding) { - this._bbFromTemplate = true; - } else { - this._cbFromTemplate = true; - } - } - - if (!node.get(ID)) { - node.set(ID, id || Y.guid()); - } - - return node; - }, - - /** - * Initializes the UI state for the Widget's bounding/content boxes. - * - * @method _renderUI - * @protected - */ - _renderUI: function() { - this._renderBoxClassNames(); - this._renderBox(this._parentNode); - }, - - /** - * Applies standard class names to the boundingBox and contentBox - * - * @method _renderBoxClassNames - * @protected - */ - _renderBoxClassNames : function() { - var classes = this._getClasses(), - cl, - boundingBox = this.get(BOUNDING_BOX), - i; - - boundingBox.addClass(_getWidgetClassName()); - - // Start from Widget Sub Class - for (i = classes.length-3; i >= 0; i--) { - cl = classes[i]; - boundingBox.addClass(cl.CSS_PREFIX || _getClassName(cl.NAME.toLowerCase())); - } - - // Use instance based name for content box - this.get(CONTENT_BOX).addClass(this.getClassName(CONTENT)); - }, - - /** - * Removes class names representative of the widget's loading state from - * the boundingBox. - * - * @method _removeLoadingClassNames - * @protected - */ - _removeLoadingClassNames: function () { - - var boundingBox = this.get(BOUNDING_BOX), - contentBox = this.get(CONTENT_BOX), - instClass = this.getClassName(LOADING), - widgetClass = _getWidgetClassName(LOADING); - - boundingBox.removeClass(widgetClass) - .removeClass(instClass); - - contentBox.removeClass(widgetClass) - .removeClass(instClass); - }, - - /** - * Sets up DOM and CustomEvent listeners for the widget. - * - * @method _bindUI - * @protected - */ - _bindUI: function() { - this._bindAttrUI(this._UI_ATTRS.BIND); - this._bindDOM(); - }, - - /** - * @method _unbindUI - * @protected - */ - _unbindUI : function(boundingBox) { - this._unbindDOM(boundingBox); - }, - - /** - * Sets up DOM listeners, on elements rendered by the widget. - * - * @method _bindDOM - * @protected - */ - _bindDOM : function() { - var oDocument = this.get(BOUNDING_BOX).get(OWNER_DOCUMENT), - focusHandle = Widget._hDocFocus; - - // Shared listener across all Widgets. - if (!focusHandle) { - focusHandle = Widget._hDocFocus = oDocument.on("focus", this._onDocFocus, this); - focusHandle.listeners = { - count: 0 - }; - } - - focusHandle.listeners[Y.stamp(this, true)] = true; - focusHandle.listeners.count++; - - // Fix for Webkit: - // Document doesn't receive focus in Webkit when the user mouses - // down on it, so the "focused" attribute won't get set to the - // correct value. Keeping this instance based for now, potential better performance. - // Otherwise we'll end up looking up widgets from the DOM on every mousedown. - if (WEBKIT){ - this._hDocMouseDown = oDocument.on("mousedown", this._onDocMouseDown, this); - } - }, - - /** - * @method _unbindDOM - * @protected - */ - _unbindDOM : function(boundingBox) { - - var focusHandle = Widget._hDocFocus, - yuid = Y.stamp(this, true), - focusListeners, - mouseHandle = this._hDocMouseDown; - - if (focusHandle) { - - focusListeners = focusHandle.listeners; - - if (focusListeners[yuid]) { - delete focusListeners[yuid]; - focusListeners.count--; - } - - if (focusListeners.count === 0) { - focusHandle.detach(); - Widget._hDocFocus = null; - } - } - - if (WEBKIT && mouseHandle) { - mouseHandle.detach(); - } - }, - - /** - * Updates the widget UI to reflect the attribute state. - * - * @method _syncUI - * @protected - */ - _syncUI: function() { - this._syncAttrUI(this._UI_ATTRS.SYNC); - }, - - /** - * Sets the height on the widget's bounding box element - * - * @method _uiSetHeight - * @protected - * @param {String | Number} val - */ - _uiSetHeight: function(val) { - this._uiSetDim(HEIGHT, val); - this._uiSizeCB((val !== EMPTY_STR && val !== AUTO)); - }, - - /** - * Sets the width on the widget's bounding box element - * - * @method _uiSetWidth - * @protected - * @param {String | Number} val - */ - _uiSetWidth: function(val) { - this._uiSetDim(WIDTH, val); - }, - - /** - * @method _uiSetDim - * @private - * @param {String} dim The dimension - "width" or "height" - * @param {Number | String} val The value to set - */ - _uiSetDim: function(dimension, val) { - this.get(BOUNDING_BOX).setStyle(dimension, L.isNumber(val) ? val + this.DEF_UNIT : val); - }, - - /** - * Sets the visible state for the UI - * - * @method _uiSetVisible - * @protected - * @param {boolean} val - */ - _uiSetVisible: function(val) { - this.get(BOUNDING_BOX).toggleClass(this.getClassName(HIDDEN), !val); - }, - - /** - * Sets the disabled state for the UI - * - * @method _uiSetDisabled - * @protected - * @param {boolean} val - */ - _uiSetDisabled: function(val) { - this.get(BOUNDING_BOX).toggleClass(this.getClassName(DISABLED), val); - }, - - /** - * Sets the focused state for the UI - * - * @method _uiSetFocused - * @protected - * @param {boolean} val - * @param {string} src String representing the source that triggered an update to - * the UI. - */ - _uiSetFocused: function(val, src) { - var boundingBox = this.get(BOUNDING_BOX); - boundingBox.toggleClass(this.getClassName(FOCUSED), val); - - if (src !== UI) { - if (val) { - boundingBox.focus(); - } else { - boundingBox.blur(); - } - } - }, - - /** - * Set the tabIndex on the widget's rendered UI - * - * @method _uiSetTabIndex - * @protected - * @param Number - */ - _uiSetTabIndex: function(index) { - var boundingBox = this.get(BOUNDING_BOX); - - if (L.isNumber(index)) { - boundingBox.set(TAB_INDEX, index); - } else { - boundingBox.removeAttribute(TAB_INDEX); - } - }, - - /** - * @method _onDocMouseDown - * @description "mousedown" event handler for the owner document of the - * widget's bounding box. - * @protected - * @param {EventFacade} evt The event facade for the DOM focus event - */ - _onDocMouseDown: function (evt) { - if (this._domFocus) { - this._onDocFocus(evt); - } - }, - - /** - * DOM focus event handler, used to sync the state of the Widget with the DOM - * - * @method _onDocFocus - * @protected - * @param {EventFacade} evt The event facade for the DOM focus event - */ - _onDocFocus: function (evt) { - var widget = Widget.getByNode(evt.target), - activeWidget = Widget._active; - - if (activeWidget && (activeWidget !== widget)) { - activeWidget._domFocus = false; - activeWidget._set(FOCUSED, false, {src:UI}); - - Widget._active = null; - } - - if (widget) { - widget._domFocus = true; - widget._set(FOCUSED, true, {src:UI}); - - Widget._active = widget; - } - }, - - /** - * Generic toString implementation for all widgets. - * - * @method toString - * @return {String} The default string value for the widget [ displays the NAME of the instance, and the unique id ] - */ - toString: function() { - // Using deprecated name prop for kweight squeeze. - return this.name + "[" + this.get(ID) + "]"; - }, - - /** - * Default unit to use for dimension values - * - * @property DEF_UNIT - * @type String - */ - DEF_UNIT : "px", - - /** - * Default node to render the bounding box to. If not set, - * will default to the current document body. - * - * @property DEF_PARENT_NODE - * @type String | Node - */ - DEF_PARENT_NODE : null, - - /** - * Property defining the markup template for content box. If your Widget doesn't - * need the dual boundingBox/contentBox structure, set CONTENT_TEMPLATE to null, - * and contentBox and boundingBox will both point to the same Node. - * - * @property CONTENT_TEMPLATE - * @type String - */ - CONTENT_TEMPLATE : DIV, - - /** - * Property defining the markup template for bounding box. - * - * @property BOUNDING_TEMPLATE - * @type String - */ - BOUNDING_TEMPLATE : DIV, - - /** - * @method _guid - * @protected - */ - _guid : function() { - return Y.guid(); - }, - - /** - * @method _validTabIndex - * @protected - * @param {Number} tabIndex - */ - _validTabIndex : function (tabIndex) { - return (L.isNumber(tabIndex) || L.isNull(tabIndex)); - }, - - /** - * Binds after listeners for the list of attributes provided - * - * @method _bindAttrUI - * @private - * @param {Array} attrs - */ - _bindAttrUI : function(attrs) { - var i, - l = attrs.length; - - for (i = 0; i < l; i++) { - this.after(attrs[i] + CHANGE, this._setAttrUI); - } - }, - - /** - * Invokes the _uiSet=ATTR NAME> method for the list of attributes provided - * - * @method _syncAttrUI - * @private - * @param {Array} attrs - */ - _syncAttrUI : function(attrs) { - var i, l = attrs.length, attr; - for (i = 0; i < l; i++) { - attr = attrs[i]; - this[_UISET + _toInitialCap(attr)](this.get(attr)); - } - }, - - /** - * @method _setAttrUI - * @private - * @param {EventFacade} e - */ - _setAttrUI : function(e) { - if (e.target === this) { - this[_UISET + _toInitialCap(e.attrName)](e.newVal, e.src); - } - }, - - /** - * The default setter for the strings attribute. Merges partial sets - * into the full string set, to allow users to partial sets of strings - * - * @method _strSetter - * @protected - * @param {Object} strings - * @return {String} The full set of strings to set - */ - _strSetter : function(strings) { - return Y.merge(this.get(STRINGS), strings); - }, - - /** - * Helper method to get a specific string value - * - * @deprecated Used by deprecated WidgetLocale implementations. - * @method getString - * @param {String} key - * @return {String} The string - */ - getString : function(key) { - return this.get(STRINGS)[key]; - }, - - /** - * Helper method to get the complete set of strings for the widget - * - * @deprecated Used by deprecated WidgetLocale implementations. - * @method getStrings - * @param {String} key - * @return {String} The strings - */ - getStrings : function() { - return this.get(STRINGS); - }, - - /** - * The lists of UI attributes to bind and sync for widget's _bindUI and _syncUI implementations - * - * @property _UI_ATTRS - * @type Object - * @private - */ - _UI_ATTRS : { - BIND: UI_ATTRS, - SYNC: UI_ATTRS - } -}); - -Y.Widget = Widget; - - -}, '3.16.0', { - "requires": [ - "attribute", - "base-base", - "base-pluginhost", - "classnamemanager", - "event-focus", - "node-base", - "node-style" - ], - "skinnable": true -}); -/* -YUI 3.16.0 (build 76f0e08) -Copyright 2014 Yahoo! Inc. All rights reserved. -Licensed under the BSD License. -http://yuilibrary.com/license/ -*/ - -YUI.add('widget-htmlparser', function (Y, NAME) { - -/** - * Adds HTML Parser support to the base Widget class - * - * @module widget - * @submodule widget-htmlparser - * @for Widget - */ - -var Widget = Y.Widget, - Node = Y.Node, - Lang = Y.Lang, - - SRC_NODE = "srcNode", - CONTENT_BOX = "contentBox"; - -/** - * Object hash, defining how attribute values are to be parsed from - * markup contained in the widget's content box. e.g.: - *
- *   {
- *       // Set single Node references using selector syntax
- *       // (selector is run through node.one)
- *       titleNode: "span.yui-title",
- *       // Set NodeList references using selector syntax
- *       // (array indicates selector is to be run through node.all)
- *       listNodes: ["li.yui-item"],
- *       // Set other attribute types, using a parse function.
- *       // Context is set to the widget instance.
- *       label: function(contentBox) {
- *           return contentBox.one("span.title").get("innerHTML");
- *       }
- *   }
- * 
- * - * @property HTML_PARSER - * @type Object - * @static - */ -Widget.HTML_PARSER = {}; - -/** - * The build configuration for the Widget class. - *

- * Defines the static fields which need to be aggregated, - * when this class is used as the main class passed to - * the Base.build method. - *

- * @property _buildCfg - * @type Object - * @static - * @final - * @private - */ -Widget._buildCfg = { - aggregates : ["HTML_PARSER"] -}; - -/** - * The DOM node to parse for configuration values, passed to the Widget's HTML_PARSER definition - * - * @attribute srcNode - * @type String | Node - * @writeOnce - */ -Widget.ATTRS[SRC_NODE] = { - value: null, - setter: Node.one, - getter: "_getSrcNode", - writeOnce: true -}; - -Y.mix(Widget.prototype, { - - /** - * @method _getSrcNode - * @protected - * @return {Node} The Node to apply HTML_PARSER to - */ - _getSrcNode : function(val) { - return val || this.get(CONTENT_BOX); - }, - - /** - * Implement the BaseCore _preAddAttrs method hook, to add - * the srcNode and related attributes, so that HTML_PARSER - * (which relies on `this.get("srcNode")`) can merge in it's - * results before the rest of the attributes are added. - * - * @method _preAddAttrs - * @protected - * - * @param attrs {Object} The full hash of statically defined ATTRS - * attributes being added for this instance - * - * @param userVals {Object} The hash of user values passed to - * the constructor - * - * @param lazy {boolean} Whether or not to add the attributes lazily - */ - _preAddAttrs : function(attrs, userVals, lazy) { - - var preAttrs = { - id : attrs.id, - boundingBox : attrs.boundingBox, - contentBox : attrs.contentBox, - srcNode : attrs.srcNode - }; - - this.addAttrs(preAttrs, userVals, lazy); - - delete attrs.boundingBox; - delete attrs.contentBox; - delete attrs.srcNode; - delete attrs.id; - - if (this._applyParser) { - this._applyParser(userVals); - } - }, - - /** - * @method _applyParsedConfig - * @protected - * @return {Object} The merged configuration literal - */ - _applyParsedConfig : function(node, cfg, parsedCfg) { - return (parsedCfg) ? Y.mix(cfg, parsedCfg, false) : cfg; - }, - - /** - * Utility method used to apply the HTML_PARSER configuration for the - * instance, to retrieve config data values. - * - * @method _applyParser - * @protected - * @param config {Object} User configuration object (will be populated with values from Node) - */ - _applyParser : function(config) { - - var widget = this, - srcNode = this._getNodeToParse(), - schema = widget._getHtmlParser(), - parsedConfig, - val; - - if (schema && srcNode) { - Y.Object.each(schema, function(v, k, o) { - val = null; - - if (Lang.isFunction(v)) { - val = v.call(widget, srcNode); - } else { - if (Lang.isArray(v)) { - val = srcNode.all(v[0]); - if (val.isEmpty()) { - val = null; - } - } else { - val = srcNode.one(v); - } - } - - if (val !== null && val !== undefined) { - parsedConfig = parsedConfig || {}; - parsedConfig[k] = val; - } - }); - } - config = widget._applyParsedConfig(srcNode, config, parsedConfig); - }, - - /** - * Determines whether we have a node reference which we should try and parse. - * - * The current implementation does not parse nodes generated from CONTENT_TEMPLATE, - * only explicitly set srcNode, or contentBox attributes. - * - * @method _getNodeToParse - * @return {Node} The node reference to apply HTML_PARSER to. - * @private - */ - _getNodeToParse : function() { - var srcNode = this.get("srcNode"); - return (!this._cbFromTemplate) ? srcNode : null; - }, - - /** - * Gets the HTML_PARSER definition for this instance, by merging HTML_PARSER - * definitions across the class hierarchy. - * - * @private - * @method _getHtmlParser - * @return {Object} HTML_PARSER definition for this instance - */ - _getHtmlParser : function() { - // Removed caching for kweight. This is a private method - // and only called once so don't need to cache HTML_PARSER - var classes = this._getClasses(), - parser = {}, - i, p; - - for (i = classes.length - 1; i >= 0; i--) { - p = classes[i].HTML_PARSER; - if (p) { - Y.mix(parser, p, true); - } - } - return parser; - } -}); - - -}, '3.16.0', {"requires": ["widget-base"]}); -/* -YUI 3.16.0 (build 76f0e08) -Copyright 2014 Yahoo! Inc. All rights reserved. -Licensed under the BSD License. -http://yuilibrary.com/license/ -*/ - -YUI.add('widget-skin', function (Y, NAME) { - -/** - * Provides skin related utlility methods. - * - * @module widget - * @submodule widget-skin - */ -var BOUNDING_BOX = "boundingBox", - CONTENT_BOX = "contentBox", - SKIN = "skin", - _getClassName = Y.ClassNameManager.getClassName; - -/** - * Returns the name of the skin that's currently applied to the widget. - * - * Searches up the Widget's ancestor axis for, by default, a class - * yui3-skin-(name), and returns the (name) portion. Otherwise, returns null. - * - * This is only really useful after the widget's DOM structure is in the - * document, either by render or by progressive enhancement. - * - * @method getSkinName - * @for Widget - * @param {String} [skinPrefix] The prefix which the implementation uses for the skin - * ("yui3-skin-" is the default). - * - * NOTE: skinPrefix will be used as part of a regular expression: - * - * new RegExp('\\b' + skinPrefix + '(\\S+)') - * - * Although an unlikely use case, literal characters which may result in an invalid - * regular expression should be escaped. - * - * @return {String} The name of the skin, or null, if a matching skin class is not found. - */ - -Y.Widget.prototype.getSkinName = function (skinPrefix) { - - var root = this.get( CONTENT_BOX ) || this.get( BOUNDING_BOX ), - match, - search; - - skinPrefix = skinPrefix || _getClassName(SKIN, ""); - - search = new RegExp( '\\b' + skinPrefix + '(\\S+)' ); - - if ( root ) { - root.ancestor( function ( node ) { - match = node.get( 'className' ).match( search ); - return match; - } ); - } - - return ( match ) ? match[1] : null; -}; - - -}, '3.16.0', {"requires": ["widget-base"]}); -/* -YUI 3.16.0 (build 76f0e08) -Copyright 2014 Yahoo! Inc. All rights reserved. -Licensed under the BSD License. -http://yuilibrary.com/license/ -*/ - -YUI.add('event-delegate', function (Y, NAME) { - -/** - * Adds event delegation support to the library. - * - * @module event - * @submodule event-delegate - */ - -var toArray = Y.Array, - YLang = Y.Lang, - isString = YLang.isString, - isObject = YLang.isObject, - isArray = YLang.isArray, - selectorTest = Y.Selector.test, - detachCategories = Y.Env.evt.handles; - -/** - *

Sets up event delegation on a container element. The delegated event - * will use a supplied selector or filtering function to test if the event - * references at least one node that should trigger the subscription - * callback.

- * - *

Selector string filters will trigger the callback if the event originated - * from a node that matches it or is contained in a node that matches it. - * Function filters are called for each Node up the parent axis to the - * subscribing container node, and receive at each level the Node and the event - * object. The function should return true (or a truthy value) if that Node - * should trigger the subscription callback. Note, it is possible for filters - * to match multiple Nodes for a single event. In this case, the delegate - * callback will be executed for each matching Node.

- * - *

For each matching Node, the callback will be executed with its 'this' - * object set to the Node matched by the filter (unless a specific context was - * provided during subscription), and the provided event's - * currentTarget will also be set to the matching Node. The - * containing Node from which the subscription was originally made can be - * referenced as e.container. - * - * @method delegate - * @param type {String} the event type to delegate - * @param fn {Function} the callback function to execute. This function - * will be provided the event object for the delegated event. - * @param el {String|node} the element that is the delegation container - * @param filter {string|Function} a selector that must match the target of the - * event or a function to test target and its parents for a match - * @param context optional argument that specifies what 'this' refers to. - * @param args* 0..n additional arguments to pass on to the callback function. - * These arguments will be added after the event object. - * @return {EventHandle} the detach handle - * @static - * @for Event - */ -function delegate(type, fn, el, filter) { - var args = toArray(arguments, 0, true), - query = isString(el) ? el : null, - typeBits, synth, container, categories, cat, i, len, handles, handle; - - // Support Y.delegate({ click: fnA, key: fnB }, el, filter, ...); - // and Y.delegate(['click', 'key'], fn, el, filter, ...); - if (isObject(type)) { - handles = []; - - if (isArray(type)) { - for (i = 0, len = type.length; i < len; ++i) { - args[0] = type[i]; - handles.push(Y.delegate.apply(Y, args)); - } - } else { - // Y.delegate({'click', fn}, el, filter) => - // Y.delegate('click', fn, el, filter) - args.unshift(null); // one arg becomes two; need to make space - - for (i in type) { - if (type.hasOwnProperty(i)) { - args[0] = i; - args[1] = type[i]; - handles.push(Y.delegate.apply(Y, args)); - } - } - } - - return new Y.EventHandle(handles); - } - - typeBits = type.split(/\|/); - - if (typeBits.length > 1) { - cat = typeBits.shift(); - args[0] = type = typeBits.shift(); - } - - synth = Y.Node.DOM_EVENTS[type]; - - if (isObject(synth) && synth.delegate) { - handle = synth.delegate.apply(synth, arguments); - } - - if (!handle) { - if (!type || !fn || !el || !filter) { - return; - } - - container = (query) ? Y.Selector.query(query, null, true) : el; - - if (!container && isString(el)) { - handle = Y.on('available', function () { - Y.mix(handle, Y.delegate.apply(Y, args), true); - }, el); - } - - if (!handle && container) { - args.splice(2, 2, container); // remove the filter - - handle = Y.Event._attach(args, { facade: false }); - handle.sub.filter = filter; - handle.sub._notify = delegate.notifySub; - } - } - - if (handle && cat) { - categories = detachCategories[cat] || (detachCategories[cat] = {}); - categories = categories[type] || (categories[type] = []); - categories.push(handle); - } - - return handle; -} - -/** -Overrides the _notify method on the normal DOM subscription to -inject the filtering logic and only proceed in the case of a match. - -This method is hosted as a private property of the `delegate` method -(e.g. `Y.delegate.notifySub`) - -@method notifySub -@param thisObj {Object} default 'this' object for the callback -@param args {Array} arguments passed to the event's fire() -@param ce {CustomEvent} the custom event managing the DOM subscriptions for - the subscribed event on the subscribing node. -@return {Boolean} false if the event was stopped -@private -@static -@since 3.2.0 -**/ -delegate.notifySub = function (thisObj, args, ce) { - // Preserve args for other subscribers - args = args.slice(); - if (this.args) { - args.push.apply(args, this.args); - } - - // Only notify subs if the event occurred on a targeted element - var currentTarget = delegate._applyFilter(this.filter, args, ce), - //container = e.currentTarget, - e, i, len, ret; - - if (currentTarget) { - // Support multiple matches up the the container subtree - currentTarget = toArray(currentTarget); - - // The second arg is the currentTarget, but we'll be reusing this - // facade, replacing the currentTarget for each use, so it doesn't - // matter what element we seed it with. - e = args[0] = new Y.DOMEventFacade(args[0], ce.el, ce); - - e.container = Y.one(ce.el); - - for (i = 0, len = currentTarget.length; i < len && !e.stopped; ++i) { - e.currentTarget = Y.one(currentTarget[i]); - - ret = this.fn.apply(this.context || e.currentTarget, args); - - if (ret === false) { // stop further notifications - break; - } - } - - return ret; - } -}; - -/** -Compiles a selector string into a filter function to identify whether -Nodes along the parent axis of an event's target should trigger event -notification. - -This function is memoized, so previously compiled filter functions are -returned if the same selector string is provided. - -This function may be useful when defining synthetic events for delegate -handling. - -Hosted as a property of the `delegate` method (e.g. `Y.delegate.compileFilter`). - -@method compileFilter -@param selector {String} the selector string to base the filtration on -@return {Function} -@since 3.2.0 -@static -**/ -delegate.compileFilter = Y.cached(function (selector) { - return function (target, e) { - return selectorTest(target._node, selector, - (e.currentTarget === e.target) ? null : e.currentTarget._node); - }; -}); - -/** -Regex to test for disabled elements during filtering. This is only relevant to -IE to normalize behavior with other browsers, which swallow events that occur -to disabled elements. IE fires the event from the parent element instead of the -original target, though it does preserve `event.srcElement` as the disabled -element. IE also supports disabled on ``, but the event still bubbles, so it -acts more like `e.preventDefault()` plus styling. That issue is not handled here -because other browsers fire the event on the ``, so delegate is supported in -both cases. - -@property _disabledRE -@type {RegExp} -@protected -@since 3.8.1 -**/ -delegate._disabledRE = /^(?:button|input|select|textarea)$/i; - -/** -Walks up the parent axis of an event's target, and tests each element -against a supplied filter function. If any Nodes, including the container, -satisfy the filter, the delegated callback will be triggered for each. - -Hosted as a protected property of the `delegate` method (e.g. -`Y.delegate._applyFilter`). - -@method _applyFilter -@param filter {Function} boolean function to test for inclusion in event - notification -@param args {Array} the arguments that would be passed to subscribers -@param ce {CustomEvent} the DOM event wrapper -@return {Node|Node[]|undefined} The Node or Nodes that satisfy the filter -@protected -**/ -delegate._applyFilter = function (filter, args, ce) { - var e = args[0], - container = ce.el, // facadeless events in IE, have no e.currentTarget - target = e.target || e.srcElement, - match = [], - isContainer = false; - - // Resolve text nodes to their containing element - if (target.nodeType === 3) { - target = target.parentNode; - } - - // For IE. IE propagates events from the parent element of disabled - // elements, where other browsers swallow the event entirely. To normalize - // this in IE, filtering for matching elements should abort if the target - // is a disabled form control. - if (target.disabled && delegate._disabledRE.test(target.nodeName)) { - return match; - } - - // passing target as the first arg rather than leaving well enough alone - // making 'this' in the filter function refer to the target. This is to - // support bound filter functions. - args.unshift(target); - - if (isString(filter)) { - while (target) { - isContainer = (target === container); - if (selectorTest(target, filter, (isContainer ? null: container))) { - match.push(target); - } - - if (isContainer) { - break; - } - - target = target.parentNode; - } - } else { - // filter functions are implementer code and should receive wrappers - args[0] = Y.one(target); - args[1] = new Y.DOMEventFacade(e, container, ce); - - while (target) { - // filter(target, e, extra args...) - this === target - if (filter.apply(args[0], args)) { - match.push(target); - } - - if (target === container) { - break; - } - - target = target.parentNode; - args[0] = Y.one(target); - } - args[1] = e; // restore the raw DOM event - } - - if (match.length <= 1) { - match = match[0]; // single match or undefined - } - - // remove the target - args.shift(); - - return match; -}; - -/** - * Sets up event delegation on a container element. The delegated event - * will use a supplied filter to test if the callback should be executed. - * This filter can be either a selector string or a function that returns - * a Node to use as the currentTarget for the event. - * - * The event object for the delegated event is supplied to the callback - * function. It is modified slightly in order to support all properties - * that may be needed for event delegation. 'currentTarget' is set to - * the element that matched the selector string filter or the Node returned - * from the filter function. 'container' is set to the element that the - * listener is delegated from (this normally would be the 'currentTarget'). - * - * Filter functions will be called with the arguments that would be passed to - * the callback function, including the event object as the first parameter. - * The function should return false (or a falsey value) if the success criteria - * aren't met, and the Node to use as the event's currentTarget and 'this' - * object if they are. - * - * @method delegate - * @param type {string} the event type to delegate - * @param fn {function} the callback function to execute. This function - * will be provided the event object for the delegated event. - * @param el {string|node} the element that is the delegation container - * @param filter {string|function} a selector that must match the target of the - * event or a function that returns a Node or false. - * @param context optional argument that specifies what 'this' refers to. - * @param args* 0..n additional arguments to pass on to the callback function. - * These arguments will be added after the event object. - * @return {EventHandle} the detach handle - * @for YUI - */ -Y.delegate = Y.Event.delegate = delegate; - - -}, '3.16.0', {"requires": ["node-base"]}); -/* -YUI 3.16.0 (build 76f0e08) -Copyright 2014 Yahoo! Inc. All rights reserved. -Licensed under the BSD License. -http://yuilibrary.com/license/ -*/ - -YUI.add('node-event-delegate', function (Y, NAME) { - -/** - * Functionality to make the node a delegated event container - * @module node - * @submodule node-event-delegate - */ - -/** - *

Sets up a delegation listener for an event occurring inside the Node. - * The delegated event will be verified against a supplied selector or - * filtering function to test if the event references at least one node that - * should trigger the subscription callback.

- * - *

Selector string filters will trigger the callback if the event originated - * from a node that matches it or is contained in a node that matches it. - * Function filters are called for each Node up the parent axis to the - * subscribing container node, and receive at each level the Node and the event - * object. The function should return true (or a truthy value) if that Node - * should trigger the subscription callback. Note, it is possible for filters - * to match multiple Nodes for a single event. In this case, the delegate - * callback will be executed for each matching Node.

- * - *

For each matching Node, the callback will be executed with its 'this' - * object set to the Node matched by the filter (unless a specific context was - * provided during subscription), and the provided event's - * currentTarget will also be set to the matching Node. The - * containing Node from which the subscription was originally made can be - * referenced as e.container. - * - * @method delegate - * @param type {String} the event type to delegate - * @param fn {Function} the callback function to execute. This function - * will be provided the event object for the delegated event. - * @param spec {String|Function} a selector that must match the target of the - * event or a function to test target and its parents for a match - * @param context {Object} optional argument that specifies what 'this' refers to. - * @param args* {any} 0..n additional arguments to pass on to the callback function. - * These arguments will be added after the event object. - * @return {EventHandle} the detach handle - * @for Node - */ -Y.Node.prototype.delegate = function(type) { - - var args = Y.Array(arguments, 0, true), - index = (Y.Lang.isObject(type) && !Y.Lang.isArray(type)) ? 1 : 2; - - args.splice(index, 0, this._node); - - return Y.delegate.apply(Y, args); -}; - - -}, '3.16.0', {"requires": ["node-base", "event-delegate"]}); -/* -YUI 3.16.0 (build 76f0e08) -Copyright 2014 Yahoo! Inc. All rights reserved. -Licensed under the BSD License. -http://yuilibrary.com/license/ -*/ - -YUI.add('widget-uievents', function (Y, NAME) { - -/** - * Support for Widget UI Events (Custom Events fired by the widget, which wrap the underlying DOM events - e.g. widget:click, widget:mousedown) - * - * @module widget - * @submodule widget-uievents - */ - -var BOUNDING_BOX = "boundingBox", - Widget = Y.Widget, - RENDER = "render", - L = Y.Lang, - EVENT_PREFIX_DELIMITER = ":", - - // Map of Node instances serving as a delegation containers for a specific - // event type to Widget instances using that delegation container. - _uievts = Y.Widget._uievts = Y.Widget._uievts || {}; - -Y.mix(Widget.prototype, { - - /** - * Destructor logic for UI event infrastructure, - * invoked during Widget destruction. - * - * @method _destroyUIEvents - * @for Widget - * @private - */ - _destroyUIEvents: function() { - - var widgetGuid = Y.stamp(this, true); - - Y.each(_uievts, function (info, key) { - if (info.instances[widgetGuid]) { - // Unregister this Widget instance as needing this delegated - // event listener. - delete info.instances[widgetGuid]; - - // There are no more Widget instances using this delegated - // event listener, so detach it. - - if (Y.Object.isEmpty(info.instances)) { - info.handle.detach(); - - if (_uievts[key]) { - delete _uievts[key]; - } - } - } - }); - }, - - /** - * Map of DOM events that should be fired as Custom Events by the - * Widget instance. - * - * @property UI_EVENTS - * @for Widget - * @type Object - */ - UI_EVENTS: Y.Node.DOM_EVENTS, - - /** - * Returns the node on which to bind delegate listeners. - * - * @method _getUIEventNode - * @for Widget - * @protected - */ - _getUIEventNode: function () { - return this.get(BOUNDING_BOX); - }, - - /** - * Binds a delegated DOM event listener of the specified type to the - * Widget's outtermost DOM element to facilitate the firing of a Custom - * Event of the same type for the Widget instance. - * - * @method _createUIEvent - * @for Widget - * @param type {String} String representing the name of the event - * @private - */ - _createUIEvent: function (type) { - - var uiEvtNode = this._getUIEventNode(), - key = (Y.stamp(uiEvtNode) + type), - info = _uievts[key], - handle; - - // For each Node instance: Ensure that there is only one delegated - // event listener used to fire Widget UI events. - - if (!info) { - - handle = uiEvtNode.delegate(type, function (evt) { - - var widget = Widget.getByNode(this); - - // Widget could be null if node instance belongs to - // another Y instance. - - if (widget) { - if (widget._filterUIEvent(evt)) { - widget.fire(evt.type, { domEvent: evt }); - } - } - - }, "." + Y.Widget.getClassName()); - - _uievts[key] = info = { instances: {}, handle: handle }; - } - - // Register this Widget as using this Node as a delegation container. - info.instances[Y.stamp(this)] = 1; - }, - - /** - * This method is used to determine if we should fire - * the UI Event or not. The default implementation makes sure - * that for nested delegates (nested unrelated widgets), we don't - * fire the UI event listener more than once at each level. - * - *

For example, without the additional filter, if you have nested - * widgets, each widget will have a delegate listener. If you - * click on the inner widget, the inner delegate listener's - * filter will match once, but the outer will match twice - * (based on delegate's design) - once for the inner widget, - * and once for the outer.

- * - * @method _filterUIEvent - * @for Widget - * @param {DOMEventFacade} evt - * @return {boolean} true if it's OK to fire the custom UI event, false if not. - * @private - * - */ - _filterUIEvent: function(evt) { - // Either it's hitting this widget's delegate container (and not some other widget's), - // or the container it's hitting is handling this widget's ui events. - return (evt.currentTarget.compareTo(evt.container) || evt.container.compareTo(this._getUIEventNode())); - }, - - /** - * Determines if the specified event is a UI event. - * - * @private - * @method _isUIEvent - * @for Widget - * @param type {String} String representing the name of the event - * @return {String} Event Returns the name of the UI Event, otherwise - * undefined. - */ - _getUIEvent: function (type) { - - if (L.isString(type)) { - var sType = this.parseType(type)[1], - iDelim, - returnVal; - - if (sType) { - // TODO: Get delimiter from ET, or have ET support this. - iDelim = sType.indexOf(EVENT_PREFIX_DELIMITER); - if (iDelim > -1) { - sType = sType.substring(iDelim + EVENT_PREFIX_DELIMITER.length); - } - - if (this.UI_EVENTS[sType]) { - returnVal = sType; - } - } - - return returnVal; - } - }, - - /** - * Sets up infrastructure required to fire a UI event. - * - * @private - * @method _initUIEvent - * @for Widget - * @param type {String} String representing the name of the event - * @return {String} - */ - _initUIEvent: function (type) { - var sType = this._getUIEvent(type), - queue = this._uiEvtsInitQueue || {}; - - if (sType && !queue[sType]) { - - this._uiEvtsInitQueue = queue[sType] = 1; - - this.after(RENDER, function() { - this._createUIEvent(sType); - delete this._uiEvtsInitQueue[sType]; - }); - } - }, - - // Override of "on" from Base to facilitate the firing of Widget events - // based on DOM events of the same name/type (e.g. "click", "mouseover"). - // Temporary solution until we have the ability to listen to when - // someone adds an event listener (bug 2528230) - on: function (type) { - this._initUIEvent(type); - return Widget.superclass.on.apply(this, arguments); - }, - - // Override of "publish" from Base to facilitate the firing of Widget events - // based on DOM events of the same name/type (e.g. "click", "mouseover"). - // Temporary solution until we have the ability to listen to when - // someone publishes an event (bug 2528230) - publish: function (type, config) { - var sType = this._getUIEvent(type); - if (sType && config && config.defaultFn) { - this._initUIEvent(sType); - } - return Widget.superclass.publish.apply(this, arguments); - } - -}, true); // overwrite existing EventTarget methods - - -}, '3.16.0', {"requires": ["node-event-delegate", "widget-base"]}); -/* -YUI 3.16.0 (build 76f0e08) -Copyright 2014 Yahoo! Inc. All rights reserved. -Licensed under the BSD License. -http://yuilibrary.com/license/ -*/ - -YUI.add('event-simulate', function (Y, NAME) { - -(function() { -/** - * Simulate user interaction by generating native DOM events. - * - * @module event-simulate - * @requires event - */ - -//shortcuts -var L = Y.Lang, - win = Y.config.win, - isFunction = L.isFunction, - isString = L.isString, - isBoolean = L.isBoolean, - isObject = L.isObject, - isNumber = L.isNumber, - - //mouse events supported - mouseEvents = { - click: 1, - dblclick: 1, - mouseover: 1, - mouseout: 1, - mousedown: 1, - mouseup: 1, - mousemove: 1, - contextmenu:1 - }, - - pointerEvents = (win && win.PointerEvent) ? { - pointerover: 1, - pointerout: 1, - pointerdown: 1, - pointerup: 1, - pointermove: 1 - } : { - MSPointerOver: 1, - MSPointerOut: 1, - MSPointerDown: 1, - MSPointerUp: 1, - MSPointerMove: 1 - }, - - //key events supported - keyEvents = { - keydown: 1, - keyup: 1, - keypress: 1 - }, - - //HTML events supported - uiEvents = { - submit: 1, - blur: 1, - change: 1, - focus: 1, - resize: 1, - scroll: 1, - select: 1 - }, - - //events that bubble by default - bubbleEvents = { - scroll: 1, - resize: 1, - reset: 1, - submit: 1, - change: 1, - select: 1, - error: 1, - abort: 1 - }, - - //touch events supported - touchEvents = { - touchstart: 1, - touchmove: 1, - touchend: 1, - touchcancel: 1 - }, - - gestureEvents = { - gesturestart: 1, - gesturechange: 1, - gestureend: 1 - }; - -//all key, mouse and touch events bubble -Y.mix(bubbleEvents, mouseEvents); -Y.mix(bubbleEvents, keyEvents); -Y.mix(bubbleEvents, touchEvents); - -/* - * Note: Intentionally not for YUIDoc generation. - * Simulates a key event using the given event information to populate - * the generated event object. This method does browser-equalizing - * calculations to account for differences in the DOM and IE event models - * as well as different browser quirks. Note: keydown causes Safari 2.x to - * crash. - * @method simulateKeyEvent - * @private - * @static - * @param {HTMLElement} target The target of the given event. - * @param {String} type The type of event to fire. This can be any one of - * the following: keyup, keydown, and keypress. - * @param {Boolean} [bubbles=true] Indicates if the event can be - * bubbled up. DOM Level 3 specifies that all key events bubble by - * default. - * @param {Boolean} [cancelable=true] Indicates if the event can be - * canceled using preventDefault(). DOM Level 3 specifies that all - * key events can be cancelled. - * @param {Window} [view=window] The view containing the target. This is - * typically the window object. - * @param {Boolean} [ctrlKey=false] Indicates if one of the CTRL keys - * is pressed while the event is firing. - * @param {Boolean} [altKey=false] Indicates if one of the ALT keys - * is pressed while the event is firing. - * @param {Boolean} [shiftKey=false] Indicates if one of the SHIFT keys - * is pressed while the event is firing. - * @param {Boolean} [metaKey=false] Indicates if one of the META keys - * is pressed while the event is firing. - * @param {Number} [keyCode=0] The code for the key that is in use. - * @param {Number} [charCode=0] The Unicode code for the character - * associated with the key being used. - */ -function simulateKeyEvent(target /*:HTMLElement*/, type /*:String*/, - bubbles /*:Boolean*/, cancelable /*:Boolean*/, - view /*:Window*/, - ctrlKey /*:Boolean*/, altKey /*:Boolean*/, - shiftKey /*:Boolean*/, metaKey /*:Boolean*/, - keyCode /*:int*/, charCode /*:int*/) /*:Void*/ -{ - //check target - if (!target){ - Y.error("simulateKeyEvent(): Invalid target."); - } - - //check event type - if (isString(type)){ - type = type.toLowerCase(); - switch(type){ - case "textevent": //DOM Level 3 - type = "keypress"; - break; - case "keyup": - case "keydown": - case "keypress": - break; - default: - Y.error("simulateKeyEvent(): Event type '" + type + "' not supported."); - } - } else { - Y.error("simulateKeyEvent(): Event type must be a string."); - } - - //setup default values - if (!isBoolean(bubbles)){ - bubbles = true; //all key events bubble - } - if (!isBoolean(cancelable)){ - cancelable = true; //all key events can be cancelled - } - if (!isObject(view)){ - view = Y.config.win; //view is typically window - } - if (!isBoolean(ctrlKey)){ - ctrlKey = false; - } - if (!isBoolean(altKey)){ - altKey = false; - } - if (!isBoolean(shiftKey)){ - shiftKey = false; - } - if (!isBoolean(metaKey)){ - metaKey = false; - } - if (!isNumber(keyCode)){ - keyCode = 0; - } - if (!isNumber(charCode)){ - charCode = 0; - } - - //try to create a mouse event - var customEvent /*:MouseEvent*/ = null; - - //check for DOM-compliant browsers first - if (isFunction(Y.config.doc.createEvent)){ - - try { - - //try to create key event - customEvent = Y.config.doc.createEvent("KeyEvents"); - - /* - * Interesting problem: Firefox implemented a non-standard - * version of initKeyEvent() based on DOM Level 2 specs. - * Key event was removed from DOM Level 2 and re-introduced - * in DOM Level 3 with a different interface. Firefox is the - * only browser with any implementation of Key Events, so for - * now, assume it's Firefox if the above line doesn't error. - */ - // @TODO: Decipher between Firefox's implementation and a correct one. - customEvent.initKeyEvent(type, bubbles, cancelable, view, ctrlKey, - altKey, shiftKey, metaKey, keyCode, charCode); - - } catch (ex /*:Error*/){ - - /* - * If it got here, that means key events aren't officially supported. - * Safari/WebKit is a real problem now. WebKit 522 won't let you - * set keyCode, charCode, or other properties if you use a - * UIEvent, so we first must try to create a generic event. The - * fun part is that this will throw an error on Safari 2.x. The - * end result is that we need another try...catch statement just to - * deal with this mess. - */ - try { - - //try to create generic event - will fail in Safari 2.x - customEvent = Y.config.doc.createEvent("Events"); - - } catch (uierror /*:Error*/){ - - //the above failed, so create a UIEvent for Safari 2.x - customEvent = Y.config.doc.createEvent("UIEvents"); - - } finally { - - customEvent.initEvent(type, bubbles, cancelable); - - //initialize - customEvent.view = view; - customEvent.altKey = altKey; - customEvent.ctrlKey = ctrlKey; - customEvent.shiftKey = shiftKey; - customEvent.metaKey = metaKey; - customEvent.keyCode = keyCode; - customEvent.charCode = charCode; - - } - - } - - //fire the event - target.dispatchEvent(customEvent); - - } else if (isObject(Y.config.doc.createEventObject)){ //IE - - //create an IE event object - customEvent = Y.config.doc.createEventObject(); - - //assign available properties - customEvent.bubbles = bubbles; - customEvent.cancelable = cancelable; - customEvent.view = view; - customEvent.ctrlKey = ctrlKey; - customEvent.altKey = altKey; - customEvent.shiftKey = shiftKey; - customEvent.metaKey = metaKey; - - /* - * IE doesn't support charCode explicitly. CharCode should - * take precedence over any keyCode value for accurate - * representation. - */ - customEvent.keyCode = (charCode > 0) ? charCode : keyCode; - - //fire the event - target.fireEvent("on" + type, customEvent); - - } else { - Y.error("simulateKeyEvent(): No event simulation framework present."); - } -} - -/* - * Note: Intentionally not for YUIDoc generation. - * Simulates a mouse event using the given event information to populate - * the generated event object. This method does browser-equalizing - * calculations to account for differences in the DOM and IE event models - * as well as different browser quirks. - * @method simulateMouseEvent - * @private - * @static - * @param {HTMLElement} target The target of the given event. - * @param {String} type The type of event to fire. This can be any one of - * the following: click, dblclick, mousedown, mouseup, mouseout, - * mouseover, and mousemove. - * @param {Boolean} bubbles (Optional) Indicates if the event can be - * bubbled up. DOM Level 2 specifies that all mouse events bubble by - * default. The default is true. - * @param {Boolean} cancelable (Optional) Indicates if the event can be - * canceled using preventDefault(). DOM Level 2 specifies that all - * mouse events except mousemove can be cancelled. The default - * is true for all events except mousemove, for which the default - * is false. - * @param {Window} view (Optional) The view containing the target. This is - * typically the window object. The default is window. - * @param {Number} detail (Optional) The number of times the mouse button has - * been used. The default value is 1. - * @param {Number} screenX (Optional) The x-coordinate on the screen at which - * point the event occured. The default is 0. - * @param {Number} screenY (Optional) The y-coordinate on the screen at which - * point the event occured. The default is 0. - * @param {Number} clientX (Optional) The x-coordinate on the client at which - * point the event occured. The default is 0. - * @param {Number} clientY (Optional) The y-coordinate on the client at which - * point the event occured. The default is 0. - * @param {Boolean} ctrlKey (Optional) Indicates if one of the CTRL keys - * is pressed while the event is firing. The default is false. - * @param {Boolean} altKey (Optional) Indicates if one of the ALT keys - * is pressed while the event is firing. The default is false. - * @param {Boolean} shiftKey (Optional) Indicates if one of the SHIFT keys - * is pressed while the event is firing. The default is false. - * @param {Boolean} metaKey (Optional) Indicates if one of the META keys - * is pressed while the event is firing. The default is false. - * @param {Number} button (Optional) The button being pressed while the event - * is executing. The value should be 0 for the primary mouse button - * (typically the left button), 1 for the terciary mouse button - * (typically the middle button), and 2 for the secondary mouse button - * (typically the right button). The default is 0. - * @param {HTMLElement} relatedTarget (Optional) For mouseout events, - * this is the element that the mouse has moved to. For mouseover - * events, this is the element that the mouse has moved from. This - * argument is ignored for all other events. The default is null. - */ -function simulateMouseEvent(target /*:HTMLElement*/, type /*:String*/, - bubbles /*:Boolean*/, cancelable /*:Boolean*/, - view /*:Window*/, detail /*:int*/, - screenX /*:int*/, screenY /*:int*/, - clientX /*:int*/, clientY /*:int*/, - ctrlKey /*:Boolean*/, altKey /*:Boolean*/, - shiftKey /*:Boolean*/, metaKey /*:Boolean*/, - button /*:int*/, relatedTarget /*:HTMLElement*/) /*:Void*/ -{ - //check target - if (!target){ - Y.error("simulateMouseEvent(): Invalid target."); - } - - - if (isString(type)){ - - //make sure it's a supported mouse event or an msPointerEvent. - if (!mouseEvents[type.toLowerCase()] && !pointerEvents[type]){ - Y.error("simulateMouseEvent(): Event type '" + type + "' not supported."); - } - } - else { - Y.error("simulateMouseEvent(): Event type must be a string."); - } - - //setup default values - if (!isBoolean(bubbles)){ - bubbles = true; //all mouse events bubble - } - if (!isBoolean(cancelable)){ - cancelable = (type !== "mousemove"); //mousemove is the only one that can't be cancelled - } - if (!isObject(view)){ - view = Y.config.win; //view is typically window - } - if (!isNumber(detail)){ - detail = 1; //number of mouse clicks must be at least one - } - if (!isNumber(screenX)){ - screenX = 0; - } - if (!isNumber(screenY)){ - screenY = 0; - } - if (!isNumber(clientX)){ - clientX = 0; - } - if (!isNumber(clientY)){ - clientY = 0; - } - if (!isBoolean(ctrlKey)){ - ctrlKey = false; - } - if (!isBoolean(altKey)){ - altKey = false; - } - if (!isBoolean(shiftKey)){ - shiftKey = false; - } - if (!isBoolean(metaKey)){ - metaKey = false; - } - if (!isNumber(button)){ - button = 0; - } - - relatedTarget = relatedTarget || null; - - //try to create a mouse event - var customEvent /*:MouseEvent*/ = null; - - //check for DOM-compliant browsers first - if (isFunction(Y.config.doc.createEvent)){ - - customEvent = Y.config.doc.createEvent("MouseEvents"); - - //Safari 2.x (WebKit 418) still doesn't implement initMouseEvent() - if (customEvent.initMouseEvent){ - customEvent.initMouseEvent(type, bubbles, cancelable, view, detail, - screenX, screenY, clientX, clientY, - ctrlKey, altKey, shiftKey, metaKey, - button, relatedTarget); - } else { //Safari - - //the closest thing available in Safari 2.x is UIEvents - customEvent = Y.config.doc.createEvent("UIEvents"); - customEvent.initEvent(type, bubbles, cancelable); - customEvent.view = view; - customEvent.detail = detail; - customEvent.screenX = screenX; - customEvent.screenY = screenY; - customEvent.clientX = clientX; - customEvent.clientY = clientY; - customEvent.ctrlKey = ctrlKey; - customEvent.altKey = altKey; - customEvent.metaKey = metaKey; - customEvent.shiftKey = shiftKey; - customEvent.button = button; - customEvent.relatedTarget = relatedTarget; - } - - /* - * Check to see if relatedTarget has been assigned. Firefox - * versions less than 2.0 don't allow it to be assigned via - * initMouseEvent() and the property is readonly after event - * creation, so in order to keep YAHOO.util.getRelatedTarget() - * working, assign to the IE proprietary toElement property - * for mouseout event and fromElement property for mouseover - * event. - */ - if (relatedTarget && !customEvent.relatedTarget){ - if (type === "mouseout"){ - customEvent.toElement = relatedTarget; - } else if (type === "mouseover"){ - customEvent.fromElement = relatedTarget; - } - } - - //fire the event - target.dispatchEvent(customEvent); - - } else if (isObject(Y.config.doc.createEventObject)){ //IE - - //create an IE event object - customEvent = Y.config.doc.createEventObject(); - - //assign available properties - customEvent.bubbles = bubbles; - customEvent.cancelable = cancelable; - customEvent.view = view; - customEvent.detail = detail; - customEvent.screenX = screenX; - customEvent.screenY = screenY; - customEvent.clientX = clientX; - customEvent.clientY = clientY; - customEvent.ctrlKey = ctrlKey; - customEvent.altKey = altKey; - customEvent.metaKey = metaKey; - customEvent.shiftKey = shiftKey; - - //fix button property for IE's wacky implementation - switch(button){ - case 0: - customEvent.button = 1; - break; - case 1: - customEvent.button = 4; - break; - case 2: - //leave as is - break; - default: - customEvent.button = 0; - } - - /* - * Have to use relatedTarget because IE won't allow assignment - * to toElement or fromElement on generic events. This keeps - * YAHOO.util.customEvent.getRelatedTarget() functional. - */ - customEvent.relatedTarget = relatedTarget; - - //fire the event - target.fireEvent("on" + type, customEvent); - - } else { - Y.error("simulateMouseEvent(): No event simulation framework present."); - } -} - -/* - * Note: Intentionally not for YUIDoc generation. - * Simulates a UI event using the given event information to populate - * the generated event object. This method does browser-equalizing - * calculations to account for differences in the DOM and IE event models - * as well as different browser quirks. - * @method simulateHTMLEvent - * @private - * @static - * @param {HTMLElement} target The target of the given event. - * @param {String} type The type of event to fire. This can be any one of - * the following: click, dblclick, mousedown, mouseup, mouseout, - * mouseover, and mousemove. - * @param {Boolean} bubbles (Optional) Indicates if the event can be - * bubbled up. DOM Level 2 specifies that all mouse events bubble by - * default. The default is true. - * @param {Boolean} cancelable (Optional) Indicates if the event can be - * canceled using preventDefault(). DOM Level 2 specifies that all - * mouse events except mousemove can be cancelled. The default - * is true for all events except mousemove, for which the default - * is false. - * @param {Window} view (Optional) The view containing the target. This is - * typically the window object. The default is window. - * @param {Number} detail (Optional) The number of times the mouse button has - * been used. The default value is 1. - */ -function simulateUIEvent(target /*:HTMLElement*/, type /*:String*/, - bubbles /*:Boolean*/, cancelable /*:Boolean*/, - view /*:Window*/, detail /*:int*/) /*:Void*/ -{ - - //check target - if (!target){ - Y.error("simulateUIEvent(): Invalid target."); - } - - //check event type - if (isString(type)){ - type = type.toLowerCase(); - - //make sure it's a supported mouse event - if (!uiEvents[type]){ - Y.error("simulateUIEvent(): Event type '" + type + "' not supported."); - } - } else { - Y.error("simulateUIEvent(): Event type must be a string."); - } - - //try to create a mouse event - var customEvent = null; - - - //setup default values - if (!isBoolean(bubbles)){ - bubbles = (type in bubbleEvents); //not all events bubble - } - if (!isBoolean(cancelable)){ - cancelable = (type === "submit"); //submit is the only one that can be cancelled - } - if (!isObject(view)){ - view = Y.config.win; //view is typically window - } - if (!isNumber(detail)){ - detail = 1; //usually not used but defaulted to this - } - - //check for DOM-compliant browsers first - if (isFunction(Y.config.doc.createEvent)){ - - //just a generic UI Event object is needed - customEvent = Y.config.doc.createEvent("UIEvents"); - customEvent.initUIEvent(type, bubbles, cancelable, view, detail); - - //fire the event - target.dispatchEvent(customEvent); - - } else if (isObject(Y.config.doc.createEventObject)){ //IE - - //create an IE event object - customEvent = Y.config.doc.createEventObject(); - - //assign available properties - customEvent.bubbles = bubbles; - customEvent.cancelable = cancelable; - customEvent.view = view; - customEvent.detail = detail; - - //fire the event - target.fireEvent("on" + type, customEvent); - - } else { - Y.error("simulateUIEvent(): No event simulation framework present."); - } -} - -/* - * (iOS only) This is for creating native DOM gesture events which only iOS - * v2.0+ is supporting. - * - * @method simulateGestureEvent - * @private - * @param {HTMLElement} target The target of the given event. - * @param {String} type The type of event to fire. This can be any one of - * the following: touchstart, touchmove, touchend, touchcancel. - * @param {Boolean} bubbles (Optional) Indicates if the event can be - * bubbled up. DOM Level 2 specifies that all mouse events bubble by - * default. The default is true. - * @param {Boolean} cancelable (Optional) Indicates if the event can be - * canceled using preventDefault(). DOM Level 2 specifies that all - * touch events except touchcancel can be cancelled. The default - * is true for all events except touchcancel, for which the default - * is false. - * @param {Window} view (Optional) The view containing the target. This is - * typically the window object. The default is window. - * @param {Number} detail (Optional) Specifies some detail information about - * the event depending on the type of event. - * @param {Number} screenX (Optional) The x-coordinate on the screen at which - * point the event occured. The default is 0. - * @param {Number} screenY (Optional) The y-coordinate on the screen at which - * point the event occured. The default is 0. - * @param {Number} clientX (Optional) The x-coordinate on the client at which - * point the event occured. The default is 0. - * @param {Number} clientY (Optional) The y-coordinate on the client at which - * point the event occured. The default is 0. - * @param {Boolean} ctrlKey (Optional) Indicates if one of the CTRL keys - * is pressed while the event is firing. The default is false. - * @param {Boolean} altKey (Optional) Indicates if one of the ALT keys - * is pressed while the event is firing. The default is false. - * @param {Boolean} shiftKey (Optional) Indicates if one of the SHIFT keys - * is pressed while the event is firing. The default is false. - * @param {Boolean} metaKey (Optional) Indicates if one of the META keys - * is pressed while the event is firing. The default is false. - * @param {Number} scale (iOS v2+ only) The distance between two fingers - * since the start of an event as a multiplier of the initial distance. - * The default value is 1.0. - * @param {Number} rotation (iOS v2+ only) The delta rotation since the start - * of an event, in degrees, where clockwise is positive and - * counter-clockwise is negative. The default value is 0.0. - */ -function simulateGestureEvent(target, type, - bubbles, // boolean - cancelable, // boolean - view, // DOMWindow - detail, // long - screenX, screenY, // long - clientX, clientY, // long - ctrlKey, altKey, shiftKey, metaKey, // boolean - scale, // float - rotation // float -) { - var customEvent; - - if(!Y.UA.ios || Y.UA.ios<2.0) { - Y.error("simulateGestureEvent(): Native gesture DOM eventframe is not available in this platform."); - } - - // check taget - if (!target){ - Y.error("simulateGestureEvent(): Invalid target."); - } - - //check event type - if (Y.Lang.isString(type)) { - type = type.toLowerCase(); - - //make sure it's a supported touch event - if (!gestureEvents[type]){ - Y.error("simulateTouchEvent(): Event type '" + type + "' not supported."); - } - } else { - Y.error("simulateGestureEvent(): Event type must be a string."); - } - - // setup default values - if (!Y.Lang.isBoolean(bubbles)) { bubbles = true; } // bubble by default - if (!Y.Lang.isBoolean(cancelable)) { cancelable = true; } - if (!Y.Lang.isObject(view)) { view = Y.config.win; } - if (!Y.Lang.isNumber(detail)) { detail = 2; } // usually not used. - if (!Y.Lang.isNumber(screenX)) { screenX = 0; } - if (!Y.Lang.isNumber(screenY)) { screenY = 0; } - if (!Y.Lang.isNumber(clientX)) { clientX = 0; } - if (!Y.Lang.isNumber(clientY)) { clientY = 0; } - if (!Y.Lang.isBoolean(ctrlKey)) { ctrlKey = false; } - if (!Y.Lang.isBoolean(altKey)) { altKey = false; } - if (!Y.Lang.isBoolean(shiftKey)){ shiftKey = false; } - if (!Y.Lang.isBoolean(metaKey)) { metaKey = false; } - - if (!Y.Lang.isNumber(scale)){ scale = 1.0; } - if (!Y.Lang.isNumber(rotation)){ rotation = 0.0; } - - customEvent = Y.config.doc.createEvent("GestureEvent"); - - customEvent.initGestureEvent(type, bubbles, cancelable, view, detail, - screenX, screenY, clientX, clientY, - ctrlKey, altKey, shiftKey, metaKey, - target, scale, rotation); - - target.dispatchEvent(customEvent); -} - - -/* - * @method simulateTouchEvent - * @private - * @param {HTMLElement} target The target of the given event. - * @param {String} type The type of event to fire. This can be any one of - * the following: touchstart, touchmove, touchend, touchcancel. - * @param {Boolean} bubbles (Optional) Indicates if the event can be - * bubbled up. DOM Level 2 specifies that all mouse events bubble by - * default. The default is true. - * @param {Boolean} cancelable (Optional) Indicates if the event can be - * canceled using preventDefault(). DOM Level 2 specifies that all - * touch events except touchcancel can be cancelled. The default - * is true for all events except touchcancel, for which the default - * is false. - * @param {Window} view (Optional) The view containing the target. This is - * typically the window object. The default is window. - * @param {Number} detail (Optional) Specifies some detail information about - * the event depending on the type of event. - * @param {Number} screenX (Optional) The x-coordinate on the screen at which - * point the event occured. The default is 0. - * @param {Number} screenY (Optional) The y-coordinate on the screen at which - * point the event occured. The default is 0. - * @param {Number} clientX (Optional) The x-coordinate on the client at which - * point the event occured. The default is 0. - * @param {Number} clientY (Optional) The y-coordinate on the client at which - * point the event occured. The default is 0. - * @param {Boolean} ctrlKey (Optional) Indicates if one of the CTRL keys - * is pressed while the event is firing. The default is false. - * @param {Boolean} altKey (Optional) Indicates if one of the ALT keys - * is pressed while the event is firing. The default is false. - * @param {Boolean} shiftKey (Optional) Indicates if one of the SHIFT keys - * is pressed while the event is firing. The default is false. - * @param {Boolean} metaKey (Optional) Indicates if one of the META keys - * is pressed while the event is firing. The default is false. - * @param {TouchList} touches A collection of Touch objects representing - * all touches associated with this event. - * @param {TouchList} targetTouches A collection of Touch objects - * representing all touches associated with this target. - * @param {TouchList} changedTouches A collection of Touch objects - * representing all touches that changed in this event. - * @param {Number} scale (iOS v2+ only) The distance between two fingers - * since the start of an event as a multiplier of the initial distance. - * The default value is 1.0. - * @param {Number} rotation (iOS v2+ only) The delta rotation since the start - * of an event, in degrees, where clockwise is positive and - * counter-clockwise is negative. The default value is 0.0. - */ -function simulateTouchEvent(target, type, - bubbles, // boolean - cancelable, // boolean - view, // DOMWindow - detail, // long - screenX, screenY, // long - clientX, clientY, // long - ctrlKey, altKey, shiftKey, metaKey, // boolean - touches, // TouchList - targetTouches, // TouchList - changedTouches, // TouchList - scale, // float - rotation // float -) { - - var customEvent; - - // check taget - if (!target){ - Y.error("simulateTouchEvent(): Invalid target."); - } - - //check event type - if (Y.Lang.isString(type)) { - type = type.toLowerCase(); - - //make sure it's a supported touch event - if (!touchEvents[type]){ - Y.error("simulateTouchEvent(): Event type '" + type + "' not supported."); - } - } else { - Y.error("simulateTouchEvent(): Event type must be a string."); - } - - // note that the caller is responsible to pass appropriate touch objects. - // check touch objects - // Android(even 4.0) doesn't define TouchList yet - /*if(type === 'touchstart' || type === 'touchmove') { - if(!touches instanceof TouchList) { - Y.error('simulateTouchEvent(): Invalid touches. It must be a TouchList'); - } else { - if(touches.length === 0) { - Y.error('simulateTouchEvent(): No touch object found.'); - } - } - } else if(type === 'touchend') { - if(!changedTouches instanceof TouchList) { - Y.error('simulateTouchEvent(): Invalid touches. It must be a TouchList'); - } else { - if(changedTouches.length === 0) { - Y.error('simulateTouchEvent(): No touch object found.'); - } - } - }*/ - - if(type === 'touchstart' || type === 'touchmove') { - if(touches.length === 0) { - Y.error('simulateTouchEvent(): No touch object in touches'); - } - } else if(type === 'touchend') { - if(changedTouches.length === 0) { - Y.error('simulateTouchEvent(): No touch object in changedTouches'); - } - } - - // setup default values - if (!Y.Lang.isBoolean(bubbles)) { bubbles = true; } // bubble by default. - if (!Y.Lang.isBoolean(cancelable)) { - cancelable = (type !== "touchcancel"); // touchcancel is not cancelled - } - if (!Y.Lang.isObject(view)) { view = Y.config.win; } - if (!Y.Lang.isNumber(detail)) { detail = 1; } // usually not used. defaulted to # of touch objects. - if (!Y.Lang.isNumber(screenX)) { screenX = 0; } - if (!Y.Lang.isNumber(screenY)) { screenY = 0; } - if (!Y.Lang.isNumber(clientX)) { clientX = 0; } - if (!Y.Lang.isNumber(clientY)) { clientY = 0; } - if (!Y.Lang.isBoolean(ctrlKey)) { ctrlKey = false; } - if (!Y.Lang.isBoolean(altKey)) { altKey = false; } - if (!Y.Lang.isBoolean(shiftKey)){ shiftKey = false; } - if (!Y.Lang.isBoolean(metaKey)) { metaKey = false; } - if (!Y.Lang.isNumber(scale)) { scale = 1.0; } - if (!Y.Lang.isNumber(rotation)) { rotation = 0.0; } - - - //check for DOM-compliant browsers first - if (Y.Lang.isFunction(Y.config.doc.createEvent)) { - if (Y.UA.android) { - /* - * Couldn't find android start version that supports touch event. - * Assumed supported(btw APIs broken till icecream sandwitch) - * from the beginning. - */ - if(Y.UA.android < 4.0) { - /* - * Touch APIs are broken in androids older than 4.0. We will use - * simulated touch apis for these versions. - * App developer still can listen for touch events. This events - * will be dispatched with touch event types. - * - * (Note) Used target for the relatedTarget. Need to verify if - * it has a side effect. - */ - customEvent = Y.config.doc.createEvent("MouseEvents"); - customEvent.initMouseEvent(type, bubbles, cancelable, view, detail, - screenX, screenY, clientX, clientY, - ctrlKey, altKey, shiftKey, metaKey, - 0, target); - - customEvent.touches = touches; - customEvent.targetTouches = targetTouches; - customEvent.changedTouches = changedTouches; - } else { - customEvent = Y.config.doc.createEvent("TouchEvent"); - - // Andoroid isn't compliant W3C initTouchEvent method signature. - customEvent.initTouchEvent(touches, targetTouches, changedTouches, - type, view, - screenX, screenY, clientX, clientY, - ctrlKey, altKey, shiftKey, metaKey); - } - } else if (Y.UA.ios) { - if(Y.UA.ios >= 2.0) { - customEvent = Y.config.doc.createEvent("TouchEvent"); - - // Available iOS 2.0 and later - customEvent.initTouchEvent(type, bubbles, cancelable, view, detail, - screenX, screenY, clientX, clientY, - ctrlKey, altKey, shiftKey, metaKey, - touches, targetTouches, changedTouches, - scale, rotation); - } else { - Y.error('simulateTouchEvent(): No touch event simulation framework present for iOS, '+Y.UA.ios+'.'); - } - } else { - Y.error('simulateTouchEvent(): Not supported agent yet, '+Y.UA.userAgent); - } - - //fire the event - target.dispatchEvent(customEvent); - //} else if (Y.Lang.isObject(doc.createEventObject)){ // Windows Mobile/IE, support later - } else { - Y.error('simulateTouchEvent(): No event simulation framework present.'); - } -} - -/** - * Simulates the event or gesture with the given name on a target. - * @param {HTMLElement} target The DOM element that's the target of the event. - * @param {String} type The type of event or name of the supported gesture to simulate - * (i.e., "click", "doubletap", "flick"). - * @param {Object} options (Optional) Extra options to copy onto the event object. - * For gestures, options are used to refine the gesture behavior. - * @for Event - * @method simulate - * @static - */ -Y.Event.simulate = function(target, type, options){ - - options = options || {}; - - if (mouseEvents[type] || pointerEvents[type]){ - simulateMouseEvent(target, type, options.bubbles, - options.cancelable, options.view, options.detail, options.screenX, - options.screenY, options.clientX, options.clientY, options.ctrlKey, - options.altKey, options.shiftKey, options.metaKey, options.button, - options.relatedTarget); - } else if (keyEvents[type]){ - simulateKeyEvent(target, type, options.bubbles, - options.cancelable, options.view, options.ctrlKey, - options.altKey, options.shiftKey, options.metaKey, - options.keyCode, options.charCode); - } else if (uiEvents[type]){ - simulateUIEvent(target, type, options.bubbles, - options.cancelable, options.view, options.detail); - - // touch low-level event simulation - } else if (touchEvents[type]) { - if((Y.config.win && ("ontouchstart" in Y.config.win)) && !(Y.UA.phantomjs) && !(Y.UA.chrome && Y.UA.chrome < 6)) { - simulateTouchEvent(target, type, - options.bubbles, options.cancelable, options.view, options.detail, - options.screenX, options.screenY, options.clientX, options.clientY, - options.ctrlKey, options.altKey, options.shiftKey, options.metaKey, - options.touches, options.targetTouches, options.changedTouches, - options.scale, options.rotation); - } else { - Y.error("simulate(): Event '" + type + "' can't be simulated. Use gesture-simulate module instead."); - } - - // ios gesture low-level event simulation (iOS v2+ only) - } else if(Y.UA.ios && Y.UA.ios >= 2.0 && gestureEvents[type]) { - simulateGestureEvent(target, type, - options.bubbles, options.cancelable, options.view, options.detail, - options.screenX, options.screenY, options.clientX, options.clientY, - options.ctrlKey, options.altKey, options.shiftKey, options.metaKey, - options.scale, options.rotation); - - // anything else - } else { - Y.error("simulate(): Event '" + type + "' can't be simulated."); - } -}; - - -})(); - - - -}, '3.16.0', {"requires": ["event-base"]}); -/* -YUI 3.16.0 (build 76f0e08) -Copyright 2014 Yahoo! Inc. All rights reserved. -Licensed under the BSD License. -http://yuilibrary.com/license/ -*/ - -YUI.add('async-queue', function (Y, NAME) { - -/** - *

AsyncQueue allows you create a chain of function callbacks executed - * via setTimeout (or synchronously) that are guaranteed to run in order. - * Items in the queue can be promoted or removed. Start or resume the - * execution chain with run(). pause() to temporarily delay execution, or - * stop() to halt and clear the queue.

- * - * @module async-queue - */ - -/** - *

A specialized queue class that supports scheduling callbacks to execute - * sequentially, iteratively, even asynchronously.

- * - *

Callbacks can be function refs or objects with the following keys. Only - * the fn key is required.

- * - *
    - *
  • fn -- The callback function
  • - *
  • context -- The execution context for the callbackFn.
  • - *
  • args -- Arguments to pass to callbackFn.
  • - *
  • timeout -- Millisecond delay before executing callbackFn. - * (Applies to each iterative execution of callback)
  • - *
  • iterations -- Number of times to repeat the callback. - *
  • until -- Repeat the callback until this function returns - * true. This setting trumps iterations.
  • - *
  • autoContinue -- Set to false to prevent the AsyncQueue from - * executing the next callback in the Queue after - * the callback completes.
  • - *
  • id -- Name that can be used to get, promote, get the - * indexOf, or delete this callback.
  • - *
- * - * @class AsyncQueue - * @extends EventTarget - * @constructor - * @param callback* {Function|Object} 0..n callbacks to seed the queue - */ -Y.AsyncQueue = function() { - this._init(); - this.add.apply(this, arguments); -}; - -var Queue = Y.AsyncQueue, - EXECUTE = 'execute', - SHIFT = 'shift', - PROMOTE = 'promote', - REMOVE = 'remove', - - isObject = Y.Lang.isObject, - isFunction = Y.Lang.isFunction; - -/** - *

Static default values used to populate callback configuration properties. - * Preconfigured defaults include:

- * - *
    - *
  • autoContinue: true
  • - *
  • iterations: 1
  • - *
  • timeout: 10 (10ms between callbacks)
  • - *
  • until: (function to run until iterations <= 0)
  • - *
- * - * @property defaults - * @type {Object} - * @static - */ -Queue.defaults = Y.mix({ - autoContinue : true, - iterations : 1, - timeout : 10, - until : function () { - this.iterations |= 0; - return this.iterations <= 0; - } -}, Y.config.queueDefaults || {}); - -Y.extend(Queue, Y.EventTarget, { - /** - * Used to indicate the queue is currently executing a callback. - * - * @property _running - * @type {Boolean|Object} true for synchronous callback execution, the - * return handle from Y.later for async callbacks. - * Otherwise false. - * @protected - */ - _running : false, - - /** - * Initializes the AsyncQueue instance properties and events. - * - * @method _init - * @protected - */ - _init : function () { - Y.EventTarget.call(this, { prefix: 'queue', emitFacade: true }); - - this._q = []; - - /** - * Callback defaults for this instance. Static defaults that are not - * overridden are also included. - * - * @property defaults - * @type {Object} - */ - this.defaults = {}; - - this._initEvents(); - }, - - /** - * Initializes the instance events. - * - * @method _initEvents - * @protected - */ - _initEvents : function () { - this.publish({ - 'execute' : { defaultFn : this._defExecFn, emitFacade: true }, - 'shift' : { defaultFn : this._defShiftFn, emitFacade: true }, - 'add' : { defaultFn : this._defAddFn, emitFacade: true }, - 'promote' : { defaultFn : this._defPromoteFn, emitFacade: true }, - 'remove' : { defaultFn : this._defRemoveFn, emitFacade: true } - }); - }, - - /** - * Returns the next callback needing execution. If a callback is - * configured to repeat via iterations or until, it will be returned until - * the completion criteria is met. - * - * When the queue is empty, null is returned. - * - * @method next - * @return {Function} the callback to execute - */ - next : function () { - var callback; - - while (this._q.length) { - callback = this._q[0] = this._prepare(this._q[0]); - if (callback && callback.until()) { - this.fire(SHIFT, { callback: callback }); - callback = null; - } else { - break; - } - } - - return callback || null; - }, - - /** - * Default functionality for the "shift" event. Shifts the - * callback stored in the event object's callback property from - * the queue if it is the first item. - * - * @method _defShiftFn - * @param e {Event} The event object - * @protected - */ - _defShiftFn : function (e) { - if (this.indexOf(e.callback) === 0) { - this._q.shift(); - } - }, - - /** - * Creates a wrapper function to execute the callback using the aggregated - * configuration generated by combining the static AsyncQueue.defaults, the - * instance defaults, and the specified callback settings. - * - * The wrapper function is decorated with the callback configuration as - * properties for runtime modification. - * - * @method _prepare - * @param callback {Object|Function} the raw callback - * @return {Function} a decorated function wrapper to execute the callback - * @protected - */ - _prepare: function (callback) { - if (isFunction(callback) && callback._prepared) { - return callback; - } - - var config = Y.merge( - Queue.defaults, - { context : this, args: [], _prepared: true }, - this.defaults, - (isFunction(callback) ? { fn: callback } : callback)), - - wrapper = Y.bind(function () { - if (!wrapper._running) { - wrapper.iterations--; - } - if (isFunction(wrapper.fn)) { - wrapper.fn.apply(wrapper.context || Y, - Y.Array(wrapper.args)); - } - }, this); - - return Y.mix(wrapper, config); - }, - - /** - * Sets the queue in motion. All queued callbacks will be executed in - * order unless pause() or stop() is called or if one of the callbacks is - * configured with autoContinue: false. - * - * @method run - * @return {AsyncQueue} the AsyncQueue instance - * @chainable - */ - run : function () { - var callback, - cont = true; - - if (this._executing) { - this._running = true; - return this; - } - - for (callback = this.next(); - callback && !this.isRunning(); - callback = this.next()) - { - cont = (callback.timeout < 0) ? - this._execute(callback) : - this._schedule(callback); - - // Break to avoid an extra call to next (final-expression of the - // 'for' loop), because the until function of the next callback - // in the queue may return a wrong result if it depends on the - // not-yet-finished work of the previous callback. - if (!cont) { - break; - } - } - - if (!callback) { - /** - * Event fired when there is no remaining callback in the running queue. Also fired after stop(). - * @event complete - */ - this.fire('complete'); - } - - return this; - }, - - /** - * Handles the execution of callbacks. Returns a boolean indicating - * whether it is appropriate to continue running. - * - * @method _execute - * @param callback {Object} the callback object to execute - * @return {Boolean} whether the run loop should continue - * @protected - */ - _execute : function (callback) { - - this._running = callback._running = true; - this._executing = callback; - - callback.iterations--; - this.fire(EXECUTE, { callback: callback }); - - var cont = this._running && callback.autoContinue; - - this._running = callback._running = false; - this._executing = false; - - return cont; - }, - - /** - * Schedules the execution of asynchronous callbacks. - * - * @method _schedule - * @param callback {Object} the callback object to execute - * @return {Boolean} whether the run loop should continue - * @protected - */ - _schedule : function (callback) { - this._running = Y.later(callback.timeout, this, function () { - if (this._execute(callback)) { - this.run(); - } - }); - - return false; - }, - - /** - * Determines if the queue is waiting for a callback to complete execution. - * - * @method isRunning - * @return {Boolean} true if queue is waiting for a - * from any initiated transactions - */ - isRunning : function () { - return !!this._running; - }, - - /** - * Default functionality for the "execute" event. Executes the - * callback function - * - * @method _defExecFn - * @param e {Event} the event object - * @protected - */ - _defExecFn : function (e) { - e.callback(); - }, - - /** - * Add any number of callbacks to the end of the queue. Callbacks may be - * provided as functions or objects. - * - * @method add - * @param callback* {Function|Object} 0..n callbacks - * @return {AsyncQueue} the AsyncQueue instance - * @chainable - */ - add : function () { - this.fire('add', { callbacks: Y.Array(arguments,0,true) }); - - return this; - }, - - /** - * Default functionality for the "add" event. Adds the callbacks - * in the event facade to the queue. Callbacks successfully added to the - * queue are present in the event's added property in the - * after phase. - * - * @method _defAddFn - * @param e {Event} the event object - * @protected - */ - _defAddFn : function(e) { - var _q = this._q, - added = []; - - Y.Array.each(e.callbacks, function (c) { - if (isObject(c)) { - _q.push(c); - added.push(c); - } - }); - - e.added = added; - }, - - /** - * Pause the execution of the queue after the execution of the current - * callback completes. If called from code outside of a queued callback, - * clears the timeout for the pending callback. Paused queue can be - * restarted with q.run() - * - * @method pause - * @return {AsyncQueue} the AsyncQueue instance - * @chainable - */ - pause: function () { - if (this._running && isObject(this._running)) { - this._running.cancel(); - } - - this._running = false; - - return this; - }, - - /** - * Stop and clear the queue after the current execution of the - * current callback completes. - * - * @method stop - * @return {AsyncQueue} the AsyncQueue instance - * @chainable - */ - stop : function () { - - this._q = []; - - if (this._running && isObject(this._running)) { - this._running.cancel(); - this._running = false; - } - // otherwise don't systematically set this._running to false, because if - // stop has been called from inside a queued callback, the _execute method - // currenty running needs to call run() one more time for the 'complete' - // event to be fired. - - // if stop is called from outside a callback, we need to explicitely call - // run() once again to fire the 'complete' event. - if (!this._executing) { - this.run(); - } - - return this; - }, - - /** - * Returns the current index of a callback. Pass in either the id or - * callback function from getCallback. - * - * @method indexOf - * @param callback {String|Function} the callback or its specified id - * @return {Number} index of the callback or -1 if not found - */ - indexOf : function (callback) { - var i = 0, len = this._q.length, c; - - for (; i < len; ++i) { - c = this._q[i]; - if (c === callback || c.id === callback) { - return i; - } - } - - return -1; - }, - - /** - * Retrieve a callback by its id. Useful to modify the configuration - * while the queue is running. - * - * @method getCallback - * @param id {String} the id assigned to the callback - * @return {Object} the callback object - */ - getCallback : function (id) { - var i = this.indexOf(id); - - return (i > -1) ? this._q[i] : null; - }, - - /** - * Promotes the named callback to the top of the queue. If a callback is - * currently executing or looping (via until or iterations), the promotion - * is scheduled to occur after the current callback has completed. - * - * @method promote - * @param callback {String|Object} the callback object or a callback's id - * @return {AsyncQueue} the AsyncQueue instance - * @chainable - */ - promote : function (callback) { - var payload = { callback : callback },e; - - if (this.isRunning()) { - e = this.after(SHIFT, function () { - this.fire(PROMOTE, payload); - e.detach(); - }, this); - } else { - this.fire(PROMOTE, payload); - } - - return this; - }, - - /** - *

Default functionality for the "promote" event. Promotes the - * named callback to the head of the queue.

- * - *

The event object will contain a property "callback", which - * holds the id of a callback or the callback object itself.

- * - * @method _defPromoteFn - * @param e {Event} the custom event - * @protected - */ - _defPromoteFn : function (e) { - var i = this.indexOf(e.callback), - promoted = (i > -1) ? this._q.splice(i,1)[0] : null; - - e.promoted = promoted; - - if (promoted) { - this._q.unshift(promoted); - } - }, - - /** - * Removes the callback from the queue. If the queue is active, the - * removal is scheduled to occur after the current callback has completed. - * - * @method remove - * @param callback {String|Object} the callback object or a callback's id - * @return {AsyncQueue} the AsyncQueue instance - * @chainable - */ - remove : function (callback) { - var payload = { callback : callback },e; - - // Can't return the removed callback because of the deferral until - // current callback is complete - if (this.isRunning()) { - e = this.after(SHIFT, function () { - this.fire(REMOVE, payload); - e.detach(); - },this); - } else { - this.fire(REMOVE, payload); - } - - return this; - }, - - /** - *

Default functionality for the "remove" event. Removes the - * callback from the queue.

- * - *

The event object will contain a property "callback", which - * holds the id of a callback or the callback object itself.

- * - * @method _defRemoveFn - * @param e {Event} the custom event - * @protected - */ - _defRemoveFn : function (e) { - var i = this.indexOf(e.callback); - - e.removed = (i > -1) ? this._q.splice(i,1)[0] : null; - }, - - /** - * Returns the number of callbacks in the queue. - * - * @method size - * @return {Number} - */ - size : function () { - // next() flushes callbacks that have met their until() criteria and - // therefore shouldn't count since they wouldn't execute anyway. - if (!this.isRunning()) { - this.next(); - } - - return this._q.length; - } -}); - - - -}, '3.16.0', {"requires": ["event-custom"]}); -/* -YUI 3.16.0 (build 76f0e08) -Copyright 2014 Yahoo! Inc. All rights reserved. -Licensed under the BSD License. -http://yuilibrary.com/license/ -*/ - -YUI.add('dom-screen', function (Y, NAME) { - -(function(Y) { - -/** - * Adds position and region management functionality to DOM. - * @module dom - * @submodule dom-screen - * @for DOM - */ - -var DOCUMENT_ELEMENT = 'documentElement', - COMPAT_MODE = 'compatMode', - POSITION = 'position', - FIXED = 'fixed', - RELATIVE = 'relative', - LEFT = 'left', - TOP = 'top', - _BACK_COMPAT = 'BackCompat', - MEDIUM = 'medium', - BORDER_LEFT_WIDTH = 'borderLeftWidth', - BORDER_TOP_WIDTH = 'borderTopWidth', - GET_BOUNDING_CLIENT_RECT = 'getBoundingClientRect', - GET_COMPUTED_STYLE = 'getComputedStyle', - - Y_DOM = Y.DOM, - - // TODO: how about thead/tbody/tfoot/tr? - // TODO: does caption matter? - RE_TABLE = /^t(?:able|d|h)$/i, - - SCROLL_NODE; - -if (Y.UA.ie) { - if (Y.config.doc[COMPAT_MODE] !== 'BackCompat') { - SCROLL_NODE = DOCUMENT_ELEMENT; - } else { - SCROLL_NODE = 'body'; - } -} - -Y.mix(Y_DOM, { - /** - * Returns the inner height of the viewport (exludes scrollbar). - * @method winHeight - * @return {Number} The current height of the viewport. - */ - winHeight: function(node) { - var h = Y_DOM._getWinSize(node).height; - return h; - }, - - /** - * Returns the inner width of the viewport (exludes scrollbar). - * @method winWidth - * @return {Number} The current width of the viewport. - */ - winWidth: function(node) { - var w = Y_DOM._getWinSize(node).width; - return w; - }, - - /** - * Document height - * @method docHeight - * @return {Number} The current height of the document. - */ - docHeight: function(node) { - var h = Y_DOM._getDocSize(node).height; - return Math.max(h, Y_DOM._getWinSize(node).height); - }, - - /** - * Document width - * @method docWidth - * @return {Number} The current width of the document. - */ - docWidth: function(node) { - var w = Y_DOM._getDocSize(node).width; - return Math.max(w, Y_DOM._getWinSize(node).width); - }, - - /** - * Amount page has been scroll horizontally - * @method docScrollX - * @return {Number} The current amount the screen is scrolled horizontally. - */ - docScrollX: function(node, doc) { - doc = doc || (node) ? Y_DOM._getDoc(node) : Y.config.doc; // perf optimization - var dv = doc.defaultView, - pageOffset = (dv) ? dv.pageXOffset : 0; - return Math.max(doc[DOCUMENT_ELEMENT].scrollLeft, doc.body.scrollLeft, pageOffset); - }, - - /** - * Amount page has been scroll vertically - * @method docScrollY - * @return {Number} The current amount the screen is scrolled vertically. - */ - docScrollY: function(node, doc) { - doc = doc || (node) ? Y_DOM._getDoc(node) : Y.config.doc; // perf optimization - var dv = doc.defaultView, - pageOffset = (dv) ? dv.pageYOffset : 0; - return Math.max(doc[DOCUMENT_ELEMENT].scrollTop, doc.body.scrollTop, pageOffset); - }, - - /** - * Gets the current position of an element based on page coordinates. - * Element must be part of the DOM tree to have page coordinates - * (display:none or elements not appended return false). - * @method getXY - * @param element The target element - * @return {Array} The XY position of the element - - TODO: test inDocument/display? - */ - getXY: function() { - if (Y.config.doc[DOCUMENT_ELEMENT][GET_BOUNDING_CLIENT_RECT]) { - return function(node) { - var xy = null, - scrollLeft, - scrollTop, - mode, - box, - offX, - offY, - doc, - win, - inDoc, - rootNode; - - if (node && node.tagName) { - doc = node.ownerDocument; - mode = doc[COMPAT_MODE]; - - if (mode !== _BACK_COMPAT) { - rootNode = doc[DOCUMENT_ELEMENT]; - } else { - rootNode = doc.body; - } - - // inline inDoc check for perf - if (rootNode.contains) { - inDoc = rootNode.contains(node); - } else { - inDoc = Y.DOM.contains(rootNode, node); - } - - if (inDoc) { - win = doc.defaultView; - - // inline scroll calc for perf - if (win && 'pageXOffset' in win) { - scrollLeft = win.pageXOffset; - scrollTop = win.pageYOffset; - } else { - scrollLeft = (SCROLL_NODE) ? doc[SCROLL_NODE].scrollLeft : Y_DOM.docScrollX(node, doc); - scrollTop = (SCROLL_NODE) ? doc[SCROLL_NODE].scrollTop : Y_DOM.docScrollY(node, doc); - } - - if (Y.UA.ie) { // IE < 8, quirks, or compatMode - if (!doc.documentMode || doc.documentMode < 8 || mode === _BACK_COMPAT) { - offX = rootNode.clientLeft; - offY = rootNode.clientTop; - } - } - box = node[GET_BOUNDING_CLIENT_RECT](); - xy = [box.left, box.top]; - - if (offX || offY) { - xy[0] -= offX; - xy[1] -= offY; - - } - if ((scrollTop || scrollLeft)) { - if (!Y.UA.ios || (Y.UA.ios >= 4.2)) { - xy[0] += scrollLeft; - xy[1] += scrollTop; - } - - } - } else { - xy = Y_DOM._getOffset(node); - } - } - return xy; - }; - } else { - return function(node) { // manually calculate by crawling up offsetParents - //Calculate the Top and Left border sizes (assumes pixels) - var xy = null, - doc, - parentNode, - bCheck, - scrollTop, - scrollLeft; - - if (node) { - if (Y_DOM.inDoc(node)) { - xy = [node.offsetLeft, node.offsetTop]; - doc = node.ownerDocument; - parentNode = node; - // TODO: refactor with !! or just falsey - bCheck = ((Y.UA.gecko || Y.UA.webkit > 519) ? true : false); - - // TODO: worth refactoring for TOP/LEFT only? - while ((parentNode = parentNode.offsetParent)) { - xy[0] += parentNode.offsetLeft; - xy[1] += parentNode.offsetTop; - if (bCheck) { - xy = Y_DOM._calcBorders(parentNode, xy); - } - } - - // account for any scrolled ancestors - if (Y_DOM.getStyle(node, POSITION) != FIXED) { - parentNode = node; - - while ((parentNode = parentNode.parentNode)) { - scrollTop = parentNode.scrollTop; - scrollLeft = parentNode.scrollLeft; - - //Firefox does something funky with borders when overflow is not visible. - if (Y.UA.gecko && (Y_DOM.getStyle(parentNode, 'overflow') !== 'visible')) { - xy = Y_DOM._calcBorders(parentNode, xy); - } - - - if (scrollTop || scrollLeft) { - xy[0] -= scrollLeft; - xy[1] -= scrollTop; - } - } - xy[0] += Y_DOM.docScrollX(node, doc); - xy[1] += Y_DOM.docScrollY(node, doc); - - } else { - //Fix FIXED position -- add scrollbars - xy[0] += Y_DOM.docScrollX(node, doc); - xy[1] += Y_DOM.docScrollY(node, doc); - } - } else { - xy = Y_DOM._getOffset(node); - } - } - - return xy; - }; - } - }(),// NOTE: Executing for loadtime branching - - /** - Gets the width of vertical scrollbars on overflowed containers in the body - content. - - @method getScrollbarWidth - @return {Number} Pixel width of a scrollbar in the current browser - **/ - getScrollbarWidth: Y.cached(function () { - var doc = Y.config.doc, - testNode = doc.createElement('div'), - body = doc.getElementsByTagName('body')[0], - // 0.1 because cached doesn't support falsy refetch values - width = 0.1; - - if (body) { - testNode.style.cssText = "position:absolute;visibility:hidden;overflow:scroll;width:20px;"; - testNode.appendChild(doc.createElement('p')).style.height = '1px'; - body.insertBefore(testNode, body.firstChild); - width = testNode.offsetWidth - testNode.clientWidth; - - body.removeChild(testNode); - } - - return width; - }, null, 0.1), - - /** - * Gets the current X position of an element based on page coordinates. - * Element must be part of the DOM tree to have page coordinates - * (display:none or elements not appended return false). - * @method getX - * @param element The target element - * @return {Number} The X position of the element - */ - - getX: function(node) { - return Y_DOM.getXY(node)[0]; - }, - - /** - * Gets the current Y position of an element based on page coordinates. - * Element must be part of the DOM tree to have page coordinates - * (display:none or elements not appended return false). - * @method getY - * @param element The target element - * @return {Number} The Y position of the element - */ - - getY: function(node) { - return Y_DOM.getXY(node)[1]; - }, - - /** - * Set the position of an html element in page coordinates. - * The element must be part of the DOM tree to have page coordinates (display:none or elements not appended return false). - * @method setXY - * @param element The target element - * @param {Array} xy Contains X & Y values for new position (coordinates are page-based) - * @param {Boolean} noRetry By default we try and set the position a second time if the first fails - */ - setXY: function(node, xy, noRetry) { - var setStyle = Y_DOM.setStyle, - pos, - delta, - newXY, - currentXY; - - if (node && xy) { - pos = Y_DOM.getStyle(node, POSITION); - - delta = Y_DOM._getOffset(node); - if (pos == 'static') { // default to relative - pos = RELATIVE; - setStyle(node, POSITION, pos); - } - currentXY = Y_DOM.getXY(node); - - if (xy[0] !== null) { - setStyle(node, LEFT, xy[0] - currentXY[0] + delta[0] + 'px'); - } - - if (xy[1] !== null) { - setStyle(node, TOP, xy[1] - currentXY[1] + delta[1] + 'px'); - } - - if (!noRetry) { - newXY = Y_DOM.getXY(node); - if (newXY[0] !== xy[0] || newXY[1] !== xy[1]) { - Y_DOM.setXY(node, xy, true); - } - } - - } else { - } - }, - - /** - * Set the X position of an html element in page coordinates, regardless of how the element is positioned. - * The element(s) must be part of the DOM tree to have page coordinates (display:none or elements not appended return false). - * @method setX - * @param element The target element - * @param {Number} x The X values for new position (coordinates are page-based) - */ - setX: function(node, x) { - return Y_DOM.setXY(node, [x, null]); - }, - - /** - * Set the Y position of an html element in page coordinates, regardless of how the element is positioned. - * The element(s) must be part of the DOM tree to have page coordinates (display:none or elements not appended return false). - * @method setY - * @param element The target element - * @param {Number} y The Y values for new position (coordinates are page-based) - */ - setY: function(node, y) { - return Y_DOM.setXY(node, [null, y]); - }, - - /** - * @method swapXY - * @description Swap the xy position with another node - * @param {Node} node The node to swap with - * @param {Node} otherNode The other node to swap with - * @return {Node} - */ - swapXY: function(node, otherNode) { - var xy = Y_DOM.getXY(node); - Y_DOM.setXY(node, Y_DOM.getXY(otherNode)); - Y_DOM.setXY(otherNode, xy); - }, - - _calcBorders: function(node, xy2) { - var t = parseInt(Y_DOM[GET_COMPUTED_STYLE](node, BORDER_TOP_WIDTH), 10) || 0, - l = parseInt(Y_DOM[GET_COMPUTED_STYLE](node, BORDER_LEFT_WIDTH), 10) || 0; - if (Y.UA.gecko) { - if (RE_TABLE.test(node.tagName)) { - t = 0; - l = 0; - } - } - xy2[0] += l; - xy2[1] += t; - return xy2; - }, - - _getWinSize: function(node, doc) { - doc = doc || (node) ? Y_DOM._getDoc(node) : Y.config.doc; - var win = doc.defaultView || doc.parentWindow, - mode = doc[COMPAT_MODE], - h = win.innerHeight, - w = win.innerWidth, - root = doc[DOCUMENT_ELEMENT]; - - if ( mode && !Y.UA.opera ) { // IE, Gecko - if (mode != 'CSS1Compat') { // Quirks - root = doc.body; - } - h = root.clientHeight; - w = root.clientWidth; - } - return { height: h, width: w }; - }, - - _getDocSize: function(node) { - var doc = (node) ? Y_DOM._getDoc(node) : Y.config.doc, - root = doc[DOCUMENT_ELEMENT]; - - if (doc[COMPAT_MODE] != 'CSS1Compat') { - root = doc.body; - } - - return { height: root.scrollHeight, width: root.scrollWidth }; - } -}); - -})(Y); -(function(Y) { -var TOP = 'top', - RIGHT = 'right', - BOTTOM = 'bottom', - LEFT = 'left', - - getOffsets = function(r1, r2) { - var t = Math.max(r1[TOP], r2[TOP]), - r = Math.min(r1[RIGHT], r2[RIGHT]), - b = Math.min(r1[BOTTOM], r2[BOTTOM]), - l = Math.max(r1[LEFT], r2[LEFT]), - ret = {}; - - ret[TOP] = t; - ret[RIGHT] = r; - ret[BOTTOM] = b; - ret[LEFT] = l; - return ret; - }, - - DOM = Y.DOM; - -Y.mix(DOM, { - /** - * Returns an Object literal containing the following about this element: (top, right, bottom, left) - * @for DOM - * @method region - * @param {HTMLElement} element The DOM element. - * @return {Object} Object literal containing the following about this element: (top, right, bottom, left) - */ - region: function(node) { - var xy = DOM.getXY(node), - ret = false; - - if (node && xy) { - ret = DOM._getRegion( - xy[1], // top - xy[0] + node.offsetWidth, // right - xy[1] + node.offsetHeight, // bottom - xy[0] // left - ); - } - - return ret; - }, - - /** - * Find the intersect information for the passed nodes. - * @method intersect - * @for DOM - * @param {HTMLElement} element The first element - * @param {HTMLElement | Object} element2 The element or region to check the interect with - * @param {Object} altRegion An object literal containing the region for the first element if we already have the data (for performance e.g. DragDrop) - * @return {Object} Object literal containing the following intersection data: (top, right, bottom, left, area, yoff, xoff, inRegion) - */ - intersect: function(node, node2, altRegion) { - var r = altRegion || DOM.region(node), region = {}, - n = node2, - off; - - if (n.tagName) { - region = DOM.region(n); - } else if (Y.Lang.isObject(node2)) { - region = node2; - } else { - return false; - } - - off = getOffsets(region, r); - return { - top: off[TOP], - right: off[RIGHT], - bottom: off[BOTTOM], - left: off[LEFT], - area: ((off[BOTTOM] - off[TOP]) * (off[RIGHT] - off[LEFT])), - yoff: ((off[BOTTOM] - off[TOP])), - xoff: (off[RIGHT] - off[LEFT]), - inRegion: DOM.inRegion(node, node2, false, altRegion) - }; - - }, - /** - * Check if any part of this node is in the passed region - * @method inRegion - * @for DOM - * @param {Object} node The node to get the region from - * @param {Object} node2 The second node to get the region from or an Object literal of the region - * @param {Boolean} all Should all of the node be inside the region - * @param {Object} altRegion An object literal containing the region for this node if we already have the data (for performance e.g. DragDrop) - * @return {Boolean} True if in region, false if not. - */ - inRegion: function(node, node2, all, altRegion) { - var region = {}, - r = altRegion || DOM.region(node), - n = node2, - off; - - if (n.tagName) { - region = DOM.region(n); - } else if (Y.Lang.isObject(node2)) { - region = node2; - } else { - return false; - } - - if (all) { - return ( - r[LEFT] >= region[LEFT] && - r[RIGHT] <= region[RIGHT] && - r[TOP] >= region[TOP] && - r[BOTTOM] <= region[BOTTOM] ); - } else { - off = getOffsets(region, r); - if (off[BOTTOM] >= off[TOP] && off[RIGHT] >= off[LEFT]) { - return true; - } else { - return false; - } - - } - }, - - /** - * Check if any part of this element is in the viewport - * @method inViewportRegion - * @for DOM - * @param {HTMLElement} element The DOM element. - * @param {Boolean} all Should all of the node be inside the region - * @param {Object} altRegion An object literal containing the region for this node if we already have the data (for performance e.g. DragDrop) - * @return {Boolean} True if in region, false if not. - */ - inViewportRegion: function(node, all, altRegion) { - return DOM.inRegion(node, DOM.viewportRegion(node), all, altRegion); - - }, - - _getRegion: function(t, r, b, l) { - var region = {}; - - region[TOP] = region[1] = t; - region[LEFT] = region[0] = l; - region[BOTTOM] = b; - region[RIGHT] = r; - region.width = region[RIGHT] - region[LEFT]; - region.height = region[BOTTOM] - region[TOP]; - - return region; - }, - - /** - * Returns an Object literal containing the following about the visible region of viewport: (top, right, bottom, left) - * @method viewportRegion - * @for DOM - * @return {Object} Object literal containing the following about the visible region of the viewport: (top, right, bottom, left) - */ - viewportRegion: function(node) { - node = node || Y.config.doc.documentElement; - var ret = false, - scrollX, - scrollY; - - if (node) { - scrollX = DOM.docScrollX(node); - scrollY = DOM.docScrollY(node); - - ret = DOM._getRegion(scrollY, // top - DOM.winWidth(node) + scrollX, // right - scrollY + DOM.winHeight(node), // bottom - scrollX); // left - } - - return ret; - } -}); -})(Y); - - -}, '3.16.0', {"requires": ["dom-base", "dom-style"]}); -/* -YUI 3.16.0 (build 76f0e08) -Copyright 2014 Yahoo! Inc. All rights reserved. -Licensed under the BSD License. -http://yuilibrary.com/license/ -*/ - -YUI.add('node-screen', function (Y, NAME) { - -/** - * Extended Node interface for managing regions and screen positioning. - * Adds support for positioning elements and normalizes window size and scroll detection. - * @module node - * @submodule node-screen - */ - -// these are all "safe" returns, no wrapping required -Y.each([ - /** - * Returns the inner width of the viewport (exludes scrollbar). - * @config winWidth - * @for Node - * @type {Number} - */ - 'winWidth', - - /** - * Returns the inner height of the viewport (exludes scrollbar). - * @config winHeight - * @type {Number} - */ - 'winHeight', - - /** - * Document width - * @config docWidth - * @type {Number} - */ - 'docWidth', - - /** - * Document height - * @config docHeight - * @type {Number} - */ - 'docHeight', - - /** - * Pixel distance the page has been scrolled horizontally - * @config docScrollX - * @type {Number} - */ - 'docScrollX', - - /** - * Pixel distance the page has been scrolled vertically - * @config docScrollY - * @type {Number} - */ - 'docScrollY' - ], - function(name) { - Y.Node.ATTRS[name] = { - getter: function() { - var args = Array.prototype.slice.call(arguments); - args.unshift(Y.Node.getDOMNode(this)); - - return Y.DOM[name].apply(this, args); - } - }; - } -); - -Y.Node.ATTRS.scrollLeft = { - getter: function() { - var node = Y.Node.getDOMNode(this); - return ('scrollLeft' in node) ? node.scrollLeft : Y.DOM.docScrollX(node); - }, - - setter: function(val) { - var node = Y.Node.getDOMNode(this); - if (node) { - if ('scrollLeft' in node) { - node.scrollLeft = val; - } else if (node.document || node.nodeType === 9) { - Y.DOM._getWin(node).scrollTo(val, Y.DOM.docScrollY(node)); // scroll window if win or doc - } - } else { - } - } -}; - -Y.Node.ATTRS.scrollTop = { - getter: function() { - var node = Y.Node.getDOMNode(this); - return ('scrollTop' in node) ? node.scrollTop : Y.DOM.docScrollY(node); - }, - - setter: function(val) { - var node = Y.Node.getDOMNode(this); - if (node) { - if ('scrollTop' in node) { - node.scrollTop = val; - } else if (node.document || node.nodeType === 9) { - Y.DOM._getWin(node).scrollTo(Y.DOM.docScrollX(node), val); // scroll window if win or doc - } - } else { - } - } -}; - -Y.Node.importMethod(Y.DOM, [ -/** - * Gets the current position of the node in page coordinates. - * @method getXY - * @for Node - * @return {Array} The XY position of the node -*/ - 'getXY', - -/** - * Set the position of the node in page coordinates, regardless of how the node is positioned. - * @method setXY - * @param {Array} xy Contains X & Y values for new position (coordinates are page-based) - * @chainable - */ - 'setXY', - -/** - * Gets the current position of the node in page coordinates. - * @method getX - * @return {Number} The X position of the node -*/ - 'getX', - -/** - * Set the position of the node in page coordinates, regardless of how the node is positioned. - * @method setX - * @param {Number} x X value for new position (coordinates are page-based) - * @chainable - */ - 'setX', - -/** - * Gets the current position of the node in page coordinates. - * @method getY - * @return {Number} The Y position of the node -*/ - 'getY', - -/** - * Set the position of the node in page coordinates, regardless of how the node is positioned. - * @method setY - * @param {Number} y Y value for new position (coordinates are page-based) - * @chainable - */ - 'setY', - -/** - * Swaps the XY position of this node with another node. - * @method swapXY - * @param {Node | HTMLElement} otherNode The node to swap with. - * @chainable - */ - 'swapXY' -]); - -/** - * @module node - * @submodule node-screen - */ - -/** - * Returns a region object for the node - * @config region - * @for Node - * @type Node - */ -Y.Node.ATTRS.region = { - getter: function() { - var node = this.getDOMNode(), - region; - - if (node && !node.tagName) { - if (node.nodeType === 9) { // document - node = node.documentElement; - } - } - if (Y.DOM.isWindow(node)) { - region = Y.DOM.viewportRegion(node); - } else { - region = Y.DOM.region(node); - } - return region; - } -}; - -/** - * Returns a region object for the node's viewport - * @config viewportRegion - * @type Node - */ -Y.Node.ATTRS.viewportRegion = { - getter: function() { - return Y.DOM.viewportRegion(Y.Node.getDOMNode(this)); - } -}; - -Y.Node.importMethod(Y.DOM, 'inViewportRegion'); - -// these need special treatment to extract 2nd node arg -/** - * Compares the intersection of the node with another node or region - * @method intersect - * @for Node - * @param {Node|Object} node2 The node or region to compare with. - * @param {Object} altRegion An alternate region to use (rather than this node's). - * @return {Object} An object representing the intersection of the regions. - */ -Y.Node.prototype.intersect = function(node2, altRegion) { - var node1 = Y.Node.getDOMNode(this); - if (Y.instanceOf(node2, Y.Node)) { // might be a region object - node2 = Y.Node.getDOMNode(node2); - } - return Y.DOM.intersect(node1, node2, altRegion); -}; - -/** - * Determines whether or not the node is within the given region. - * @method inRegion - * @param {Node|Object} node2 The node or region to compare with. - * @param {Boolean} all Whether or not all of the node must be in the region. - * @param {Object} altRegion An alternate region to use (rather than this node's). - * @return {Boolean} True if in region, false if not. - */ -Y.Node.prototype.inRegion = function(node2, all, altRegion) { - var node1 = Y.Node.getDOMNode(this); - if (Y.instanceOf(node2, Y.Node)) { // might be a region object - node2 = Y.Node.getDOMNode(node2); - } - return Y.DOM.inRegion(node1, node2, all, altRegion); -}; - - -}, '3.16.0', {"requires": ["dom-screen", "node-base"]}); -/* -YUI 3.16.0 (build 76f0e08) -Copyright 2014 Yahoo! Inc. All rights reserved. -Licensed under the BSD License. -http://yuilibrary.com/license/ -*/ - -YUI.add('gesture-simulate', function (Y, NAME) { - -/** - * Simulate high-level user gestures by generating a set of native DOM events. - * - * @module gesture-simulate - * @requires event-simulate, async-queue, node-screen - */ - -var NAME = "gesture-simulate", - - // phantomjs check may be temporary, until we determine if it really support touch all the way through, like it claims to (http://code.google.com/p/phantomjs/issues/detail?id=375) - SUPPORTS_TOUCH = ((Y.config.win && ("ontouchstart" in Y.config.win)) && !(Y.UA.phantomjs) && !(Y.UA.chrome && Y.UA.chrome < 6)), - - gestureNames = { - tap: 1, - doubletap: 1, - press: 1, - move: 1, - flick: 1, - pinch: 1, - rotate: 1 - }, - - touchEvents = { - touchstart: 1, - touchmove: 1, - touchend: 1, - touchcancel: 1 - }, - - document = Y.config.doc, - emptyTouchList, - - EVENT_INTERVAL = 20, // 20ms - START_PAGEX, // will be adjusted to the node element center - START_PAGEY, // will be adjusted to the node element center - - // defaults that user can override. - DEFAULTS = { - // tap gestures - HOLD_TAP: 10, // 10ms - DELAY_TAP: 10, // 10ms - - // press gesture - HOLD_PRESS: 3000, // 3sec - MIN_HOLD_PRESS: 1000, // 1sec - MAX_HOLD_PRESS: 60000, // 1min - - // move gesture - DISTANCE_MOVE: 200, // 200 pixels - DURATION_MOVE: 1000, // 1sec - MAX_DURATION_MOVE: 5000,// 5sec - - // flick gesture - MIN_VELOCITY_FLICK: 1.3, - DISTANCE_FLICK: 200, // 200 pixels - DURATION_FLICK: 1000, // 1sec - MAX_DURATION_FLICK: 5000,// 5sec - - // pinch/rotation - DURATION_PINCH: 1000 // 1sec - }, - - TOUCH_START = 'touchstart', - TOUCH_MOVE = 'touchmove', - TOUCH_END = 'touchend', - - GESTURE_START = 'gesturestart', - GESTURE_CHANGE = 'gesturechange', - GESTURE_END = 'gestureend', - - MOUSE_UP = 'mouseup', - MOUSE_MOVE = 'mousemove', - MOUSE_DOWN = 'mousedown', - MOUSE_CLICK = 'click', - MOUSE_DBLCLICK = 'dblclick', - - X_AXIS = 'x', - Y_AXIS = 'y'; - - -function Simulations(node) { - if(!node) { - Y.error(NAME+': invalid target node'); - } - this.node = node; - this.target = Y.Node.getDOMNode(node); - - var startXY = this.node.getXY(), - dims = this._getDims(); - - START_PAGEX = startXY[0] + (dims[0])/2; - START_PAGEY = startXY[1] + (dims[1])/2; -} - -Simulations.prototype = { - - /** - * Helper method to convert a degree to a radian. - * - * @method _toRadian - * @private - * @param {Number} deg A degree to be converted to a radian. - * @return {Number} The degree in radian. - */ - _toRadian: function(deg) { - return deg * (Math.PI/180); - }, - - /** - * Helper method to get height/width while accounting for - * rotation/scale transforms where possible by using the - * bounding client rectangle height/width instead of the - * offsetWidth/Height which region uses. - * @method _getDims - * @private - * @return {Array} Array with [height, width] - */ - _getDims : function() { - var region, - width, - height; - - // Ideally, this should be in DOM somewhere. - if (this.target.getBoundingClientRect) { - region = this.target.getBoundingClientRect(); - - if ("height" in region) { - height = region.height; - } else { - // IE7,8 has getBCR, but no height. - height = Math.abs(region.bottom - region.top); - } - - if ("width" in region) { - width = region.width; - } else { - // IE7,8 has getBCR, but no width. - width = Math.abs(region.right - region.left); - } - } else { - region = this.node.get("region"); - width = region.width; - height = region.height; - } - - return [width, height]; - }, - - /** - * Helper method to convert a point relative to the node element into - * the point in the page coordination. - * - * @method _calculateDefaultPoint - * @private - * @param {Array} point A point relative to the node element. - * @return {Array} The same point in the page coordination. - */ - _calculateDefaultPoint: function(point) { - - var height; - - if(!Y.Lang.isArray(point) || point.length === 0) { - point = [START_PAGEX, START_PAGEY]; - } else { - if(point.length == 1) { - height = this._getDims[1]; - point[1] = height/2; - } - // convert to page(viewport) coordination - point[0] = this.node.getX() + point[0]; - point[1] = this.node.getY() + point[1]; - } - - return point; - }, - - /** - * The "rotate" and "pinch" methods are essencially same with the exact same - * arguments. Only difference is the required parameters. The rotate method - * requires "rotation" parameter while the pinch method requires "startRadius" - * and "endRadius" parameters. - * - * @method rotate - * @param {Function} cb The callback to execute when the gesture simulation - * is completed. - * @param {Array} center A center point where the pinch gesture of two fingers - * should happen. It is relative to the top left corner of the target - * node element. - * @param {Number} startRadius A radius of start circle where 2 fingers are - * on when the gesture starts. This is optional. The default is a fourth of - * either target node width or height whichever is smaller. - * @param {Number} endRadius A radius of end circle where 2 fingers will be on when - * the pinch or spread gestures are completed. This is optional. - * The default is a fourth of either target node width or height whichever is less. - * @param {Number} duration A duration of the gesture in millisecond. - * @param {Number} start A start angle(0 degree at 12 o'clock) where the - * gesture should start. Default is 0. - * @param {Number} rotation A rotation in degree. It is required. - */ - rotate: function(cb, center, startRadius, endRadius, duration, start, rotation) { - var radius, - r1 = startRadius, // optional - r2 = endRadius; // optional - - if(!Y.Lang.isNumber(r1) || !Y.Lang.isNumber(r2) || r1<0 || r2<0) { - radius = (this.target.offsetWidth < this.target.offsetHeight)? - this.target.offsetWidth/4 : this.target.offsetHeight/4; - r1 = radius; - r2 = radius; - } - - // required - if(!Y.Lang.isNumber(rotation)) { - Y.error(NAME+'Invalid rotation detected.'); - } - - this.pinch(cb, center, r1, r2, duration, start, rotation); - }, - - /** - * The "rotate" and "pinch" methods are essencially same with the exact same - * arguments. Only difference is the required parameters. The rotate method - * requires "rotation" parameter while the pinch method requires "startRadius" - * and "endRadius" parameters. - * - * The "pinch" gesture can simulate various 2 finger gestures such as pinch, - * spread and/or rotation. The "startRadius" and "endRadius" are required. - * If endRadius is larger than startRadius, it becomes a spread gesture - * otherwise a pinch gesture. - * - * @method pinch - * @param {Function} cb The callback to execute when the gesture simulation - * is completed. - * @param {Array} center A center point where the pinch gesture of two fingers - * should happen. It is relative to the top left corner of the target - * node element. - * @param {Number} startRadius A radius of start circle where 2 fingers are - * on when the gesture starts. This paramenter is required. - * @param {Number} endRadius A radius of end circle where 2 fingers will be on when - * the pinch or spread gestures are completed. This parameter is required. - * @param {Number} duration A duration of the gesture in millisecond. - * @param {Number} start A start angle(0 degree at 12 o'clock) where the - * gesture should start. Default is 0. - * @param {Number} rotation If rotation is desired during the pinch or - * spread gestures, this parameter can be used. Default is 0 degree. - */ - pinch: function(cb, center, startRadius, endRadius, duration, start, rotation) { - var eventQueue, - i, - interval = EVENT_INTERVAL, - touches, - id = 0, - r1 = startRadius, // required - r2 = endRadius, // required - radiusPerStep, - centerX, centerY, - startScale, endScale, scalePerStep, - startRot, endRot, rotPerStep, - path1 = {start: [], end: []}, // paths for 1st and 2nd fingers. - path2 = {start: [], end: []}, - steps, - touchMove; - - center = this._calculateDefaultPoint(center); - - if(!Y.Lang.isNumber(r1) || !Y.Lang.isNumber(r2) || r1<0 || r2<0) { - Y.error(NAME+'Invalid startRadius and endRadius detected.'); - } - - if(!Y.Lang.isNumber(duration) || duration <= 0) { - duration = DEFAULTS.DURATION_PINCH; - } - - if(!Y.Lang.isNumber(start)) { - start = 0.0; - } else { - start = start%360; - while(start < 0) { - start += 360; - } - } - - if(!Y.Lang.isNumber(rotation)) { - rotation = 0.0; - } - - Y.AsyncQueue.defaults.timeout = interval; - eventQueue = new Y.AsyncQueue(); - - // range determination - centerX = center[0]; - centerY = center[1]; - - startRot = start; - endRot = start + rotation; - - // 1st finger path - path1.start = [ - centerX + r1*Math.sin(this._toRadian(startRot)), - centerY - r1*Math.cos(this._toRadian(startRot)) - ]; - path1.end = [ - centerX + r2*Math.sin(this._toRadian(endRot)), - centerY - r2*Math.cos(this._toRadian(endRot)) - ]; - - // 2nd finger path - path2.start = [ - centerX - r1*Math.sin(this._toRadian(startRot)), - centerY + r1*Math.cos(this._toRadian(startRot)) - ]; - path2.end = [ - centerX - r2*Math.sin(this._toRadian(endRot)), - centerY + r2*Math.cos(this._toRadian(endRot)) - ]; - - startScale = 1.0; - endScale = endRadius/startRadius; - - // touch/gesture start - eventQueue.add({ - fn: function() { - var coord1, coord2, coord, touches; - - // coordinate for each touch object. - coord1 = { - pageX: path1.start[0], - pageY: path1.start[1], - clientX: path1.start[0], - clientY: path1.start[1] - }; - coord2 = { - pageX: path2.start[0], - pageY: path2.start[1], - clientX: path2.start[0], - clientY: path2.start[1] - }; - touches = this._createTouchList([Y.merge({ - identifier: (id++) - }, coord1), Y.merge({ - identifier: (id++) - }, coord2)]); - - // coordinate for top level event - coord = { - pageX: (path1.start[0] + path2.start[0])/2, - pageY: (path1.start[0] + path2.start[1])/2, - clientX: (path1.start[0] + path2.start[0])/2, - clientY: (path1.start[0] + path2.start[1])/2 - }; - - this._simulateEvent(this.target, TOUCH_START, Y.merge({ - touches: touches, - targetTouches: touches, - changedTouches: touches, - scale: startScale, - rotation: startRot - }, coord)); - - if(Y.UA.ios >= 2.0) { - /* gesture starts when the 2nd finger touch starts. - * The implementation will fire 1 touch start event for both fingers, - * simulating 2 fingers touched on the screen at the same time. - */ - this._simulateEvent(this.target, GESTURE_START, Y.merge({ - scale: startScale, - rotation: startRot - }, coord)); - } - }, - timeout: 0, - context: this - }); - - // gesture change - steps = Math.floor(duration/interval); - radiusPerStep = (r2 - r1)/steps; - scalePerStep = (endScale - startScale)/steps; - rotPerStep = (endRot - startRot)/steps; - - touchMove = function(step) { - var radius = r1 + (radiusPerStep)*step, - px1 = centerX + radius*Math.sin(this._toRadian(startRot + rotPerStep*step)), - py1 = centerY - radius*Math.cos(this._toRadian(startRot + rotPerStep*step)), - px2 = centerX - radius*Math.sin(this._toRadian(startRot + rotPerStep*step)), - py2 = centerY + radius*Math.cos(this._toRadian(startRot + rotPerStep*step)), - px = (px1+px2)/2, - py = (py1+py2)/2, - coord1, coord2, coord, touches; - - // coordinate for each touch object. - coord1 = { - pageX: px1, - pageY: py1, - clientX: px1, - clientY: py1 - }; - coord2 = { - pageX: px2, - pageY: py2, - clientX: px2, - clientY: py2 - }; - touches = this._createTouchList([Y.merge({ - identifier: (id++) - }, coord1), Y.merge({ - identifier: (id++) - }, coord2)]); - - // coordinate for top level event - coord = { - pageX: px, - pageY: py, - clientX: px, - clientY: py - }; - - this._simulateEvent(this.target, TOUCH_MOVE, Y.merge({ - touches: touches, - targetTouches: touches, - changedTouches: touches, - scale: startScale + scalePerStep*step, - rotation: startRot + rotPerStep*step - }, coord)); - - if(Y.UA.ios >= 2.0) { - this._simulateEvent(this.target, GESTURE_CHANGE, Y.merge({ - scale: startScale + scalePerStep*step, - rotation: startRot + rotPerStep*step - }, coord)); - } - }; - - for (i=0; i < steps; i++) { - eventQueue.add({ - fn: touchMove, - args: [i], - context: this - }); - } - - // gesture end - eventQueue.add({ - fn: function() { - var emptyTouchList = this._getEmptyTouchList(), - coord1, coord2, coord, touches; - - // coordinate for each touch object. - coord1 = { - pageX: path1.end[0], - pageY: path1.end[1], - clientX: path1.end[0], - clientY: path1.end[1] - }; - coord2 = { - pageX: path2.end[0], - pageY: path2.end[1], - clientX: path2.end[0], - clientY: path2.end[1] - }; - touches = this._createTouchList([Y.merge({ - identifier: (id++) - }, coord1), Y.merge({ - identifier: (id++) - }, coord2)]); - - // coordinate for top level event - coord = { - pageX: (path1.end[0] + path2.end[0])/2, - pageY: (path1.end[0] + path2.end[1])/2, - clientX: (path1.end[0] + path2.end[0])/2, - clientY: (path1.end[0] + path2.end[1])/2 - }; - - if(Y.UA.ios >= 2.0) { - this._simulateEvent(this.target, GESTURE_END, Y.merge({ - scale: endScale, - rotation: endRot - }, coord)); - } - - this._simulateEvent(this.target, TOUCH_END, Y.merge({ - touches: emptyTouchList, - targetTouches: emptyTouchList, - changedTouches: touches, - scale: endScale, - rotation: endRot - }, coord)); - }, - context: this - }); - - if(cb && Y.Lang.isFunction(cb)) { - eventQueue.add({ - fn: cb, - - // by default, the callback runs the node context where - // simulateGesture method is called. - context: this.node - - //TODO: Use args to pass error object as 1st param if there is an error. - //args: - }); - } - - eventQueue.run(); - }, - - /** - * The "tap" gesture can be used for various single touch point gestures - * such as single tap, N number of taps, long press. The default is a single - * tap. - * - * @method tap - * @param {Function} cb The callback to execute when the gesture simulation - * is completed. - * @param {Array} point A point(relative to the top left corner of the - * target node element) where the tap gesture should start. The default - * is the center of the taget node. - * @param {Number} times The number of taps. Default is 1. - * @param {Number} hold The hold time in milliseconds between "touchstart" and - * "touchend" event generation. Default is 10ms. - * @param {Number} delay The time gap in millisecond between taps if this - * gesture has more than 1 tap. Default is 10ms. - */ - tap: function(cb, point, times, hold, delay) { - var eventQueue = new Y.AsyncQueue(), - emptyTouchList = this._getEmptyTouchList(), - touches, - coord, - i, - touchStart, - touchEnd; - - point = this._calculateDefaultPoint(point); - - if(!Y.Lang.isNumber(times) || times < 1) { - times = 1; - } - - if(!Y.Lang.isNumber(hold)) { - hold = DEFAULTS.HOLD_TAP; - } - - if(!Y.Lang.isNumber(delay)) { - delay = DEFAULTS.DELAY_TAP; - } - - coord = { - pageX: point[0], - pageY: point[1], - clientX: point[0], - clientY: point[1] - }; - - touches = this._createTouchList([Y.merge({identifier: 0}, coord)]); - - touchStart = function() { - this._simulateEvent(this.target, TOUCH_START, Y.merge({ - touches: touches, - targetTouches: touches, - changedTouches: touches - }, coord)); - }; - - touchEnd = function() { - this._simulateEvent(this.target, TOUCH_END, Y.merge({ - touches: emptyTouchList, - targetTouches: emptyTouchList, - changedTouches: touches - }, coord)); - }; - - for (i=0; i < times; i++) { - eventQueue.add({ - fn: touchStart, - context: this, - timeout: (i === 0)? 0 : delay - }); - - eventQueue.add({ - fn: touchEnd, - context: this, - timeout: hold - }); - } - - if(times > 1 && !SUPPORTS_TOUCH) { - eventQueue.add({ - fn: function() { - this._simulateEvent(this.target, MOUSE_DBLCLICK, coord); - }, - context: this - }); - } - - if(cb && Y.Lang.isFunction(cb)) { - eventQueue.add({ - fn: cb, - - // by default, the callback runs the node context where - // simulateGesture method is called. - context: this.node - - //TODO: Use args to pass error object as 1st param if there is an error. - //args: - }); - } - - eventQueue.run(); - }, - - /** - * The "flick" gesture is a specialized "move" that has some velocity - * and the movement always runs either x or y axis. The velocity is calculated - * with "distance" and "duration" arguments. If the calculated velocity is - * below than the minimum velocity, the given duration will be ignored and - * new duration will be created to make a valid flick gesture. - * - * @method flick - * @param {Function} cb The callback to execute when the gesture simulation - * is completed. - * @param {Array} point A point(relative to the top left corner of the - * target node element) where the flick gesture should start. The default - * is the center of the taget node. - * @param {String} axis Either "x" or "y". - * @param {Number} distance A distance in pixels to flick. - * @param {Number} duration A duration of the gesture in millisecond. - * - */ - flick: function(cb, point, axis, distance, duration) { - var path; - - point = this._calculateDefaultPoint(point); - - if(!Y.Lang.isString(axis)) { - axis = X_AXIS; - } else { - axis = axis.toLowerCase(); - if(axis !== X_AXIS && axis !== Y_AXIS) { - Y.error(NAME+'(flick): Only x or y axis allowed'); - } - } - - if(!Y.Lang.isNumber(distance)) { - distance = DEFAULTS.DISTANCE_FLICK; - } - - if(!Y.Lang.isNumber(duration)){ - duration = DEFAULTS.DURATION_FLICK; // ms - } else { - if(duration > DEFAULTS.MAX_DURATION_FLICK) { - duration = DEFAULTS.MAX_DURATION_FLICK; - } - } - - /* - * Check if too slow for a flick. - * Adjust duration if the calculated velocity is less than - * the minimum velcocity to be claimed as a flick. - */ - if(Math.abs(distance)/duration < DEFAULTS.MIN_VELOCITY_FLICK) { - duration = Math.abs(distance)/DEFAULTS.MIN_VELOCITY_FLICK; - } - - path = { - start: Y.clone(point), - end: [ - (axis === X_AXIS) ? point[0]+distance : point[0], - (axis === Y_AXIS) ? point[1]+distance : point[1] - ] - }; - - this._move(cb, path, duration); - }, - - /** - * The "move" gesture simulate the movement of any direction between - * the straight line of start and end point for the given duration. - * The path argument is an object with "point", "xdist" and "ydist" properties. - * The "point" property is an array with x and y coordinations(relative to the - * top left corner of the target node element) while "xdist" and "ydist" - * properties are used for the distance along the x and y axis. A negative - * distance number can be used to drag either left or up direction. - * - * If no arguments are given, it will simulate the default move, which - * is moving 200 pixels from the center of the element to the positive X-axis - * direction for 1 sec. - * - * @method move - * @param {Function} cb The callback to execute when the gesture simulation - * is completed. - * @param {Object} path An object with "point", "xdist" and "ydist". - * @param {Number} duration A duration of the gesture in millisecond. - */ - move: function(cb, path, duration) { - var convertedPath; - - if(!Y.Lang.isObject(path)) { - path = { - point: this._calculateDefaultPoint([]), - xdist: DEFAULTS.DISTANCE_MOVE, - ydist: 0 - }; - } else { - // convert to the page coordination - if(!Y.Lang.isArray(path.point)) { - path.point = this._calculateDefaultPoint([]); - } else { - path.point = this._calculateDefaultPoint(path.point); - } - - if(!Y.Lang.isNumber(path.xdist)) { - path.xdist = DEFAULTS.DISTANCE_MOVE; - } - - if(!Y.Lang.isNumber(path.ydist)) { - path.ydist = 0; - } - } - - if(!Y.Lang.isNumber(duration)){ - duration = DEFAULTS.DURATION_MOVE; // ms - } else { - if(duration > DEFAULTS.MAX_DURATION_MOVE) { - duration = DEFAULTS.MAX_DURATION_MOVE; - } - } - - convertedPath = { - start: Y.clone(path.point), - end: [path.point[0]+path.xdist, path.point[1]+path.ydist] - }; - - this._move(cb, convertedPath, duration); - }, - - /** - * A base method on top of "move" and "flick" methods. The method takes - * the path with start/end properties and duration to generate a set of - * touch events for the movement gesture. - * - * @method _move - * @private - * @param {Function} cb The callback to execute when the gesture simulation - * is completed. - * @param {Object} path An object with "start" and "end" properties. Each - * property should be an array with x and y coordination (e.g. start: [100, 50]) - * @param {Number} duration A duration of the gesture in millisecond. - */ - _move: function(cb, path, duration) { - var eventQueue, - i, - interval = EVENT_INTERVAL, - steps, stepX, stepY, - id = 0, - touchMove; - - if(!Y.Lang.isNumber(duration)){ - duration = DEFAULTS.DURATION_MOVE; // ms - } else { - if(duration > DEFAULTS.MAX_DURATION_MOVE) { - duration = DEFAULTS.MAX_DURATION_MOVE; - } - } - - if(!Y.Lang.isObject(path)) { - path = { - start: [ - START_PAGEX, - START_PAGEY - ], - end: [ - START_PAGEX + DEFAULTS.DISTANCE_MOVE, - START_PAGEY - ] - }; - } else { - if(!Y.Lang.isArray(path.start)) { - path.start = [ - START_PAGEX, - START_PAGEY - ]; - } - if(!Y.Lang.isArray(path.end)) { - path.end = [ - START_PAGEX + DEFAULTS.DISTANCE_MOVE, - START_PAGEY - ]; - } - } - - Y.AsyncQueue.defaults.timeout = interval; - eventQueue = new Y.AsyncQueue(); - - // start - eventQueue.add({ - fn: function() { - var coord = { - pageX: path.start[0], - pageY: path.start[1], - clientX: path.start[0], - clientY: path.start[1] - }, - touches = this._createTouchList([ - Y.merge({identifier: (id++)}, coord) - ]); - - this._simulateEvent(this.target, TOUCH_START, Y.merge({ - touches: touches, - targetTouches: touches, - changedTouches: touches - }, coord)); - }, - timeout: 0, - context: this - }); - - // move - steps = Math.floor(duration/interval); - stepX = (path.end[0] - path.start[0])/steps; - stepY = (path.end[1] - path.start[1])/steps; - - touchMove = function(step) { - var px = path.start[0]+(stepX * step), - py = path.start[1]+(stepY * step), - coord = { - pageX: px, - pageY: py, - clientX: px, - clientY: py - }, - touches = this._createTouchList([ - Y.merge({identifier: (id++)}, coord) - ]); - - this._simulateEvent(this.target, TOUCH_MOVE, Y.merge({ - touches: touches, - targetTouches: touches, - changedTouches: touches - }, coord)); - }; - - for (i=0; i < steps; i++) { - eventQueue.add({ - fn: touchMove, - args: [i], - context: this - }); - } - - // last move - eventQueue.add({ - fn: function() { - var coord = { - pageX: path.end[0], - pageY: path.end[1], - clientX: path.end[0], - clientY: path.end[1] - }, - touches = this._createTouchList([ - Y.merge({identifier: id}, coord) - ]); - - this._simulateEvent(this.target, TOUCH_MOVE, Y.merge({ - touches: touches, - targetTouches: touches, - changedTouches: touches - }, coord)); - }, - timeout: 0, - context: this - }); - - // end - eventQueue.add({ - fn: function() { - var coord = { - pageX: path.end[0], - pageY: path.end[1], - clientX: path.end[0], - clientY: path.end[1] - }, - emptyTouchList = this._getEmptyTouchList(), - touches = this._createTouchList([ - Y.merge({identifier: id}, coord) - ]); - - this._simulateEvent(this.target, TOUCH_END, Y.merge({ - touches: emptyTouchList, - targetTouches: emptyTouchList, - changedTouches: touches - }, coord)); - }, - context: this - }); - - if(cb && Y.Lang.isFunction(cb)) { - eventQueue.add({ - fn: cb, - - // by default, the callback runs the node context where - // simulateGesture method is called. - context: this.node - - //TODO: Use args to pass error object as 1st param if there is an error. - //args: - }); - } - - eventQueue.run(); - }, - - /** - * Helper method to return a singleton instance of empty touch list. - * - * @method _getEmptyTouchList - * @private - * @return {TouchList | Array} An empty touch list object. - */ - _getEmptyTouchList: function() { - if(!emptyTouchList) { - emptyTouchList = this._createTouchList([]); - } - - return emptyTouchList; - }, - - /** - * Helper method to convert an array with touch points to TouchList object as - * defined in http://www.w3.org/TR/touch-events/ - * - * @method _createTouchList - * @private - * @param {Array} touchPoints - * @return {TouchList | Array} If underlaying platform support creating touch list - * a TouchList object will be returned otherwise a fake Array object - * will be returned. - */ - _createTouchList: function(touchPoints) { - /* - * Android 4.0.3 emulator: - * Native touch api supported starting in version 4.0 (Ice Cream Sandwich). - * However the support seems limited. In Android 4.0.3 emulator, I got - * "TouchList is not defined". - */ - var touches = [], - touchList, - self = this; - - if(!!touchPoints && Y.Lang.isArray(touchPoints)) { - if(Y.UA.android && Y.UA.android >= 4.0 || Y.UA.ios && Y.UA.ios >= 2.0) { - Y.each(touchPoints, function(point) { - if(!point.identifier) {point.identifier = 0;} - if(!point.pageX) {point.pageX = 0;} - if(!point.pageY) {point.pageY = 0;} - if(!point.screenX) {point.screenX = 0;} - if(!point.screenY) {point.screenY = 0;} - - touches.push(document.createTouch(Y.config.win, - self.target, - point.identifier, - point.pageX, point.pageY, - point.screenX, point.screenY)); - }); - - touchList = document.createTouchList.apply(document, touches); - } else if(Y.UA.ios && Y.UA.ios < 2.0) { - Y.error(NAME+': No touch event simulation framework present.'); - } else { - // this will inclide android(Y.UA.android && Y.UA.android < 4.0) - // and desktops among all others. - - /* - * Touch APIs are broken in androids older than 4.0. We will use - * simulated touch apis for these versions. - */ - touchList = []; - Y.each(touchPoints, function(point) { - if(!point.identifier) {point.identifier = 0;} - if(!point.clientX) {point.clientX = 0;} - if(!point.clientY) {point.clientY = 0;} - if(!point.pageX) {point.pageX = 0;} - if(!point.pageY) {point.pageY = 0;} - if(!point.screenX) {point.screenX = 0;} - if(!point.screenY) {point.screenY = 0;} - - touchList.push({ - target: self.target, - identifier: point.identifier, - clientX: point.clientX, - clientY: point.clientY, - pageX: point.pageX, - pageY: point.pageY, - screenX: point.screenX, - screenY: point.screenY - }); - }); - - touchList.item = function(i) { - return touchList[i]; - }; - } - } else { - Y.error(NAME+': Invalid touchPoints passed'); - } - - return touchList; - }, - - /** - * @method _simulateEvent - * @private - * @param {HTMLElement} target The DOM element that's the target of the event. - * @param {String} type The type of event or name of the supported gesture to simulate - * (i.e., "click", "doubletap", "flick"). - * @param {Object} options (Optional) Extra options to copy onto the event object. - * For gestures, options are used to refine the gesture behavior. - */ - _simulateEvent: function(target, type, options) { - var touches; - - if (touchEvents[type]) { - if(SUPPORTS_TOUCH) { - Y.Event.simulate(target, type, options); - } else { - // simulate using mouse events if touch is not applicable on this platform. - // but only single touch event can be simulated. - if(this._isSingleTouch(options.touches, options.targetTouches, options.changedTouches)) { - type = { - touchstart: MOUSE_DOWN, - touchmove: MOUSE_MOVE, - touchend: MOUSE_UP - }[type]; - - options.button = 0; - options.relatedTarget = null; // since we are not using mouseover event. - - // touchend has none in options.touches. - touches = (type === MOUSE_UP)? options.changedTouches : options.touches; - - options = Y.mix(options, { - screenX: touches.item(0).screenX, - screenY: touches.item(0).screenY, - clientX: touches.item(0).clientX, - clientY: touches.item(0).clientY - }, true); - - Y.Event.simulate(target, type, options); - - if(type == MOUSE_UP) { - Y.Event.simulate(target, MOUSE_CLICK, options); - } - } else { - Y.error("_simulateEvent(): Event '" + type + "' has multi touch objects that can't be simulated in your platform."); - } - } - } else { - // pass thru for all non touch events - Y.Event.simulate(target, type, options); - } - }, - - /** - * Helper method to check the single touch. - * @method _isSingleTouch - * @private - * @param {TouchList} touches - * @param {TouchList} targetTouches - * @param {TouchList} changedTouches - */ - _isSingleTouch: function(touches, targetTouches, changedTouches) { - return (touches && (touches.length <= 1)) && - (targetTouches && (targetTouches.length <= 1)) && - (changedTouches && (changedTouches.length <= 1)); - } -}; - -/* - * A gesture simulation class. - */ -Y.GestureSimulation = Simulations; - -/* - * Various simulation default behavior properties. If user override - * Y.GestureSimulation.defaults, overriden values will be used and this - * should be done before the gesture simulation. - */ -Y.GestureSimulation.defaults = DEFAULTS; - -/* - * The high level gesture names that YUI knows how to simulate. - */ -Y.GestureSimulation.GESTURES = gestureNames; - -/** - * Simulates the higher user level gesture of the given name on a target. - * This method generates a set of low level touch events(Apple specific gesture - * events as well for the iOS platforms) asynchronously. Note that gesture - * simulation is relying on `Y.Event.simulate()` method to generate - * the touch events under the hood. The `Y.Event.simulate()` method - * itself is a synchronous method. - * - * Users are suggested to use `Node.simulateGesture()` method which - * basically calls this method internally. Supported gestures are `tap`, - * `doubletap`, `press`, `move`, `flick`, `pinch` and `rotate`. - * - * The `pinch` gesture is used to simulate the pinching and spreading of two - * fingers. During a pinch simulation, rotation is also possible. Essentially - * `pinch` and `rotate` simulations share the same base implementation to allow - * both pinching and rotation at the same time. The only difference is `pinch` - * requires `start` and `end` option properties while `rotate` requires `rotation` - * option property. - * - * The `pinch` and `rotate` gestures can be described as placing 2 fingers along a - * circle. Pinching and spreading can be described by start and end circles while - * rotation occurs on a single circle. If the radius of the start circle is greater - * than the end circle, the gesture becomes a pinch, otherwise it is a spread spread. - * - * @example - * - * var node = Y.one("#target"); - * - * // double tap example - * node.simulateGesture("doubletap", function() { - * // my callback function - * }); - * - * // flick example from the center of the node, move 50 pixels down for 50ms) - * node.simulateGesture("flick", { - * axis: y, - * distance: -100 - * duration: 50 - * }, function() { - * // my callback function - * }); - * - * // simulate rotating a node 75 degrees counter-clockwise - * node.simulateGesture("rotate", { - * rotation: -75 - * }); - * - * // simulate a pinch and a rotation at the same time. - * // fingers start on a circle of radius 100 px, placed at top/bottom - * // fingers end on a circle of radius 50px, placed at right/left - * node.simulateGesture("pinch", { - * r1: 100, - * r2: 50, - * start: 0 - * rotation: 90 - * }); - * - * @method simulateGesture - * @param {HTMLElement|Node} node The YUI node or HTML element that's the target - * of the event. - * @param {String} name The name of the supported gesture to simulate. The - * supported gesture name is one of "tap", "doubletap", "press", "move", - * "flick", "pinch" and "rotate". - * @param {Object} [options] Extra options used to define the gesture behavior: - * - * Valid options properties for the `tap` gesture: - * - * @param {Array} [options.point] (Optional) Indicates the [x,y] coordinates - * where the tap should be simulated. Default is the center of the node - * element. - * @param {Number} [options.hold=10] (Optional) The hold time in milliseconds. - * This is the time between `touchstart` and `touchend` event generation. - * @param {Number} [options.times=1] (Optional) Indicates the number of taps. - * @param {Number} [options.delay=10] (Optional) The number of milliseconds - * before the next tap simulation happens. This is valid only when `times` - * is more than 1. - * - * Valid options properties for the `doubletap` gesture: - * - * @param {Array} [options.point] (Optional) Indicates the [x,y] coordinates - * where the doubletap should be simulated. Default is the center of the - * node element. - * - * Valid options properties for the `press` gesture: - * - * @param {Array} [options.point] (Optional) Indicates the [x,y] coordinates - * where the press should be simulated. Default is the center of the node - * element. - * @param {Number} [options.hold=3000] (Optional) The hold time in milliseconds. - * This is the time between `touchstart` and `touchend` event generation. - * Default is 3000ms (3 seconds). - * - * Valid options properties for the `move` gesture: - * - * @param {Object} [options.path] (Optional) Indicates the path of the finger - * movement. It's an object with three optional properties: `point`, - * `xdist` and `ydist`. - * @param {Array} [options.path.point] A starting point of the gesture. - * Default is the center of the node element. - * @param {Number} [options.path.xdist=200] A distance to move in pixels - * along the X axis. A negative distance value indicates moving left. - * @param {Number} [options.path.ydist=0] A distance to move in pixels - * along the Y axis. A negative distance value indicates moving up. - * @param {Number} [options.duration=1000] (Optional) The duration of the - * gesture in milliseconds. - * - * Valid options properties for the `flick` gesture: - * - * @param {Array} [options.point] (Optional) Indicates the [x, y] coordinates - * where the flick should be simulated. Default is the center of the - * node element. - * @param {String} [options.axis='x'] (Optional) Valid values are either - * "x" or "y". Indicates axis to move along. The flick can move to one of - * 4 directions(left, right, up and down). - * @param {Number} [options.distance=200] (Optional) Distance to move in pixels - * @param {Number} [options.duration=1000] (Optional) The duration of the - * gesture in milliseconds. User given value could be automatically - * adjusted by the framework if it is below the minimum velocity to be - * a flick gesture. - * - * Valid options properties for the `pinch` gesture: - * - * @param {Array} [options.center] (Optional) The center of the circle where - * two fingers are placed. Default is the center of the node element. - * @param {Number} [options.r1] (Required) Pixel radius of the start circle - * where 2 fingers will be on when the gesture starts. The circles are - * centered at the center of the element. - * @param {Number} [options.r2] (Required) Pixel radius of the end circle - * when this gesture ends. - * @param {Number} [options.duration=1000] (Optional) The duration of the - * gesture in milliseconds. - * @param {Number} [options.start=0] (Optional) Starting degree of the first - * finger. The value is relative to the path of the north. Default is 0 - * (i.e., 12:00 on a clock). - * @param {Number} [options.rotation=0] (Optional) Degrees to rotate from - * the starting degree. A negative value means rotation to the - * counter-clockwise direction. - * - * Valid options properties for the `rotate` gesture: - * - * @param {Array} [options.center] (Optional) The center of the circle where - * two fingers are placed. Default is the center of the node element. - * @param {Number} [options.r1] (Optional) Pixel radius of the start circle - * where 2 fingers will be on when the gesture starts. The circles are - * centered at the center of the element. Default is a fourth of the node - * element width or height, whichever is smaller. - * @param {Number} [options.r2] (Optional) Pixel radius of the end circle - * when this gesture ends. Default is a fourth of the node element width or - * height, whichever is smaller. - * @param {Number} [options.duration=1000] (Optional) The duration of the - * gesture in milliseconds. - * @param {Number} [options.start=0] (Optional) Starting degree of the first - * finger. The value is relative to the path of the north. Default is 0 - * (i.e., 12:00 on a clock). - * @param {Number} [options.rotation] (Required) Degrees to rotate from - * the starting degree. A negative value means rotation to the - * counter-clockwise direction. - * - * @param {Function} [cb] The callback to execute when the asynchronouse gesture - * simulation is completed. - * @param {Error} cb.err An error object if the simulation is failed. - * @for Event - * @static - */ -Y.Event.simulateGesture = function(node, name, options, cb) { - - node = Y.one(node); - - var sim = new Y.GestureSimulation(node); - name = name.toLowerCase(); - - if(!cb && Y.Lang.isFunction(options)) { - cb = options; - options = {}; - } - - options = options || {}; - - if (gestureNames[name]) { - switch(name) { - // single-touch: point gestures - case 'tap': - sim.tap(cb, options.point, options.times, options.hold, options.delay); - break; - case 'doubletap': - sim.tap(cb, options.point, 2); - break; - case 'press': - if(!Y.Lang.isNumber(options.hold)) { - options.hold = DEFAULTS.HOLD_PRESS; - } else if(options.hold < DEFAULTS.MIN_HOLD_PRESS) { - options.hold = DEFAULTS.MIN_HOLD_PRESS; - } else if(options.hold > DEFAULTS.MAX_HOLD_PRESS) { - options.hold = DEFAULTS.MAX_HOLD_PRESS; - } - sim.tap(cb, options.point, 1, options.hold); - break; - - // single-touch: move gestures - case 'move': - sim.move(cb, options.path, options.duration); - break; - case 'flick': - sim.flick(cb, options.point, options.axis, options.distance, - options.duration); - break; - - // multi-touch: pinch/rotation gestures - case 'pinch': - sim.pinch(cb, options.center, options.r1, options.r2, - options.duration, options.start, options.rotation); - break; - case 'rotate': - sim.rotate(cb, options.center, options.r1, options.r2, - options.duration, options.start, options.rotation); - break; - } - } else { - Y.error(NAME+': Not a supported gesture simulation: '+name); - } -}; - - -}, '3.16.0', {"requires": ["async-queue", "event-simulate", "node-screen"]}); -/* -YUI 3.16.0 (build 76f0e08) -Copyright 2014 Yahoo! Inc. All rights reserved. -Licensed under the BSD License. -http://yuilibrary.com/license/ -*/ - -YUI.add('node-event-simulate', function (Y, NAME) { - -/** - * Adds functionality to simulate events. - * @module node - * @submodule node-event-simulate - */ - -/** - * Simulates an event on the node. - * @param {String} type The type of event (i.e., "click"). - * @param {Object} options (Optional) Extra options to copy onto the event object. - * @for Node - * @method simulate - */ -Y.Node.prototype.simulate = function (type, options) { - - Y.Event.simulate(Y.Node.getDOMNode(this), type, options); -}; - -/** - * Simulates the higher user level gesture of the given name on this node. - * This method generates a set of low level touch events(Apple specific gesture - * events as well for the iOS platforms) asynchronously. Note that gesture - * simulation is relying on `Y.Event.simulate()` method to generate - * the touch events under the hood. The `Y.Event.simulate()` method - * itself is a synchronous method. - * - * Supported gestures are `tap`, `doubletap`, `press`, `move`, `flick`, `pinch` - * and `rotate`. - * - * The `pinch` gesture is used to simulate the pinching and spreading of two - * fingers. During a pinch simulation, rotation is also possible. Essentially - * `pinch` and `rotate` simulations share the same base implementation to allow - * both pinching and rotation at the same time. The only difference is `pinch` - * requires `start` and `end` option properties while `rotate` requires `rotation` - * option property. - * - * The `pinch` and `rotate` gestures can be described as placing 2 fingers along a - * circle. Pinching and spreading can be described by start and end circles while - * rotation occurs on a single circle. If the radius of the start circle is greater - * than the end circle, the gesture becomes a pinch, otherwise it is a spread spread. - * - * @example - * - * var node = Y.one("#target"); - * - * // double tap example - * node.simulateGesture("doubletap", function() { - * // my callback function - * }); - * - * // flick example from the center of the node, move 50 pixels down for 50ms) - * node.simulateGesture("flick", { - * axis: y, - * distance: -100 - * duration: 50 - * }, function() { - * // my callback function - * }); - * - * // simulate rotating a node 75 degrees counter-clockwise - * node.simulateGesture("rotate", { - * rotation: -75 - * }); - * - * // simulate a pinch and a rotation at the same time. - * // fingers start on a circle of radius 100 px, placed at top/bottom - * // fingers end on a circle of radius 50px, placed at right/left - * node.simulateGesture("pinch", { - * r1: 100, - * r2: 50, - * start: 0 - * rotation: 90 - * }); - * - * @method simulateGesture - * @param {String} name The name of the supported gesture to simulate. The - * supported gesture name is one of "tap", "doubletap", "press", "move", - * "flick", "pinch" and "rotate". - * @param {Object} [options] Extra options used to define the gesture behavior: - * - * Valid options properties for the `tap` gesture: - * - * @param {Array} [options.point] (Optional) Indicates the [x,y] coordinates - * where the tap should be simulated. Default is the center of the node - * element. - * @param {Number} [options.hold=10] (Optional) The hold time in milliseconds. - * This is the time between `touchstart` and `touchend` event generation. - * @param {Number} [options.times=1] (Optional) Indicates the number of taps. - * @param {Number} [options.delay=10] (Optional) The number of milliseconds - * before the next tap simulation happens. This is valid only when `times` - * is more than 1. - * - * Valid options properties for the `doubletap` gesture: - * - * @param {Array} [options.point] (Optional) Indicates the [x,y] coordinates - * where the doubletap should be simulated. Default is the center of the - * node element. - * - * Valid options properties for the `press` gesture: - * - * @param {Array} [options.point] (Optional) Indicates the [x,y] coordinates - * where the press should be simulated. Default is the center of the node - * element. - * @param {Number} [options.hold=3000] (Optional) The hold time in milliseconds. - * This is the time between `touchstart` and `touchend` event generation. - * Default is 3000ms (3 seconds). - * - * Valid options properties for the `move` gesture: - * - * @param {Object} [options.path] (Optional) Indicates the path of the finger - * movement. It's an object with three optional properties: `point`, - * `xdist` and `ydist`. - * @param {Array} [options.path.point] A starting point of the gesture. - * Default is the center of the node element. - * @param {Number} [options.path.xdist=200] A distance to move in pixels - * along the X axis. A negative distance value indicates moving left. - * @param {Number} [options.path.ydist=0] A distance to move in pixels - * along the Y axis. A negative distance value indicates moving up. - * @param {Number} [options.duration=1000] (Optional) The duration of the - * gesture in milliseconds. - * - * Valid options properties for the `flick` gesture: - * - * @param {Array} [options.point] (Optional) Indicates the [x, y] coordinates - * where the flick should be simulated. Default is the center of the - * node element. - * @param {String} [options.axis='x'] (Optional) Valid values are either - * "x" or "y". Indicates axis to move along. The flick can move to one of - * 4 directions(left, right, up and down). - * @param {Number} [options.distance=200] (Optional) Distance to move in pixels - * @param {Number} [options.duration=1000] (Optional) The duration of the - * gesture in milliseconds. User given value could be automatically - * adjusted by the framework if it is below the minimum velocity to be - * a flick gesture. - * - * Valid options properties for the `pinch` gesture: - * - * @param {Array} [options.center] (Optional) The center of the circle where - * two fingers are placed. Default is the center of the node element. - * @param {Number} [options.r1] (Required) Pixel radius of the start circle - * where 2 fingers will be on when the gesture starts. The circles are - * centered at the center of the element. - * @param {Number} [options.r2] (Required) Pixel radius of the end circle - * when this gesture ends. - * @param {Number} [options.duration=1000] (Optional) The duration of the - * gesture in milliseconds. - * @param {Number} [options.start=0] (Optional) Starting degree of the first - * finger. The value is relative to the path of the north. Default is 0 - * (i.e., 12:00 on a clock). - * @param {Number} [options.rotation=0] (Optional) Degrees to rotate from - * the starting degree. A negative value means rotation to the - * counter-clockwise direction. - * - * Valid options properties for the `rotate` gesture: - * - * @param {Array} [options.center] (Optional) The center of the circle where - * two fingers are placed. Default is the center of the node element. - * @param {Number} [options.r1] (Optional) Pixel radius of the start circle - * where 2 fingers will be on when the gesture starts. The circles are - * centered at the center of the element. Default is a fourth of the node - * element width or height, whichever is smaller. - * @param {Number} [options.r2] (Optional) Pixel radius of the end circle - * when this gesture ends. Default is a fourth of the node element width or - * height, whichever is smaller. - * @param {Number} [options.duration=1000] (Optional) The duration of the - * gesture in milliseconds. - * @param {Number} [options.start=0] (Optional) Starting degree of the first - * finger. The value is relative to the path of the north. Default is 0 - * (i.e., 12:00 on a clock). - * @param {Number} [options.rotation] (Required) Degrees to rotate from - * the starting degree. A negative value means rotation to the - * counter-clockwise direction. - * - * @param {Function} [cb] The callback to execute when the asynchronouse gesture - * simulation is completed. - * @param {Error} cb.err An error object if the simulation is failed. - * @for Node - */ -Y.Node.prototype.simulateGesture = function (name, options, cb) { - - Y.Event.simulateGesture(this, name, options, cb); -}; - - -}, '3.16.0', {"requires": ["node-base", "event-simulate", "gesture-simulate"]}); -/* -YUI 3.16.0 (build 76f0e08) -Copyright 2014 Yahoo! Inc. All rights reserved. -Licensed under the BSD License. -http://yuilibrary.com/license/ -*/ - -YUI.add('base-build', function (Y, NAME) { - - /** - * The base-build submodule provides Base.build functionality, which - * can be used to create custom classes, by aggregating extensions onto - * a main class. - * - * @module base - * @submodule base-build - * @for Base - */ - var BaseCore = Y.BaseCore, - Base = Y.Base, - L = Y.Lang, - - INITIALIZER = "initializer", - DESTRUCTOR = "destructor", - AGGREGATES = ["_PLUG", "_UNPLUG"], - - build; - - // Utility function used in `_buildCfg` to aggregate array values into a new - // array from the sender constructor to the receiver constructor. - function arrayAggregator(prop, r, s) { - if (s[prop]) { - r[prop] = (r[prop] || []).concat(s[prop]); - } - } - - // Utility function used in `_buildCfg` to aggregate `_ATTR_CFG` array - // values from the sender constructor into a new array on receiver's - // constructor, and clear the cached hash. - function attrCfgAggregator(prop, r, s) { - if (s._ATTR_CFG) { - // Clear cached hash. - r._ATTR_CFG_HASH = null; - - arrayAggregator.apply(null, arguments); - } - } - - // Utility function used in `_buildCfg` to aggregate ATTRS configs from one - // the sender constructor to the receiver constructor. - function attrsAggregator(prop, r, s) { - BaseCore.modifyAttrs(r, s.ATTRS); - } - - Base._build = function(name, main, extensions, px, sx, cfg) { - - var build = Base._build, - - builtClass = build._ctor(main, cfg), - buildCfg = build._cfg(main, cfg, extensions), - - _mixCust = build._mixCust, - - dynamic = builtClass._yuibuild.dynamic, - - i, l, extClass, extProto, - initializer, - destructor; - - // Augment/Aggregate - for (i = 0, l = extensions.length; i < l; i++) { - extClass = extensions[i]; - - extProto = extClass.prototype; - - initializer = extProto[INITIALIZER]; - destructor = extProto[DESTRUCTOR]; - delete extProto[INITIALIZER]; - delete extProto[DESTRUCTOR]; - - // Prototype, old non-displacing augment - Y.mix(builtClass, extClass, true, null, 1); - - // Custom Statics - _mixCust(builtClass, extClass, buildCfg); - - if (initializer) { - extProto[INITIALIZER] = initializer; - } - - if (destructor) { - extProto[DESTRUCTOR] = destructor; - } - - builtClass._yuibuild.exts.push(extClass); - } - - if (px) { - Y.mix(builtClass.prototype, px, true); - } - - if (sx) { - Y.mix(builtClass, build._clean(sx, buildCfg), true); - _mixCust(builtClass, sx, buildCfg); - } - - builtClass.prototype.hasImpl = build._impl; - - if (dynamic) { - builtClass.NAME = name; - builtClass.prototype.constructor = builtClass; - - // Carry along the reference to `modifyAttrs()` from `main`. - builtClass.modifyAttrs = main.modifyAttrs; - } - - return builtClass; - }; - - build = Base._build; - - Y.mix(build, { - - _mixCust: function(r, s, cfg) { - - var aggregates, - custom, - statics, - aggr, - l, - i; - - if (cfg) { - aggregates = cfg.aggregates; - custom = cfg.custom; - statics = cfg.statics; - } - - if (statics) { - Y.mix(r, s, true, statics); - } - - if (aggregates) { - for (i = 0, l = aggregates.length; i < l; i++) { - aggr = aggregates[i]; - if (!r.hasOwnProperty(aggr) && s.hasOwnProperty(aggr)) { - r[aggr] = L.isArray(s[aggr]) ? [] : {}; - } - Y.aggregate(r, s, true, [aggr]); - } - } - - if (custom) { - for (i in custom) { - if (custom.hasOwnProperty(i)) { - custom[i](i, r, s); - } - } - } - - }, - - _tmpl: function(main) { - - function BuiltClass() { - BuiltClass.superclass.constructor.apply(this, arguments); - } - Y.extend(BuiltClass, main); - - return BuiltClass; - }, - - _impl : function(extClass) { - var classes = this._getClasses(), i, l, cls, exts, ll, j; - for (i = 0, l = classes.length; i < l; i++) { - cls = classes[i]; - if (cls._yuibuild) { - exts = cls._yuibuild.exts; - ll = exts.length; - - for (j = 0; j < ll; j++) { - if (exts[j] === extClass) { - return true; - } - } - } - } - return false; - }, - - _ctor : function(main, cfg) { - - var dynamic = (cfg && false === cfg.dynamic) ? false : true, - builtClass = (dynamic) ? build._tmpl(main) : main, - buildCfg = builtClass._yuibuild; - - if (!buildCfg) { - buildCfg = builtClass._yuibuild = {}; - } - - buildCfg.id = buildCfg.id || null; - buildCfg.exts = buildCfg.exts || []; - buildCfg.dynamic = dynamic; - - return builtClass; - }, - - _cfg : function(main, cfg, exts) { - var aggr = [], - cust = {}, - statics = [], - buildCfg, - cfgAggr = (cfg && cfg.aggregates), - cfgCustBuild = (cfg && cfg.custom), - cfgStatics = (cfg && cfg.statics), - c = main, - i, - l; - - // Prototype Chain - while (c && c.prototype) { - buildCfg = c._buildCfg; - if (buildCfg) { - if (buildCfg.aggregates) { - aggr = aggr.concat(buildCfg.aggregates); - } - if (buildCfg.custom) { - Y.mix(cust, buildCfg.custom, true); - } - if (buildCfg.statics) { - statics = statics.concat(buildCfg.statics); - } - } - c = c.superclass ? c.superclass.constructor : null; - } - - // Exts - if (exts) { - for (i = 0, l = exts.length; i < l; i++) { - c = exts[i]; - buildCfg = c._buildCfg; - if (buildCfg) { - if (buildCfg.aggregates) { - aggr = aggr.concat(buildCfg.aggregates); - } - if (buildCfg.custom) { - Y.mix(cust, buildCfg.custom, true); - } - if (buildCfg.statics) { - statics = statics.concat(buildCfg.statics); - } - } - } - } - - if (cfgAggr) { - aggr = aggr.concat(cfgAggr); - } - - if (cfgCustBuild) { - Y.mix(cust, cfg.cfgBuild, true); - } - - if (cfgStatics) { - statics = statics.concat(cfgStatics); - } - - return { - aggregates: aggr, - custom: cust, - statics: statics - }; - }, - - _clean : function(sx, cfg) { - var prop, i, l, sxclone = Y.merge(sx), - aggregates = cfg.aggregates, - custom = cfg.custom; - - for (prop in custom) { - if (sxclone.hasOwnProperty(prop)) { - delete sxclone[prop]; - } - } - - for (i = 0, l = aggregates.length; i < l; i++) { - prop = aggregates[i]; - if (sxclone.hasOwnProperty(prop)) { - delete sxclone[prop]; - } - } - - return sxclone; - } - }); - - /** - *

- * Builds a custom constructor function (class) from the - * main function, and array of extension functions (classes) - * provided. The NAME field for the constructor function is - * defined by the first argument passed in. - *

- *

- * The cfg object supports the following properties - *

- *
- *
dynamic <boolean>
- *
- *

If true (default), a completely new class - * is created which extends the main class, and acts as the - * host on which the extension classes are augmented.

- *

If false, the extensions classes are augmented directly to - * the main class, modifying the main class' prototype.

- *
- *
aggregates <String[]>
- *
An array of static property names, which will get aggregated - * on to the built class, in addition to the default properties build - * will always aggregate as defined by the main class' static _buildCfg - * property. - *
- *
- * - * @method build - * @deprecated Use the more convenient Base.create and Base.mix methods instead - * @static - * @param {Function} name The name of the new class. Used to define the NAME property for the new class. - * @param {Function} main The main class on which to base the built class - * @param {Function[]} extensions The set of extension classes which will be - * augmented/aggregated to the built class. - * @param {Object} cfg Optional. Build configuration for the class (see description). - * @return {Function} A custom class, created from the provided main and extension classes - */ - Base.build = function(name, main, extensions, cfg) { - return build(name, main, extensions, null, null, cfg); - }; - - /** - * Creates a new class (constructor function) which extends the base class passed in as the second argument, - * and mixes in the array of extensions provided. - * - * Prototype properties or methods can be added to the new class, using the px argument (similar to Y.extend). - * - * Static properties or methods can be added to the new class, using the sx argument (similar to Y.extend). - * - * **NOTE FOR COMPONENT DEVELOPERS**: Both the `base` class, and `extensions` can define static a `_buildCfg` - * property, which acts as class creation meta-data, and drives how special static properties from the base - * class, or extensions should be copied, aggregated or (custom) mixed into the newly created class. - * - * The `_buildCfg` property is a hash with 3 supported properties: `statics`, `aggregates` and `custom`, e.g: - * - * // If the Base/Main class is the thing introducing the property: - * - * MyBaseClass._buildCfg = { - * - * // Static properties/methods to copy (Alias) to the built class. - * statics: ["CopyThisMethod", "CopyThisProperty"], - * - * // Static props to aggregate onto the built class. - * aggregates: ["AggregateThisProperty"], - * - * // Static properties which need custom handling (e.g. deep merge etc.) - * custom: { - * "CustomProperty" : function(property, Receiver, Supplier) { - * ... - * var triggers = Receiver.CustomProperty.triggers; - * Receiver.CustomProperty.triggers = triggers.concat(Supplier.CustomProperty.triggers); - * ... - * } - * } - * }; - * - * MyBaseClass.CopyThisMethod = function() {...}; - * MyBaseClass.CopyThisProperty = "foo"; - * MyBaseClass.AggregateThisProperty = {...}; - * MyBaseClass.CustomProperty = { - * triggers: [...] - * } - * - * // Or, if the Extension is the thing introducing the property: - * - * MyExtension._buildCfg = { - * statics : ... - * aggregates : ... - * custom : ... - * } - * - * This way, when users pass your base or extension class to `Y.Base.create` or `Y.Base.mix`, they don't need to - * know which properties need special handling. `Y.Base` has a buildCfg which defines `ATTRS` for custom mix handling - * (to protect the static config objects), and `Y.Widget` has a buildCfg which specifies `HTML_PARSER` for - * straight up aggregation. - * - * @method create - * @static - * @param {String} name The name of the newly created class. Used to define the NAME property for the new class. - * @param {Function} main The base class which the new class should extend. - * This class needs to be Base or a class derived from base (e.g. Widget). - * @param {Function[]} extensions The list of extensions which will be mixed into the built class. - * @param {Object} px The set of prototype properties/methods to add to the built class. - * @param {Object} sx The set of static properties/methods to add to the built class. - * @return {Function} The newly created class. - */ - Base.create = function(name, base, extensions, px, sx) { - return build(name, base, extensions, px, sx); - }; - - /** - *

Mixes in a list of extensions to an existing class.

- * @method mix - * @static - * @param {Function} main The existing class into which the extensions should be mixed. - * The class needs to be Base or a class derived from Base (e.g. Widget) - * @param {Function[]} extensions The set of extension classes which will mixed into the existing main class. - * @return {Function} The modified main class, with extensions mixed in. - */ - Base.mix = function(main, extensions) { - - if (main._CACHED_CLASS_DATA) { - main._CACHED_CLASS_DATA = null; - } - - return build(null, main, extensions, null, null, {dynamic:false}); - }; - - /** - * The build configuration for the Base class. - * - * Defines the static fields which need to be aggregated when the Base class - * is used as the main class passed to the - *
Base.build method. - * - * @property _buildCfg - * @type Object - * @static - * @final - * @private - */ - BaseCore._buildCfg = { - aggregates: AGGREGATES.concat(), - - custom: { - ATTRS : attrsAggregator, - _ATTR_CFG : attrCfgAggregator, - _NON_ATTRS_CFG: arrayAggregator - } - }; - - // Makes sure Base and BaseCore use separate `_buildCfg` objects. - Base._buildCfg = { - aggregates: AGGREGATES.concat(), - - custom: { - ATTRS : attrsAggregator, - _ATTR_CFG : attrCfgAggregator, - _NON_ATTRS_CFG: arrayAggregator - } - }; - - -}, '3.16.0', {"requires": ["base-base"]}); -/* -YUI 3.16.0 (build 76f0e08) -Copyright 2014 Yahoo! Inc. All rights reserved. -Licensed under the BSD License. -http://yuilibrary.com/license/ -*/ - -YUI.add('file-html5', function (Y, NAME) { - - /** - * The FileHTML5 class provides a wrapper for a file pointer in an HTML5 The File wrapper - * also implements the mechanics for uploading a file and tracking its progress. - * @module file-html5 - */ - - /** - * The class provides a wrapper for a file pointer. - * @class FileHTML5 - * @extends Base - * @constructor - * @param {Object} config Configuration object. - */ - var Lang = Y.Lang, - Bind = Y.bind, - Win = Y.config.win; - - var FileHTML5 = function(o) { - - var file = null; - - if (FileHTML5.isValidFile(o)) { - file = o; - } - else if (FileHTML5.isValidFile(o.file)) { - file = o.file; - } - else { - file = false; - } - - FileHTML5.superclass.constructor.apply(this, arguments); - - if (file && FileHTML5.canUpload()) { - if (!this.get("file")) { - this._set("file", file); - } - - if (!this.get("name")) { - this._set("name", file.name || file.fileName); - } - - if (this.get("size") != (file.size || file.fileSize)) { - this._set("size", file.size || file.fileSize); - } - - if (!this.get("type")) { - this._set("type", file.type); - } - - if (file.hasOwnProperty("lastModifiedDate") && !this.get("dateModified")) { - this._set("dateModified", file.lastModifiedDate); - } - } - }; - - - Y.extend(FileHTML5, Y.Base, { - - /** - * Construction logic executed during FileHTML5 instantiation. - * - * @method initializer - * @protected - */ - initializer : function (cfg) { - if (!this.get("id")) { - this._set("id", Y.guid("file")); - } - }, - - /** - * Handler of events dispatched by the XMLHTTPRequest. - * - * @method _uploadEventHandler - * @param {Event} event The event object received from the XMLHTTPRequest. - * @protected - */ - _uploadEventHandler: function (event) { - var xhr = this.get("xhr"); - - switch (event.type) { - case "progress": - /** - * Signals that progress has been made on the upload of this file. - * - * @event uploadprogress - * @param event {Event} The event object for the `uploadprogress` with the - * following payload: - *
- *
originEvent
- *
The original event fired by the XMLHttpRequest instance.
- *
bytesLoaded
- *
The number of bytes of the file that has been uploaded.
- *
bytesTotal
- *
The total number of bytes in the file (the file size)
- *
percentLoaded
- *
The fraction of the file that has been uploaded, out of 100.
- *
- */ - this.fire("uploadprogress", {originEvent: event, - bytesLoaded: event.loaded, - bytesTotal: this.get("size"), - percentLoaded: Math.min(100, Math.round(10000*event.loaded/this.get("size"))/100) - }); - this._set("bytesUploaded", event.loaded); - break; - - case "load": - /** - * Signals that this file's upload has completed and data has been received from the server. - * - * @event uploadcomplete - * @param event {Event} The event object for the `uploadcomplete` with the - * following payload: - *
- *
originEvent
- *
The original event fired by the XMLHttpRequest instance.
- *
data
- *
The data returned by the server.
- *
- */ - - if (xhr.status >= 200 && xhr.status <= 299) { - this.fire("uploadcomplete", {originEvent: event, - data: event.target.responseText}); - var xhrupload = xhr.upload, - boundEventHandler = this.get("boundEventHandler"); - - xhrupload.removeEventListener ("progress", boundEventHandler); - xhrupload.removeEventListener ("error", boundEventHandler); - xhrupload.removeEventListener ("abort", boundEventHandler); - xhr.removeEventListener ("load", boundEventHandler); - xhr.removeEventListener ("error", boundEventHandler); - xhr.removeEventListener ("readystatechange", boundEventHandler); - - this._set("xhr", null); - } - else { - this.fire("uploaderror", {originEvent: event, - data: xhr.responseText, - status: xhr.status, - statusText: xhr.statusText, - source: "http"}); - } - break; - - case "error": - /** - * Signals that this file's upload has encountered an error. - * - * @event uploaderror - * @param event {Event} The event object for the `uploaderror` with the - * following payload: - *
- *
originEvent
- *
The original event fired by the XMLHttpRequest instance.
- *
data
- *
The data returned by the server.
- *
status
- *
The status code reported by the XMLHttpRequest. If it's an HTTP error, - then this corresponds to the HTTP status code received by the uploader.
- *
statusText
- *
The text of the error event reported by the XMLHttpRequest instance
- *
source
- *
Either "http" (if it's an HTTP error), or "io" (if it's a network transmission - * error.)
- * - *
- */ - this.fire("uploaderror", {originEvent: event, - data: xhr.responseText, - status: xhr.status, - statusText: xhr.statusText, - source: "io"}); - break; - - case "abort": - - /** - * Signals that this file's upload has been cancelled. - * - * @event uploadcancel - * @param event {Event} The event object for the `uploadcancel` with the - * following payload: - *
- *
originEvent
- *
The original event fired by the XMLHttpRequest instance.
- *
- */ - this.fire("uploadcancel", {originEvent: event}); - break; - - case "readystatechange": - - /** - * Signals that XMLHttpRequest has fired a readystatechange event. - * - * @event readystatechange - * @param event {Event} The event object for the `readystatechange` with the - * following payload: - *
- *
readyState
- *
The readyState code reported by the XMLHttpRequest instance.
- *
originEvent
- *
The original event fired by the XMLHttpRequest instance.
- *
- */ - this.fire("readystatechange", {readyState: event.target.readyState, - originEvent: event}); - break; - } - }, - - /** - * Starts the upload of a specific file. - * - * @method startUpload - * @param url {String} The URL to upload the file to. - * @param parameters {Object} (optional) A set of key-value pairs to send as variables along with the file upload HTTP request. - * @param fileFieldName {String} (optional) The name of the POST variable that should contain the uploaded file ('Filedata' by default) - */ - startUpload: function(url, parameters, fileFieldName) { - - this._set("bytesUploaded", 0); - - this._set("xhr", new XMLHttpRequest()); - this._set("boundEventHandler", Bind(this._uploadEventHandler, this)); - - var uploadData = new FormData(), - fileField = fileFieldName || "Filedata", - xhr = this.get("xhr"), - xhrupload = this.get("xhr").upload, - boundEventHandler = this.get("boundEventHandler"); - - Y.each(parameters, function (value, key) {uploadData.append(key, value);}); - uploadData.append(fileField, this.get("file")); - - - - - xhr.addEventListener ("loadstart", boundEventHandler, false); - xhrupload.addEventListener ("progress", boundEventHandler, false); - xhr.addEventListener ("load", boundEventHandler, false); - xhr.addEventListener ("error", boundEventHandler, false); - xhrupload.addEventListener ("error", boundEventHandler, false); - xhrupload.addEventListener ("abort", boundEventHandler, false); - xhr.addEventListener ("abort", boundEventHandler, false); - xhr.addEventListener ("loadend", boundEventHandler, false); - xhr.addEventListener ("readystatechange", boundEventHandler, false); - - xhr.open("POST", url, true); - - xhr.withCredentials = this.get("xhrWithCredentials"); - - Y.each(this.get("xhrHeaders"), function (value, key) { - xhr.setRequestHeader(key, value); - }); - - xhr.send(uploadData); - - /** - * Signals that this file's upload has started. - * - * @event uploadstart - * @param event {Event} The event object for the `uploadstart` with the - * following payload: - *
- *
xhr
- *
The XMLHttpRequest instance handling the file upload.
- *
- */ - this.fire("uploadstart", {xhr: xhr}); - - }, - - /** - * Cancels the upload of a specific file, if currently in progress. - * - * @method cancelUpload - */ - cancelUpload: function () { - var xhr = this.get('xhr'); - if (xhr) { - xhr.abort(); - } - } - - - }, { - - /** - * The identity of the class. - * - * @property NAME - * @type String - * @default 'file' - * @readOnly - * @protected - * @static - */ - NAME: 'file', - - /** - * The type of transport. - * - * @property TYPE - * @type String - * @default 'html5' - * @readOnly - * @protected - * @static - */ - TYPE: 'html5', - - /** - * Static property used to define the default attribute configuration of - * the File. - * - * @property ATTRS - * @type {Object} - * @protected - * @static - */ - ATTRS: { - - /** - * A String containing the unique id of the file wrapped by the FileFlash instance. - * The id is supplied by the Flash player uploader. - * - * @attribute id - * @type {String} - * @initOnly - */ - id: { - writeOnce: "initOnly", - value: null - }, - - /** - * The size of the file wrapped by FileHTML5. This value is supplied by the instance of File(). - * - * @attribute size - * @type {Number} - * @initOnly - */ - size: { - writeOnce: "initOnly", - value: 0 - }, - - /** - * The name of the file wrapped by FileHTML5. This value is supplied by the instance of File(). - * - * @attribute name - * @type {String} - * @initOnly - */ - name: { - writeOnce: "initOnly", - value: null - }, - - /** - * The date that the file wrapped by FileHTML5 was created on. This value is supplied by the instance of File(). - * - * @attribute dateCreated - * @type {Date} - * @initOnly - * @default null - */ - dateCreated: { - writeOnce: "initOnly", - value: null - }, - - /** - * The date that the file wrapped by FileHTML5 was last modified on. This value is supplied by the instance of File(). - * - * @attribute dateModified - * @type {Date} - * @initOnly - */ - dateModified: { - writeOnce: "initOnly", - value: null - }, - - /** - * The number of bytes of the file that has been uploaded to the server. This value is - * non-zero only while a file is being uploaded. - * - * @attribute bytesUploaded - * @type {Date} - * @readOnly - */ - bytesUploaded: { - readOnly: true, - value: 0 - }, - - /** - * The type of the file wrapped by FileHTML. This value is provided by the instance of File() - * - * @attribute type - * @type {String} - * @initOnly - */ - type: { - writeOnce: "initOnly", - value: null - }, - - /** - * The pointer to the instance of File() wrapped by FileHTML5. - * - * @attribute file - * @type {File} - * @initOnly - */ - file: { - writeOnce: "initOnly", - value: null - }, - - /** - * The pointer to the instance of XMLHttpRequest used by FileHTML5 to upload the file. - * - * @attribute xhr - * @type {XMLHttpRequest} - * @initOnly - */ - xhr: { - readOnly: true, - value: null - }, - - /** - * The dictionary of headers that should be set on the XMLHttpRequest object before - * sending it. - * - * @attribute xhrHeaders - * @type {Object} - * @initOnly - */ - xhrHeaders: { - value: {} - }, - - /** - * A Boolean indicating whether the XMLHttpRequest should be sent with user credentials. - * This does not affect same-site requests. - * - * @attribute xhrWithCredentials - * @type {Boolean} - * @initOnly - */ - xhrWithCredentials: { - value: true - }, - - /** - * The bound event handler used to handle events from XMLHttpRequest. - * - * @attribute boundEventHandler - * @type {Function} - * @initOnly - */ - boundEventHandler: { - readOnly: true, - value: null - } - }, - - /** - * Checks whether a specific native file instance is valid - * - * @method isValidFile - * @param file {File} A native File() instance. - * @static - */ - isValidFile: function (file) { - return (Win && Win.File && file instanceof File); - }, - - /** - * Checks whether the browser has a native upload capability - * via XMLHttpRequest Level 2. - * - * @method canUpload - * @static - */ - canUpload: function () { - return (Win && Win.FormData && Win.XMLHttpRequest); - } - }); - - Y.FileHTML5 = FileHTML5; - - -}, '3.16.0', {"requires": ["base"]}); -/* -YUI 3.16.0 (build 76f0e08) -Copyright 2014 Yahoo! Inc. All rights reserved. -Licensed under the BSD License. -http://yuilibrary.com/license/ -*/ - -YUI.add('uploader-queue', function (Y, NAME) { - -/** -* The class manages a queue of files that should be uploaded to the server. -* It initializes the required number of uploads, tracks them as they progress, -* and automatically advances to the next upload when a preceding one has completed. -* @module uploader-queue -*/ - - - -/** -* This class manages a queue of files to be uploaded to the server. -* @class Uploader.Queue -* @extends Base -* @constructor -*/ -var UploaderQueue = function() { - this.queuedFiles = []; - this.uploadRetries = {}; - this.numberOfUploads = 0; - this.currentUploadedByteValues = {}; - this.currentFiles = {}; - this.totalBytesUploaded = 0; - this.totalBytes = 0; - - UploaderQueue.superclass.constructor.apply(this, arguments); -}; - - -Y.extend(UploaderQueue, Y.Base, { - - /** - * Stored value of the current queue state - * @property _currentState - * @type {String} - * @protected - * @default UploaderQueue.STOPPED - */ - _currentState: UploaderQueue.STOPPED, - - /** - * Construction logic executed during UploaderQueue instantiation. - * - * @method initializer - * @protected - */ - initializer : function () {}, - - /** - * Handles and retransmits upload start event. - * - * @method _uploadStartHandler - * @param event The event dispatched during the upload process. - * @private - */ - _uploadStartHandler : function (event) { - var updatedEvent = event; - updatedEvent.file = event.target; - updatedEvent.originEvent = event; - - this.fire("uploadstart", updatedEvent); - }, - - /** - * Handles and retransmits upload error event. - * - * @method _uploadErrorHandler - * @param event The event dispatched during the upload process. - * @private - */ - _uploadErrorHandler : function (event) { - var errorAction = this.get("errorAction"), - updatedEvent = event, - fileid, - retries; - - updatedEvent.file = event.target; - updatedEvent.originEvent = event; - - this.numberOfUploads-=1; - delete this.currentFiles[event.target.get("id")]; - this._detachFileEvents(event.target); - - event.target.cancelUpload(); - - if (errorAction === UploaderQueue.STOP) { - this.pauseUpload(); - } - - else if (errorAction === UploaderQueue.RESTART_ASAP) { - fileid = event.target.get("id"); - retries = this.uploadRetries[fileid] || 0; - - if (retries < this.get("retryCount")) { - this.uploadRetries[fileid] = retries + 1; - this.addToQueueTop(event.target); - } - this._startNextFile(); - } - else if (errorAction === UploaderQueue.RESTART_AFTER) { - fileid = event.target.get("id"); - retries = this.uploadRetries[fileid] || 0; - - if (retries < this.get("retryCount")) { - this.uploadRetries[fileid] = retries + 1; - this.addToQueueBottom(event.target); - } - this._startNextFile(); - } - - this.fire("uploaderror", updatedEvent); - }, - - /** - * Launches the upload of the next file in the queue. - * - * @method _startNextFile - * @private - */ - _startNextFile : function () { - if (this.queuedFiles.length > 0) { - var currentFile = this.queuedFiles.shift(), - fileId = currentFile.get("id"), - parameters = this.get("perFileParameters"), - fileParameters = parameters.hasOwnProperty(fileId) ? parameters[fileId] : parameters; - - this.currentUploadedByteValues[fileId] = 0; - - currentFile.on("uploadstart", this._uploadStartHandler, this); - currentFile.on("uploadprogress", this._uploadProgressHandler, this); - currentFile.on("uploadcomplete", this._uploadCompleteHandler, this); - currentFile.on("uploaderror", this._uploadErrorHandler, this); - currentFile.on("uploadcancel", this._uploadCancelHandler, this); - - currentFile.set("xhrHeaders", this.get("uploadHeaders")); - currentFile.set("xhrWithCredentials", this.get("withCredentials")); - - currentFile.startUpload(this.get("uploadURL"), fileParameters, this.get("fileFieldName")); - - this._registerUpload(currentFile); - } - }, - - /** - * Register a new upload process. - * - * @method _registerUpload - * @private - */ - _registerUpload : function (file) { - this.numberOfUploads += 1; - this.currentFiles[file.get("id")] = file; - }, - - /** - * Unregisters a new upload process. - * - * @method _unregisterUpload - * @private - */ - _unregisterUpload : function (file) { - if (this.numberOfUploads > 0) { - this.numberOfUploads -= 1; - } - - delete this.currentFiles[file.get("id")]; - delete this.uploadRetries[file.get("id")]; - - this._detachFileEvents(file); - }, - - _detachFileEvents : function (file) { - file.detach("uploadstart", this._uploadStartHandler); - file.detach("uploadprogress", this._uploadProgressHandler); - file.detach("uploadcomplete", this._uploadCompleteHandler); - file.detach("uploaderror", this._uploadErrorHandler); - file.detach("uploadcancel", this._uploadCancelHandler); - }, - - /** - * Handles and retransmits upload complete event. - * - * @method _uploadCompleteHandler - * @param event The event dispatched during the upload process. - * @private - */ - _uploadCompleteHandler : function (event) { - - this._unregisterUpload(event.target); - - this.totalBytesUploaded += event.target.get("size"); - delete this.currentUploadedByteValues[event.target.get("id")]; - - - if (this.queuedFiles.length > 0 && this._currentState === UploaderQueue.UPLOADING) { - this._startNextFile(); - } - - var updatedEvent = event, - uploadedTotal = this.totalBytesUploaded, - percentLoaded = Math.min(100, Math.round(10000*uploadedTotal/this.totalBytes) / 100); - - updatedEvent.file = event.target; - updatedEvent.originEvent = event; - - Y.each(this.currentUploadedByteValues, function (value) { - uploadedTotal += value; - }); - - this.fire("totaluploadprogress", { - bytesLoaded: uploadedTotal, - bytesTotal: this.totalBytes, - percentLoaded: percentLoaded - }); - - this.fire("uploadcomplete", updatedEvent); - - if (this.queuedFiles.length === 0 && this.numberOfUploads <= 0) { - this.fire("alluploadscomplete"); - this._currentState = UploaderQueue.STOPPED; - } - }, - - /** - * Handles and retransmits upload cancel event. - * - * @method _uploadCancelHandler - * @param event The event dispatched during the upload process. - * @private - */ - _uploadCancelHandler : function (event) { - - var updatedEvent = event; - updatedEvent.originEvent = event; - updatedEvent.file = event.target; - - this.fire("uploadcancel", updatedEvent); - }, - - - - /** - * Handles and retransmits upload progress event. - * - * @method _uploadProgressHandler - * @param event The event dispatched during the upload process. - * @private - */ - _uploadProgressHandler : function (event) { - - this.currentUploadedByteValues[event.target.get("id")] = event.bytesLoaded; - - var updatedEvent = event, - uploadedTotal = this.totalBytesUploaded, - percentLoaded = Math.min(100, Math.round(10000*uploadedTotal/this.totalBytes) / 100); - - updatedEvent.originEvent = event; - updatedEvent.file = event.target; - - this.fire("uploadprogress", updatedEvent); - - Y.each(this.currentUploadedByteValues, function (value) { - uploadedTotal += value; - }); - - this.fire("totaluploadprogress", { - bytesLoaded: uploadedTotal, - bytesTotal: this.totalBytes, - percentLoaded: percentLoaded - }); - }, - - /** - * Starts uploading the queued up file list. - * - * @method startUpload - */ - startUpload: function() { - this.queuedFiles = this.get("fileList").slice(0); - this.numberOfUploads = 0; - this.currentUploadedByteValues = {}; - this.currentFiles = {}; - this.totalBytesUploaded = 0; - - this._currentState = UploaderQueue.UPLOADING; - - while (this.numberOfUploads < this.get("simUploads") && this.queuedFiles.length > 0) { - this._startNextFile(); - } - }, - - /** - * Pauses the upload process. The ongoing file uploads - * will complete after this method is called, but no - * new ones will be launched. - * - * @method pauseUpload - */ - pauseUpload: function () { - this._currentState = UploaderQueue.STOPPED; - }, - - /** - * Restarts a paused upload process. - * - * @method restartUpload - */ - restartUpload: function () { - this._currentState = UploaderQueue.UPLOADING; - while (this.numberOfUploads < this.get("simUploads")) { - this._startNextFile(); - } - }, - - /** - * If a particular file is stuck in an ongoing upload without - * any progress events, this method allows to force its reupload - * by cancelling its upload and immediately relaunching it. - * - * @method forceReupload - * @param file {File} The file to force reupload on. - */ - forceReupload : function (file) { - var id = file.get("id"); - if (this.currentFiles.hasOwnProperty(id)) { - file.cancelUpload(); - this._unregisterUpload(file); - this.addToQueueTop(file); - this._startNextFile(); - } - }, - - /** - * Add a new file to the top of the queue (the upload will be - * launched as soon as the current number of uploading files - * drops below the maximum permissible value). - * - * @method addToQueueTop - * @param file {File} The file to add to the top of the queue. - */ - addToQueueTop: function (file) { - this.queuedFiles.unshift(file); - }, - - /** - * Add a new file to the bottom of the queue (the upload will be - * launched after all the other queued files are uploaded.) - * - * @method addToQueueBottom - * @param file {File} The file to add to the bottom of the queue. - */ - addToQueueBottom: function (file) { - this.queuedFiles.push(file); - }, - - /** - * Cancels a specific file's upload. If no argument is passed, - * all ongoing uploads are cancelled and the upload process is - * stopped. - * - * @method cancelUpload - * @param file {File} An optional parameter - the file whose upload - * should be cancelled. - */ - cancelUpload: function (file) { - var id, - i, - fid; - - if (file) { - id = file.get("id"); - - if (this.currentFiles[id]) { - this.currentFiles[id].cancelUpload(); - this._unregisterUpload(this.currentFiles[id]); - if (this._currentState === UploaderQueue.UPLOADING) { - this._startNextFile(); - } - } - else { - for (i = 0, len = this.queuedFiles.length; i < len; i++) { - if (this.queuedFiles[i].get("id") === id) { - this.queuedFiles.splice(i, 1); - break; - } - } - } - } - else { - for (fid in this.currentFiles) { - this.currentFiles[fid].cancelUpload(); - this._unregisterUpload(this.currentFiles[fid]); - } - - this.currentUploadedByteValues = {}; - this.currentFiles = {}; - this.totalBytesUploaded = 0; - this.fire("alluploadscancelled"); - this._currentState = UploaderQueue.STOPPED; - } - } -}, { - /** - * Static constant for the value of the `errorAction` attribute: - * prescribes the queue to continue uploading files in case of - * an error. - * @property CONTINUE - * @readOnly - * @type {String} - * @static - */ - CONTINUE: "continue", - - /** - * Static constant for the value of the `errorAction` attribute: - * prescribes the queue to stop uploading files in case of - * an error. - * @property STOP - * @readOnly - * @type {String} - * @static - */ - STOP: "stop", - - /** - * Static constant for the value of the `errorAction` attribute: - * prescribes the queue to restart a file upload immediately in case of - * an error. - * @property RESTART_ASAP - * @readOnly - * @type {String} - * @static - */ - RESTART_ASAP: "restartasap", - - /** - * Static constant for the value of the `errorAction` attribute: - * prescribes the queue to restart an errored out file upload after - * other files have finished uploading. - * @property RESTART_AFTER - * @readOnly - * @type {String} - * @static - */ - RESTART_AFTER: "restartafter", - - /** - * Static constant for the value of the `_currentState` property: - * implies that the queue is currently not uploading files. - * @property STOPPED - * @readOnly - * @type {String} - * @static - */ - STOPPED: "stopped", - - /** - * Static constant for the value of the `_currentState` property: - * implies that the queue is currently uploading files. - * @property UPLOADING - * @readOnly - * @type {String} - * @static - */ - UPLOADING: "uploading", - - /** - * The identity of the class. - * - * @property NAME - * @type String - * @default 'uploaderqueue' - * @readOnly - * @protected - * @static - */ - NAME: 'uploaderqueue', - - /** - * Static property used to define the default attribute configuration of - * the class. - * - * @property ATTRS - * @type {Object} - * @protected - * @static - */ - ATTRS: { - - /** - * Maximum number of simultaneous uploads; must be in the - * range between 1 and 5. The value of `2` is default. It - * is recommended that this value does not exceed 3. - * @attribute simUploads - * @type Number - * @default 2 - */ - simUploads: { - value: 2, - validator: function (val) { - return (val >= 1 && val <= 5); - } - }, - - /** - * The action to take in case of error. The valid values for this attribute are: - * `Y.Uploader.Queue.CONTINUE` (the upload process should continue on other files, - * ignoring the error), `Y.Uploader.Queue.STOP` (the upload process - * should stop completely), `Y.Uploader.Queue.RESTART_ASAP` (the upload - * should restart immediately on the errored out file and continue as planned), or - * Y.Uploader.Queue.RESTART_AFTER (the upload of the errored out file should restart - * after all other files have uploaded) - * @attribute errorAction - * @type String - * @default Y.Uploader.Queue.CONTINUE - */ - errorAction: { - value: "continue", - validator: function (val) { - return ( - val === UploaderQueue.CONTINUE || - val === UploaderQueue.STOP || - val === UploaderQueue.RESTART_ASAP || - val === UploaderQueue.RESTART_AFTER - ); - } - }, - - /** - * The total number of bytes that has been uploaded. - * @attribute bytesUploaded - * @type Number - */ - bytesUploaded: { - readOnly: true, - value: 0 - }, - - /** - * The total number of bytes in the queue. - * @attribute bytesTotal - * @type Number - */ - bytesTotal: { - readOnly: true, - value: 0 - }, - - /** - * The queue file list. This file list should only be modified - * before the upload has been started; modifying it after starting - * the upload has no effect, and `addToQueueTop` or `addToQueueBottom` methods - * should be used instead. - * @attribute fileList - * @type Array - */ - fileList: { - value: [], - lazyAdd: false, - setter: function (val) { - var newValue = val; - Y.Array.each(newValue, function (value) { - this.totalBytes += value.get("size"); - }, this); - - return val; - } - }, - - /** - * A String specifying what should be the POST field name for the file - * content in the upload request. - * - * @attribute fileFieldName - * @type {String} - * @default Filedata - */ - fileFieldName: { - value: "Filedata" - }, - - /** - * The URL to POST the file upload requests to. - * - * @attribute uploadURL - * @type {String} - * @default "" - */ - uploadURL: { - value: "" - }, - - /** - * Additional HTTP headers that should be included - * in the upload request. Due to Flash Player security - * restrictions, this attribute is only honored in the - * HTML5 Uploader. - * - * @attribute uploadHeaders - * @type {Object} - * @default {} - */ - uploadHeaders: { - value: {} - }, - - /** - * A Boolean that specifies whether the file should be - * uploaded with the appropriate user credentials for the - * domain. Due to Flash Player security restrictions, this - * attribute is only honored in the HTML5 Uploader. - * - * @attribute withCredentials - * @type {Boolean} - * @default true - */ - withCredentials: { - value: true - }, - - - /** - * An object, keyed by `fileId`, containing sets of key-value pairs - * that should be passed as POST variables along with each corresponding - * file. - * - * @attribute perFileParameters - * @type {Object} - * @default {} - */ - perFileParameters: { - value: {} - }, - - /** - * The number of times to try re-uploading a file that failed to upload before - * cancelling its upload. - * - * @attribute retryCount - * @type {Number} - * @default 3 - */ - retryCount: { - value: 3 - } - - } -}); - - -Y.namespace('Uploader'); -Y.Uploader.Queue = UploaderQueue; - - -}, '3.16.0', {"requires": ["base"]}); -/* -YUI 3.16.0 (build 76f0e08) -Copyright 2014 Yahoo! Inc. All rights reserved. -Licensed under the BSD License. -http://yuilibrary.com/license/ -*/ - -YUI.add('uploader-html5', function (Y, NAME) { - -/** -* This module provides a UI for file selection and multiple file upload capability using -* HTML5 XMLHTTPRequest Level 2 as a transport engine. -* The supported features include: automatic upload queue management, upload progress -* tracking, drag-and-drop support, server response retrieval and error reporting. -* -* @module uploader-html5 -*/ - -// Shorthands for the external modules -var substitute = Y.Lang.sub, - UploaderQueue = Y.Uploader.Queue; - -/** -* This module provides a UI for file selection and multiple file upload capability using -* HTML5 XMLHTTPRequest Level 2 as a transport engine. -* @class UploaderHTML5 -* @extends Widget -* @constructor -*/ -function UploaderHTML5() { - UploaderHTML5.superclass.constructor.apply ( this, arguments ); -} - - - -Y.UploaderHTML5 = Y.extend( UploaderHTML5, Y.Widget, { - - /** - * Stored reference to the instance of the file input field used to - * initiate the file selection dialog. - * - * @property _fileInputField - * @type {Node} - * @protected - */ - _fileInputField: null, - - /** - * Stored reference to the click event binding of the `Select Files` - * button. - * - * @property _buttonBinding - * @type {EventHandle} - * @protected - */ - _buttonBinding: null, - - /** - * Stored reference to the instance of Uploader.Queue used to manage - * the upload process. This is a read-only property that only exists - * during an active upload process. Only one queue can be active at - * a time; if an upload start is attempted while a queue is active, - * it will be ignored. - * - * @property queue - * @type {Uploader.Queue} - */ - queue: null, - - // Y.UploaderHTML5 prototype - - /** - * Construction logic executed during UploaderHTML5 instantiation. - * - * @method initializer - * @protected - */ - initializer : function () { - - this._fileInputField = null; - this.queue = null; - this._buttonBinding = null; - this._fileList = []; - - // Publish available events - - /** - * Signals that files have been selected. - * - * @event fileselect - * @param event {Event} The event object for the `fileselect` with the - * following payload: - *
- *
fileList
- *
An `Array` of files selected by the user, encapsulated - * in Y.FileHTML5 objects.
- *
- */ - this.publish("fileselect"); - - /** - * Signals that an upload of multiple files has been started. - * - * @event uploadstart - * @param event {Event} The event object for the `uploadstart`. - */ - this.publish("uploadstart"); - - /** - * Signals that an upload of a specific file has started. - * - * @event fileuploadstart - * @param event {Event} The event object for the `fileuploadstart` with the - * following payload: - *
- *
file
- *
A reference to the Y.File that dispatched the event.
- *
originEvent
- *
The original event dispatched by Y.File.
- *
- */ - this.publish("fileuploadstart"); - - /** - * Reports on upload progress of a specific file. - * - * @event uploadprogress - * @param event {Event} The event object for the `uploadprogress` with the - * following payload: - *
- *
file
- *
The pointer to the instance of `Y.File` that dispatched the event.
- *
bytesLoaded
- *
The number of bytes of the file that has been uploaded
- *
bytesTotal
- *
The total number of bytes in the file
- *
percentLoaded
- *
The fraction of the file that has been uploaded, out of 100
- *
originEvent
- *
The original event dispatched by the HTML5 uploader
- *
- */ - this.publish("uploadprogress"); - - /** - * Reports on the total upload progress of the file list. - * - * @event totaluploadprogress - * @param event {Event} The event object for the `totaluploadprogress` with the - * following payload: - *
- *
bytesLoaded
- *
The number of bytes of the file list that has been uploaded
- *
bytesTotal
- *
The total number of bytes in the file list
- *
percentLoaded
- *
The fraction of the file list that has been uploaded, out of 100
- *
- */ - this.publish("totaluploadprogress"); - - /** - * Signals that a single file upload has been completed. - * - * @event uploadcomplete - * @param event {Event} The event object for the `uploadcomplete` with the - * following payload: - *
- *
file
- *
The pointer to the instance of `Y.File` whose upload has been completed.
- *
originEvent
- *
The original event fired by the SWF Uploader
- *
data
- *
Data returned by the server.
- *
- */ - this.publish("uploadcomplete"); - - /** - * Signals that the upload process of the entire file list has been completed. - * - * @event alluploadscomplete - * @param event {Event} The event object for the `alluploadscomplete`. - */ - this.publish("alluploadscomplete"); - - /** - * Signals that a error has occurred in a specific file's upload process. - * - * @event uploaderror - * @param event {Event} The event object for the `uploaderror` with the - * following payload: - *
- *
originEvent
- *
The original error event fired by the HTML5 Uploader.
- *
file
- *
The pointer at the instance of Y.File that returned the error.
- *
status
- *
The status reported by the XMLHttpRequest object.
- *
statusText
- *
The statusText reported by the XMLHttpRequest object.
- *
- */ - this.publish("uploaderror"); - - /** - * Signals that a dragged object has entered into the uploader's associated drag-and-drop area. - * - * @event dragenter - * @param event {Event} The event object for the `dragenter`. - */ - this.publish("dragenter"); - - /** - * Signals that an object has been dragged over the uploader's associated drag-and-drop area. - * - * @event dragover - * @param event {Event} The event object for the `dragover`. - */ - this.publish("dragover"); - - /** - * Signals that an object has been dragged off of the uploader's associated drag-and-drop area. - * - * @event dragleave - * @param event {Event} The event object for the `dragleave`. - */ - this.publish("dragleave"); - - /** - * Signals that an object has been dropped over the uploader's associated drag-and-drop area. - * - * @event drop - * @param event {Event} The event object for the `drop` with the - * following payload: - *
- *
fileList
- *
An `Array` of files dropped by the user, encapsulated - * in Y.FileHTML5 objects.
- *
- */ - this.publish("drop"); - - }, - - /** - * Create the DOM structure for the UploaderHTML5. - * UploaderHTML5's DOM structure consists of a "Select Files" button that can - * be replaced by the developer's widget of choice; and a hidden file input field - * that is used to instantiate the File Select dialog. - * - * @method renderUI - * @protected - */ - renderUI : function () { - var contentBox = this.get('contentBox'), - selButton = this.get("selectFilesButton"); - - selButton.setStyles({width:"100%", height:"100%"}); - contentBox.append(selButton); - this._fileInputField = Y.Node.create(UploaderHTML5.HTML5FILEFIELD_TEMPLATE); - contentBox.append(this._fileInputField); - }, - - /** - * Binds to the UploaderHTML5 UI and subscribes to the necessary events. - * - * @method bindUI - * @protected - */ - bindUI : function () { - - this._bindSelectButton(); - this._setMultipleFiles(); - this._setFileFilters(); - this._bindDropArea(); - this._triggerEnabled(); - - this.after("multipleFilesChange", this._setMultipleFiles, this); - this.after("fileFiltersChange", this._setFileFilters, this); - this.after("enabledChange", this._triggerEnabled, this); - this.after("selectFilesButtonChange", this._bindSelectButton, this); - this.after("dragAndDropAreaChange", this._bindDropArea, this); - this.after("tabIndexChange", function () { - this.get("selectFilesButton").set("tabIndex", this.get("tabIndex")); - }, this); - this._fileInputField.on("change", this._updateFileList, this); - this._fileInputField.on("click", function(event) { - event.stopPropagation(); - }, this); - - this.get("selectFilesButton").set("tabIndex", this.get("tabIndex")); - }, - - - /** - * Recreates the file field to null out the previous list of files and - * thus allow for an identical file list selection. - * - * @method _rebindFileField - * @protected - */ - _rebindFileField : function () { - this._fileInputField.remove(true); - this._fileInputField = Y.Node.create(UploaderHTML5.HTML5FILEFIELD_TEMPLATE); - this.get("contentBox").append(this._fileInputField); - this._fileInputField.on("change", this._updateFileList, this); - this._setMultipleFiles(); - this._setFileFilters(); - }, - - - /** - * Binds the specified drop area's drag and drop events to the - * uploader's custom handler. - * - * @method _bindDropArea - * @protected - */ - _bindDropArea : function (event) { - var ev = event || {prevVal: null}, - ddArea = this.get("dragAndDropArea"); - - if (ev.prevVal !== null) { - ev.prevVal.detach('drop', this._ddEventHandler); - ev.prevVal.detach('dragenter', this._ddEventHandler); - ev.prevVal.detach('dragover', this._ddEventHandler); - ev.prevVal.detach('dragleave', this._ddEventHandler); - } - - if (ddArea !== null) { - ddArea.on('drop', this._ddEventHandler, this); - ddArea.on('dragenter', this._ddEventHandler, this); - ddArea.on('dragover', this._ddEventHandler, this); - ddArea.on('dragleave', this._ddEventHandler, this); - } - }, - - /** - * Binds the instantiation of the file select dialog to the current file select - * control. - * - * @method _bindSelectButton - * @protected - */ - _bindSelectButton : function () { - this._buttonBinding = this.get("selectFilesButton").on("click", this.openFileSelectDialog, this); - }, - - /** - * Handles the drag and drop events from the uploader's specified drop - * area. - * - * @method _ddEventHandler - * @protected - */ - _ddEventHandler : function (event) { - - - event.stopPropagation(); - event.preventDefault(); - - if (Y.Array.indexOf(event._event.dataTransfer.types, 'Files') > -1) { - switch (event.type) { - case "dragenter": - this.fire("dragenter"); - break; - case "dragover": - this.fire("dragover"); - break; - case "dragleave": - this.fire("dragleave"); - break; - case "drop": - - var newfiles = event._event.dataTransfer.files, - parsedFiles = [], - filterFunc = this.get("fileFilterFunction"), - oldfiles; - - if (filterFunc) { - Y.each(newfiles, function (value) { - var newfile = new Y.FileHTML5(value); - if (filterFunc(newfile)) { - parsedFiles.push(newfile); - } - }); - } - else { - Y.each(newfiles, function (value) { - parsedFiles.push(new Y.FileHTML5(value)); - }); - } - - if (parsedFiles.length > 0) { - oldfiles = this.get("fileList"); - this.set("fileList", - this.get("appendNewFiles") ? oldfiles.concat(parsedFiles) : parsedFiles); - this.fire("fileselect", {fileList: parsedFiles}); - } - - this.fire("drop", {fileList: parsedFiles}); - break; - } - } - }, - - /** - * Adds or removes a specified state CSS class to the underlying uploader button. - * - * @method _setButtonClass - * @protected - * @param state {String} The name of the state enumerated in `buttonClassNames` attribute - * from which to derive the needed class name. - * @param add {Boolean} A Boolean indicating whether to add or remove the class. - */ - _setButtonClass : function (state, add) { - if (add) { - this.get("selectFilesButton").addClass(this.get("buttonClassNames")[state]); - } - else { - this.get("selectFilesButton").removeClass(this.get("buttonClassNames")[state]); - } - }, - - /** - * Syncs the state of the `multipleFiles` attribute between this class - * and the file input field. - * - * @method _setMultipleFiles - * @protected - */ - _setMultipleFiles : function () { - if (this.get("multipleFiles") === true) { - this._fileInputField.set("multiple", "multiple"); - } - else { - this._fileInputField.set("multiple", ""); - } - }, - - /** - * Syncs the state of the `fileFilters` attribute between this class - * and the file input field. - * - * @method _setFileFilters - * @protected - */ - _setFileFilters : function () { - if (this.get("fileFilters").length > 0) { - this._fileInputField.set("accept", this.get("fileFilters").join(",")); - } - else { - this._fileInputField.set("accept", ""); - } - }, - - - /** - * Syncs the state of the `enabled` attribute between this class - * and the underlying button. - * - * @method _triggerEnabled - * @private - */ - _triggerEnabled : function () { - if (this.get("enabled") && this._buttonBinding === null) { - this._bindSelectButton(); - this._setButtonClass("disabled", false); - this.get("selectFilesButton").setAttribute("aria-disabled", "false"); - } - else if (!this.get("enabled") && this._buttonBinding) { - this._buttonBinding.detach(); - this._buttonBinding = null; - this._setButtonClass("disabled", true); - this.get("selectFilesButton").setAttribute("aria-disabled", "true"); - } - }, - - /** - * Getter for the `fileList` attribute - * - * @method _getFileList - * @private - */ - _getFileList : function () { - return this._fileList.concat(); - }, - - /** - * Setter for the `fileList` attribute - * - * @method _setFileList - * @private - */ - _setFileList : function (val) { - this._fileList = val.concat(); - return this._fileList.concat(); - }, - - /** - * Adjusts the content of the `fileList` based on the results of file selection - * and the `appendNewFiles` attribute. If the `appendNewFiles` attribute is true, - * then selected files are appended to the existing list; otherwise, the list is - * cleared and populated with the newly selected files. - * - * @method _updateFileList - * @param ev {Event} The file selection event received from the uploader. - * @protected - */ - _updateFileList : function (ev) { - var newfiles = ev.target.getDOMNode().files, - parsedFiles = [], - filterFunc = this.get("fileFilterFunction"), - oldfiles; - - if (filterFunc) { - Y.each(newfiles, function (value) { - var newfile = new Y.FileHTML5(value); - if (filterFunc(newfile)) { - parsedFiles.push(newfile); - } - }); - } - else { - Y.each(newfiles, function (value) { - parsedFiles.push(new Y.FileHTML5(value)); - }); - } - - if (parsedFiles.length > 0) { - oldfiles = this.get("fileList"); - - this.set("fileList", - this.get("appendNewFiles") ? oldfiles.concat(parsedFiles) : parsedFiles ); - - this.fire("fileselect", {fileList: parsedFiles}); - } - - this._rebindFileField(); - }, - - - /** - * Handles and retransmits events fired by `Y.File` and `Y.Uploader.Queue`. - * - * @method _uploadEventHandler - * @param event The event dispatched during the upload process. - * @protected - */ - _uploadEventHandler : function (event) { - - switch (event.type) { - case "file:uploadstart": - this.fire("fileuploadstart", event); - break; - case "file:uploadprogress": - this.fire("uploadprogress", event); - break; - case "uploaderqueue:totaluploadprogress": - this.fire("totaluploadprogress", event); - break; - case "file:uploadcomplete": - this.fire("uploadcomplete", event); - break; - case "uploaderqueue:alluploadscomplete": - this.queue = null; - this.fire("alluploadscomplete", event); - break; - case "file:uploaderror": // overflow intentional - case "uploaderqueue:uploaderror": - this.fire("uploaderror", event); - break; - case "file:uploadcancel": // overflow intentional - case "uploaderqueue:uploadcancel": - this.fire("uploadcancel", event); - break; - } - - }, - - /** - * Opens the File Selection dialog by simulating a click on the file input field. - * - * @method openFileSelectDialog - */ - openFileSelectDialog : function () { - var fileDomNode = this._fileInputField.getDOMNode(); - if (fileDomNode.click) { - fileDomNode.click(); - } - }, - - /** - * Starts the upload of a specific file. - * - * @method upload - * @param file {File} Reference to the instance of the file to be uploaded. - * @param url {String} The URL to upload the file to. - * @param postVars {Object} (optional) A set of key-value pairs to send as variables along with the file upload HTTP request. - * If not specified, the values from the attribute `postVarsPerFile` are used instead. - */ - upload : function (file, url, postvars) { - - var uploadURL = url || this.get("uploadURL"), - postVars = postvars || this.get("postVarsPerFile"), - fileId = file.get("id"); - - postVars = postVars.hasOwnProperty(fileId) ? postVars[fileId] : postVars; - - if (file instanceof Y.FileHTML5) { - - file.on("uploadstart", this._uploadEventHandler, this); - file.on("uploadprogress", this._uploadEventHandler, this); - file.on("uploadcomplete", this._uploadEventHandler, this); - file.on("uploaderror", this._uploadEventHandler, this); - file.on("uploadcancel", this._uploadEventHandler, this); - - file.startUpload(uploadURL, postVars, this.get("fileFieldName")); - } - }, - - /** - * Starts the upload of all files on the file list, using an automated queue. - * - * @method uploadAll - * @param url {String} The URL to upload the files to. - * @param [postVars] {Object} A set of key-value pairs to send as variables along with the file upload HTTP request. - * If not specified, the values from the attribute `postVarsPerFile` are used instead. - */ - uploadAll : function (url, postvars) { - this.uploadThese(this.get("fileList"), url, postvars); - }, - - /** - * Starts the upload of the files specified in the first argument, using an automated queue. - * - * @method uploadThese - * @param files {Array} The list of files to upload. - * @param url {String} The URL to upload the files to. - * @param [postVars] {Object} A set of key-value pairs to send as variables along with the file upload HTTP request. - * If not specified, the values from the attribute `postVarsPerFile` are used instead. - */ - uploadThese : function (files, url, postvars) { - if (!this.queue) { - var uploadURL = url || this.get("uploadURL"), - postVars = postvars || this.get("postVarsPerFile"); - - this.queue = new UploaderQueue({ - simUploads: this.get("simLimit"), - errorAction: this.get("errorAction"), - fileFieldName: this.get("fileFieldName"), - fileList: files, - uploadURL: uploadURL, - perFileParameters: postVars, - retryCount: this.get("retryCount"), - uploadHeaders: this.get("uploadHeaders"), - withCredentials: this.get("withCredentials") - }); - - this.queue.on("uploadstart", this._uploadEventHandler, this); - this.queue.on("uploadprogress", this._uploadEventHandler, this); - this.queue.on("totaluploadprogress", this._uploadEventHandler, this); - this.queue.on("uploadcomplete", this._uploadEventHandler, this); - this.queue.on("alluploadscomplete", this._uploadEventHandler, this); - this.queue.on("uploadcancel", this._uploadEventHandler, this); - this.queue.on("uploaderror", this._uploadEventHandler, this); - this.queue.startUpload(); - - this.fire("uploadstart"); - } - else if (this.queue._currentState === UploaderQueue.UPLOADING) { - this.queue.set("perFileParameters", this.get("postVarsPerFile")); - Y.each(files, function (file) { - this.queue.addToQueueBottom(file); - }, this); - } - } -}, { - - /** - * The template for the hidden file input field container. The file input field will only - * accept clicks if its visibility is set to hidden (and will not if it's `display` value - * is set to `none`) - * - * @property HTML5FILEFIELD_TEMPLATE - * @type {String} - * @static - */ - HTML5FILEFIELD_TEMPLATE: "", - - /** - * The template for the "Select Files" button. - * - * @property SELECT_FILES_BUTTON - * @type {String} - * @static - * @default '' - */ - SELECT_FILES_BUTTON: '', - - /** - * The static property reflecting the type of uploader that `Y.Uploader` - * aliases. The UploaderHTML5 value is `"html5"`. - * - * @property TYPE - * @type {String} - * @static - */ - TYPE: "html5", - - /** - * The identity of the widget. - * - * @property NAME - * @type String - * @default 'uploader' - * @readOnly - * @protected - * @static - */ - NAME: "uploader", - - /** - * Static property used to define the default attribute configuration of - * the Widget. - * - * @property ATTRS - * @type {Object} - * @protected - * @static - */ - ATTRS: { - - /** - * A Boolean indicating whether newly selected files should be appended - * to the existing file list, or whether they should replace it. - * - * @attribute appendNewFiles - * @type {Boolean} - * @default true - */ - appendNewFiles : { - value: true - }, - - /** - * The names of CSS classes that correspond to different button states - * of the "Select Files" control. These classes are assigned to the - * "Select Files" control based on the configuration of the uploader. - * Currently, the only class name used is that corresponding to the - * `disabled` state of the uploader. Other button states should be managed - * directly via CSS selectors. - *
    - *
  • `disabled`: the class corresponding to the disabled state - * of the "Select Files" button.
  • - *
- * @attribute buttonClassNames - * @type {Object} - * @default { - * disabled: "yui3-button-disabled" - * } - */ - buttonClassNames: { - value: { - "hover": "yui3-button-hover", - "active": "yui3-button-active", - "disabled": "yui3-button-disabled", - "focus": "yui3-button-selected" - } - }, - - /** - * The node that serves as the drop target for files. - * - * @attribute dragAndDropArea - * @type {Node} - * @default null - */ - dragAndDropArea: { - value: null, - setter: function (val) { - return Y.one(val); - } - }, - - /** - * A Boolean indicating whether the uploader is enabled or disabled for user input. - * - * @attribute enabled - * @type {Boolean} - * @default true - */ - enabled : { - value: true - }, - - /** - * The action performed when an upload error occurs for a specific file being uploaded. - * The possible values are: - *
    - *
  • `UploaderQueue.CONTINUE`: the error is ignored and the upload process is continued.
  • - *
  • `UploaderQueue.STOP`: the upload process is stopped as soon as any other parallel file - * uploads are finished.
  • - *
  • `UploaderQueue.RESTART_ASAP`: the file is added back to the front of the queue.
  • - *
  • `UploaderQueue.RESTART_AFTER`: the file is added to the back of the queue.
  • - *
- * @attribute errorAction - * @type {String} - * @default UploaderQueue.CONTINUE - */ - errorAction: { - value: "continue", - validator: function (val) { - return ( - val === UploaderQueue.CONTINUE || - val === UploaderQueue.STOP || - val === UploaderQueue.RESTART_ASAP || - val === UploaderQueue.RESTART_AFTER - ); - } - }, - - /** - * An array indicating what fileFilters should be applied to the file - * selection dialog. Each element in the array should be a string - * indicating the Media (MIME) type for the files that should be supported - * for selection. The Media type strings should be properly formatted - * or this parameter will be ignored. Examples of valid strings include: - * "audio/*", "video/*", "application/pdf", etc. More information - * on valid Media type strings is available here: - * http://www.iana.org/assignments/media-types/index.html - * @attribute fileFilters - * @type {Array} - * @default [] - */ - fileFilters: { - value: [] - }, - - /** - * A filtering function that is applied to every file selected by the user. - * The function receives the `Y.File` object and must return a Boolean value. - * If a `false` value is returned, the file in question is not added to the - * list of files to be uploaded. - * Use this function to put limits on file sizes or check the file names for - * correct extension, but make sure that a server-side check is also performed, - * since any client-side restrictions are only advisory and can be circumvented. - * - * @attribute fileFilterFunction - * @type {Function} - * @default null - */ - fileFilterFunction: { - value: null - }, - - /** - * A String specifying what should be the POST field name for the file - * content in the upload request. - * - * @attribute fileFieldName - * @type {String} - * @default Filedata - */ - fileFieldName: { - value: "Filedata" - }, - - /** - * The array of files to be uploaded. All elements in the array - * must be instances of `Y.File` and be instantiated with an instance - * of native JavaScript File() class. - * - * @attribute fileList - * @type {Array} - * @default [] - */ - fileList: { - value: [], - getter: "_getFileList", - setter: "_setFileList" - }, - - /** - * A Boolean indicating whether multiple file selection is enabled. - * - * @attribute multipleFiles - * @type {Boolean} - * @default false - */ - multipleFiles: { - value: false - }, - - /** - * An object, keyed by `fileId`, containing sets of key-value pairs - * that should be passed as POST variables along with each corresponding - * file. This attribute is only used if no POST variables are specifed - * in the upload method call. - * - * @attribute postVarsPerFile - * @type {Object} - * @default {} - */ - postVarsPerFile: { - value: {} - }, - - /** - * The label for the "Select Files" widget. This is the value that replaces the - * `{selectButtonLabel}` token in the `SELECT_FILES_BUTTON` template. - * - * @attribute selectButtonLabel - * @type {String} - * @default "Select Files" - */ - selectButtonLabel: { - value: "Select Files" - }, - - /** - * The widget that serves as the "Select Files control for the file uploader - * - * - * @attribute selectFilesButton - * @type {Node | Widget} - * @default A standard HTML button with YUI CSS Button skin. - */ - selectFilesButton : { - valueFn: function () { - return Y.Node.create(substitute(Y.UploaderHTML5.SELECT_FILES_BUTTON, { - selectButtonLabel: this.get("selectButtonLabel"), - tabIndex: this.get("tabIndex") - })); - } - }, - - /** - * The number of files that can be uploaded - * simultaneously if the automatic queue management - * is used. This value can be in the range between 2 - * and 5. - * - * @attribute simLimit - * @type {Number} - * @default 2 - */ - simLimit: { - value: 2, - validator: function (val) { - return (val >= 1 && val <= 5); - } - }, - - /** - * The URL to which file upload requested are POSTed. Only used if a different url is not passed to the upload method call. - * - * @attribute uploadURL - * @type {String} - * @default "" - */ - uploadURL: { - value: "" - }, - - /** - * Additional HTTP headers that should be included - * in the upload request. - * - * - * @attribute uploadHeaders - * @type {Object} - * @default {} - */ - uploadHeaders: { - value: {} - }, - - /** - * A Boolean that specifies whether the file should be - * uploaded with the appropriate user credentials for the - * domain. - * - * @attribute withCredentials - * @type {Boolean} - * @default true - */ - withCredentials: { - value: true - }, - - /** - * The number of times to try re-uploading a file that failed to upload before - * cancelling its upload. - * - * @attribute retryCount - * @type {Number} - * @default 3 - */ - retryCount: { - value: 3 - } - } -}); - -Y.UploaderHTML5.Queue = UploaderQueue; - - - -}, '3.16.0', {"requires": ["widget", "node-event-simulate", "file-html5", "uploader-queue"]}); -/* -YUI 3.16.0 (build 76f0e08) -Copyright 2014 Yahoo! Inc. All rights reserved. -Licensed under the BSD License. -http://yuilibrary.com/license/ -*/ - -YUI.add('swfdetect', function (Y, NAME) { - -/** - * Utility for Flash version detection - * @module swfdetect - */ - -// Shortcuts and helper methods -var version = 0, - uA = Y.UA, - lG = Y.Lang, - sF = "ShockwaveFlash", - mF, eP, vS, ax6, ax; - -function makeInt(n) { - return parseInt(n, 10); -} - -function parseFlashVersion (flashVer) { - if (lG.isNumber(makeInt(flashVer[0]))) { - uA.flashMajor = flashVer[0]; - } - - if (lG.isNumber(makeInt(flashVer[1]))) { - uA.flashMinor = flashVer[1]; - } - - if (lG.isNumber(makeInt(flashVer[2]))) { - uA.flashRev = flashVer[2]; - } -} - -if (uA.gecko || uA.webkit || uA.opera) { - if ((mF = navigator.mimeTypes['application/x-shockwave-flash'])) { - if ((eP = mF.enabledPlugin)) { - vS = eP.description.replace(/\s[rd]/g, '.').replace(/[A-Za-z\s]+/g, '').split('.'); - parseFlashVersion(vS); - } - } -} -else if(uA.ie) { - try - { - ax6 = new ActiveXObject(sF + "." + sF + ".6"); - ax6.AllowScriptAccess = "always"; - } - catch (e) - { - if(ax6 !== null) - { - version = 6.0; - } - } - if (version === 0) { - try - { - ax = new ActiveXObject(sF + "." + sF); - vS = ax.GetVariable("$version").replace(/[A-Za-z\s]+/g, '').split(','); - parseFlashVersion(vS); - } catch (e2) {} - } -} - -/** Create a calendar view to represent a single or multiple - * month range of dates, rendered as a grid with date and - * weekday labels. - * - * @class SWFDetect - * @constructor - */ - - -Y.SWFDetect = { - - /** - * Returns the version of either the Flash Player plugin (in Mozilla/WebKit/Opera browsers), - * or the Flash Player ActiveX control (in IE), as a String of the form "MM.mm.rr", where - * MM is the major version, mm is the minor version, and rr is the revision. - * @method getFlashVersion - */ - - getFlashVersion : function () { - return (String(uA.flashMajor) + "." + String(uA.flashMinor) + "." + String(uA.flashRev)); - }, - - /** - * Checks whether the version of the Flash player installed on the user's machine is greater - * than or equal to the one specified. If it is, this method returns true; it is false otherwise. - * @method isFlashVersionAtLeast - * @return {Boolean} Whether the Flash player version is greater than or equal to the one specified. - * @param flashMajor {Number} The Major version of the Flash player to compare against. - * @param flashMinor {Number} The Minor version of the Flash player to compare against. - * @param flashRev {Number} The Revision version of the Flash player to compare against. - */ - isFlashVersionAtLeast : function (flashMajor, flashMinor, flashRev) { - var uaMajor = makeInt(uA.flashMajor), - uaMinor = makeInt(uA.flashMinor), - uaRev = makeInt(uA.flashRev); - - flashMajor = makeInt(flashMajor || 0); - flashMinor = makeInt(flashMinor || 0); - flashRev = makeInt(flashRev || 0); - - if (flashMajor === uaMajor) { - if (flashMinor === uaMinor) { - return flashRev <= uaRev; - } - return flashMinor < uaMinor; - } - return flashMajor < uaMajor; - } -}; - - -}, '3.16.0', {"requires": ["yui-base"]}); -/* -YUI 3.16.0 (build 76f0e08) -Copyright 2014 Yahoo! Inc. All rights reserved. -Licensed under the BSD License. -http://yuilibrary.com/license/ -*/ - -YUI.add('escape', function (Y, NAME) { - -/** -Provides utility methods for escaping strings. - -@module escape -@class Escape -@static -@since 3.3.0 -**/ - -var HTML_CHARS = { - '&': '&', - '<': '<', - '>': '>', - '"': '"', - "'": ''', - '/': '/', - '`': '`' - }, - -Escape = { - // -- Public Static Methods ------------------------------------------------ - - /** - Returns a copy of the specified string with special HTML characters - escaped. The following characters will be converted to their - corresponding character entities: - - & < > " ' / ` - - This implementation is based on the [OWASP HTML escaping - recommendations][1]. In addition to the characters in the OWASP - recommendations, we also escape the ` character, since IE - interprets it as an attribute delimiter. - - If _string_ is not already a string, it will be coerced to a string. - - [1]: http://www.owasp.org/index.php/XSS_(Cross_Site_Scripting)_Prevention_Cheat_Sheet - - @method html - @param {String} string String to escape. - @return {String} Escaped string. - @static - **/ - html: function (string) { - return (string + '').replace(/[&<>"'\/`]/g, Escape._htmlReplacer); - }, - - /** - Returns a copy of the specified string with special regular expression - characters escaped, allowing the string to be used safely inside a regex. - The following characters, and all whitespace characters, are escaped: - - - $ ^ * ( ) + [ ] { } | \ , . ? - - If _string_ is not already a string, it will be coerced to a string. - - @method regex - @param {String} string String to escape. - @return {String} Escaped string. - @static - **/ - regex: function (string) { - // There's no need to escape !, =, and : since they only have meaning - // when they follow a parenthesized ?, as in (?:...), and we already - // escape parens and question marks. - return (string + '').replace(/[\-$\^*()+\[\]{}|\\,.?\s]/g, '\\$&'); - }, - - // -- Protected Static Methods --------------------------------------------- - - /** - * Regex replacer for HTML escaping. - * - * @method _htmlReplacer - * @param {String} match Matched character (must exist in HTML_CHARS). - * @return {String} HTML entity. - * @static - * @protected - */ - _htmlReplacer: function (match) { - return HTML_CHARS[match]; - } -}; - -Escape.regexp = Escape.regex; - -Y.Escape = Escape; - - -}, '3.16.0', {"requires": ["yui-base"]}); -/* -YUI 3.16.0 (build 76f0e08) -Copyright 2014 Yahoo! Inc. All rights reserved. -Licensed under the BSD License. -http://yuilibrary.com/license/ -*/ - -YUI.add('node-pluginhost', function (Y, NAME) { - -/** - * @module node - * @submodule node-pluginhost - */ - -/** - * Registers plugins to be instantiated at the class level (plugins - * which should be plugged into every instance of Node by default). - * - * @method plug - * @static - * @for Node - * @param {Function | Array} plugin Either the plugin class, an array of plugin classes or an array of objects (with fn and cfg properties defined) - * @param {Object} config (Optional) If plugin is the plugin class, the configuration for the plugin - */ -Y.Node.plug = function() { - var args = Y.Array(arguments); - args.unshift(Y.Node); - Y.Plugin.Host.plug.apply(Y.Base, args); - return Y.Node; -}; - -/** - * Unregisters any class level plugins which have been registered by the Node - * - * @method unplug - * @static - * - * @param {Function | Array} plugin The plugin class, or an array of plugin classes - */ -Y.Node.unplug = function() { - var args = Y.Array(arguments); - args.unshift(Y.Node); - Y.Plugin.Host.unplug.apply(Y.Base, args); - return Y.Node; -}; - -Y.mix(Y.Node, Y.Plugin.Host, false, null, 1); - -// run PluginHost constructor on cached Node instances -Y.Object.each(Y.Node._instances, function (node) { - Y.Plugin.Host.apply(node); -}); - -// allow batching of plug/unplug via NodeList -// doesn't use NodeList.importMethod because we need real Nodes (not tmpNode) -/** - * Adds a plugin to each node in the NodeList. - * This will instantiate the plugin and attach it to the configured namespace on each node - * @method plug - * @for NodeList - * @param P {Function | Object |Array} Accepts the plugin class, or an - * object with a "fn" property specifying the plugin class and - * a "cfg" property specifying the configuration for the Plugin. - *

- * Additionally an Array can also be passed in, with the above function or - * object values, allowing the user to add multiple plugins in a single call. - *

- * @param config (Optional) If the first argument is the plugin class, the second argument - * can be the configuration for the plugin. - * @chainable - */ -Y.NodeList.prototype.plug = function() { - var args = arguments; - Y.NodeList.each(this, function(node) { - Y.Node.prototype.plug.apply(Y.one(node), args); - }); - return this; -}; - -/** - * Removes a plugin from all nodes in the NodeList. This will destroy the - * plugin instance and delete the namespace each node. - * @method unplug - * @for NodeList - * @param {String | Function} plugin The namespace of the plugin, or the plugin class with the static NS namespace property defined. If not provided, - * all registered plugins are unplugged. - * @chainable - */ -Y.NodeList.prototype.unplug = function() { - var args = arguments; - Y.NodeList.each(this, function(node) { - Y.Node.prototype.unplug.apply(Y.one(node), args); - }); - return this; -}; - - -}, '3.16.0', {"requires": ["node-base", "pluginhost"]}); -/* -YUI 3.16.0 (build 76f0e08) -Copyright 2014 Yahoo! Inc. All rights reserved. -Licensed under the BSD License. -http://yuilibrary.com/license/ -*/ - -YUI.add('uploader-flash', function (Y, NAME) { - -/** -* This module provides a UI for file selection and multiple file upload capability using -* Flash as a transport engine. -* The supported features include: automatic upload queue management, upload progress -* tracking, file filtering, server response retrieval and error reporting. -* -* @module uploader-flash -* @deprecated -*/ - -// Shorthands for external modules -var substitute = Y.Lang.sub, - UploaderQueue = Y.Uploader.Queue; - - -/** - * Embed a Flash applications in a standard manner and communicate with it - * via External Interface. - * @module swf - */ - - var Event = Y.Event, - SWFDetect = Y.SWFDetect, - Lang = Y.Lang, - uA = Y.UA, - Node = Y.Node, - Escape = Y.Escape, - - // private - FLASH_CID = "clsid:d27cdb6e-ae6d-11cf-96b8-444553540000", - FLASH_TYPE = "application/x-shockwave-flash", - FLASH_VER = "10.0.22", - EXPRESS_INSTALL_URL = "http://fpdownload.macromedia.com/pub/flashplayer/update/current/swf/autoUpdater.swf?" + Math.random(), - EVENT_HANDLER = "SWF.eventHandler", - possibleAttributes = {align:"", allowFullScreen:"", allowNetworking:"", allowScriptAccess:"", base:"", bgcolor:"", loop:"", menu:"", name:"", play: "", quality:"", salign:"", scale:"", tabindex:"", wmode:""}; - - /** - * The SWF utility is a tool for embedding Flash applications in HTML pages. - * @module swf - * @title SWF Utility - * @requires event-custom, node, swfdetect - */ - - /** - * Creates the SWF instance and keeps the configuration data - * - * @class SWF - * @uses Y.Event.Target - * @constructor - * @param {String|HTMLElement} id The id of the element, or the element itself that the SWF will be inserted into. - * The width and height of the SWF will be set to the width and height of this container element. - * @param {String} swfURL The URL of the SWF to be embedded into the page. - * @param {Object} p_oAttributes (optional) Configuration parameters for the Flash application and values for Flashvars - * to be passed to the SWF. The p_oAttributes object allows the following additional properties: - *
- *
version : String
- *
The minimum version of Flash required on the user's machine.
- *
fixedAttributes : Object
- *
An object literal containing one or more of the following String keys and their values: align, - * allowFullScreen, allowNetworking, allowScriptAccess, base, bgcolor, menu, name, quality, salign, scale, - * tabindex, wmode. event from the thumb
- *
- */ - -function SWF (p_oElement /*:String*/, swfURL /*:String*/, p_oAttributes /*:Object*/ ) { - - this._id = Y.guid("yuiswf"); - - - var _id = this._id; - var oElement = Node.one(p_oElement); - - var p_oAttributes = p_oAttributes || {}; - - var flashVersion = p_oAttributes.version || FLASH_VER; - - var flashVersionSplit = (flashVersion + '').split("."); - var isFlashVersionRight = SWFDetect.isFlashVersionAtLeast(parseInt(flashVersionSplit[0], 10), parseInt(flashVersionSplit[1], 10), parseInt(flashVersionSplit[2], 10)); - var canExpressInstall = (SWFDetect.isFlashVersionAtLeast(8,0,0)); - var shouldExpressInstall = canExpressInstall && !isFlashVersionRight && p_oAttributes.useExpressInstall; - var flashURL = (shouldExpressInstall)?EXPRESS_INSTALL_URL:swfURL; - var objstring = ''; - - if (uA.ie) { - objstring += ''; - } - - for (var attribute in p_oAttributes.fixedAttributes) { - if (possibleAttributes.hasOwnProperty(attribute)) { - objstring += ''; - } - } - - for (var flashvar in p_oAttributes.flashVars) { - var fvar = p_oAttributes.flashVars[flashvar]; - if (Lang.isString(fvar)) { - flashvarstring += "&" + Escape.html(flashvar) + "=" + Escape.html(encodeURIComponent(fvar)); - } - } - - if (flashvarstring) { - objstring += ''; - } - - objstring += ""; - //using innerHTML as setHTML/setContent causes some issues with ExternalInterface for IE versions of the player - oElement.set("innerHTML", objstring); - - this._swf = Node.one("#" + _id); - } else { - /** - * Fired when the Flash player version on the user's machine is - * below the required value. - * - * @event wrongflashversion - */ - var event = {}; - event.type = "wrongflashversion"; - this.publish("wrongflashversion", {fireOnce:true}); - this.fire("wrongflashversion", event); - } -} - -/** - * @private - * The static collection of all instances of the SWFs on the page. - * @property _instances - * @type Object - */ - -SWF._instances = SWF._instances || {}; - -/** - * @private - * Handles an event coming from within the SWF and delegate it - * to a specific instance of SWF. - * @method eventHandler - * @param swfid {String} the id of the SWF dispatching the event - * @param event {Object} the event being transmitted. - */ -SWF.eventHandler = function (swfid, event) { - SWF._instances[swfid]._eventHandler(event); -}; - -SWF.prototype = { - /** - * @private - * Propagates a specific event from Flash to JS. - * @method _eventHandler - * @param event {Object} The event to be propagated from Flash. - */ - _eventHandler: function(event) { - if (event.type === "swfReady") { - this.publish("swfReady", {fireOnce:true}); - this.fire("swfReady", event); - } else if(event.type === "log") { - } else { - this.fire(event.type, event); - } - }, - - /** - * Calls a specific function exposed by the SWF's - * ExternalInterface. - * @method callSWF - * @param func {String} the name of the function to call - * @param args {Array} the set of arguments to pass to the function. - */ - - callSWF: function (func, args) - { - if (!args) { - args= []; - } - if (this._swf._node[func]) { - return(this._swf._node[func].apply(this._swf._node, args)); - } else { - return null; - } - }, - - /** - * Public accessor to the unique name of the SWF instance. - * - * @method toString - * @return {String} Unique name of the SWF instance. - */ - toString: function() - { - return "SWF " + this._id; - } -}; - -Y.augment(SWF, Y.EventTarget); - -Y.SWF = SWF; - /** - * The FileFlash class provides a wrapper for a file pointer stored in Flash. The File wrapper - * also implements the mechanics for uploading a file and tracking its progress. - * @module file-flash - */ - /** - * The class provides a wrapper for a file pointer in Flash. - * @class FileFlash - * @extends Base - * @constructor - * @param {Object} config Configuration object. - */ - - var FileFlash = function(o) { - FileFlash.superclass.constructor.apply(this, arguments); - }; - - Y.extend(FileFlash, Y.Base, { - - /** - * Construction logic executed during FileFlash instantiation. - * - * @method initializer - * @protected - */ - initializer : function (cfg) { - if (!this.get("id")) { - this._set("id", Y.guid("file")); - } - }, - - /** - * Handler of events dispatched by the Flash player. - * - * @method _swfEventHandler - * @param {Event} event The event object received from the Flash player. - * @protected - */ - _swfEventHandler: function (event) { - if (event.id === this.get("id")) { - switch (event.type) { - /** - * Signals that this file's upload has started. - * - * @event uploadstart - * @param event {Event} The event object for the `uploadstart` with the - * following payload: - *
- *
uploader
- *
The Y.SWF instance of Flash uploader that's handling the upload.
- *
- */ - case "uploadstart": - this.fire("uploadstart", {uploader: this.get("uploader")}); - break; - case "uploadprogress": - - /** - * Signals that progress has been made on the upload of this file. - * - * @event uploadprogress - * @param event {Event} The event object for the `uploadprogress` with the - * following payload: - *
- *
originEvent
- *
The original event fired by the Flash uploader instance.
- *
bytesLoaded
- *
The number of bytes of the file that has been uploaded.
- *
bytesTotal
- *
The total number of bytes in the file (the file size)
- *
percentLoaded
- *
The fraction of the file that has been uploaded, out of 100.
- *
- */ - this.fire("uploadprogress", {originEvent: event, - bytesLoaded: event.bytesLoaded, - bytesTotal: event.bytesTotal, - percentLoaded: Math.min(100, Math.round(10000*event.bytesLoaded/event.bytesTotal)/100) - }); - this._set("bytesUploaded", event.bytesLoaded); - break; - case "uploadcomplete": - - /** - * Signals that this file's upload has completed, but data has not yet been received from the server. - * - * @event uploadfinished - * @param event {Event} The event object for the `uploadfinished` with the - * following payload: - *
- *
originEvent
- *
The original event fired by the Flash player instance.
- *
- */ - this.fire("uploadfinished", {originEvent: event}); - break; - case "uploadcompletedata": - /** - * Signals that this file's upload has completed and data has been received from the server. - * - * @event uploadcomplete - * @param event {Event} The event object for the `uploadcomplete` with the - * following payload: - *
- *
originEvent
- *
The original event fired by the Flash player instance.
- *
data
- *
The data returned by the server.
- *
- */ - this.fire("uploadcomplete", {originEvent: event, - data: event.data}); - break; - case "uploadcancel": - - /** - * Signals that this file's upload has been cancelled. - * - * @event uploadcancel - * @param event {Event} The event object for the `uploadcancel` with the - * following payload: - *
- *
originEvent
- *
The original event fired by the Flash player instance.
- *
- */ - this.fire("uploadcancel", {originEvent: event}); - break; - case "uploaderror": - - /** - * Signals that this file's upload has encountered an error. - * - * @event uploaderror - * @param event {Event} The event object for the `uploaderror` with the - * following payload: - *
- *
originEvent
- *
The original event fired by the Flash player instance.
- *
status
- *
The status code reported by the Flash Player. If it's an HTTP error, - * then this corresponds to the HTTP status code received by the uploader.
- *
statusText
- *
The text of the error event reported by the Flash Player.
- *
source
- *
Either "http" (if it's an HTTP error), or "io" (if it's a network transmission - * error.)
- *
- */ - this.fire("uploaderror", {originEvent: event, status: event.status, statusText: event.message, source: event.source}); - - } - } - }, - - /** - * Starts the upload of a specific file. - * - * @method startUpload - * @param url {String} The URL to upload the file to. - * @param parameters {Object} (optional) A set of key-value pairs to send as variables along with the file upload HTTP request. - * @param fileFieldName {String} (optional) The name of the POST variable that should contain the uploaded file ('Filedata' by default) - */ - startUpload: function(url, parameters, fileFieldName) { - - if (this.get("uploader")) { - - var myUploader = this.get("uploader"), - fileField = fileFieldName || "Filedata", - id = this.get("id"), - params = parameters || null; - - this._set("bytesUploaded", 0); - - myUploader.on("uploadstart", this._swfEventHandler, this); - myUploader.on("uploadprogress", this._swfEventHandler, this); - myUploader.on("uploadcomplete", this._swfEventHandler, this); - myUploader.on("uploadcompletedata", this._swfEventHandler, this); - myUploader.on("uploaderror", this._swfEventHandler, this); - - myUploader.callSWF("upload", [id, url, params, fileField]); - } - - }, - - /** - * Cancels the upload of a specific file, if currently in progress. - * - * @method cancelUpload - */ - cancelUpload: function () { - if (this.get("uploader")) { - this.get("uploader").callSWF("cancel", [this.get("id")]); - this.fire("uploadcancel"); - } - } - - }, { - - /** - * The identity of the class. - * - * @property NAME - * @type String - * @default 'file' - * @readOnly - * @protected - * @static - */ - NAME: 'file', - - /** - * The type of transport. - * - * @property TYPE - * @type String - * @default 'flash' - * @readOnly - * @protected - * @static - */ - TYPE: "flash", - - /** - * Static property used to define the default attribute configuration of - * the File. - * - * @property ATTRS - * @type {Object} - * @protected - * @static - */ - ATTRS: { - - /** - * A String containing the unique id of the file wrapped by the FileFlash instance. - * The id is supplied by the Flash player uploader. - * - * @attribute id - * @type {String} - * @initOnly - */ - id: { - writeOnce: "initOnly", - value: null - }, - - /** - * The size of the file wrapped by FileFlash. This value is supplied by the Flash player uploader. - * - * @attribute size - * @type {Number} - * @initOnly - */ - size: { - writeOnce: "initOnly", - value: 0 - }, - - /** - * The name of the file wrapped by FileFlash. This value is supplied by the Flash player uploader. - * - * @attribute name - * @type {String} - * @initOnly - */ - name: { - writeOnce: "initOnly", - value: null - }, - - /** - * The date that the file wrapped by FileFlash was created on. This value is supplied by the Flash player uploader. - * - * @attribute dateCreated - * @type {Date} - * @initOnly - */ - dateCreated: { - writeOnce: "initOnly", - value: null - }, - - /** - * The date that the file wrapped by FileFlash was last modified on. This value is supplied by the Flash player uploader. - * - * @attribute dateModified - * @type {Date} - * @initOnly - */ - dateModified: { - writeOnce: "initOnly", - value: null - }, - - /** - * The number of bytes of the file that has been uploaded to the server. This value is - * non-zero only while a file is being uploaded. - * - * @attribute bytesUploaded - * @type {Date} - * @readOnly - */ - bytesUploaded: { - readOnly: true, - value: 0 - }, - - /** - * The type of the file wrapped by FileFlash. This value is provided by the Flash player - * uploader. - * - * @attribute type - * @type {String} - * @initOnly - */ - type: { - writeOnce: "initOnly", - value: null - }, - - /** - * The instance of Y.SWF wrapping the Flash player uploader associated with this file. - * - * @attribute uploder - * @type {SWF} - * @initOnly - */ - uploader: { - writeOnce: "initOnly", - value: null - } - } - }); - - Y.FileFlash = FileFlash; -/** -* This module provides a UI for file selection and multiple file upload capability -* using Flash as a transport engine. -* @class UploaderFlash -* @extends Widget -* @param {Object} config Configuration object. -* @constructor -* @deprecated -*/ - -function UploaderFlash() { - UploaderFlash.superclass.constructor.apply ( this, arguments ); -} - - - -Y.UploaderFlash = Y.extend(UploaderFlash, Y.Widget, { - - /** - * Stored value of the current button state (based on - * mouse events dispatched by the Flash player) - * @property _buttonState - * @type {String} - * @protected - */ - _buttonState: "up", - - /** - * Stored value of the current button focus state (based - * on keyboard and mouse events). - * @property _buttonFocus - * @type {Boolean} - * @protected - */ - _buttonFocus: false, - - /** - * Stored value of the unique id for the container that holds the - * Flash uploader. - * - * @property _swfContainerId - * @type {String} - * @protected - */ - _swfContainerId: null, - - /** - * Stored reference to the instance of SWF used to host the - * Flash uploader. - * - * @property _swfReference - * @type {SWF} - * @protected - */ - _swfReference: null, - - /** - * Stored reference to the instance of Uploader.Queue used to manage - * the upload process. This is a read-only property that only exists - * during an active upload process. Only one queue can be active at - * a time; if an upload start is attempted while a queue is active, - * it will be ignored. - * - * @property queue - * @type {Uploader.Queue} - */ - queue: null, - - /** - * Stored event bindings for keyboard navigation to and from the uploader. - * - * @property _tabElementBindings - * @type {Object} - * @protected - */ - _tabElementBindings: null, - - - /** - * Construction logic executed during UploaderFlash instantiation. - * - * @method initializer - * @protected - */ - initializer : function () { - - // Assign protected variable values - this._swfContainerId = Y.guid("uploader"); - this._swfReference = null; - this.queue = null; - this._buttonState = "up"; - this._buttonFocus = null; - this._tabElementBindings = null; - this._fileList = []; - - // Publish available events - - /** - * Signals that files have been selected. - * - * @event fileselect - * @param event {Event} The event object for the `fileselect` with the - * following payload: - *
- *
fileList
- *
An `Array` of files selected by the user, encapsulated - * in Y.FileFlash objects.
- *
- */ - this.publish("fileselect"); - - /** - * Signals that an upload of multiple files has been started. - * - * @event uploadstart - * @param event {Event} The event object for the `uploadstart`. - */ - this.publish("uploadstart"); - - /** - * Signals that an upload of a specific file has started. - * - * @event fileuploadstart - * @param event {Event} The event object for the `fileuploadstart` with the - * following payload: - *
- *
file
- *
A reference to the Y.File that dispatched the event.
- *
originEvent
- *
The original event dispatched by Y.File.
- *
- */ - this.publish("fileuploadstart"); - - /** - * Reports on upload progress of a specific file. - * - * @event uploadprogress - * @param event {Event} The event object for the `uploadprogress` with the - * following payload: - *
- *
bytesLoaded
- *
The number of bytes of the file that has been uploaded
- *
bytesTotal
- *
The total number of bytes in the file
- *
percentLoaded
- *
The fraction of the file that has been uploaded, out of 100
- *
originEvent
- *
The original event dispatched by the SWF uploader
- *
- */ - this.publish("uploadprogress"); - - /** - * Reports on the total upload progress of the file list. - * - * @event totaluploadprogress - * @param event {Event} The event object for the `totaluploadprogress` with the - * following payload: - *
- *
bytesLoaded
- *
The number of bytes of the file list that has been uploaded
- *
bytesTotal
- *
The total number of bytes in the file list
- *
percentLoaded
- *
The fraction of the file list that has been uploaded, out of 100
- *
- */ - this.publish("totaluploadprogress"); - - /** - * Signals that a single file upload has been completed. - * - * @event uploadcomplete - * @param event {Event} The event object for the `uploadcomplete` with the - * following payload: - *
- *
file
- *
The pointer to the instance of `Y.File` whose upload has been completed.
- *
originEvent
- *
The original event fired by the SWF Uploader
- *
data
- *
Data returned by the server.
- *
- */ - this.publish("uploadcomplete"); - - /** - * Signals that the upload process of the entire file list has been completed. - * - * @event alluploadscomplete - * @param event {Event} The event object for the `alluploadscomplete`. - */ - this.publish("alluploadscomplete"); - - /** - * Signals that a error has occurred in a specific file's upload process. - * - * @event uploaderror - * @param event {Event} The event object for the `uploaderror` with the - * following payload: - *
- *
originEvent
- *
The original error event fired by the SWF Uploader.
- *
file
- *
The pointer at the instance of Y.FileFlash that returned the error.
- *
source
- *
The source of the upload error, either "io" or "http"
- *
message
- *
The message that accompanied the error. Corresponds to the text of - * the error in cases where source is "io", and to the HTTP status for - cases where source is "http".
- *
- */ - this.publish("uploaderror"); - - /** - * Signals that a mouse has begun hovering over the `Select Files` button. - * - * @event mouseenter - * @param event {Event} The event object for the `mouseenter` event. - */ - this.publish("mouseenter"); - - /** - * Signals that a mouse has stopped hovering over the `Select Files` button. - * - * @event mouseleave - * @param event {Event} The event object for the `mouseleave` event. - */ - this.publish("mouseleave"); - - /** - * Signals that a mouse button has been pressed over the `Select Files` button. - * - * @event mousedown - * @param event {Event} The event object for the `mousedown` event. - */ - this.publish("mousedown"); - - /** - * Signals that a mouse button has been released over the `Select Files` button. - * - * @event mouseup - * @param event {Event} The event object for the `mouseup` event. - */ - this.publish("mouseup"); - - /** - * Signals that a mouse has been clicked over the `Select Files` button. - * - * @event click - * @param event {Event} The event object for the `click` event. - */ - this.publish("click"); - }, - - /** - * Creates the DOM structure for the UploaderFlash. - * UploaderFlash's DOM structure consists of two layers: the base "Select Files" - * button that can be replaced by the developer's widget of choice; and a transparent - * Flash overlay positoned above the button that captures all input events. - * The `position` style attribute of the `boundingBox` of the `Uploader` widget - * is forced to be `relative`, in order to accommodate the Flash player overlay - * (which is `position`ed `absolute`ly). - * - * @method renderUI - * @protected - */ - renderUI : function () { - var boundingBox = this.get("boundingBox"), - contentBox = this.get('contentBox'), - selFilesButton = this.get("selectFilesButton"), - flashContainer = Y.Node.create(substitute(UploaderFlash.FLASH_CONTAINER, { - swfContainerId: this._swfContainerId - })), - params = { - version: "10.0.45", - fixedAttributes: { - wmode: "transparent", - allowScriptAccess:"always", - allowNetworking:"all", - scale: "noscale" - } - }; - - boundingBox.setStyle("position", "relative"); - selFilesButton.setStyles({width: "100%", height: "100%"}); - contentBox.append(selFilesButton); - contentBox.append(flashContainer); - - this._swfReference = new Y.SWF(flashContainer, this.get("swfURL"), params); - }, - - /** - * Binds handlers to the UploaderFlash UI events and propagates attribute - * values to the Flash player. - * The propagation of initial values is set to occur once the Flash player - * instance is ready (as indicated by the `swfReady` event.) - * - * @method bindUI - * @protected - */ - bindUI : function () { - - this._swfReference.on("swfReady", function () { - this._setMultipleFiles(); - this._setFileFilters(); - this._triggerEnabled(); - this._attachTabElements(); - this.after("multipleFilesChange", this._setMultipleFiles, this); - this.after("fileFiltersChange", this._setFileFilters, this); - this.after("enabledChange", this._triggerEnabled, this); - this.after("tabElementsChange", this._attachTabElements); - }, this); - - this._swfReference.on("fileselect", this._updateFileList, this); - - - - // this._swfReference.on("trace", function (ev) {console.log(ev.message);}); - - this._swfReference.on("mouseenter", function () { - this.fire("mouseenter"); - this._setButtonClass("hover", true); - if (this._buttonState === "down") { - this._setButtonClass("active", true); - } - }, this); - - this._swfReference.on("mouseleave", function () { - this.fire("mouseleave"); - this._setButtonClass("hover", false); - this._setButtonClass("active", false); - }, this); - - this._swfReference.on("mousedown", function () { - this.fire("mousedown"); - this._buttonState = "down"; - this._setButtonClass("active", true); - }, this); - - this._swfReference.on("mouseup", function () { - this.fire("mouseup"); - this._buttonState = "up"; - this._setButtonClass("active", false); - }, this); - - this._swfReference.on("click", function () { - this.fire("click"); - this._buttonFocus = true; - this._setButtonClass("focus", true); - Y.one("body").focus(); - this._swfReference._swf.focus(); - }, this); - }, - - /** - * Attaches keyboard bindings to enabling tabbing to and from the instance of the Flash - * player in the Uploader widget. If the previous and next elements are specified, the - * keyboard bindings enable the user to tab from the `tabElements["from"]` node to the - * Flash-powered "Select Files" button, and to the `tabElements["to"]` node. - * - * @method _attachTabElements - * @protected - * @param ev {Event} Optional event payload if called as a `tabElementsChange` handler. - */ - _attachTabElements : function () { - if (this.get("tabElements") !== null && this.get("tabElements").from !== null && this.get("tabElements").to !== null) { - - if (this._tabElementBindings !== null) { - this._tabElementBindings.from.detach(); - this._tabElementBindings.to.detach(); - this._tabElementBindings.tabback.detach(); - this._tabElementBindings.tabforward.detach(); - this._tabElementBindings.focus.detach(); - this._tabElementBindings.blur.detach(); - } - else { - this._tabElementBindings = {}; - } - - var fromElement = Y.one(this.get("tabElements").from), - toElement = Y.one(this.get("tabElements").to); - - - this._tabElementBindings.from = fromElement.on("keydown", function (ev) { - if (ev.keyCode === 9 && !ev.shiftKey) { - ev.preventDefault(); - this._swfReference._swf.setAttribute("tabindex", 0); - this._swfReference._swf.setAttribute("role", "button"); - this._swfReference._swf.setAttribute("aria-label", this.get("selectButtonLabel")); - this._swfReference._swf.focus(); - } - }, this); - - this._tabElementBindings.to = toElement.on("keydown", function (ev) { - if (ev.keyCode === 9 && ev.shiftKey) { - ev.preventDefault(); - this._swfReference._swf.setAttribute("tabindex", 0); - this._swfReference._swf.setAttribute("role", "button"); - this._swfReference._swf.setAttribute("aria-label", this.get("selectButtonLabel")); - this._swfReference._swf.focus(); - } - }, this); - - this._tabElementBindings.tabback = this._swfReference.on("tabback", function () { - this._swfReference._swf.blur(); - setTimeout(function () { - fromElement.focus(); - }, 30); - }, this); - - this._tabElementBindings.tabforward = this._swfReference.on("tabforward", function () { - this._swfReference._swf.blur(); - setTimeout(function () { - toElement.focus(); - }, 30); - }, this); - - this._tabElementBindings.focus = this._swfReference._swf.on("focus", function () { - this._buttonFocus = true; - this._setButtonClass("focus", true); - }, this); - - this._tabElementBindings.blur = this._swfReference._swf.on("blur", function () { - this._buttonFocus = false; - this._setButtonClass("focus", false); - }, this); - } - else if (this._tabElementBindings !== null) { - this._tabElementBindings.from.detach(); - this._tabElementBindings.to.detach(); - this._tabElementBindings.tabback.detach(); - this._tabElementBindings.tabforward.detach(); - this._tabElementBindings.focus.detach(); - this._tabElementBindings.blur.detach(); - } - }, - - - /** - * Adds or removes a specified state CSS class to the underlying uploader button. - * - * @method _setButtonClass - * @protected - * @param state {String} The name of the state enumerated in `buttonClassNames` attribute - * from which to derive the needed class name. - * @param add {Boolean} A Boolean indicating whether to add or remove the class. - */ - _setButtonClass : function (state, add) { - if (add) { - this.get("selectFilesButton").addClass(this.get("buttonClassNames")[state]); - } - else { - this.get("selectFilesButton").removeClass(this.get("buttonClassNames")[state]); - } - }, - - - /** - * Syncs the state of the `fileFilters` attribute between the instance of UploaderFlash - * and the Flash player. - * - * @method _setFileFilters - * @private - */ - _setFileFilters : function () { - if (this._swfReference && this.get("fileFilters").length > 0) { - this._swfReference.callSWF("setFileFilters", [this.get("fileFilters")]); - } - }, - - - - /** - * Syncs the state of the `multipleFiles` attribute between this class - * and the Flash uploader. - * - * @method _setMultipleFiles - * @private - */ - _setMultipleFiles : function () { - if (this._swfReference) { - this._swfReference.callSWF("setAllowMultipleFiles", [this.get("multipleFiles")]); - } - }, - - /** - * Syncs the state of the `enabled` attribute between this class - * and the Flash uploader. - * - * @method _triggerEnabled - * @private - */ - _triggerEnabled : function () { - if (this.get("enabled")) { - this._swfReference.callSWF("enable"); - this._swfReference._swf.setAttribute("aria-disabled", "false"); - this._setButtonClass("disabled", false); - } - else { - this._swfReference.callSWF("disable"); - this._swfReference._swf.setAttribute("aria-disabled", "true"); - this._setButtonClass("disabled", true); - } - }, - - /** - * Getter for the `fileList` attribute - * - * @method _getFileList - * @private - */ - _getFileList : function () { - return this._fileList.concat(); - }, - - /** - * Setter for the `fileList` attribute - * - * @method _setFileList - * @private - */ - _setFileList : function (val) { - this._fileList = val.concat(); - return this._fileList.concat(); - }, - - /** - * Adjusts the content of the `fileList` based on the results of file selection - * and the `appendNewFiles` attribute. If the `appendNewFiles` attribute is true, - * then selected files are appended to the existing list; otherwise, the list is - * cleared and populated with the newly selected files. - * - * @method _updateFileList - * @param ev {Event} The file selection event received from the uploader. - * @private - */ - _updateFileList : function (ev) { - - Y.one("body").focus(); - this._swfReference._swf.focus(); - - - var newfiles = ev.fileList, - fileConfObjects = [], - parsedFiles = [], - swfRef = this._swfReference, - filterFunc = this.get("fileFilterFunction"), - oldfiles; - - Y.each(newfiles, function (value) { - var newFileConf = {}; - newFileConf.id = value.fileId; - newFileConf.name = value.fileReference.name; - newFileConf.size = value.fileReference.size; - newFileConf.type = value.fileReference.type; - newFileConf.dateCreated = value.fileReference.creationDate; - newFileConf.dateModified = value.fileReference.modificationDate; - newFileConf.uploader = swfRef; - - fileConfObjects.push(newFileConf); - }); - - if (filterFunc) { - Y.each(fileConfObjects, function (value) { - var newfile = new Y.FileFlash(value); - if (filterFunc(newfile)) { - parsedFiles.push(newfile); - } - }); - } - else { - Y.each(fileConfObjects, function (value) { - parsedFiles.push(new Y.FileFlash(value)); - }); - } - - if (parsedFiles.length > 0) { - oldfiles = this.get("fileList"); - - this.set("fileList", - this.get("appendNewFiles") ? oldfiles.concat(parsedFiles) : parsedFiles ); - - this.fire("fileselect", { fileList: parsedFiles }); - } - - }, - - - - /** - * Handles and retransmits events fired by `Y.FileFlash` and `Y.Uploader.Queue`. - * - * @method _uploadEventHandler - * @param event The event dispatched during the upload process. - * @private - */ - _uploadEventHandler : function (event) { - - switch (event.type) { - case "file:uploadstart": - this.fire("fileuploadstart", event); - break; - case "file:uploadprogress": - this.fire("uploadprogress", event); - break; - case "uploaderqueue:totaluploadprogress": - this.fire("totaluploadprogress", event); - break; - case "file:uploadcomplete": - this.fire("uploadcomplete", event); - break; - case "uploaderqueue:alluploadscomplete": - this.queue = null; - this.fire("alluploadscomplete", event); - break; - case "file:uploaderror": //overflow intentional - case "uploaderqueue:uploaderror": - this.fire("uploaderror", event); - break; - case "file:uploadcancel": // overflow intentional - case "uploaderqueue:uploadcancel": - this.fire("uploadcancel", event); - break; - } - - }, - - - - /** - * Starts the upload of a specific file. - * - * @method upload - * @param file {FileFlash} Reference to the instance of the file to be uploaded. - * @param url {String} The URL to upload the file to. - * @param [postVars] {Object} A set of key-value pairs to send as variables along with the file upload HTTP request. - * If not specified, the values from the attribute `postVarsPerFile` are used instead. - */ - upload : function (file, url, postvars) { - - var uploadURL = url || this.get("uploadURL"), - postVars = postvars || this.get("postVarsPerFile"), - fileId = file.get("id"); - - postVars = postVars.hasOwnProperty(fileId) ? postVars[fileId] : postVars; - - if (file instanceof Y.FileFlash) { - - file.on("uploadstart", this._uploadEventHandler, this); - file.on("uploadprogress", this._uploadEventHandler, this); - file.on("uploadcomplete", this._uploadEventHandler, this); - file.on("uploaderror", this._uploadEventHandler, this); - file.on("uploadcancel", this._uploadEventHandler, this); - - file.startUpload(uploadURL, postVars, this.get("fileFieldName")); - } - }, - - /** - * Starts the upload of all files on the file list, using an automated queue. - * - * @method uploadAll - * @param url {String} The URL to upload the files to. - * @param [postVars] {Object} A set of key-value pairs to send as variables along with the file upload HTTP request. - * If not specified, the values from the attribute `postVarsPerFile` are used instead. - */ - uploadAll : function (url, postvars) { - this.uploadThese(this.get("fileList"), url, postvars); - }, - - /** - * Starts the upload of the files specified in the first argument, using an automated queue. - * - * @method uploadThese - * @param files {Array} The list of files to upload. - * @param url {String} The URL to upload the files to. - * @param [postVars] {Object} A set of key-value pairs to send as variables along with the file upload HTTP request. - * If not specified, the values from the attribute `postVarsPerFile` are used instead. - */ - uploadThese : function (files, url, postvars) { - if (!this.queue) { - var uploadURL = url || this.get("uploadURL"), - postVars = postvars || this.get("postVarsPerFile"); - - this.queue = new UploaderQueue({ - simUploads: this.get("simLimit"), - errorAction: this.get("errorAction"), - fileFieldName: this.get("fileFieldName"), - fileList: files, - uploadURL: uploadURL, - perFileParameters: postVars, - retryCount: this.get("retryCount") - }); - - this.queue.on("uploadstart", this._uploadEventHandler, this); - this.queue.on("uploadprogress", this._uploadEventHandler, this); - this.queue.on("totaluploadprogress", this._uploadEventHandler, this); - this.queue.on("uploadcomplete", this._uploadEventHandler, this); - this.queue.on("alluploadscomplete", this._uploadEventHandler, this); - this.queue.on("alluploadscancelled", function () {this.queue = null;}, this); - this.queue.on("uploaderror", this._uploadEventHandler, this); - this.queue.startUpload(); - - this.fire("uploadstart"); - } - } -}, - -{ - /** - * The template for the Flash player container. Since the Flash player container needs - * to completely overlay the &lquot;Select Files&rqot; control, it's positioned absolutely, - * with width and height set to 100% of the parent. - * - * @property FLASH_CONTAINER - * @type {String} - * @static - * @default '
' - */ - FLASH_CONTAINER: '
', - - /** - * The template for the "Select Files" button. - * - * @property SELECT_FILES_BUTTON - * @type {String} - * @static - * @default "" - */ - SELECT_FILES_BUTTON: "", - - /** - * The static property reflecting the type of uploader that `Y.Uploader` - * aliases. The UploaderFlash value is `"flash"`. - * - * @property TYPE - * @type {String} - * @static - */ - TYPE: "flash", - - /** - * The identity of the widget. - * - * @property NAME - * @type String - * @default 'uploader' - * @readOnly - * @protected - * @static - */ - NAME: "uploader", - - /** - * Static property used to define the default attribute configuration of - * the Widget. - * - * @property ATTRS - * @type {Object} - * @protected - * @static - */ - ATTRS: { - - /** - * A Boolean indicating whether newly selected files should be appended - * to the existing file list, or whether they should replace it. - * - * @attribute appendNewFiles - * @type {Boolean} - * @default true - */ - appendNewFiles : { - value: true - }, - - /** - * The names of CSS classes that correspond to different button states - * of the "Select Files" control. These classes are assigned to the - * "Select Files" control based on the mouse states reported by the - * Flash player. The keys for the class names are: - *
    - *
  • `hover`: the class corresponding to mouse hovering over - * the "Select Files" button.
  • - *
  • `active`: the class corresponding to mouse down state of - * the "Select Files" button.
  • - *
  • `disabled`: the class corresponding to the disabled state - * of the "Select Files" button.
  • - *
  • `focus`: the class corresponding to the focused state of - * the "Select Files" button.
  • - *
- * @attribute buttonClassNames - * @type {Object} - * @default { hover: "yui3-button-hover", - * active: "yui3-button-active", - * disabled: "yui3-button-disabled", - * focus: "yui3-button-selected" - * } - */ - buttonClassNames: { - value: { - "hover": "yui3-button-hover", - "active": "yui3-button-active", - "disabled": "yui3-button-disabled", - "focus": "yui3-button-selected" - } - }, - - /** - * A Boolean indicating whether the uploader is enabled or disabled for user input. - * - * @attribute enabled - * @type {Boolean} - * @default true - */ - enabled : { - value: true - }, - - /** - * The action performed when an upload error occurs for a specific file being uploaded. - * The possible values are: - *
    - *
  • `UploaderQueue.CONTINUE`: the error is ignored and the upload process is continued.
  • - *
  • `UploaderQueue.STOP`: the upload process is stopped as soon as any other parallel file - * uploads are finished.
  • - *
  • `UploaderQueue.RESTART_ASAP`: the file is added back to the front of the queue.
  • - *
  • `UploaderQueue.RESTART_AFTER`: the file is added to the back of the queue.
  • - *
- * @attribute errorAction - * @type {String} - * @default UploaderQueue.CONTINUE - */ - errorAction: { - value: "continue", - validator: function (val) { - return ( - val === UploaderQueue.CONTINUE || - val === UploaderQueue.STOP || - val === UploaderQueue.RESTART_ASAP || - val === UploaderQueue.RESTART_AFTER - ); - } - }, - - /** - * An array indicating what fileFilters should be applied to the file - * selection dialog. Each element in the array should be an object with - * the following key-value pairs: - * { - * description : String - extensions: String of the form &lquot;*.ext1;*.ext2;*.ext3;...&rquot; - * } - * @attribute fileFilters - * @type {Array} - * @default [] - */ - fileFilters: { - value: [] - }, - - /** - * A filtering function that is applied to every file selected by the user. - * The function receives the `Y.File` object and must return a Boolean value. - * If a `false` value is returned, the file in question is not added to the - * list of files to be uploaded. - * Use this function to put limits on file sizes or check the file names for - * correct extension, but make sure that a server-side check is also performed, - * since any client-side restrictions are only advisory and can be circumvented. - * - * @attribute fileFilterFunction - * @type {Function} - * @default null - */ - fileFilterFunction: { - value: null - }, - - /** - * A String specifying what should be the POST field name for the file - * content in the upload request. - * - * @attribute fileFieldName - * @type {String} - * @default Filedata - */ - fileFieldName: { - value: "Filedata" - }, - - /** - * The array of files to be uploaded. All elements in the array - * must be instances of `Y.FileFlash` and be instantiated with a `fileId` - * retrieved from an instance of the uploader. - * - * @attribute fileList - * @type {Array} - * @default [] - */ - fileList: { - value: [], - getter: "_getFileList", - setter: "_setFileList" - }, - - /** - * A Boolean indicating whether multiple file selection is enabled. - * - * @attribute multipleFiles - * @type {Boolean} - * @default false - */ - multipleFiles: { - value: false - }, - - /** - * An object, keyed by `fileId`, containing sets of key-value pairs - * that should be passed as POST variables along with each corresponding - * file. This attribute is only used if no POST variables are specifed - * in the upload method call. - * - * @attribute postVarsPerFile - * @type {Object} - * @default {} - */ - postVarsPerFile: { - value: {} - }, - - /** - * The label for the "Select Files" widget. This is the value that replaces the - * `{selectButtonLabel}` token in the `SELECT_FILES_BUTTON` template. - * - * @attribute selectButtonLabel - * @type {String} - * @default "Select Files" - */ - selectButtonLabel: { - value: "Select Files" - }, - - /** - * The widget that serves as the "Select Files" control for the file uploader - * - * - * @attribute selectFilesButton - * @type {Node | Widget} - * @default A standard HTML button with YUI CSS Button skin. - */ - selectFilesButton : { - valueFn: function () { - return Y.Node.create(substitute(Y.UploaderFlash.SELECT_FILES_BUTTON, {selectButtonLabel: this.get("selectButtonLabel")})); - } - }, - - /** - * The number of files that can be uploaded - * simultaneously if the automatic queue management - * is used. This value can be in the range between 2 - * and 5. - * - * @attribute simLimit - * @type {Number} - * @default 2 - */ - simLimit: { - value: 2, - validator: function (val) { - return (val >= 2 && val <= 5); - } - }, - - /** - * The URL to the SWF file of the flash uploader. A copy local to - * the server that hosts the page on which the uploader appears is - * recommended. - * - * @attribute swfURL - * @type {String} - * @default "flashuploader.swf" with a - * random GET parameter for IE (to prevent buggy behavior when the SWF - * is cached). - */ - swfURL: { - valueFn: function () { - var prefix = "flashuploader.swf"; - - if (Y.UA.ie > 0) { - return (prefix + "?t=" + Y.guid("uploader")); - } - - return prefix; - } - }, - - /** - * The id's or `Node` references of the DOM elements that precede - * and follow the `Select Files` button in the tab order. Specifying - * these allows keyboard navigation to and from the Flash player - * layer of the uploader. - * The two keys corresponding to the DOM elements are: -
    - *
  • `from`: the id or the `Node` reference corresponding to the - * DOM element that precedes the `Select Files` button in the tab order.
  • - *
  • `to`: the id or the `Node` reference corresponding to the - * DOM element that follows the `Select Files` button in the tab order.
  • - *
- * @attribute tabElements - * @type {Object} - * @default null - */ - tabElements: { - value: null - }, - - /** - * The URL to which file upload requested are POSTed. Only used if a different url is not passed to the upload method call. - * - * @attribute uploadURL - * @type {String} - * @default "" - */ - uploadURL: { - value: "" - }, - - /** - * The number of times to try re-uploading a file that failed to upload before - * cancelling its upload. - * - * @attribute retryCount - * @type {Number} - * @default 3 - */ - retryCount: { - value: 3 - } - } -}); - -Y.UploaderFlash.Queue = UploaderQueue; - - -}, '3.16.0', { - "requires": [ - "swfdetect", - "escape", - "widget", - "base", - "cssbutton", - "node", - "event-custom", - "uploader-queue" - ] -}); -/* -YUI 3.16.0 (build 76f0e08) -Copyright 2014 Yahoo! Inc. All rights reserved. -Licensed under the BSD License. -http://yuilibrary.com/license/ -*/ - -YUI.add('uploader', function (Y, NAME) { - -/** -* Provides UI for selecting multiple files and functionality for -* uploading multiple files to the server with support for either -* html5 or Flash transport mechanisms, automatic queue management, -* upload progress monitoring, and error events. -* @module uploader -* @main uploader -* @since 3.5.0 -*/ - -/** -* `Y.Uploader` serves as an alias for either `Y.UploaderFlash` -* or `Y.UploaderHTML5`, depending on the feature set available -* in a specific browser. If neither HTML5 nor Flash transport layers are available, `Y.Uploader.TYPE` -* static property is set to `"none"`. -* -* @class Uploader -*/ - -/** -* The static property reflecting the type of uploader that `Y.Uploader` -* aliases. The possible values are: -*
    -*
  • `"html5"`: Y.Uploader is an alias for Y.UploaderHTML5
  • -*
  • `"flash"`: Y.Uploader is an alias for Y.UploaderFlash
  • -*
  • `"none"`: Neither Flash not HTML5 are available, and Y.Uploader does -* not reference an actual implementation.
  • -*
-* -* @property TYPE -* @type {String} -* @static -*/ - -var Win = Y.config.win; - -if (Win && Win.File && Win.FormData && Win.XMLHttpRequest) { - Y.Uploader = Y.UploaderHTML5; -} - -else if (Y.SWFDetect.isFlashVersionAtLeast(10,0,45)) { - Y.Uploader = Y.UploaderFlash; -} - -else { - Y.namespace("Uploader"); - Y.Uploader.TYPE = "none"; +'\n \n
\n
\n
\n
\n \n
\n
\n
\n'; } +return __p; +}; }); -}, '3.16.0', {"requires": ["uploader-html5", "uploader-flash"]}); - -define("yui-uploader", ["yui-base","yui-loader","css!yui-combo"], (function (global) { - return function () { - var ret, fn; - return ret || global.YUI; - }; -}(this))); - -var HQMediaUploaderTypes = { - 'bulk': HQMediaBulkUploadController, - 'file': HQMediaFileUploadController, -}; - -function BaseHQMediaUploadController (uploader_name, marker, options) { - 'use strict'; - var self = this; - - // These are necessary for having multiple upload controllers on the same page. - self.container = "#" + uploader_name; - self.marker = marker + "_"; - - ///// YUI Uploader Specific Params - self.fileFilters = options.fileFilters; - self.isMultiFileUpload = options.isMultiFileUpload; - - // Essential Selectors - self.selectFilesButtonContainer = self.container + " .hqm-select-files-container"; - self.selectFilesButton = self.container + " .hqm-select"; - - self.uploadButtonSelector = self.container + " .hqm-upload"; - self.confirmUploadSelector = self.container + " .hqm-upload-confirm"; - - self.processingFilesListSelector = self.container + " .hqm-upload-processing"; - self.uploadedFilesListSelector = self.container + " .hqm-uploaded-files"; - self.queueSelector = self.container + " .hqm-queue"; - self.uploadFormSelector = self.container + " .hqm-upload-form"; - - self.notSupportedNotice = self.container + " .hqm-not-supported"; - - // behavior controls - self.allowCloseDuringUpload = options.allowCloseDuringUpload || false; - - // Templates - self.queueTemplate = options.queueTemplate; - self.errorsTemplate = options.errorsTemplate; - - // Stuff for processing the upload - self.uploadParams = options.uploadParams || {}; - self.licensingParams = options.licensingParams || []; - self.uploadURL = options.uploadURL; - self.processingURL = options.processingURL; - - // Polling - self.pollInterval = 2000; // 2 sec - self.maxPollInterval = 20000; // 20 seconds - self.currentPollAttempts = 0; - self.maxPollAttempts = 20; - self.allowClose = true; - - $(self.container).on('hide.bs.modal', function (event) { - if (!self.allowClose) { - event.preventDefault(); - } - }); - - self._getActiveUploadSelectors = function (file) { - /* - All the different active parts of the queued item template that the upload controller cares about. - file is an instance of Y.file - */ - var selector = '#' + self.marker + file.get('id'); - return { - selector: selector, - progressBarContainer: selector + ' .progress', - progressBar: selector + ' .progress .progress-bar', - cancel: selector + ' .hqm-cancel', - remove: selector + ' .hqm-remove', - beginNotice: selector + ' .hqm-begin', - processingQueuedNotice: selector + ' .hqm-processing-queued', - processingNotice: selector + ' .hqm-processing', - completeNotice: selector + ' .hqm-upload-completed', - errorNotice: selector + ' .hqm-error', - status: selector + ' .hqm-status', - details: selector + ' .hqm-details', - }; - }; - - // templates - self._processQueueTemplate = function (file) { - /* - This renders the template for the queued item display. - */ - var MEGABYTE = 1048576; - return _.template(self.queueTemplate)({ - unique_id: self.marker + file.get('id'), - file_size: (file.get('size')/MEGABYTE).toFixed(3), - file_name: file.get('name'), - }); - }; - - - - self._processErrorsTemplate = function (errors) { - return _.template(self.errorsTemplate)({ - errors: errors, - }); - }; - - // actions - self._cancelFileUpload = function (file) { - /* - What happens when you cancel a file from uploading. - */ - return function (event) { - file.cancelUpload(); - self.uploader.queue = null; // https://github.com/yui/yui3/issues/1179#issuecomment-24175982 - var activeSelector = self._getActiveUploadSelectors(file); - $(activeSelector.progressBar).attr('style', 'width: 0%;'); - $(activeSelector.cancel).addClass('hide'); - $(activeSelector.remove).removeClass('hide'); - event.preventDefault(); - self.allowClose = true; - }; - }; - - self._removeFileFromQueue = function (file) { - /* - What happens when you remove a file from the queue - */ - return function (event) { - self._removeFileFromUploader(file); - self._removeFileFromUI(file); - event.preventDefault(); - }; - }; - - - // UI related - self._startUploadUI = function () { - // optional: set the state of the uploader UI here when the upload starts - }; - - self._removeFileFromUI = function (file) { - var activeSelectors = self._getActiveUploadSelectors(file); - $(activeSelectors.selector).remove(); - self._toggleUploadButton(); - }; - - self._toggleUploadButton = function () { - var $uploadButton = $(self.uploadButtonSelector); - (self.filesInQueueUI.length > 0) ? $uploadButton.addClass('btn-success').removeClass('disabled') : $uploadButton.addClass('disabled').removeClass('btn-success'); - }; - - self._activateQueueUI = function () { - for (var i=0; i < self.filesInQueueUI.length; i++) { - var queuedFile = self.filesInQueueUI[i]; - var currentSelector = self._getActiveUploadSelectors(queuedFile); - $(currentSelector.beginNotice).addClass('hide'); - $(currentSelector.remove).addClass('hide'); - $(currentSelector.cancel).removeClass('hide'); - } - }; - - self._resetUploadForm = function () { - var $uploadForm = $(self.uploadFormSelector); - $uploadForm.find('.hqm-share-media').prop('checked', false); - $uploadForm.find('.hqm-sharing').addClass('hide'); - $uploadForm.find('[name="license"]').val('cc'); - $uploadForm.find('[name="author"]').val(''); - $uploadForm.find('[name="attribution-notes"]').val(''); - }; - - self.getLicensingParams = function () { - var $form = $(self.uploadFormSelector), - params = {}; - for (var i = 0; i < self.licensingParams.length; i++) { - var param_name = self.licensingParams[i]; - var param_val = $form.find('[name="' + param_name + '"]').val(); - if (param_val.length > 0) params[param_name] = param_val; - } - return params; - }; - - // Uploader flow - self.init = function () { - /* - Initialize the YUI uploader. - Use HTML5 version; flash version wasn't properly triggering fileselect events, - which are needed for app manager's bulk multimedia uploader. - */ - YUI().use('uploader', function (Y) { - var buttonRegion = Y.one(self.selectFilesButton).get('region'); - if (Y.Uploader.TYPE == "none") { - $(self.notSupportedNotice).removeClass('hide'); - $(self.selectFilesButtonContainer).parent().addClass('hide'); - return; - } else { - $(self.notSupportedNotice).remove(); - } - - self.uploader = new Y.Uploader({ - width: buttonRegion.width || '100px', - height: buttonRegion.height || '35px', - selectFilesButton: Y.one(self.selectFilesButton), - multipleFiles: self.isMultiFileUpload, - }); - - self.uploader.on("fileselect", self._fileSelect); - self.uploader.on("uploadprogress", self._uploadProgress); - self.uploader.on("uploadcomplete", self.uploadComplete); - self.uploader.on("uploaderror", self._uploadError); - - self.uploader.render(self.selectFilesButtonContainer); - }); - - $(function () { - self.resetUploader(); - $(self.confirmUploadSelector).click(self.startUpload); - $(self.uploadFormSelector).find('.hqm-share-media').change(function () { - var $sharingOptions = $(self.uploadFormSelector).find('.hqm-sharing'); - ($(this).prop('checked')) ? $sharingOptions.removeClass('hide') : $sharingOptions.addClass('hide'); - }); - }); - }; - - self.resetUploader = function () { - /* - Start over. - */ - self.filesInQueueUI = []; - self.processingIdToFile = {}; - self.allowClose = true; - self._toggleUploadButton(); - self._resetUploadForm(); - if (!self.isMultiFileUpload) { - $(self.queueSelector).empty(); - } - }; - - self._clearUploaderData = function () { - self.uploader.set('fileList', []); - }; - - self._removeFileFromUploader = function (file) { - var fileList = self.uploader.get('fileList'); - self.uploader.set('fileList', _.without(fileList, file)); - self.filesInQueueUI = _.without(self.filesInQueueUI, file); - }; - - self._fileSelect = function (event) { - /* - After files have been selected by the select files function, do this. - */ - if (!self.isMultiFileUpload) { - self.resetUploader(); - self.uploader.set('fileList', event.fileList); - } - for (var f = 0; f < event.fileList.length; f++) { - var queuedFile = event.fileList[f]; - if (self.filesInQueueUI.indexOf(queuedFile) < 0) { - self.filesInQueueUI.push(queuedFile); - $(self.queueSelector).append(self._processQueueTemplate(queuedFile)); - var activeSelector = self._getActiveUploadSelectors(queuedFile); - $(activeSelector.cancel).click(self._cancelFileUpload(queuedFile)); - if ($(activeSelector.remove)) { - $(activeSelector.remove).click(self._removeFileFromQueue(queuedFile)); - } - } - } - self._toggleUploadButton(); - }; - - self.startUpload = function (event) { - /* - Begin Upload was clicked. - */ - - // if this has been configured to disallow closing, then disable it - if (!self.allowCloseDuringUpload) { - self.allowClose = false; - } - if (!self.isMultiFileUpload) { - var newExtension = '.' + self.filesInQueueUI[0].get('name').split('.').pop().toLowerCase(); - self.uploadParams.path = self.uploadParams.path.replace(/(\.[^/.]+)?$/, newExtension); - } - $(self.uploadButtonSelector).addClass('disabled').removeClass('btn-success'); - self._startUploadUI(); - var postParams = _.clone(self.uploadParams); - for (var key in self.uploadParams) { - if (self.uploadParams.hasOwnProperty(key) - && $(self.uploadFormSelector).find('[name="'+key+'"]').prop('checked')) { - postParams[key] = true; - } - } - // With YUI 3.9 you can trigger downloads on a per file basis, but for now just keep the original behavior - // of uploading the entire queue. - self.uploader.uploadAll(self.uploadURL, postParams); - self._activateQueueUI(); - event.preventDefault(); - }; - - self._uploadProgress = function (event) { - var curUpload = self._getActiveUploadSelectors(event.file); - $(curUpload.progressBar).attr('style', 'width: ' + event.percentLoaded + '%;'); - }; - - self.uploadComplete = function (event) { - throw new Error("Missing implementation for uploadComplete"); - }; - - self._uploadError = function (event) { - /* - An error occurred while uploading the file. - */ - self.allowClose = true; - self.uploader.queue = null; - var response = JSON.parse(event.data); - var errors = []; - if (response && response.errors) { - errors = errors.concat(response.errors); - } else { - errors.push('Upload Failed: Issue communicating with server. This usually means your Internet connection is not strong enough. Try again later.') - } - var curUpload = self._getActiveUploadSelectors(event.file); - $(curUpload.progressBarContainer).addClass('progress-danger'); - $(curUpload.progressBar).addClass('progress-bar-danger'); - self._showErrors(event.file, errors); - }; - - self._showErrors = function (file, errors) { - var curUpload = self._getActiveUploadSelectors(file); - (errors.length > 0) ? $(curUpload.errorNotice).removeClass('hide') : $(curUpload.errorNotice).addClass('hide'); - $(curUpload.status).append(self._processErrorsTemplate(errors)); - }; - +define('tpl/tpl!vellum/templates/multimedia_upload_trigger', ['underscore'], function (_) { return function(obj){ +var __t,__p='',__j=Array.prototype.join,print=function(){__p+=__j.call(arguments,'');}; +with(obj||{}){ +__p+='\n '+ +((__t=( multimediaExists ? gettext("Replace") : gettext("Upload") ))==null?'':_.escape(__t))+ +' '+ +((__t=(mediaType))==null?'':__t)+ +'\n\n'; } - -function HQMediaBulkUploadController (uploader_name, marker, options) { - 'use strict'; - BaseHQMediaUploadController.call(this, uploader_name, marker, options); - var self = this; - self.confirmUploadModalSelector = "#hqm-upload-modal"; - - // Templates - self.detailsTemplate = options.detailsTemplate; - self.statusTemplate = options.statusTemplate; - - self._processDetailsTemplate = function (images, audio, video, unknowns) { - return _.template(self.detailsTemplate)({ - images: images, - audio: audio, - video: video, - unknowns: unknowns, - }); - }; - - self._processStatusTemplate = function (images, audio, video) { - var numMatches = images.length + audio.length + video.length; - return _.template(self.statusTemplate)({ - num: numMatches, - }); - }; +return __p; +}; }); - self._startUploadUI = function () { - // set the state of the uploader UI here when the upload starts - if ($(self.confirmUploadModalSelector)) { - $(self.confirmUploadModalSelector).modal('hide'); - } - }; +define('text/text!vellum/templates/multimedia_upload_status.html',[],function () { return '
\n
\n <%= file_name %> [<%= file_size %> MB]\n
\n

\n <%=gettext("Ready to upload. Click Begin Upload below to start.")%>\n

\n

\n <%-gettext("There were errors.")%>\n

\n
\n
\n';}); - // uploader - self.uploadComplete = function (event) { - var curUpload = self._getActiveUploadSelectors(event.file); - $(curUpload.progressBarContainer).removeClass('active'); - $(curUpload.cancel).addClass('hide'); - self._removeFileFromUploader(event.file); - var $queuedItem = $(curUpload.selector); - $queuedItem.remove(); - $queuedItem.insertAfter($(self.processingFilesListSelector).find('.hqm-list-notice')); - self._beginProcessing(event); - self._toggleUploadButton(); - }; - // processing flow - self._beginProcessing = function(event) { - /* - The upload completed. Do this... - */ - var response = JSON.parse(event.data); - - var processing_id = response.processing_id; - self.processingIdToFile[response.processing_id] = event.file; - var curUpload = self._getActiveUploadSelectors(event.file); - $(curUpload.progressBar).addClass('hide').attr('style', 'width: 0%;'); // reset progress bar for processing - $(curUpload.progressBarContainer).addClass('progress-warning active'); - $(curUpload.progressBar).addClass('progress-bar-warning'); - $(curUpload.processingQueuedNotice).removeClass('hide'); - self._pollProcessingQueue(processing_id)(); - }; +define('text/text!vellum/templates/multimedia_errors.html',[],function () { return '<% if (errors.length > 0) { %>\n
\n <% for (var e = 0; e < errors.length; e++) {\n var error = errors[e]; %>\n

<%- error %>

\n <% } %>\n
\n<% } %>\n';}); - self._pollProcessingQueue = function (processing_id) { - return function _poll () { - setTimeout(function () { - if (processing_id in self.processingIdToFile) { - $.ajax({ - url: self.processingURL, - dataType: 'json', - data: { - processing_id: processing_id, - }, - type: 'POST', - success: self._processingProgress, - error: self._processingError(processing_id), - complete: _poll, - timeout: self.pollInterval, - }); - } - }, self.pollInterval); - }; - }; - self._processingProgress = function (data) { - self.currentPollAttempts = 0; - var curUpload = self._getActiveUploadSelectors(self.processingIdToFile[data.processing_id]); - if (data.in_celery) { - $(curUpload.processingQueuedNotice).addClass('hide'); - $(curUpload.processingNotice).removeClass('hide'); - $(curUpload.progressBar).removeClass('hide').attr('style', 'width: ' + data.progress + '%;'); - if (data.total_files) { - var $file_status = $(curUpload.processingNotice).find('.label'); - $file_status.find('.denominator').text(data.total_files); - $file_status.find('.numerator').text(data.processed_files || 0); - $file_status.removeClass('hide'); - } - } - if (data.complete) { - self._processingComplete(data); - } - }; +define('text/text!vellum/templates/multimedia_existing_image.html',[],function () { return '

\n uploaded image\n "><%-gettext("View Full Size")%>\n

\n

\n <%-gettext("New Image Uploaded Successfully")%>\n

\n';}); - self._processingComplete = function (data) { - var processingFile = self.processingIdToFile[data.processing_id]; - delete self.processingIdToFile[data.processing_id]; - var curUpload = self._getActiveUploadSelectors(processingFile); - self._stopProcessingFile(processingFile); - $(curUpload.progressBarContainer).addClass('progress-success'); - $(curUpload.progressBar).addClass('progress-bar-success'); - self._showMatches(processingFile, data); - self._showErrors(processingFile, data.errors); - }; +define('text/text!vellum/templates/multimedia_existing_audio.html',[],function () { return '

\n "><%-gettext("Open Audio")%>\n

\n

\n <%-gettext("New Audio Uploaded Successfully")%>\n

\n';}); - self._processingError = function (processing_id) { - return function (data, status) { - if (self.pollInterval < self.maxPollInterval) { - // first try increasing their timeout, maybe the connection is poor - self.pollInterval = Math.min(self.pollInterval + 2000, self.maxPollInterval); - } else { - self.currentPollAttempts += 1; - } - if (self.currentPollAttempts > self.maxPollAttempts) { - var processingFile = self.processingIdToFile[processing_id]; - delete self.processingIdToFile[processing_id]; - var curUpload = self._getActiveUploadSelectors(processingFile); - self._stopProcessingFile(processingFile); - $(curUpload.progressBarContainer).addClass('progress-danger'); - $(curUpload.progressBar).addClass('progress-bar-danger'); - self._showErrors(processingFile, ['There was an issue communicating with the server at this time. ' + - 'The upload has failed.']); - } - }; - }; +define('text/text!vellum/templates/multimedia_existing_video.html',[],function () { return '

\n "><%-gettext("Open Video")%>\n

\n

\n <%-gettext("New Video Uploaded Successfully")%>\n

\n';}); - self._stopProcessingFile = function (file) { - var curUpload = self._getActiveUploadSelectors(file); - if (self.isMultiFileUpload) { - var $processingItem = $(curUpload.selector); - $processingItem.remove(); - $processingItem.insertAfter($(self.uploadedFilesListSelector).find('.hqm-list-notice')); - } - $(curUpload.processingNotice).addClass('hide'); - $(curUpload.completeNotice).removeClass('hide'); - $(curUpload.progressBar).attr('style', 'width: 100%;'); - $(curUpload.progressBarContainer).removeClass('active progress-warning'); - $(curUpload.progressBar).removeClass('progress-bar-warning'); - }; +define('text/text!vellum/templates/multimedia_existing_text.html',[],function () { return '

\n "><%-gettext("Open HTML")%>\n

\n

\n <%-gettext("New HTML Document Uploaded Successfully")%>\n

\n';}); - self._showMatches = function (file, data) { - var curUpload = self._getActiveUploadSelectors(file); - if (data.type === 'zip' && data.matched_files) { - var images = data.matched_files.CommCareImage, - audio = data.matched_files.CommCareAudio, - video = data.matched_files.CommCareVideo, - unknowns = data.unmatched_files; - $(curUpload.status).append(self._processStatusTemplate(images, audio, video)); - - $(curUpload.details).html(self._processDetailsTemplate(images, audio, video, unknowns)); - $(curUpload.details).find('.match-info').popover({ - html: true, - title: 'Click to open in new tab.', - trigger: 'hover', - placement: 'bottom', - sanitize: false, - }); - } - }; +define('tpl/tpl!vellum/templates/multimedia_nomedia', ['underscore'], function (_) { return function(obj){ +var __t,__p='',__j=Array.prototype.join,print=function(){__p+=__j.call(arguments,'');}; +with(obj||{}){ +__p+='

\n \n '+ +((__t=(gettext("No Reference")))==null?'':_.escape(__t))+ +'\n

\n'; } +return __p; +}; }); -HQMediaBulkUploadController.prototype = Object.create( BaseHQMediaUploadController.prototype ); -HQMediaBulkUploadController.prototype.constructor = HQMediaBulkUploadController; - - -function HQMediaFileUploadController (uploader_name, marker, options) { - 'use strict'; - BaseHQMediaUploadController.call(this, uploader_name, marker, options); - var self = this; - self.currentReference = null; - self.existingFileTemplate = options.existingFileTemplate; - - self._processExistingFileTemplate = function (url) { - return _.template(self.existingFileTemplate)({ - url: url, - }); - }; - - // Essential Selectors - self.existingFileSelector = self.container + " .hqm-existing"; - self.fileUploadCompleteSelector = self.existingFileSelector + ' .hqm-upload-completed'; - - self.updateUploadFormUI = function () { - var $existingFile = $(self.existingFileSelector); - $(self.fileUploadCompleteSelector).addClass('hide'); - - if (self.currentReference.getUrl() && self.currentReference.isMediaMatched()) { - $existingFile.removeClass('hide'); - $existingFile.find('.hqm-existing-controls').html(self._processExistingFileTemplate(self.currentReference.getUrl())); - } else { - $existingFile.addClass('hide'); - $existingFile.find('.hqm-existing-controls').empty(); - } - $('.existing-media').tooltip({ - placement: 'bottom', - }); - }; - - self.uploadComplete = function (event) { - self.allowClose = true; - var curUpload = self._getActiveUploadSelectors(event.file); - $(curUpload.cancel).addClass('hide'); - $(curUpload.progressBarContainer).removeClass('active').addClass('progress-success'); - $(curUpload.progressBar).addClass('progress-bar-success'); - - var response = JSON.parse(event.data.replace(/\r|\n|\r\n/, '\\n')); - $('[data-hqmediapath^="' + self.currentReference.path.replace(/\.\w+$/, ".") + '"]').trigger('mediaUploadComplete', response); - if (!response.errors.length) { - self.updateUploadFormUI(); - $(self.fileUploadCompleteSelector).removeClass('hide'); - self._removeFileFromUI(event.file); - self.resetUploader(); - } else { - self._showErrors(event.file, response.errors); - } - self._clearUploaderData(); - }; +define('tpl/tpl!vellum/templates/multimedia_block', ['underscore'], function (_) { return function(obj){ +var __t,__p='',__j=Array.prototype.join,print=function(){__p+=__j.call(arguments,'');}; +with(obj||{}){ +__p+='
\n
\n \n
\n
\n
\n
\n
\n \n
\n
\n
\n'; } - -HQMediaFileUploadController.prototype = Object.create( BaseHQMediaUploadController.prototype ); -HQMediaFileUploadController.prototype.constructor = HQMediaFileUploadController; - -define("file-uploader", ["yui-uploader","underscore","jquery"], (function (global) { - return function () { - var ret, fn; - return ret || global.HQMediaFileUploadController; - }; -}(this))); +return __p; +}; }); define('vellum/uploader',[ 'require', @@ -94556,7 +55802,7 @@ define('vellum/uploader',[ 'jquery', 'tpl!vellum/templates/multimedia_modal', 'tpl!vellum/templates/multimedia_upload_trigger', - 'text!vellum/templates/multimedia_queue.html', + 'text!vellum/templates/multimedia_upload_status.html', 'text!vellum/templates/multimedia_errors.html', 'text!vellum/templates/multimedia_existing_image.html', 'text!vellum/templates/multimedia_existing_audio.html', @@ -94572,7 +55818,7 @@ define('vellum/uploader',[ $, multimedia_modal, multimedia_upload_trigger, - multimedia_queue, + multimedia_upload_status, multimedia_errors, multimedia_existing_image, multimedia_existing_audio, @@ -94583,37 +55829,12 @@ define('vellum/uploader',[ ) { "use strict"; - var SUPPORTED_EXTENSIONS = { - image: [ - { - 'description': gettext('Image'), - 'extensions': '*.jpg;*.png;*.gif' - } - ], - audio: [ - { - 'description': gettext('Audio'), - 'extensions': '*.mp3;*.wav' - } - ], - video: [ - { - 'description': gettext('Video'), - 'extensions': '*.3gp;*.mp4' - } - ], - 'video-inline': [ - { - 'description': gettext('Inline Video'), - 'extensions': '*.3gp;*.mp4' - } - ], - text: [ - { - 'description': gettext('HTML'), - 'extensions': '*.html' - } - ], + var SLUG_TO_DESCRIPTION = { + image: gettext('Image'), + audio: gettext('Audio'), + video: gettext('Video'), + 'video-inline': gettext('Inline Video'), + text: gettext('HTML'), }, PREVIEW_TEMPLATES = { image: multimedia_existing_image, @@ -94641,8 +55862,8 @@ define('vellum/uploader',[ // These functions were extracted out when separating the uploader code from // the JavaRosa Itext media widget code. They could easily be made part of // the plugin interface in order to avoid passing around objectMap and - // uploadControls, but it seems fine either way. - var multimediaReference = function (mediaType, objectMap, uploadControls) { + // uploadControllers, but it seems fine either way. + var multimediaReference = function (mediaType, objectMap, uploadControllers) { var ref = {}; ref.mediaType = mediaType; @@ -94655,15 +55876,12 @@ define('vellum/uploader',[ return _.isObject(ref.linkedObj); }; - // gets called by uploadController ref.getUrl = function () { - return ref.linkedObj.url; + return ref.linkedObj ? ref.linkedObj.url : undefined; }; ref.updateController = function (widget) { - // see note about poor man's promise below - var uploadController = uploadControls[ref.mediaType].value; - uploadController.resetUploader(); + var uploadController = uploadControllers[ref.mediaType]; uploadController.currentReference = ref; uploadController.updateMediaPath = function () { var params = uploadController.uploadParams; @@ -94676,15 +55894,13 @@ define('vellum/uploader',[ old_ref: (ref.isMediaMatched()) ? ref.linkedObj.m_id : "", replace_attachment: true }; - uploadController.updateUploadFormUI(); }; return ref; }; - var addUploaderToWidget = function (widget, objectMap, uploadControls) { - widget.mediaRef = multimediaReference( - widget.form, objectMap, uploadControls); + var addUploaderToWidget = function (widget, objectMap, uploadControllers) { + widget.mediaRef = multimediaReference(widget.form, objectMap, uploadControllers); if (!widget.getBaseMediaPath) { throw new Error("required method not found: widget.getBaseMediaPath()"); @@ -94692,10 +55908,7 @@ define('vellum/uploader',[ widget.getRandomizedMediaPath = function (oldPath) { // The file type extension of the path returned here is replaced by - // the extension of the uploaded file, so it is not strictly - // necessary to pass in oldPath. However, the returned path must - // have an extension because of the way - // BaseHQMediaUploadController.startUpload() replaces it. + // the extension of the uploaded file. var extension = EXT.exec(oldPath)[0].toLowerCase() || ".xyz", // generates 1 or 2 duplicates in 100K samples (probably random enough) rand6 = Math.random().toString(36).slice(2, 8); @@ -94710,6 +55923,29 @@ define('vellum/uploader',[ .addClass('fd-mm-preview-container'), ICONS = widget.mug.form.vellum.data.javaRosa.ICONS; + widget.getUploaderModal = function () { + return $("#" + SLUG_TO_UPLOADER_SLUG[widget.form]); + }; + + widget.updateModalExistingFile = function (objectMap, isComplete) { + var ICONS = widget.mug.form.vellum.data.javaRosa.ICONS, + $uploaderModal = widget.getUploaderModal(), + $existingFile = $uploaderModal.find(".hqm-existing"); + if (widget.mediaRef.getUrl() && widget.mediaRef.isMediaMatched()) { + $existingFile.removeClass('hide'); + $existingFile.find('.hqm-existing-controls').html(getPreviewUI(widget, objectMap, ICONS)); + if (isComplete) { + $uploaderModal.find(".hqm-upload-completed").removeClass('hide'); + } + } else { + $existingFile.addClass('hide'); + $existingFile.find('.hqm-existing-controls').empty(); + } + $('.existing-media').tooltip({ + placement: 'bottom', + }); + }; + widget.getUIElement = function () { $uiElem = _getParentUIElement(); var $controlBlock = $uiElem.find('.controls'), @@ -94724,6 +55960,7 @@ define('vellum/uploader',[ $controlBlock.append($previewContainer); $uploadContainer.html(multimedia_block()); + $uploadContainer.find('.fd-mm-upload-trigger') .append(getUploadButtonUI(widget, objectMap)); $uploadContainer.find('.fd-mm-path-input') @@ -94765,9 +56002,11 @@ define('vellum/uploader',[ } objectMap[data.ref.path] = data.ref; } + widget.updateMultimediaBlockUI(objectMap); + widget.updateModalExistingFile(objectMap, true); }; - + widget.updateMultimediaBlockUI = function (objectMap) { $previewContainer.html(getPreviewUI(widget, objectMap, ICONS)) .find('.existing-media').tooltip(); @@ -94813,17 +56052,20 @@ define('vellum/uploader',[ $uploadBtn = $(multimedia_upload_trigger({ multimediaExists: currentPath in objectMap, uploaderId: SLUG_TO_UPLOADER_SLUG[widget.form], - mediaType: SUPPORTED_EXTENSIONS[widget.form][0].description + mediaType: SLUG_TO_DESCRIPTION[widget.form], })); $uploadBtn.click(function () { widget.mediaRef.updateController(widget); + var $uploaderModal = widget.getUploaderModal(); + $uploaderModal.find(".hqm-upload-status").empty(); + widget.updateModalExistingFile(objectMap); }); + return $uploadBtn; }; $.vellum.plugin("uploader", { objectMap: false, - sessionid: false, uploadUrls: { image: false, audio: false, @@ -94836,8 +56078,7 @@ define('vellum/uploader',[ var opts = this.opts().uploader, uploadUrls = opts.uploadUrls, uploadEnabled = opts.objectMap && opts.uploadUrls && - opts.uploadUrls.image, - sessionid = opts.sessionid; + opts.uploadUrls.image; this.data.uploader.uploadEnabled = uploadEnabled; this.data.uploader.objectMap = opts.objectMap; @@ -94845,39 +56086,32 @@ define('vellum/uploader',[ return; } - this.data.uploader.deferredInit = function () { - this.data.uploader.uploadControls = { - 'image': this.initUploadController({ - uploaderSlug: 'fd_hqimage', - mediaType: 'image', - sessionid: sessionid, - uploadUrl: uploadUrls.image, - }), - 'audio': this.initUploadController({ - uploaderSlug: 'fd_hqaudio', - mediaType: 'audio', - sessionid: sessionid, - uploadUrl: uploadUrls.audio, - }), - 'video': this.initUploadController({ - uploaderSlug: 'fd_hqvideo', - mediaType: 'video', - sessionid: sessionid, - uploadUrl: uploadUrls.video, - }), - 'video-inline': this.initUploadController({ - uploaderSlug: 'fd_hqInlineVideo', - mediaType: 'video-inline', - sessionid: sessionid, - uploadUrl: uploadUrls.video, - }), - 'text': this.initUploadController({ - uploaderSlug: 'fd_hqtext', - mediaType: 'text', - sessionid: sessionid, - uploadUrl: uploadUrls.text, - }) - }; + this.data.uploader.uploadControllers = { + 'image': this.initUploadController({ + uploaderSlug: 'fd_hqimage', + mediaType: 'image', + uploadUrl: uploadUrls.image, + }), + 'audio': this.initUploadController({ + uploaderSlug: 'fd_hqaudio', + mediaType: 'audio', + uploadUrl: uploadUrls.audio, + }), + 'video': this.initUploadController({ + uploaderSlug: 'fd_hqvideo', + mediaType: 'video', + uploadUrl: uploadUrls.video, + }), + 'video-inline': this.initUploadController({ + uploaderSlug: 'fd_hqInlineVideo', + mediaType: 'video-inline', + uploadUrl: uploadUrls.video, + }), + 'text': this.initUploadController({ + uploaderSlug: 'fd_hqtext', + mediaType: 'text', + uploadUrl: uploadUrls.text, + }) }; }, initMediaUploaderWidget: function (widget) { @@ -94886,15 +56120,9 @@ define('vellum/uploader',[ return; } - var deferredInit = this.data.uploader.deferredInit; - if (deferredInit !== null) { - this.data.uploader.deferredInit = null; - deferredInit.apply(this); - } - - addUploaderToWidget(widget, - this.data.uploader.objectMap, - this.data.uploader.uploadControls); + addUploaderToWidget(widget, + this.data.uploader.objectMap, + this.data.uploader.uploadControllers); }, initUploadController: function (options) { var $uploaderModal = $(multimedia_modal({ @@ -94903,56 +56131,100 @@ define('vellum/uploader',[ })); this.$f.find('.fd-multimedia-modal-container').append($uploaderModal); - // Load the uploader and its dependencies in the background after - // core dependencies are already loaded, since it's not necessary at - // page load. - // uploadControls is referenced in the initMediaUploaderWidget call - // path, but never actually used until the upload button is clicked. - // We use an object here as a poor man's promise. - // Feel free to undo this if it's not worth it. - - var uploadController = {value: null}; - - require(['file-uploader'], function (HQMediaFileUploadController) { - if (uploadController.value !== null) { - return; + // Don't allow user to close modal while server is processing upload + var allowClose = true; + $uploaderModal.on('hide.bs.modal', function (event) { + if (!allowClose) { + event.preventDefault(); } - uploadController.value = new HQMediaFileUploadController( - options.uploaderSlug, - options.mediaType, - { - fileFilters: SUPPORTED_EXTENSIONS[options.mediaType], - uploadURL: options.uploadUrl, - isMultiFileUpload: false, - queueTemplate: multimedia_queue, - errorsTemplate: multimedia_errors, - existingFileTemplate: PREVIEW_TEMPLATES[options.mediaType], - licensingParams: [ - 'shared', 'license', 'author', 'attribution-notes'], - uploadParams: {}, - sessionid: options.sessionid + }); + + var $fileInputTrigger = $uploaderModal.find(".btn-primary"), + $fileInput = $uploaderModal.find("input[type='file']"), + $uploadButton = $uploaderModal.find(".hqm-upload-confirm"), + _updateUploadButton = function (enable, spin) { + if (enable) { + $uploadButton.removeClass('disabled'); + } else { + $uploadButton.addClass('disabled'); + } + if (spin) { + $uploadButton.find(".fa-spin").removeClass("hide"); + $uploadButton.find(".fa-cloud-arrow-up").addClass("hide"); + } else { + $uploadButton.find(".fa-spin").addClass("hide"); + $uploadButton.find(".fa-cloud-arrow-up").removeClass("hide"); } - ); - var super_startUpload = uploadController.value.startUpload; - uploadController.value.startUpload = function (event) { - uploadController.value.updateMediaPath(); - return super_startUpload.call(this, event); }; - uploadController.value.init(); + + $fileInputTrigger.click(function () { + $fileInput.click(); }); - return uploadController; - }, - destroy: function () { - _.each(this.data.uploader.uploadControls, function (control, key) { - if (control.value) { - // HACK deep reach - // HQMediaFileUploadController should have a destroy method - control.value.uploader.destroy(); + + $fileInput.change(function () { + var MEGABYTE = 1048576, + $uploadStatusContainer = $uploaderModal.find(".hqm-upload-status"); + + if ($fileInput.get(0).files.length) { + var file = $fileInput.get(0).files[0]; + $uploadStatusContainer.html(_.template(multimedia_upload_status)({ + file_size: (file.size / MEGABYTE).toFixed(3), + file_name: file.name, + })); + _updateUploadButton(true, false); + } else { + $uploadStatusContainer.empty(); + _updateUploadButton(false, false); } - delete control.value; }); - this.__callOld(); - } + + var uploadController = {}; + $uploadButton.click(function () { + _updateUploadButton(false, true); + allowClose = false; + + var file = $fileInput.get(0).files[0], + data = new FormData(); + data.append("Filedata", file); + uploadController.updateMediaPath(); + + var newExtension = '.' + file.name.split('.').pop().toLowerCase(); + uploadController.uploadParams.path = uploadController.uploadParams.path.replace(/(\.[^/.]+)?$/, newExtension); + + _.each(uploadController.uploadParams, function (value, key) { + data.append(key, value); + }); + + var $uploadStatusContainer = $uploaderModal.find(".hqm-upload-status"); + $.ajax({ + url: options.uploadUrl, + type: 'POST', + data: data, + contentType: false, + processData: false, + enctype: 'multipart/form-data', + success: function (response) { + response = JSON.parse(response); + $('[data-hqmediapath^="' + response.ref.path.replace(/\.\w+$/, ".") + '"]').trigger('mediaUploadComplete', response); + $uploadStatusContainer.empty(); + _updateUploadButton(false, false); + allowClose = true; + }, + error: function (response) { + response = JSON.parse(response.responseText); + $uploadStatusContainer.find(".hqm-error").show(); + $uploadStatusContainer.find(".hqm-errors").html(_.template(multimedia_errors)({ + errors: response.errors, + })); + $uploadStatusContainer.find(".hqm-begin").hide(); + _updateUploadButton(false, false); + allowClose = true; + }, + }); + }); + + return uploadController; + }, }); }); @@ -96333,19 +57605,12 @@ requirejs.config({ 'underscore': '../node_modules/underscore/underscore', 'XMLWriter': '../node_modules/XMLWriter/XMLWriter', - // todo: should convert xpath submodule to AMD 'xpath': '../node_modules/xpath/dist/js-xpath', 'langCodes': '../node_modules/langcodes/langs.json', 'save-button': '../lib/SaveButton', - 'yui-base': '../node_modules/MediaUploader/yui-base', - 'yui-combo': '../node_modules/MediaUploader/yui-combo', - 'yui-loader': '../node_modules/MediaUploader/yui-loader', - 'yui-uploader': '../node_modules/MediaUploader/yui-uploader', - - 'file-uploader': '../node_modules/MediaUploader/hqmedia.upload_controller', 'jsdiff': '../node_modules/jsdiff/diff', 'markdown-it': '../node_modules/markdown-it/dist/markdown-it', 'caretjs': '../node_modules/Caret.js/dist/jquery.caret', @@ -96382,22 +57647,6 @@ requirejs.config({ exports: 'SaveButton' }, - 'yui-base': { - exports: 'YUI' - }, - 'yui-loader': { - deps: ['yui-base'], - exports: 'YUI' - }, - 'yui-uploader': { - deps: ['yui-base', 'yui-loader', 'css!yui-combo'], - exports: 'YUI' - }, - 'file-uploader': { - deps: ['yui-uploader', 'underscore', 'jquery'], - exports: 'HQMediaFileUploadController' - }, - 'xpath': { exports: 'xpath' }, diff --git a/corehq/apps/app_manager/static/app_manager/js/vellum/src/main.js b/corehq/apps/app_manager/static/app_manager/js/vellum/src/main.js index 00313780b158..8239d4f4d40c 100644 --- a/corehq/apps/app_manager/static/app_manager/js/vellum/src/main.js +++ b/corehq/apps/app_manager/static/app_manager/js/vellum/src/main.js @@ -17,7 +17,6 @@ requirejs.config({ "ckeditor-jquery", "css/css!../node_modules/codemirror/lib/codemirror", "css/css!../node_modules/jstree/dist/themes/default/style", - "css/css!yui-combo", "css/css!../node_modules/at.js/dist/css/jquery.atwho" ], "main-components": [ diff --git a/corehq/apps/app_manager/static/app_manager/js/vellum/style.css b/corehq/apps/app_manager/static/app_manager/js/vellum/style.css index 813fe2bc96ad..7680b6904e53 100644 --- a/corehq/apps/app_manager/static/app_manager/js/vellum/style.css +++ b/corehq/apps/app_manager/static/app_manager/js/vellum/style.css @@ -1 +1 @@ -@-moz-keyframes blink{50%{background-color:transparent}}@-webkit-keyframes blink{50%{background-color:transparent}}@keyframes blink{50%{background-color:transparent}}.jstree-children,.jstree-container-ul,.jstree-node{display:block;margin:0;padding:0;list-style-type:none;list-style-image:none}.jstree-anchor,.jstree-node{white-space:nowrap}.jstree-anchor{display:inline-block;padding:0 4px 0 1px;margin:0;vertical-align:top}.jstree-anchor:focus{outline:0}.jstree-anchor,.jstree-anchor:active,.jstree-anchor:hover,.jstree-anchor:link,.jstree-anchor:visited{text-decoration:none;color:inherit}.jstree-icon{display:inline-block;text-decoration:none;margin:0;padding:0;vertical-align:top;text-align:center}.jstree-icon:empty{display:inline-block;text-decoration:none;margin:0;padding:0;vertical-align:top;text-align:center}.jstree-ocl{cursor:pointer}.jstree-leaf>.jstree-ocl{cursor:default}.jstree .jstree-open>.jstree-children{display:block}.jstree-anchor>.jstree-themeicon{margin-right:2px}.jstree .jstree-closed>.jstree-children,.jstree .jstree-leaf>.jstree-children,.jstree-anchor>.jstree-themeicon-hidden,.jstree-hidden,.jstree-no-icons .jstree-themeicon,.jstree-node.jstree-hidden{display:none}.jstree-rtl .jstree-anchor{padding:0 1px 0 4px}.jstree-rtl .jstree-anchor>.jstree-themeicon{margin-left:2px;margin-right:0}.jstree-rtl .jstree-node{margin-left:0}.jstree-rtl .jstree-container-ul>.jstree-node{margin-right:0}.jstree-wholerow-ul{position:relative;display:inline-block;min-width:100%}.jstree-wholerow-ul .jstree-leaf>.jstree-ocl{cursor:pointer}.jstree-wholerow-ul .jstree-anchor,.jstree-wholerow-ul .jstree-icon{position:relative}.jstree-wholerow-ul .jstree-wholerow{width:100%;cursor:pointer;position:absolute;left:0;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.jstree-contextmenu .jstree-anchor{-webkit-user-select:none;-webkit-touch-callout:none}.jstree-default .jstree-no-icons .jstree-anchor>.jstree-themeicon,.vakata-context{display:none}.vakata-context,.vakata-context ul{margin:0;padding:2px;position:absolute;background:#f5f5f5;border:1px solid #979797;box-shadow:2px 2px 2px #999}.vakata-context ul{list-style:none;left:100%;margin:-2.7em 0 0 -4px}.vakata-context .vakata-context-right ul,.vakata-context-rtl ul{left:auto;right:100%;margin-left:auto;margin-right:-4px}.vakata-context li{list-style:none}.vakata-context li>a{display:block;padding:0 2em;text-decoration:none;width:auto;color:#000;white-space:nowrap;line-height:2.4em;text-shadow:1px 1px 0 #fff;border-radius:1px}.vakata-context .vakata-context-hover>a,.vakata-context li>a:hover{position:relative;background-color:#e8eff7;box-shadow:0 0 2px #0a6aa1}.vakata-context li>a.vakata-context-parent{background-image:url(data:image/gif;base64,R0lGODlhCwAHAIAAACgoKP///yH5BAEAAAEALAAAAAALAAcAAAIORI4JlrqN1oMSnmmZDQUAOw==);background-position:right center;background-repeat:no-repeat}.vakata-context li>a:focus{outline:0}.vakata-context .vakata-context-separator>a,.vakata-context .vakata-context-separator>a:hover{background:#fff;border:0;border-top:1px solid #e2e3e3;height:1px;min-height:1px;max-height:1px;padding:0;margin:0 0 0 2.4em;border-left:1px solid #e0e0e0;text-shadow:0 0 0 transparent;box-shadow:0 0 0 transparent;border-radius:0}.vakata-context .vakata-contextmenu-disabled a,.vakata-context .vakata-contextmenu-disabled a:hover{color:silver;background-color:transparent;border:0;box-shadow:0 0 0}.vakata-context .vakata-contextmenu-disabled>a>i{filter:grayscale(100%)}.vakata-context li>a>i{text-decoration:none;display:inline-block;width:2.4em;height:2.4em;background:0 0;margin:0 0 0 -2em;vertical-align:top;text-align:center;line-height:2.4em}.vakata-context li>a>i:empty{width:2.4em;line-height:2.4em}.vakata-context li>a .vakata-contextmenu-sep{display:inline-block;width:1px;height:2.4em;background:#fff;margin:0 .5em 0 0;border-left:1px solid #e2e3e3}.vakata-context .vakata-contextmenu-shortcut{font-size:.8em;color:silver;opacity:.5;display:none}.vakata-context-rtl li>a.vakata-context-parent{background-image:url(data:image/gif;base64,R0lGODlhCwAHAIAAACgoKP///yH5BAEAAAEALAAAAAALAAcAAAINjI+AC7rWHIsPtmoxLAA7);background-position:left center;background-repeat:no-repeat}.vakata-context-rtl .vakata-context-separator>a{margin:0 2.4em 0 0;border-left:0;border-right:1px solid #e2e3e3}.vakata-context-rtl .vakata-context-left ul{right:auto;left:100%;margin-left:-4px;margin-right:auto}.vakata-context-rtl li>a>i{margin:0 -2em 0 0}.vakata-context-rtl li>a .vakata-contextmenu-sep{margin:0 0 0 .5em;border-left-color:#fff;background:#e2e3e3}#jstree-marker{position:absolute;top:0;left:0;margin:-5px 0 0;padding:0;border-right:0;border-top:5px solid transparent;border-bottom:5px solid transparent;border-left:5px solid;width:0;height:0;font-size:0;line-height:0}#jstree-dnd{line-height:16px;margin:0;padding:4px}#jstree-dnd .jstree-icon{margin:0 2px 0 0}#jstree-dnd .jstree-copy,#jstree-dnd .jstree-icon{display:inline-block;text-decoration:none;padding:0;width:16px;height:16px}#jstree-dnd .jstree-ok{background:green}#jstree-dnd .jstree-er{background:red}#jstree-dnd .jstree-copy{margin:0 2px}.jstree-default .jstree-node{background-color:transparent}.jstree-default .jstree-icon{background-repeat:no-repeat;background-color:transparent}.jstree-default .jstree-anchor,.jstree-default .jstree-animated,.jstree-default .jstree-wholerow{transition:background-color .15s,box-shadow .15s}.jstree-default .jstree-context,.jstree-default .jstree-hovered{background:#e7f4f9;border-radius:2px;box-shadow:inset 0 0 1px #ccc}.jstree-default .jstree-clicked{background:#beebff;border-radius:2px;box-shadow:inset 0 0 1px #999}.jstree-default .jstree-disabled{color:#666}.jstree-default .jstree-disabled.jstree-hovered{box-shadow:none}.jstree-default .jstree-disabled>.jstree-icon{opacity:.8;filter:gray;-webkit-filter:grayscale(100%)}.jstree-default .jstree-search{font-style:italic;color:#8b0000;font-weight:700}.jstree-default .jstree-no-checkboxes .jstree-checkbox{display:none!important}.jstree-default.jstree-checkbox-no-clicked .jstree-clicked{background:0 0;box-shadow:none}.jstree-default.jstree-checkbox-no-clicked .jstree-clicked.jstree-hovered,.jstree-default.jstree-checkbox-no-clicked>.jstree-wholerow-ul .jstree-wholerow-clicked.jstree-wholerow-hovered{background:#e7f4f9}.jstree-default.jstree-checkbox-no-clicked>.jstree-wholerow-ul .jstree-wholerow-clicked{background:0 0}.jstree-default>.jstree-striped{min-width:100%;display:inline-block;background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAAkCAMAAAB/qqA+AAAABlBMVEUAAAAAAAClZ7nPAAAAAnRSTlMNAMM9s3UAAAAXSURBVHjajcEBAQAAAIKg/H/aCQZ70AUBjAATb6YPDgAAAABJRU5ErkJggg==) left top}.jstree-default>.jstree-wholerow-ul .jstree-clicked,.jstree-default>.jstree-wholerow-ul .jstree-hovered{background:0 0;box-shadow:none;border-radius:0}.jstree-default .jstree-wholerow{-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box}.jstree-default .jstree-wholerow-hovered{background:#e7f4f9}.jstree-default .jstree-wholerow-clicked{background:#beebff;background:-webkit-linear-gradient(top,#beebff 0,#a8e4ff 100%);background:linear-gradient(to bottom,#beebff 0,#a8e4ff 100%)}.jstree-default .jstree-node{min-height:24px;line-height:24px;margin-left:24px;min-width:24px}.jstree-default .jstree-anchor{line-height:24px;height:24px}.jstree-default .jstree-icon{width:24px;height:24px;line-height:24px}.jstree-default .jstree-icon:empty{width:24px;height:24px;line-height:24px}.jstree-default.jstree-rtl .jstree-node{margin-right:24px}.jstree-default .jstree-wholerow{height:24px}#jstree-dnd.jstree-default .jstree-er,#jstree-dnd.jstree-default .jstree-ok,.jstree-default .jstree-icon,.jstree-default .jstree-node{background-image:url(src/../node_modules/jstree/dist/themes/default/32px.png)}.jstree-default .jstree-node{background-position:-292px -4px;background-repeat:repeat-y}.jstree-default .jstree-last{background:0 0}.jstree-default .jstree-open>.jstree-ocl{background-position:-132px -4px}.jstree-default .jstree-closed>.jstree-ocl{background-position:-100px -4px}.jstree-default .jstree-leaf>.jstree-ocl{background-position:-68px -4px}.jstree-default .jstree-themeicon{background-position:-260px -4px}.jstree-default .jstree-disabled,.jstree-default .jstree-disabled.jstree-hovered,.jstree-default>.jstree-no-dots .jstree-leaf>.jstree-ocl,.jstree-default>.jstree-no-dots .jstree-node{background:0 0}.jstree-default>.jstree-no-dots .jstree-open>.jstree-ocl{background-position:-36px -4px}.jstree-default>.jstree-no-dots .jstree-closed>.jstree-ocl{background-position:-4px -4px}.jstree-default .jstree-disabled.jstree-clicked{background:#efefef}.jstree-default .jstree-checkbox{background-position:-164px -4px}.jstree-default .jstree-checkbox:hover{background-position:-164px -36px}.jstree-default .jstree-checked>.jstree-checkbox,.jstree-default.jstree-checkbox-selection .jstree-clicked>.jstree-checkbox{background-position:-228px -4px}.jstree-default .jstree-checked>.jstree-checkbox:hover,.jstree-default.jstree-checkbox-selection .jstree-clicked>.jstree-checkbox:hover{background-position:-228px -36px}.jstree-default .jstree-anchor>.jstree-undetermined{background-position:-196px -4px}.jstree-default .jstree-anchor>.jstree-undetermined:hover{background-position:-196px -36px}.jstree-default .jstree-checkbox-disabled{opacity:.8;filter:gray;-webkit-filter:grayscale(100%)}.jstree-default>.jstree-striped{background-size:auto 48px}.jstree-default.jstree-rtl .jstree-node{background-position:100% 1px;background-repeat:repeat-y}.jstree-default.jstree-rtl .jstree-open>.jstree-ocl{background-position:-132px -36px}.jstree-default.jstree-rtl .jstree-closed>.jstree-ocl{background-position:-100px -36px}.jstree-default.jstree-rtl .jstree-leaf>.jstree-ocl{background-position:-68px -36px}.jstree-default.jstree-rtl>.jstree-no-dots .jstree-leaf>.jstree-ocl,.jstree-default.jstree-rtl>.jstree-no-dots .jstree-node{background:0 0}.jstree-default.jstree-rtl>.jstree-no-dots .jstree-open>.jstree-ocl{background-position:-36px -36px}.jstree-default.jstree-rtl>.jstree-no-dots .jstree-closed>.jstree-ocl{background-position:-4px -36px}.jstree-default .jstree-themeicon-custom{background-color:transparent;background-image:none;background-position:0 0}.jstree-default>.jstree-container-ul .jstree-loading>.jstree-ocl{background:url(src/../node_modules/jstree/dist/themes/default/throbber.gif) center center no-repeat}.jstree-default .jstree-file{background:url(src/../node_modules/jstree/dist/themes/default/32px.png) -100px -68px no-repeat}.jstree-default .jstree-folder{background:url(src/../node_modules/jstree/dist/themes/default/32px.png) -260px -4px no-repeat}.jstree-default>.jstree-container-ul>.jstree-node{margin-left:0;margin-right:0}#jstree-dnd.jstree-default{line-height:24px;padding:0 4px}#jstree-dnd.jstree-default .jstree-er,#jstree-dnd.jstree-default .jstree-ok{background-repeat:no-repeat;background-color:transparent}#jstree-dnd.jstree-default i{background:0 0;width:24px;height:24px;line-height:24px}#jstree-dnd.jstree-default .jstree-ok{background-position:-4px -68px}#jstree-dnd.jstree-default .jstree-er{background-position:-36px -68px}.jstree-default .jstree-ellipsis{overflow:hidden}.jstree-default .jstree-ellipsis .jstree-anchor{width:calc(100% - 29px);text-overflow:ellipsis;overflow:hidden}.jstree-default.jstree-rtl .jstree-node{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAACAQMAAAB49I5GAAAABlBMVEUAAAAdHRvEkCwcAAAAAXRSTlMAQObYZgAAAAxJREFUCNdjAAMOBgAAGAAJMwQHdQAAAABJRU5ErkJggg==)}.jstree-default.jstree-rtl .jstree-last{background:0 0}.jstree-default-small .jstree-node{min-height:18px;line-height:18px;margin-left:18px;min-width:18px}.jstree-default-small .jstree-anchor{line-height:18px;height:18px}.jstree-default-small .jstree-icon{width:18px;height:18px;line-height:18px}.jstree-default-small .jstree-icon:empty{width:18px;height:18px;line-height:18px}.jstree-default-small.jstree-rtl .jstree-node{margin-right:18px}.jstree-default-small .jstree-wholerow{height:18px}.jstree-default-small .jstree-icon,.jstree-default-small .jstree-node{background-image:url(src/../node_modules/jstree/dist/themes/default/32px.png)}.jstree-default-small .jstree-node{background-position:-295px -7px;background-repeat:repeat-y}.jstree-default-small .jstree-last{background:0 0}.jstree-default-small .jstree-open>.jstree-ocl{background-position:-135px -7px}.jstree-default-small .jstree-closed>.jstree-ocl{background-position:-103px -7px}.jstree-default-small .jstree-leaf>.jstree-ocl{background-position:-71px -7px}.jstree-default-small .jstree-themeicon{background-position:-263px -7px}.jstree-default-small .jstree-disabled,.jstree-default-small .jstree-disabled.jstree-hovered,.jstree-default-small>.jstree-no-dots .jstree-leaf>.jstree-ocl,.jstree-default-small>.jstree-no-dots .jstree-node{background:0 0}.jstree-default-small>.jstree-no-dots .jstree-open>.jstree-ocl{background-position:-39px -7px}.jstree-default-small>.jstree-no-dots .jstree-closed>.jstree-ocl{background-position:-7px -7px}.jstree-default-small .jstree-disabled.jstree-clicked{background:#efefef}.jstree-default-small .jstree-checkbox{background-position:-167px -7px}.jstree-default-small .jstree-checkbox:hover{background-position:-167px -39px}.jstree-default-small .jstree-checked>.jstree-checkbox,.jstree-default-small.jstree-checkbox-selection .jstree-clicked>.jstree-checkbox{background-position:-231px -7px}.jstree-default-small .jstree-checked>.jstree-checkbox:hover,.jstree-default-small.jstree-checkbox-selection .jstree-clicked>.jstree-checkbox:hover{background-position:-231px -39px}.jstree-default-small .jstree-anchor>.jstree-undetermined{background-position:-199px -7px}.jstree-default-small .jstree-anchor>.jstree-undetermined:hover{background-position:-199px -39px}.jstree-default-small .jstree-checkbox-disabled{opacity:.8;filter:gray;-webkit-filter:grayscale(100%)}.jstree-default-small>.jstree-striped{background-size:auto 36px}.jstree-default-small.jstree-rtl .jstree-node{background-position:100% 1px;background-repeat:repeat-y}.jstree-default-small.jstree-rtl .jstree-open>.jstree-ocl{background-position:-135px -39px}.jstree-default-small.jstree-rtl .jstree-closed>.jstree-ocl{background-position:-103px -39px}.jstree-default-small.jstree-rtl .jstree-leaf>.jstree-ocl{background-position:-71px -39px}.jstree-default-small.jstree-rtl>.jstree-no-dots .jstree-leaf>.jstree-ocl,.jstree-default-small.jstree-rtl>.jstree-no-dots .jstree-node{background:0 0}.jstree-default-small.jstree-rtl>.jstree-no-dots .jstree-open>.jstree-ocl{background-position:-39px -39px}.jstree-default-small.jstree-rtl>.jstree-no-dots .jstree-closed>.jstree-ocl{background-position:-7px -39px}.jstree-default-small .jstree-themeicon-custom{background-color:transparent;background-image:none;background-position:0 0}.jstree-default-small>.jstree-container-ul .jstree-loading>.jstree-ocl{background:url(src/../node_modules/jstree/dist/themes/default/throbber.gif) center center no-repeat}.jstree-default-small .jstree-file{background:url(src/../node_modules/jstree/dist/themes/default/32px.png) -103px -71px no-repeat}.jstree-default-small .jstree-folder{background:url(src/../node_modules/jstree/dist/themes/default/32px.png) -263px -7px no-repeat}.jstree-default-small>.jstree-container-ul>.jstree-node{margin-left:0;margin-right:0}#jstree-dnd.jstree-default-small{line-height:18px;padding:0 4px}#jstree-dnd.jstree-default-small .jstree-er,#jstree-dnd.jstree-default-small .jstree-ok{background-image:url(src/../node_modules/jstree/dist/themes/default/32px.png);background-repeat:no-repeat;background-color:transparent}#jstree-dnd.jstree-default-small i{background:0 0;width:18px;height:18px;line-height:18px}#jstree-dnd.jstree-default-small .jstree-ok{background-position:-7px -71px}#jstree-dnd.jstree-default-small .jstree-er{background-position:-39px -71px}.jstree-default-small .jstree-ellipsis{overflow:hidden}.jstree-default-small .jstree-ellipsis .jstree-anchor{width:calc(100% - 23px);text-overflow:ellipsis;overflow:hidden}.jstree-default-small.jstree-rtl .jstree-node{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABIAAAACAQMAAABv1h6PAAAABlBMVEUAAAAdHRvEkCwcAAAAAXRSTlMAQObYZgAAAAxJREFUCNdjAAMHBgAAiABBI4gz9AAAAABJRU5ErkJggg==)}.jstree-default-small.jstree-rtl .jstree-last{background:0 0}.jstree-default-large .jstree-node{min-height:32px;line-height:32px;margin-left:32px;min-width:32px}.jstree-default-large .jstree-anchor{line-height:32px;height:32px}.jstree-default-large .jstree-icon{width:32px;height:32px;line-height:32px}.jstree-default-large .jstree-icon:empty{width:32px;height:32px;line-height:32px}.jstree-default-large.jstree-rtl .jstree-node{margin-right:32px}.jstree-default-large .jstree-wholerow{height:32px}.jstree-default-large .jstree-icon,.jstree-default-large .jstree-node{background-image:url(src/../node_modules/jstree/dist/themes/default/32px.png)}.jstree-default-large .jstree-node{background-position:-288px 0;background-repeat:repeat-y}.jstree-default-large .jstree-last{background:0 0}.jstree-default-large .jstree-open>.jstree-ocl{background-position:-128px 0}.jstree-default-large .jstree-closed>.jstree-ocl{background-position:-96px 0}.jstree-default-large .jstree-leaf>.jstree-ocl{background-position:-64px 0}.jstree-default-large .jstree-themeicon{background-position:-256px 0}.jstree-default-large .jstree-disabled,.jstree-default-large .jstree-disabled.jstree-hovered,.jstree-default-large>.jstree-no-dots .jstree-leaf>.jstree-ocl,.jstree-default-large>.jstree-no-dots .jstree-node{background:0 0}.jstree-default-large>.jstree-no-dots .jstree-open>.jstree-ocl{background-position:-32px 0}.jstree-default-large>.jstree-no-dots .jstree-closed>.jstree-ocl{background-position:0 0}.jstree-default-large .jstree-disabled.jstree-clicked{background:#efefef}.jstree-default-large .jstree-checkbox{background-position:-160px 0}.jstree-default-large .jstree-checkbox:hover{background-position:-160px -32px}.jstree-default-large .jstree-checked>.jstree-checkbox,.jstree-default-large.jstree-checkbox-selection .jstree-clicked>.jstree-checkbox{background-position:-224px 0}.jstree-default-large .jstree-checked>.jstree-checkbox:hover,.jstree-default-large.jstree-checkbox-selection .jstree-clicked>.jstree-checkbox:hover{background-position:-224px -32px}.jstree-default-large .jstree-anchor>.jstree-undetermined{background-position:-192px 0}.jstree-default-large .jstree-anchor>.jstree-undetermined:hover{background-position:-192px -32px}.jstree-default-large .jstree-checkbox-disabled{opacity:.8;filter:gray;-webkit-filter:grayscale(100%)}.jstree-default-large>.jstree-striped{background-size:auto 64px}.jstree-default-large.jstree-rtl .jstree-node{background-position:100% 1px;background-repeat:repeat-y}.jstree-default-large.jstree-rtl .jstree-open>.jstree-ocl{background-position:-128px -32px}.jstree-default-large.jstree-rtl .jstree-closed>.jstree-ocl{background-position:-96px -32px}.jstree-default-large.jstree-rtl .jstree-leaf>.jstree-ocl{background-position:-64px -32px}.jstree-default-large.jstree-rtl>.jstree-no-dots .jstree-leaf>.jstree-ocl,.jstree-default-large.jstree-rtl>.jstree-no-dots .jstree-node{background:0 0}.jstree-default-large.jstree-rtl>.jstree-no-dots .jstree-open>.jstree-ocl{background-position:-32px -32px}.jstree-default-large.jstree-rtl>.jstree-no-dots .jstree-closed>.jstree-ocl{background-position:0 -32px}.jstree-default-large .jstree-themeicon-custom{background-color:transparent;background-image:none;background-position:0 0}.jstree-default-large>.jstree-container-ul .jstree-loading>.jstree-ocl{background:url(src/../node_modules/jstree/dist/themes/default/throbber.gif) center center no-repeat}.jstree-default-large .jstree-file{background:url(src/../node_modules/jstree/dist/themes/default/32px.png) -96px -64px no-repeat}.jstree-default-large .jstree-folder{background:url(src/../node_modules/jstree/dist/themes/default/32px.png) -256px 0 no-repeat}.jstree-default-large>.jstree-container-ul>.jstree-node{margin-left:0;margin-right:0}#jstree-dnd.jstree-default-large{line-height:32px;padding:0 4px}#jstree-dnd.jstree-default-large .jstree-er,#jstree-dnd.jstree-default-large .jstree-ok{background-image:url(src/../node_modules/jstree/dist/themes/default/32px.png);background-repeat:no-repeat;background-color:transparent}#jstree-dnd.jstree-default-large i{background:0 0;width:32px;height:32px;line-height:32px}#jstree-dnd.jstree-default-large .jstree-ok{background-position:0 -64px}#jstree-dnd.jstree-default-large .jstree-er{background-position:-32px -64px}.jstree-default-large .jstree-ellipsis{overflow:hidden}.jstree-default-large .jstree-ellipsis .jstree-anchor{width:calc(100% - 37px);text-overflow:ellipsis;overflow:hidden}.jstree-default-large.jstree-rtl .jstree-node{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAACAQMAAAAD0EyKAAAABlBMVEUAAAAdHRvEkCwcAAAAAXRSTlMAQObYZgAAAAxJREFUCNdjgIIGBgABCgCBvVLXcAAAAABJRU5ErkJggg==)}.jstree-default-large.jstree-rtl .jstree-last,span.CodeMirror-selectedtext{background:0 0}@media (max-width:768px){#jstree-dnd.jstree-dnd-responsive{line-height:40px;font-weight:700;font-size:1.1em;text-shadow:1px 1px #fff}#jstree-dnd.jstree-dnd-responsive>i{background:0 0;width:40px;height:40px}#jstree-dnd.jstree-dnd-responsive>.jstree-er,#jstree-dnd.jstree-dnd-responsive>.jstree-ok{background-image:url(src/../node_modules/jstree/dist/themes/default/40px.png);background-position:0 -200px;background-size:120px 240px}#jstree-dnd.jstree-dnd-responsive>.jstree-er{background-position:-40px -200px}#jstree-marker.jstree-dnd-responsive{border-left-width:10px;border-top-width:10px;border-bottom-width:10px;margin-top:-10px}.jstree-default-responsive .jstree-node{background:0 0;min-height:40px;line-height:40px;margin-left:40px;min-width:40px;white-space:nowrap}.jstree-default-responsive .jstree-anchor{line-height:40px;height:40px}.jstree-default-responsive .jstree-icon,.jstree-default-responsive .jstree-icon:empty{width:40px;height:40px;line-height:40px}.jstree-default-responsive.jstree-rtl .jstree-node{margin-left:0;margin-right:40px;background:0 0}.jstree-default-responsive.jstree-rtl .jstree-container-ul>.jstree-node{margin-right:0}.jstree-default-responsive .jstree-ocl{background-size:120px 240px}.jstree-default-responsive .jstree-leaf>.jstree-ocl,.jstree-default-responsive.jstree-rtl .jstree-leaf>.jstree-ocl{background:0 0}.jstree-default-responsive .jstree-open>.jstree-ocl{background-position:0 0!important}.jstree-default-responsive .jstree-closed>.jstree-ocl{background-position:0 -40px!important}.jstree-default-responsive.jstree-rtl .jstree-closed>.jstree-ocl{background-position:-40px 0!important}.jstree-default-responsive .jstree-themeicon{background-position:-40px -40px}.jstree-default-responsive .jstree-checkbox,.jstree-default-responsive .jstree-checkbox:hover{background-position:-40px -80px}.jstree-default-responsive .jstree-checked>.jstree-checkbox,.jstree-default-responsive .jstree-checked>.jstree-checkbox:hover,.jstree-default-responsive.jstree-checkbox-selection .jstree-clicked>.jstree-checkbox,.jstree-default-responsive.jstree-checkbox-selection .jstree-clicked>.jstree-checkbox:hover{background-position:0 -80px}.jstree-default-responsive .jstree-anchor>.jstree-undetermined,.jstree-default-responsive .jstree-anchor>.jstree-undetermined:hover{background-position:0 -120px}.jstree-default-responsive .jstree-anchor{font-weight:700;font-size:1.1em;text-shadow:1px 1px #fff}.jstree-default-responsive>.jstree-striped{background:0 0}.jstree-default-responsive .jstree-wholerow{border-top:1px solid rgba(255,255,255,.7);border-bottom:1px solid rgba(64,64,64,.2);background:#ebebeb;height:40px}.jstree-default-responsive .jstree-wholerow-hovered{background:#e7f4f9}.jstree-default-responsive .jstree-wholerow-clicked{background:#beebff}.jstree-default-responsive .jstree-children .jstree-last>.jstree-wholerow{box-shadow:inset 0 -6px 3px -5px #666}.jstree-default-responsive .jstree-children .jstree-open>.jstree-wholerow{box-shadow:inset 0 6px 3px -5px #666;border-top:0}.jstree-default-responsive .jstree-children .jstree-open+.jstree-open{box-shadow:none}.jstree-default-responsive .jstree-checkbox,.jstree-default-responsive .jstree-icon,.jstree-default-responsive .jstree-node,.jstree-default-responsive .jstree-node>.jstree-ocl,.jstree-default-responsive .jstree-themeicon{background-image:url(src/../node_modules/jstree/dist/themes/default/40px.png);background-size:120px 240px}.jstree-default-responsive .jstree-node{background-position:-80px 0;background-repeat:repeat-y}.jstree-default-responsive .jstree-last{background:0 0}.jstree-default-responsive .jstree-leaf>.jstree-ocl{background-position:-40px -120px}.jstree-default-responsive .jstree-last>.jstree-ocl{background-position:-40px -160px}.jstree-default-responsive .jstree-themeicon-custom{background-color:transparent;background-image:none;background-position:0 0}.jstree-default-responsive .jstree-file{background:url(src/../node_modules/jstree/dist/themes/default/40px.png) 0 -160px no-repeat;background-size:120px 240px}.jstree-default-responsive .jstree-folder{background:url(src/../node_modules/jstree/dist/themes/default/40px.png) -40px -40px no-repeat;background-size:120px 240px}.jstree-default-responsive>.jstree-container-ul>.jstree-node{margin-left:0;margin-right:0}}.CodeMirror{font-family:monospace;height:300px;color:#000;direction:ltr}.CodeMirror-lines{padding:4px 0}.CodeMirror pre.CodeMirror-line,.CodeMirror pre.CodeMirror-line-like{padding:0 4px;-moz-border-radius:0;-webkit-border-radius:0;border-radius:0;border-width:0;background:0 0;font-family:inherit;font-size:inherit;margin:0;white-space:pre;word-wrap:normal;line-height:inherit;color:inherit;z-index:2;position:relative;overflow:visible;-webkit-tap-highlight-color:transparent;-webkit-font-variant-ligatures:contextual;font-variant-ligatures:contextual}.CodeMirror-gutter-filler,.CodeMirror-scrollbar-filler{background-color:#fff}.CodeMirror-gutters{border-right:1px solid #ddd;background-color:#f7f7f7;white-space:nowrap}.CodeMirror-linenumber{padding:0 3px 0 5px;min-width:20px;text-align:right;color:#999;white-space:nowrap}.CodeMirror-guttermarker{color:#000}.CodeMirror-guttermarker-subtle{color:#999}.CodeMirror-cursor{border-left:1px solid #000;border-right:none;width:0}.CodeMirror div.CodeMirror-secondarycursor{border-left:1px solid silver}.cm-fat-cursor .CodeMirror-cursor{width:auto;border:0!important;background:#7e7}.cm-fat-cursor div.CodeMirror-cursors{z-index:1}.cm-animate-fat-cursor,.cm-fat-cursor-mark{-webkit-animation:blink 1.06s steps(1) infinite;-moz-animation:blink 1.06s steps(1) infinite;animation:blink 1.06s steps(1) infinite}.cm-fat-cursor-mark{background-color:rgba(20,255,20,.5)}.cm-animate-fat-cursor{width:auto;border:0;background-color:#7e7}.cm-tab{display:inline-block;text-decoration:inherit}.CodeMirror-rulers{position:absolute;left:0;right:0;top:-50px;bottom:0;overflow:hidden}.CodeMirror-ruler{border-left:1px solid #ccc;top:0;bottom:0;position:absolute}.cm-s-default .cm-header{color:#00f}.cm-s-default .cm-quote{color:#090}.cm-negative{color:#d44}.cm-positive{color:#292}.cm-header,.cm-strong{font-weight:700}.cm-em{font-style:italic}.cm-link{text-decoration:underline}.cm-strikethrough{text-decoration:line-through}.cm-s-default .cm-keyword{color:#708}.cm-s-default .cm-atom{color:#219}.cm-s-default .cm-number{color:#164}.cm-s-default .cm-def{color:#00f}.cm-s-default .cm-variable-2{color:#05a}.cm-s-default .cm-type,.cm-s-default .cm-variable-3{color:#085}.cm-s-default .cm-comment{color:#a50}.cm-s-default .cm-string{color:#a11}.cm-s-default .cm-string-2{color:#f50}.cm-s-default .cm-meta,.cm-s-default .cm-qualifier{color:#555}.cm-s-default .cm-builtin{color:#30a}.cm-s-default .cm-bracket{color:#997}.cm-s-default .cm-tag{color:#170}.cm-s-default .cm-attribute{color:#00c}.cm-s-default .cm-hr{color:#999}.cm-s-default .cm-link{color:#00c}.cm-invalidchar,.cm-s-default .cm-error{color:red}.CodeMirror-composing{border-bottom:2px solid}div.CodeMirror span.CodeMirror-matchingbracket{color:#0b0}div.CodeMirror span.CodeMirror-nonmatchingbracket{color:#a22}.CodeMirror-matchingtag{background:rgba(255,150,0,.3)}.CodeMirror-activeline-background{background:#e8f2ff}.CodeMirror{position:relative;overflow:hidden;background:#fff}.CodeMirror-scroll{overflow:scroll!important;margin-bottom:-50px;margin-right:-50px;padding-bottom:50px;height:100%;outline:0;position:relative}.CodeMirror-sizer{position:relative;border-right:50px solid transparent}.CodeMirror-gutter-filler,.CodeMirror-hscrollbar,.CodeMirror-scrollbar-filler,.CodeMirror-vscrollbar{position:absolute;z-index:6;display:none;outline:0}.CodeMirror-vscrollbar{right:0;top:0;overflow-x:hidden;overflow-y:scroll}.CodeMirror-hscrollbar{bottom:0;left:0;overflow-y:hidden;overflow-x:scroll}.CodeMirror-scrollbar-filler{right:0;bottom:0}.CodeMirror-gutter-filler{left:0;bottom:0}.CodeMirror-gutters{position:absolute;left:0;top:0;min-height:100%;z-index:3}.CodeMirror-gutter{white-space:normal;height:100%;display:inline-block;vertical-align:top;margin-bottom:-50px}.CodeMirror-gutter-wrapper{position:absolute;z-index:4;background:0 0!important;border:0!important}.CodeMirror-gutter-background{position:absolute;top:0;bottom:0;z-index:4}.CodeMirror-gutter-elt{position:absolute;cursor:default;z-index:4}.CodeMirror-gutter-wrapper ::selection{background-color:transparent}.CodeMirror-gutter-wrapper ::-moz-selection{background-color:transparent}.CodeMirror-lines{cursor:text;min-height:1px}.CodeMirror-wrap pre.CodeMirror-line,.CodeMirror-wrap pre.CodeMirror-line-like{word-wrap:break-word;white-space:pre-wrap;word-break:normal}.CodeMirror-linebackground{position:absolute;left:0;right:0;top:0;bottom:0;z-index:0}.CodeMirror-linewidget{position:relative;z-index:2;padding:.1px}.CodeMirror-rtl pre{direction:rtl}.CodeMirror-code{outline:0}.CodeMirror-gutter,.CodeMirror-gutters,.CodeMirror-linenumber,.CodeMirror-scroll,.CodeMirror-sizer{-moz-box-sizing:content-box;box-sizing:content-box}.CodeMirror-measure{position:absolute;width:100%;height:0;overflow:hidden;visibility:hidden}.CodeMirror-cursor{position:absolute;pointer-events:none}.CodeMirror-measure pre{position:static}div.CodeMirror-cursors{visibility:hidden;position:relative;z-index:3}.CodeMirror-focused div.CodeMirror-cursors,div.CodeMirror-dragcursors{visibility:visible}.CodeMirror-selected{background:#d9d9d9}.CodeMirror-focused .CodeMirror-selected{background:#d7d4f0}.CodeMirror-crosshair{cursor:crosshair}.CodeMirror-line::selection,.CodeMirror-line>span::selection,.CodeMirror-line>span>span::selection{background:#d7d4f0}.CodeMirror-line::-moz-selection,.CodeMirror-line>span::-moz-selection,.CodeMirror-line>span>span::-moz-selection{background:#d7d4f0}.cm-searching{background-color:#ffa;background-color:rgba(255,255,0,.4)}.cm-force-border{padding-right:.1px}@media print{.CodeMirror div.CodeMirror-cursors{visibility:hidden}}.cm-tab-wrap-hack:after{content:''}#yui3-css-stamp.skin-sam-widget-base,.yui3-widget-hidden{display:none}.yui3-widget-content{overflow:hidden}.yui3-widget-content-expanded{-moz-box-sizing:border-box;-webkit-box-sizing:border-box;-ms-box-sizing:border-box;box-sizing:border-box;height:100%}.yui3-widget-tmp-forcesize{overflow:hidden!important}.yui3-button{display:inline-block;*display:inline;zoom:1;font-size:100%;*font-size:90%;*overflow:visible;padding:.4em 1em .45em;line-height:normal;white-space:nowrap;vertical-align:baseline;text-align:center;cursor:pointer;-webkit-user-drag:none;-webkit-user-select:none;-moz-user-select:none;user-select:none;*color:#444;border:transparent;background-color:#e6e6e6;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#80ffffff',endColorstr='#00ffffff',GradientType=0);background-image:-webkit-gradient(linear,0 0,0 100%,from(rgba(255,255,255,.3)),color-stop(40%,rgba(255,255,255,.15)),to(transparent));background-image:-webkit-linear-gradient(rgba(255,255,255,.3),rgba(255,255,255,.15) 40%,transparent);background-image:-moz-linear-gradient(top,rgba(255,255,255,.3),rgba(255,255,255,.15) 40%,transparent);background-image:-ms-linear-gradient(rgba(255,255,255,.3),rgba(255,255,255,.15) 40%,transparent);background-image:-o-linear-gradient(rgba(255,255,255,.3),rgba(255,255,255,.15) 40%,transparent);background-image:linear-gradient(rgba(255,255,255,.3),rgba(255,255,255,.15) 40%,transparent);-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;-webkit-box-shadow:0 0 0 1px rgba(0,0,0,.25) inset,0 2px 0 rgba(255,255,255,.3) inset,0 1px 2px rgba(0,0,0,.15);-moz-box-shadow:0 0 0 1px rgba(0,0,0,.25) inset,0 2px 0 rgba(255,255,255,.3) inset,0 1px 2px rgba(0,0,0,.15);box-shadow:0 0 0 1px rgba(0,0,0,.25) inset,0 2px 0 rgba(255,255,255,.3) inset,0 1px 2px rgba(0,0,0,.15);-webkit-transition:.1s linear -webkit-box-shadow;-moz-transition:.1s linear -moz-box-shadow;-ms-transition:.1s linear box-shadow;-o-transition:.1s linear box-shadow;transition:.1s linear box-shadow}.yui3-button,a.yui3-button{color:rgba(0,0,0,.8);color:#444;text-decoration:none}.yui3-button-hover,.yui3-button:hover{filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#00000000',endColorstr='#26000000',GradientType=0);background-image:-webkit-gradient(linear,0 0,0 100%,from(transparent),color-stop(40%,rgba(0,0,0,.05)),to(rgba(0,0,0,.15)));background-image:-webkit-linear-gradient(transparent,rgba(0,0,0,.05) 40%,rgba(0,0,0,.15));background-image:-moz-linear-gradient(top,transparent,rgba(0,0,0,.05) 40%,rgba(0,0,0,.15));background-image:-ms-linear-gradient(transparent,rgba(0,0,0,.05) 40%,rgba(0,0,0,.15));background-image:-o-linear-gradient(transparent,rgba(0,0,0,.05) 40%,rgba(0,0,0,.15));background-image:linear-gradient(transparent,rgba(0,0,0,.05) 40%,rgba(0,0,0,.15))}.yui3-button-active,.yui3-button:active{border:transparent;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#1A000000',endColorstr='#26000000',GradientType=0);background-image:-webkit-gradient(linear,0 0,0 100%,from(rgba(0,0,0,.1)),to(rgba(0,0,0,.15)));background-image:-webkit-linear-gradient(rgba(0,0,0,.1),rgba(0,0,0,.15));background-image:-moz-linear-gradient(top,rgba(0,0,0,.1),rgba(0,0,0,.15));background-image:-ms-linear-gradient(rgba(0,0,0,.1),rgba(0,0,0,.15));background-image:-o-linear-gradient(rgba(0,0,0,.1),rgba(0,0,0,.15));background-image:linear-gradient(rgba(0,0,0,.1),rgba(0,0,0,.15));-webkit-box-shadow:0 0 0 1px rgba(0,0,0,.25) inset,0 2px 4px rgba(0,0,0,.3) inset;-moz-box-shadow:0 0 0 1px rgba(0,0,0,.25) inset,0 2px 4px rgba(0,0,0,.3) inset;box-shadow:0 0 0 1px rgba(0,0,0,.25) inset,0 2px 4px rgba(0,0,0,.3) inset}.yui3-button-disabled,.yui3-button-disabled:active,.yui3-button-disabled:hover,.yui3-button[disabled]{cursor:default;background-image:none;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);filter:alpha(opacity=55);-khtml-opacity:.55;-moz-opacity:.55;opacity:.55;-webkit-box-shadow:0 0 0 1px rgba(0,0,0,.25) inset;-moz-box-shadow:0 0 0 1px rgba(0,0,0,.25) inset;box-shadow:0 0 0 1px rgba(0,0,0,.25) inset}#yui3-css-stamp.cssbutton,.yui3-button-hidden{display:none}.yui3-button::-moz-focus-inner{padding:0;border:0}.yui3-button:-moz-focusring{outline:thin dotted}.yui3-skin-sam .yui3-button-primary,.yui3-skin-sam .yui3-button-selected{background-color:#345fcb;color:#fff;-webkit-box-shadow:0 0 0 1px rgba(0,0,0,.25) inset,0 2px 0 rgba(255,255,255,.17) inset,0 1px 2px rgba(0,0,0,.15);-moz-box-shadow:0 0 0 1px rgba(0,0,0,.25) inset,0 2px 0 rgba(255,255,255,.17) inset,0 1px 2px rgba(0,0,0,.15);box-shadow:0 0 0 1px rgba(0,0,0,.25) inset,0 2px 0 rgba(255,255,255,.17) inset,0 1px 2px rgba(0,0,0,.15)}.yui3-skin-sam .yui3-button:-moz-focusring{outline-color:rgba(0,0,0,.85)}.yui3-skin-night .yui3-button{border:0;background-color:#343536;color:#dcdcdc;-webkit-box-shadow:0 0 0 1px rgba(0,0,0,.25) inset,0 2px 0 rgba(255,255,255,.15) inset,0 1px 2px rgba(0,0,0,.15);-moz-box-shadow:0 0 0 1px rgba(0,0,0,.25) inset,0 2px 0 rgba(255,255,255,.15) inset,0 1px 2px rgba(0,0,0,.15);box-shadow:0 0 0 1px rgba(0,0,0,.25) inset,0 2px 0 rgba(255,255,255,.15) inset,0 1px 2px rgba(0,0,0,.15)}.yui3-skin-night .yui3-button-primary,.yui3-skin-night .yui3-button-selected{background-color:#747576;text-shadow:0 1px 2px rgba(0,0,0,.7)}.yui3-skin-night .yui3-button:-moz-focusring{outline-color:rgba(255,255,255,.85)}.atwho-view{position:absolute;top:0;left:0;display:none;margin-top:18px;background:#fff;color:#000;border:1px solid #ddd;border-radius:3px;box-shadow:0 0 5px rgba(0,0,0,.1);min-width:120px;z-index:11110!important}.atwho-view .atwho-header{padding:5px;margin:5px;cursor:pointer;border-bottom:solid 1px #eaeff1;color:#6f8092;font-size:11px;font-weight:700}.atwho-view .atwho-header .small{color:#6f8092;float:right;padding-top:2px;margin-right:-5px;font-size:12px;font-weight:400}.atwho-view .atwho-header:hover{cursor:default}.atwho-view .cur{background:#36f;color:#fff}.atwho-view .cur small{color:#fff}.atwho-view strong{color:#36f}.atwho-view .cur strong{color:#fff;font:700}.atwho-view ul{list-style:none;padding:0;margin:auto;max-height:200px;overflow-y:auto}.atwho-view ul li{display:block;padding:5px 10px;border-bottom:1px solid #ddd;cursor:pointer}.atwho-view small{font-size:smaller;color:#777;font-weight:400}@-moz-keyframes blink{50%{background-color:transparent}}@-webkit-keyframes blink{50%{background-color:transparent}}@keyframes blink{50%{background-color:transparent}}.atwho-view ul{overflow:hidden}.atwho-jrtext{padding-left:1em;color:gray}.cur>.atwho-jrtext{padding-left:1em;color:#fff}.dropdown-menu a>i{display:inline-block;width:16px}.checklist i.fa-check{display:none;width:auto}.checklist .selected i.fa-check{display:inline-block;margin-left:-14px;margin-right:2px}.dropdown-submenu,.fd-xpath-editor .fd-xpath-editor-content fieldset{position:relative}.dropdown-submenu>a:after{display:block;content:" ";float:right;width:0;height:0;border-color:transparent transparent transparent #ccc;border-style:solid;border-width:5px 0 5px 5px;margin-top:5px;margin-right:-10px}.dropdown-submenu>.dropdown-menu{top:0;left:100%;margin-top:-6px;margin-left:-1px;border-radius:0 6px 6px 6px}.dropdown-submenu:hover>.dropdown-menu{display:block}.dropdown-submenu:hover>a:after{border-left-color:#fff}.fd-input{-moz-appearance:textfield;-webkit-appearance:textfield;border:1px solid #ccc;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);-moz-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 linear .2s,box-shadow linear .2s;-moz-transition:border linear .2s,box-shadow linear .2s;-o-transition:border linear .2s,box-shadow linear .2s;transition:border linear .2s,box-shadow linear .2s;height:28px;padding:6px 12px;font-size:12px;background:#fff;vertical-align:middle;color:#555;white-space:nowrap;overflow:hidden}.fd-input:focus,.fd-textarea:focus{border-color:rgba(82,168,236,.8);outline:0;outline:thin dotted \9;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(82,168,236,.6);-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(82,168,236,.6);box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(82,168,236,.6)}.fd-input p,.fd-textarea p{margin:0}.fd-textarea{-webkit-appearance:textfield;border:1px solid #ccc;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);-moz-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 linear .2s,box-shadow linear .2s;-moz-transition:border linear .2s,box-shadow linear .2s;-o-transition:border linear .2s,box-shadow linear .2s;transition:border linear .2s,box-shadow linear .2s;padding:6px 12px;font-size:12px;background:#fff;vertical-align:middle;color:#555;-moz-appearance:textfield-multiline;min-height:4em;height:4.5em;overflow:auto;resize:both;white-space:normal;word-break:break-word}.fd-textarea.fd-xpath-editor-text{height:13em;font-family:monospace}.fd-search{background-color:#f2f2f1;margin-bottom:5px}.fd-search>.form-inline,.formdesigner .fd-ui-container .fd-external-sources-container .fd-external-resource-search>form{position:relative;padding:0 12px}.fd-search>.form-inline i,.formdesigner .fd-ui-container .fd-external-sources-container .fd-external-resource-search>form i{line-height:42px}.fd-search .control-label{padding-top:0}.fd-search .fd-search-control{position:absolute;top:5px;margin-left:18px;width:100%}.fd-commander{background-color:#f2f2f1;padding:5px}.fd-commander input{border:1px solid #d6d6d4;height:19px;width:calc(100% - 15px)}.fd-commander .fd-commander-close{background:0 0;border:0;color:#373534;position:absolute;top:8px;right:8px;cursor:pointer}.label-datanode{text-shadow:none;line-height:16px;padding:0 2px;margin:0 2px 2px;font-size:12px;border:1px solid;vertical-align:middle;font-weight:400}.label-datanode:hover{cursor:pointer;color:#fff}.label-datanode .close{color:#00799a;opacity:.4;font-weight:500;line-height:13px;font-size:18px;padding:0 5px 3px;margin-right:-3px}.label-datanode .close:hover{opacity:.9}.label-datanode .fcc{padding:0 3px;font-size:.8em}.label-datanode-internal{color:#00799a;border-color:#88d0d2;background-color:#d2edee}.label-datanode-internal .close{color:#00799a}.label-datanode-internal:hover{background-color:#1ea2a7;border-color:#1a8d92}.label-datanode-internal:hover .close{color:#d2edee}.label-datanode-external{color:#373534;border-color:#c1c1bc;background-color:#e6e6e4}.label-datanode-external .close{color:#373534}.label-datanode-external:hover{background-color:#685c53}.formdesigner .fd-ui-container .fd-content .fd-head .fd-head-max-indicator i,.label-datanode-external:hover .close{color:#d6d6d4}.label-datanode-external-unknown{color:#685300;border-color:#eed161;background-color:#f6e5a6}.label-datanode-external-unknown .close{color:#685300}.label-datanode-external-unknown:hover{background-color:#f9c700}.label-datanode-external-unknown:hover .close{color:#f8ecbd}.label-datanode-unknown{color:#812627;border-color:#c6948e;background-color:#e8d4d2}.label-datanode-unknown .close{color:#812627}.label-datanode-unknown:hover{background-color:#e53e30}.label-datanode-unknown:hover .close{color:#efcfcb}.datanode-tree-bubble{font-size:11px;color:#fff;line-height:18px;display:inline-block;padding:0 5px;border-radius:3px}.datanode-tree-bubble .fcc{font-size:9px}.datanode-tree-bubble-internal{color:#00799a;background-color:#ccf3f4}.datanode-tree-bubble-external{color:#373534;background-color:#f2f2f1}.datanode-tree-bubble-internal.on{background-color:#00bdc5;color:#fff}.datanode-tree-bubble-external.on{background-color:#685c53;color:#fff}.cke_widget_wrapper:hover>.label-datanode{outline:0!important;-webkit-box-shadow:0 0 8px #004ebc;-moz-box-shadow:0 0 8px #004ebc;box-shadow:0 0 8px #004ebc}.cke_widget_focused .label-datanode{outline:0!important;-webkit-box-shadow:0 0 8px #002c5f;-moz-box-shadow:0 0 8px #002c5f;box-shadow:0 0 8px #002c5f;border-color:#0073f8}.cke_widget_drag_handler_container{top:-2px!important;background:0 0!important}.cke_widget_drag_handler{width:100%!important;height:100%!important}.itext-block-container.has-markdown .markdown-group{display:block!important}.itext-block-container.has-markdown .fd-help,.itext-block-container.has-markdown .markdown-output:not(:empty),.itext-block-container.has-markdown .turn-markdown-off{display:inline-block!important}.itext-block-container.has-markdown .turn-markdown-on{display:none!important}.itext-block-container:not(.has-markdown) .markdown-group,.itext-block-container:not(.has-markdown) .markdown-output,.itext-block-container:not(.has-markdown) .turn-markdown-off{display:none!important}.itext-block-container:not(.has-markdown) .fd-help,.itext-block-container:not(.has-markdown) .turn-markdown-on{display:inline-block!important}.itext-block-container.markdown-ignorant .fd-help,.itext-block-container.markdown-ignorant .markdown-output,.itext-block-container.markdown-ignorant .turn-markdown-off,.itext-block-container.markdown-ignorant .turn-markdown-on{display:none!important}.markdown-output{width:100%;margin:0}.markdown-output table{padding:0}.markdown-output table tr{border-top:1px solid #ccc;background-color:#fff;margin:0;padding:0}.markdown-output table tr th{font-weight:700;border:1px solid #ccc;text-align:left;margin:0;padding:6px 13px}.markdown-output table tr td:first-child,.markdown-output table tr th:first-child{margin-top:0}.markdown-output table tr td:last-child,.markdown-output table tr th:last-child{margin-bottom:0}.markdown-output table tr td{border:1px solid #ccc;text-align:left;margin:0;padding:6px 13px}.markdown-output table tr:nth-child(2n){background-color:#f8f8f8}.fd-valid-alert-icon{color:#d83a2e}.fd-form-saving{position:fixed;top:0;bottom:0;left:0;right:0;opacity:.8;background-color:#000;z-index:2000}.fd-form-saving>div{opacity:1;position:fixed;top:calc(50% - 24px);left:calc(50% - 24px);-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;width:48px;height:48px;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;background-color:#fff;padding:8px}.fd-form-saving>div>div{width:32px;height:32px;background-image:url(images/ajax-loader.gif)}.fd-full-screen-modal .modal-dialog{position:fixed;left:0;right:0;top:0;bottom:0;margin:0;width:auto}.fd-full-screen-modal .modal-dialog .modal-content{position:absolute;top:20px;bottom:20px;left:20px;right:20px}.fd-full-screen-modal .modal-dialog .modal-content .modal-body{overflow-y:auto}.formdesigner .fd-ui-container .fd-mm-preview-container{text-align:center;width:115px;float:left}.formdesigner .fd-ui-container .fd-mm-preview-container .fd-mm-no-ref,.formdesigner .fd-ui-container .fd-mm-preview-container img{border:1px solid #eee}.formdesigner .fd-ui-container .fd-mm-preview-container img{padding:.5em;background-color:#fff;margin-bottom:10px}.formdesigner .fd-ui-container .fd-mm-preview-container .fd-mm-no-ref{color:#999;background-color:#fff;padding:10px}.formdesigner .fd-ui-container .fd-mm-preview-container .fd-mm-no-ref i{display:block;font-size:56px}.formdesigner .fd-ui-container .fd-mm-upload-container{margin-left:125px}.formdesigner .fd-ui-container .fd-mm-upload-container>.control-row{margin:0 0 10px}.formdesigner .fd-ui-container .fd-mm-upload-container>.control-row:first-child{height:25px}.formdesigner .fd-ui-container .fd-mm-upload-container .fd-mm-path-input{margin-right:92px}.rich-text-popover{-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px;word-wrap:break-word;min-width:236px;max-width:276px}.rich-text-popover .popover-title h3{font-weight:600;font-size:14px;margin:0}.rich-text-popover .popover-title .text-muted{margin-top:5px;line-height:1.3em}.rich-text-popover.bottom,.rich-text-popover.left,.rich-text-popover.right,.rich-text-popover.top{margin:0}.rich-text-popover.bottom{margin-top:5px}.rich-text-popover.top{margin-bottom:-10px}.rich-text-popover.right{margin-left:5px}.rich-text-popover .arrow,.rich-text-popover .arrow:after{display:none}.popover-content .alert{margin-bottom:0}.formdesigner .fd-ui-container .fd-props-toolbar{margin-bottom:5px;border-bottom:1px solid #f4f4f4;padding:12px}.formdesigner .fd-ui-container .fd-props-toolbar .fd-question-comment{margin-top:10px;white-space:pre-line}.formdesigner .fd-ui-container .fd-props-content{padding:0 12px}.formdesigner .fd-ui-container .fd-props-content .fd-help{width:25px;font-size:21px}.formdesigner .fd-ui-container .fd-props-content .fd-help a:hover{text-decoration:none;color:#46a546}.formdesigner .fd-ui-container .fd-props-content .fd-copy-paste-help .row{padding:0 2em;margin-bottom:2em}.formdesigner .fd-ui-container .fd-props-content .fd-copy-paste-help .copy-paste-box textarea{width:100%;height:100px}.formdesigner .fd-ui-container .fd-props-content .fd-question-fieldset{position:relative;min-width:0;display:table-column}.formdesigner .fd-ui-container .fd-props-content .fd-question-fieldset:first-child{margin-top:20px}.formdesigner .fd-ui-container .fd-props-content .fd-question-fieldset:first-child legend{display:none}.formdesigner .fd-ui-container .fd-props-content .fd-question-fieldset legend{min-height:30px}.formdesigner .fd-ui-container .fd-props-content .fd-question-fieldset legend .fd-help{right:0;top:0}.formdesigner .fd-ui-container .fd-props-content .fd-question-fieldset .fd-fieldset-content .control-label .fd-help{position:relative;top:-8px;height:15px;display:inline-block}.formdesigner .fd-ui-container .fd-props-content .fd-question-fieldset .fd-fieldset-content .control-label label{vertical-align:top}.formdesigner .fd-ui-container .fd-props-content .fd-question-fieldset .fd-fieldset-content .messages .alert{margin:10px 0 0}.formdesigner .fd-ui-container .fd-props-content .fd-question-fieldset .fd-fieldset-content .itext-block-container .btn-danger{margin:10px}.formdesigner .fd-ui-container .fd-props-content .fd-question-fieldset .fd-itextID-checkbox-container{width:55px;padding:0 5px;background-color:#f1f9f1;-webkit-border-radius:5px;-moz-border-radius:5px;border-radius:5px}.formdesigner .fd-ui-container .fd-props-content .fd-question-fieldset .fd-kv{margin-bottom:0}.formdesigner .fd-ui-container .fd-props-content .fd-question-fieldset .fd-kv .fd-kv-arrow{text-align:center}.formdesigner .fd-ui-container .fd-props-content .fd-question-fieldset .fd-kv .fd-kv-arrow i{margin-top:8px}body.vellum-full-screen{overflow-y:hidden}.formdesigner .fd-ui-container{top:0;width:100%;background-color:#fff}.formdesigner .fd-ui-container.full-screen{z-index:1031}.formdesigner .fd-ui-container .fd-content{float:left}.formdesigner .fd-ui-container .fd-content.fd-content-left{width:30%}.formdesigner .fd-ui-container .fd-content.fd-content-left .fd-add-question{width:100%;border-radius:0;text-align:left;border:0}.formdesigner .fd-ui-container .fd-content.fd-content-left .fd-accessory-pane{overflow-x:hidden;overflow-y:auto}.formdesigner .fd-ui-container .fd-content.fd-content-right .fd-head{height:31px}.formdesigner .fd-ui-container .fd-content.fd-content-right .fd-head h2{line-height:30px}.formdesigner .fd-ui-container .fd-content.fd-content-right .well{padding:10px}.formdesigner .fd-ui-container .fd-content.fd-content-right .well .col-sm-1{padding:0}.formdesigner .fd-ui-container .fd-content.fd-content-right .fd-form-actions{background-color:#004ebc!important;padding:5px 8px 8px}.formdesigner .fd-ui-container .fd-content .fd-default-panel{padding-left:12px}.formdesigner .fd-ui-container .fd-content .fd-head{color:#fff;background-color:#002c5f;font-size:17px;height:25px;position:relative}.formdesigner .fd-ui-container .fd-content .fd-head .fd-head-max-indicator{position:absolute;right:10px}.atwho-view .cur small,.formdesigner .fd-ui-container .fd-content .fd-head:hover .fd-head-max-indicator i{color:#fff}.formdesigner .fd-ui-container .fd-content .fd-head>h2{font-size:12.6px;padding:1px 12px 0;margin:0;font-weight:400;line-height:23px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;position:absolute;left:0;right:38px}.formdesigner .fd-ui-container .fd-content .fd-head .fd-head-menu-container{position:absolute;right:0;top:0;line-height:23px;font-size:12.6px;min-width:50px}.formdesigner .fd-ui-container .fd-content .fd-head .fd-head-menu-container .dropdown .dropdown-toggle{color:#fff;cursor:pointer;display:block;padding:0 12px;text-decoration:none;background-color:#002c5f}.formdesigner .fd-ui-container .fd-content .fd-head .fd-head-menu-container .dropdown .dropdown-toggle:hover{text-decoration:none;background-color:#004ebc}.formdesigner .fd-ui-container .fd-content .fd-head .fd-head-menu-container .dropdown .dropdown-menu a{min-width:170px}.formdesigner .fd-ui-container .fd-content .fd-head .fd-head-menu-container .dropdown .dropdown-menu a>.hotkey{float:right}.formdesigner .fd-ui-container .fd-content-vertical-divider{width:5px;background:#004ebc}.formdesigner .fd-ui-container .fd-content-horizontal-divider{height:5px;margin:1px 0;background:#f4f4f4;background-repeat:no-repeat;background-position:center center;background-image:url(images/ellipsis.png);background-size:auto 80%}.formdesigner .fd-ui-container .fd-messages{position:fixed;bottom:40px;left:0;width:100%}.formdesigner .fd-ui-container .fd-messages .alert{-webkit-box-shadow:0 0 10px rgba(0,0,0,.4);-moz-box-shadow:0 0 10px rgba(0,0,0,.4);box-shadow:0 0 10px rgba(0,0,0,.4);margin:20px;height:auto;overflow:auto;max-height:200px}.formdesigner .fd-ui-container .fd-scrollable,.formdesigner .fd-ui-container .fd-scrollable-minimal{overflow-x:hidden;overflow-y:auto;transform:translate3d(0,0,0)}.formdesigner .fd-ui-container .fd-scrollable{height:606px;width:100%}.formdesigner .fd-ui-container .fd-scrollable-minimal{max-height:606px}.formdesigner .fd-ui-container .jstree .jstree-node .jstree-anchor{color:#37475d;line-height:27px;height:26px}.formdesigner .fd-ui-container .jstree .jstree-node .jstree-anchor.jstree-clicked,.formdesigner .fd-ui-container .jstree .jstree-node .jstree-anchor.jstree-hovered{border:0;background:#eaeff5}.formdesigner .fd-ui-container .jstree .jstree-node .jstree-anchor.jstree-clicked{-webkit-box-shadow:0 0 4px rgba(21,87,162,.6);-moz-box-shadow:0 0 4px rgba(21,87,162,.6);box-shadow:0 0 4px rgba(21,87,162,.6)}.formdesigner .fd-ui-container .jstree .jstree-node .jstree-anchor>.jstree-icon{background:0 0;font-size:.85em;color:#004ebc}.formdesigner .fd-ui-container .jstree .jstree-node .add_choice:before{background:0 0;color:#004ebc;margin-right:6px;font:14px/1 FontAwesome}.formdesigner .fd-ui-container .jstree .jstree-node .add_choice{display:block;margin-left:50px;cursor:pointer;padding:0 5px;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;line-height:24px;height:24px}.formdesigner .fd-ui-container .jstree .jstree-node .add_choice:hover{border:0;background-color:#eaeff5;width:95px}.formdesigner .fd-ui-container .jstree .jstree-node.jstree-closed .add_choice{display:none}.formdesigner .fd-ui-container .jstree .jstree-node .fd-valid-alert-icon{margin-right:3px;margin-left:-3px}.formdesigner .fd-ui-container .fd-tree .fd-head{height:46px}.formdesigner .fd-ui-container .fd-tree .fd-head h2{line-height:46px;font-size:14px}.formdesigner .fd-ui-container .fd-tree .fd-head .fd-head-menu-container{line-height:46px}.formdesigner .fd-ui-container .fd-tree .fd-scrollable{overflow-x:auto}.formdesigner .fd-ui-container .fd-tree .fd-scrollable .jstree{margin:5px 0}.formdesigner .fd-ui-container .fd-tree .fd-undo-delete{margin-bottom:0}.formdesigner .fd-ui-container .fd-external-sources-container .fd-head.fd-head-external-sources{cursor:pointer}.formdesigner .fd-ui-container .fd-external-sources-container .fd-head.fd-head-external-sources h2{font-size:12px}.formdesigner .fd-ui-container .fd-external-sources-container .fd-external-resource-search{background-color:#f2f2f1;margin-bottom:5px}.formdesigner .fd-ui-container .fd-external-sources-container .fd-external-resource-search .fd-search-control{position:absolute;top:5px;margin-left:18px;width:100%}.formdesigner .fd-ui-container .fd-external-sources-container .fd-external-sources-tree .jstree-anchor{color:#373534}.formdesigner .fd-ui-container .fd-external-sources-container .fd-external-sources-tree .jstree-anchor.jstree-clicked{background-color:#f2f2f1;-webkit-box-shadow:0 0 4px rgba(104,92,83,.8);-moz-box-shadow:0 0 4px rgba(104,92,83,.8);box-shadow:0 0 4px rgba(104,92,83,.8)}.formdesigner .fd-ui-container .fd-external-sources-container .fd-external-sources-tree .jstree-anchor>.jstree-icon{color:#685c53}.formdesigner .fd-ui-container .fd-undo-delete p{margin-top:1em}#jstree-dnd{max-width:300px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.clearfix,.fd-xpath-editor .fd-xpath-editor-content fieldset legend{*zoom:1}.clearfix:after,.clearfix:before,.fd-xpath-editor .fd-xpath-editor-content fieldset legend:after,.fd-xpath-editor .fd-xpath-editor-content fieldset legend:before{display:table;content:"";line-height:0}.clearfix:after,.fd-xpath-editor .fd-xpath-editor-content fieldset legend:after{clear:both}.hide-text{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.input-block-level{display:block;width:100%;min-height:30px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.fd-xpath-editor .fd-xpath-editor-content{padding:20px}.fd-xpath-editor .fd-xpath-editor-content fieldset legend button{margin-bottom:5px}.fd-xpath-editor .fd-xpath-editor-content fieldset .fd-xpath-editor-expressions .xpath-expression-group:last-child{margin-bottom:0}.fd-xpath-editor .fd-xpath-editor-content fieldset .fd-xpath-editor-expressions .xpath-expression-group .validation-results{display:inline-block;padding:5px 25px;margin-bottom:0}.jstree-children,.jstree-container-ul,.jstree-node{display:block;margin:0;padding:0;list-style-type:none;list-style-image:none}.jstree-anchor,.jstree-node{white-space:nowrap}.jstree-anchor{display:inline-block;padding:0 4px 0 1px;margin:0;vertical-align:top}.jstree-anchor:focus{outline:0}.jstree-anchor,.jstree-anchor:active,.jstree-anchor:hover,.jstree-anchor:link,.jstree-anchor:visited{text-decoration:none;color:inherit}.jstree-icon{display:inline-block;text-decoration:none;margin:0;padding:0;vertical-align:top;text-align:center}.jstree-icon:empty{display:inline-block;text-decoration:none;margin:0;padding:0;vertical-align:top;text-align:center}.jstree-ocl{cursor:pointer}.jstree-leaf>.jstree-ocl{cursor:default}.jstree .jstree-open>.jstree-children{display:block}.jstree-anchor>.jstree-themeicon{margin-right:2px}.jstree .jstree-closed>.jstree-children,.jstree .jstree-leaf>.jstree-children,.jstree-anchor>.jstree-themeicon-hidden,.jstree-hidden,.jstree-no-icons .jstree-themeicon,.jstree-node.jstree-hidden{display:none}.jstree-rtl .jstree-anchor{padding:0 1px 0 4px}.jstree-rtl .jstree-anchor>.jstree-themeicon{margin-left:2px;margin-right:0}.jstree-rtl .jstree-node{margin-left:0}.jstree-rtl .jstree-container-ul>.jstree-node{margin-right:0}.jstree-wholerow-ul{position:relative;display:inline-block;min-width:100%}.jstree-wholerow-ul .jstree-leaf>.jstree-ocl{cursor:pointer}.jstree-wholerow-ul .jstree-anchor,.jstree-wholerow-ul .jstree-icon{position:relative}.jstree-wholerow-ul .jstree-wholerow{width:100%;cursor:pointer;position:absolute;left:0;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.jstree-contextmenu .jstree-anchor{-webkit-user-select:none;-webkit-touch-callout:none}.jstree-default .jstree-no-icons .jstree-anchor>.jstree-themeicon,.vakata-context{display:none}.vakata-context,.vakata-context ul{margin:0;padding:2px;position:absolute;background:#f5f5f5;border:1px solid #979797;box-shadow:2px 2px 2px #999}.vakata-context ul{list-style:none;left:100%;margin:-2.7em 0 0 -4px}.vakata-context .vakata-context-right ul,.vakata-context-rtl ul{left:auto;right:100%;margin-left:auto;margin-right:-4px}.vakata-context li{list-style:none}.vakata-context li>a{display:block;padding:0 2em;text-decoration:none;width:auto;color:#000;white-space:nowrap;line-height:2.4em;text-shadow:1px 1px 0 #fff;border-radius:1px}.vakata-context .vakata-context-hover>a,.vakata-context li>a:hover{position:relative;background-color:#e8eff7;box-shadow:0 0 2px #0a6aa1}.vakata-context li>a.vakata-context-parent{background-image:url(data:image/gif;base64,R0lGODlhCwAHAIAAACgoKP///yH5BAEAAAEALAAAAAALAAcAAAIORI4JlrqN1oMSnmmZDQUAOw==);background-position:right center;background-repeat:no-repeat}.vakata-context li>a:focus{outline:0}.vakata-context .vakata-context-separator>a,.vakata-context .vakata-context-separator>a:hover{background:#fff;border:0;border-top:1px solid #e2e3e3;height:1px;min-height:1px;max-height:1px;padding:0;margin:0 0 0 2.4em;border-left:1px solid #e0e0e0;text-shadow:0 0 0 transparent;box-shadow:0 0 0 transparent;border-radius:0}.vakata-context .vakata-contextmenu-disabled a,.vakata-context .vakata-contextmenu-disabled a:hover{color:silver;background-color:transparent;border:0;box-shadow:0 0 0}.vakata-context .vakata-contextmenu-disabled>a>i{filter:grayscale(100%)}.vakata-context li>a>i{text-decoration:none;display:inline-block;width:2.4em;height:2.4em;background:0 0;margin:0 0 0 -2em;vertical-align:top;text-align:center;line-height:2.4em}.vakata-context li>a>i:empty{width:2.4em;line-height:2.4em}.vakata-context li>a .vakata-contextmenu-sep{display:inline-block;width:1px;height:2.4em;background:#fff;margin:0 .5em 0 0;border-left:1px solid #e2e3e3}.vakata-context .vakata-contextmenu-shortcut{font-size:.8em;color:silver;opacity:.5;display:none}.vakata-context-rtl li>a.vakata-context-parent{background-image:url(data:image/gif;base64,R0lGODlhCwAHAIAAACgoKP///yH5BAEAAAEALAAAAAALAAcAAAINjI+AC7rWHIsPtmoxLAA7);background-position:left center;background-repeat:no-repeat}.vakata-context-rtl .vakata-context-separator>a{margin:0 2.4em 0 0;border-left:0;border-right:1px solid #e2e3e3}.vakata-context-rtl .vakata-context-left ul{right:auto;left:100%;margin-left:-4px;margin-right:auto}.vakata-context-rtl li>a>i{margin:0 -2em 0 0}.vakata-context-rtl li>a .vakata-contextmenu-sep{margin:0 0 0 .5em;border-left-color:#fff;background:#e2e3e3}#jstree-marker{position:absolute;top:0;left:0;margin:-5px 0 0;padding:0;border-right:0;border-top:5px solid transparent;border-bottom:5px solid transparent;border-left:5px solid;width:0;height:0;font-size:0;line-height:0}#jstree-dnd{line-height:16px;margin:0;padding:4px}#jstree-dnd .jstree-icon{margin:0 2px 0 0}#jstree-dnd .jstree-copy,#jstree-dnd .jstree-icon{display:inline-block;text-decoration:none;padding:0;width:16px;height:16px}#jstree-dnd .jstree-ok{background:green}#jstree-dnd .jstree-er{background:red}#jstree-dnd .jstree-copy{margin:0 2px}.jstree-default .jstree-node{background-color:transparent}.jstree-default .jstree-icon{background-repeat:no-repeat;background-color:transparent}.jstree-default .jstree-anchor,.jstree-default .jstree-animated,.jstree-default .jstree-wholerow{transition:background-color .15s,box-shadow .15s}.jstree-default .jstree-context,.jstree-default .jstree-hovered{background:#e7f4f9;border-radius:2px;box-shadow:inset 0 0 1px #ccc}.jstree-default .jstree-clicked{background:#beebff;border-radius:2px;box-shadow:inset 0 0 1px #999}.jstree-default .jstree-disabled{color:#666}.jstree-default .jstree-disabled.jstree-hovered{box-shadow:none}.jstree-default .jstree-disabled>.jstree-icon{opacity:.8;filter:gray;-webkit-filter:grayscale(100%)}.jstree-default .jstree-search{font-style:italic;color:#8b0000;font-weight:700}.jstree-default .jstree-no-checkboxes .jstree-checkbox{display:none!important}.jstree-default.jstree-checkbox-no-clicked .jstree-clicked{background:0 0;box-shadow:none}.jstree-default.jstree-checkbox-no-clicked .jstree-clicked.jstree-hovered,.jstree-default.jstree-checkbox-no-clicked>.jstree-wholerow-ul .jstree-wholerow-clicked.jstree-wholerow-hovered{background:#e7f4f9}.jstree-default.jstree-checkbox-no-clicked>.jstree-wholerow-ul .jstree-wholerow-clicked{background:0 0}.jstree-default>.jstree-striped{min-width:100%;display:inline-block;background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAAkCAMAAAB/qqA+AAAABlBMVEUAAAAAAAClZ7nPAAAAAnRSTlMNAMM9s3UAAAAXSURBVHjajcEBAQAAAIKg/H/aCQZ70AUBjAATb6YPDgAAAABJRU5ErkJggg==) left top}.jstree-default>.jstree-wholerow-ul .jstree-clicked,.jstree-default>.jstree-wholerow-ul .jstree-hovered{background:0 0;box-shadow:none;border-radius:0}.jstree-default .jstree-wholerow{-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box}.jstree-default .jstree-wholerow-hovered{background:#e7f4f9}.jstree-default .jstree-wholerow-clicked{background:#beebff;background:-webkit-linear-gradient(top,#beebff 0,#a8e4ff 100%);background:linear-gradient(to bottom,#beebff 0,#a8e4ff 100%)}.jstree-default .jstree-node{min-height:24px;line-height:24px;margin-left:24px;min-width:24px}.jstree-default .jstree-anchor{line-height:24px;height:24px}.jstree-default .jstree-icon{width:24px;height:24px;line-height:24px}.jstree-default .jstree-icon:empty{width:24px;height:24px;line-height:24px}.jstree-default.jstree-rtl .jstree-node{margin-right:24px}.jstree-default .jstree-wholerow{height:24px}#jstree-dnd.jstree-default .jstree-er,#jstree-dnd.jstree-default .jstree-ok,.jstree-default .jstree-icon,.jstree-default .jstree-node{background-image:url(src/../node_modules/jstree/dist/themes/default/32px.png)}.jstree-default .jstree-node{background-position:-292px -4px;background-repeat:repeat-y}.jstree-default .jstree-last{background:0 0}.jstree-default .jstree-open>.jstree-ocl{background-position:-132px -4px}.jstree-default .jstree-closed>.jstree-ocl{background-position:-100px -4px}.jstree-default .jstree-leaf>.jstree-ocl{background-position:-68px -4px}.jstree-default .jstree-themeicon{background-position:-260px -4px}.jstree-default .jstree-disabled,.jstree-default .jstree-disabled.jstree-hovered,.jstree-default>.jstree-no-dots .jstree-leaf>.jstree-ocl,.jstree-default>.jstree-no-dots .jstree-node{background:0 0}.jstree-default>.jstree-no-dots .jstree-open>.jstree-ocl{background-position:-36px -4px}.jstree-default>.jstree-no-dots .jstree-closed>.jstree-ocl{background-position:-4px -4px}.jstree-default .jstree-disabled.jstree-clicked{background:#efefef}.jstree-default .jstree-checkbox{background-position:-164px -4px}.jstree-default .jstree-checkbox:hover{background-position:-164px -36px}.jstree-default .jstree-checked>.jstree-checkbox,.jstree-default.jstree-checkbox-selection .jstree-clicked>.jstree-checkbox{background-position:-228px -4px}.jstree-default .jstree-checked>.jstree-checkbox:hover,.jstree-default.jstree-checkbox-selection .jstree-clicked>.jstree-checkbox:hover{background-position:-228px -36px}.jstree-default .jstree-anchor>.jstree-undetermined{background-position:-196px -4px}.jstree-default .jstree-anchor>.jstree-undetermined:hover{background-position:-196px -36px}.jstree-default .jstree-checkbox-disabled{opacity:.8;filter:gray;-webkit-filter:grayscale(100%)}.jstree-default>.jstree-striped{background-size:auto 48px}.jstree-default.jstree-rtl .jstree-node{background-position:100% 1px;background-repeat:repeat-y}.jstree-default.jstree-rtl .jstree-open>.jstree-ocl{background-position:-132px -36px}.jstree-default.jstree-rtl .jstree-closed>.jstree-ocl{background-position:-100px -36px}.jstree-default.jstree-rtl .jstree-leaf>.jstree-ocl{background-position:-68px -36px}.jstree-default.jstree-rtl>.jstree-no-dots .jstree-leaf>.jstree-ocl,.jstree-default.jstree-rtl>.jstree-no-dots .jstree-node{background:0 0}.jstree-default.jstree-rtl>.jstree-no-dots .jstree-open>.jstree-ocl{background-position:-36px -36px}.jstree-default.jstree-rtl>.jstree-no-dots .jstree-closed>.jstree-ocl{background-position:-4px -36px}.jstree-default .jstree-themeicon-custom{background-color:transparent;background-image:none;background-position:0 0}.jstree-default>.jstree-container-ul .jstree-loading>.jstree-ocl{background:url(src/../node_modules/jstree/dist/themes/default/throbber.gif) center center no-repeat}.jstree-default .jstree-file{background:url(src/../node_modules/jstree/dist/themes/default/32px.png) -100px -68px no-repeat}.jstree-default .jstree-folder{background:url(src/../node_modules/jstree/dist/themes/default/32px.png) -260px -4px no-repeat}.jstree-default>.jstree-container-ul>.jstree-node{margin-left:0;margin-right:0}#jstree-dnd.jstree-default{line-height:24px;padding:0 4px}#jstree-dnd.jstree-default .jstree-er,#jstree-dnd.jstree-default .jstree-ok{background-repeat:no-repeat;background-color:transparent}#jstree-dnd.jstree-default i{background:0 0;width:24px;height:24px;line-height:24px}#jstree-dnd.jstree-default .jstree-ok{background-position:-4px -68px}#jstree-dnd.jstree-default .jstree-er{background-position:-36px -68px}.jstree-default .jstree-ellipsis{overflow:hidden}.jstree-default .jstree-ellipsis .jstree-anchor{width:calc(100% - 29px);text-overflow:ellipsis;overflow:hidden}.jstree-default.jstree-rtl .jstree-node{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAACAQMAAAB49I5GAAAABlBMVEUAAAAdHRvEkCwcAAAAAXRSTlMAQObYZgAAAAxJREFUCNdjAAMOBgAAGAAJMwQHdQAAAABJRU5ErkJggg==)}.jstree-default.jstree-rtl .jstree-last{background:0 0}.jstree-default-small .jstree-node{min-height:18px;line-height:18px;margin-left:18px;min-width:18px}.jstree-default-small .jstree-anchor{line-height:18px;height:18px}.jstree-default-small .jstree-icon{width:18px;height:18px;line-height:18px}.jstree-default-small .jstree-icon:empty{width:18px;height:18px;line-height:18px}.jstree-default-small.jstree-rtl .jstree-node{margin-right:18px}.jstree-default-small .jstree-wholerow{height:18px}.jstree-default-small .jstree-icon,.jstree-default-small .jstree-node{background-image:url(src/../node_modules/jstree/dist/themes/default/32px.png)}.jstree-default-small .jstree-node{background-position:-295px -7px;background-repeat:repeat-y}.jstree-default-small .jstree-last{background:0 0}.jstree-default-small .jstree-open>.jstree-ocl{background-position:-135px -7px}.jstree-default-small .jstree-closed>.jstree-ocl{background-position:-103px -7px}.jstree-default-small .jstree-leaf>.jstree-ocl{background-position:-71px -7px}.jstree-default-small .jstree-themeicon{background-position:-263px -7px}.jstree-default-small .jstree-disabled,.jstree-default-small .jstree-disabled.jstree-hovered,.jstree-default-small>.jstree-no-dots .jstree-leaf>.jstree-ocl,.jstree-default-small>.jstree-no-dots .jstree-node{background:0 0}.jstree-default-small>.jstree-no-dots .jstree-open>.jstree-ocl{background-position:-39px -7px}.jstree-default-small>.jstree-no-dots .jstree-closed>.jstree-ocl{background-position:-7px -7px}.jstree-default-small .jstree-disabled.jstree-clicked{background:#efefef}.jstree-default-small .jstree-checkbox{background-position:-167px -7px}.jstree-default-small .jstree-checkbox:hover{background-position:-167px -39px}.jstree-default-small .jstree-checked>.jstree-checkbox,.jstree-default-small.jstree-checkbox-selection .jstree-clicked>.jstree-checkbox{background-position:-231px -7px}.jstree-default-small .jstree-checked>.jstree-checkbox:hover,.jstree-default-small.jstree-checkbox-selection .jstree-clicked>.jstree-checkbox:hover{background-position:-231px -39px}.jstree-default-small .jstree-anchor>.jstree-undetermined{background-position:-199px -7px}.jstree-default-small .jstree-anchor>.jstree-undetermined:hover{background-position:-199px -39px}.jstree-default-small .jstree-checkbox-disabled{opacity:.8;filter:gray;-webkit-filter:grayscale(100%)}.jstree-default-small>.jstree-striped{background-size:auto 36px}.jstree-default-small.jstree-rtl .jstree-node{background-position:100% 1px;background-repeat:repeat-y}.jstree-default-small.jstree-rtl .jstree-open>.jstree-ocl{background-position:-135px -39px}.jstree-default-small.jstree-rtl .jstree-closed>.jstree-ocl{background-position:-103px -39px}.jstree-default-small.jstree-rtl .jstree-leaf>.jstree-ocl{background-position:-71px -39px}.jstree-default-small.jstree-rtl>.jstree-no-dots .jstree-leaf>.jstree-ocl,.jstree-default-small.jstree-rtl>.jstree-no-dots .jstree-node{background:0 0}.jstree-default-small.jstree-rtl>.jstree-no-dots .jstree-open>.jstree-ocl{background-position:-39px -39px}.jstree-default-small.jstree-rtl>.jstree-no-dots .jstree-closed>.jstree-ocl{background-position:-7px -39px}.jstree-default-small .jstree-themeicon-custom{background-color:transparent;background-image:none;background-position:0 0}.jstree-default-small>.jstree-container-ul .jstree-loading>.jstree-ocl{background:url(src/../node_modules/jstree/dist/themes/default/throbber.gif) center center no-repeat}.jstree-default-small .jstree-file{background:url(src/../node_modules/jstree/dist/themes/default/32px.png) -103px -71px no-repeat}.jstree-default-small .jstree-folder{background:url(src/../node_modules/jstree/dist/themes/default/32px.png) -263px -7px no-repeat}.jstree-default-small>.jstree-container-ul>.jstree-node{margin-left:0;margin-right:0}#jstree-dnd.jstree-default-small{line-height:18px;padding:0 4px}#jstree-dnd.jstree-default-small .jstree-er,#jstree-dnd.jstree-default-small .jstree-ok{background-image:url(src/../node_modules/jstree/dist/themes/default/32px.png);background-repeat:no-repeat;background-color:transparent}#jstree-dnd.jstree-default-small i{background:0 0;width:18px;height:18px;line-height:18px}#jstree-dnd.jstree-default-small .jstree-ok{background-position:-7px -71px}#jstree-dnd.jstree-default-small .jstree-er{background-position:-39px -71px}.jstree-default-small .jstree-ellipsis{overflow:hidden}.jstree-default-small .jstree-ellipsis .jstree-anchor{width:calc(100% - 23px);text-overflow:ellipsis;overflow:hidden}.jstree-default-small.jstree-rtl .jstree-node{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABIAAAACAQMAAABv1h6PAAAABlBMVEUAAAAdHRvEkCwcAAAAAXRSTlMAQObYZgAAAAxJREFUCNdjAAMHBgAAiABBI4gz9AAAAABJRU5ErkJggg==)}.jstree-default-small.jstree-rtl .jstree-last{background:0 0}.jstree-default-large .jstree-node{min-height:32px;line-height:32px;margin-left:32px;min-width:32px}.jstree-default-large .jstree-anchor{line-height:32px;height:32px}.jstree-default-large .jstree-icon{width:32px;height:32px;line-height:32px}.jstree-default-large .jstree-icon:empty{width:32px;height:32px;line-height:32px}.jstree-default-large.jstree-rtl .jstree-node{margin-right:32px}.jstree-default-large .jstree-wholerow{height:32px}.jstree-default-large .jstree-icon,.jstree-default-large .jstree-node{background-image:url(src/../node_modules/jstree/dist/themes/default/32px.png)}.jstree-default-large .jstree-node{background-position:-288px 0;background-repeat:repeat-y}.jstree-default-large .jstree-last{background:0 0}.jstree-default-large .jstree-open>.jstree-ocl{background-position:-128px 0}.jstree-default-large .jstree-closed>.jstree-ocl{background-position:-96px 0}.jstree-default-large .jstree-leaf>.jstree-ocl{background-position:-64px 0}.jstree-default-large .jstree-themeicon{background-position:-256px 0}.jstree-default-large .jstree-disabled,.jstree-default-large .jstree-disabled.jstree-hovered,.jstree-default-large>.jstree-no-dots .jstree-leaf>.jstree-ocl,.jstree-default-large>.jstree-no-dots .jstree-node{background:0 0}.jstree-default-large>.jstree-no-dots .jstree-open>.jstree-ocl{background-position:-32px 0}.jstree-default-large>.jstree-no-dots .jstree-closed>.jstree-ocl{background-position:0 0}.jstree-default-large .jstree-disabled.jstree-clicked{background:#efefef}.jstree-default-large .jstree-checkbox{background-position:-160px 0}.jstree-default-large .jstree-checkbox:hover{background-position:-160px -32px}.jstree-default-large .jstree-checked>.jstree-checkbox,.jstree-default-large.jstree-checkbox-selection .jstree-clicked>.jstree-checkbox{background-position:-224px 0}.jstree-default-large .jstree-checked>.jstree-checkbox:hover,.jstree-default-large.jstree-checkbox-selection .jstree-clicked>.jstree-checkbox:hover{background-position:-224px -32px}.jstree-default-large .jstree-anchor>.jstree-undetermined{background-position:-192px 0}.jstree-default-large .jstree-anchor>.jstree-undetermined:hover{background-position:-192px -32px}.jstree-default-large .jstree-checkbox-disabled{opacity:.8;filter:gray;-webkit-filter:grayscale(100%)}.jstree-default-large>.jstree-striped{background-size:auto 64px}.jstree-default-large.jstree-rtl .jstree-node{background-position:100% 1px;background-repeat:repeat-y}.jstree-default-large.jstree-rtl .jstree-open>.jstree-ocl{background-position:-128px -32px}.jstree-default-large.jstree-rtl .jstree-closed>.jstree-ocl{background-position:-96px -32px}.jstree-default-large.jstree-rtl .jstree-leaf>.jstree-ocl{background-position:-64px -32px}.jstree-default-large.jstree-rtl>.jstree-no-dots .jstree-leaf>.jstree-ocl,.jstree-default-large.jstree-rtl>.jstree-no-dots .jstree-node{background:0 0}.jstree-default-large.jstree-rtl>.jstree-no-dots .jstree-open>.jstree-ocl{background-position:-32px -32px}.jstree-default-large.jstree-rtl>.jstree-no-dots .jstree-closed>.jstree-ocl{background-position:0 -32px}.jstree-default-large .jstree-themeicon-custom{background-color:transparent;background-image:none;background-position:0 0}.jstree-default-large>.jstree-container-ul .jstree-loading>.jstree-ocl{background:url(src/../node_modules/jstree/dist/themes/default/throbber.gif) center center no-repeat}.jstree-default-large .jstree-file{background:url(src/../node_modules/jstree/dist/themes/default/32px.png) -96px -64px no-repeat}.jstree-default-large .jstree-folder{background:url(src/../node_modules/jstree/dist/themes/default/32px.png) -256px 0 no-repeat}.jstree-default-large>.jstree-container-ul>.jstree-node{margin-left:0;margin-right:0}#jstree-dnd.jstree-default-large{line-height:32px;padding:0 4px}#jstree-dnd.jstree-default-large .jstree-er,#jstree-dnd.jstree-default-large .jstree-ok{background-image:url(src/../node_modules/jstree/dist/themes/default/32px.png);background-repeat:no-repeat;background-color:transparent}#jstree-dnd.jstree-default-large i{background:0 0;width:32px;height:32px;line-height:32px}#jstree-dnd.jstree-default-large .jstree-ok{background-position:0 -64px}#jstree-dnd.jstree-default-large .jstree-er{background-position:-32px -64px}.jstree-default-large .jstree-ellipsis{overflow:hidden}.jstree-default-large .jstree-ellipsis .jstree-anchor{width:calc(100% - 37px);text-overflow:ellipsis;overflow:hidden}.jstree-default-large.jstree-rtl .jstree-node{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAACAQMAAAAD0EyKAAAABlBMVEUAAAAdHRvEkCwcAAAAAXRSTlMAQObYZgAAAAxJREFUCNdjgIIGBgABCgCBvVLXcAAAAABJRU5ErkJggg==)}.jstree-default-large.jstree-rtl .jstree-last,span.CodeMirror-selectedtext{background:0 0}@media (max-width:768px){#jstree-dnd.jstree-dnd-responsive{line-height:40px;font-weight:700;font-size:1.1em;text-shadow:1px 1px #fff}#jstree-dnd.jstree-dnd-responsive>i{background:0 0;width:40px;height:40px}#jstree-dnd.jstree-dnd-responsive>.jstree-er,#jstree-dnd.jstree-dnd-responsive>.jstree-ok{background-image:url(src/../node_modules/jstree/dist/themes/default/40px.png);background-position:0 -200px;background-size:120px 240px}#jstree-dnd.jstree-dnd-responsive>.jstree-er{background-position:-40px -200px}#jstree-marker.jstree-dnd-responsive{border-left-width:10px;border-top-width:10px;border-bottom-width:10px;margin-top:-10px}.jstree-default-responsive .jstree-node{background:0 0;min-height:40px;line-height:40px;margin-left:40px;min-width:40px;white-space:nowrap}.jstree-default-responsive .jstree-anchor{line-height:40px;height:40px}.jstree-default-responsive .jstree-icon,.jstree-default-responsive .jstree-icon:empty{width:40px;height:40px;line-height:40px}.jstree-default-responsive.jstree-rtl .jstree-node{margin-left:0;margin-right:40px;background:0 0}.jstree-default-responsive.jstree-rtl .jstree-container-ul>.jstree-node{margin-right:0}.jstree-default-responsive .jstree-ocl{background-size:120px 240px}.jstree-default-responsive .jstree-leaf>.jstree-ocl,.jstree-default-responsive.jstree-rtl .jstree-leaf>.jstree-ocl{background:0 0}.jstree-default-responsive .jstree-open>.jstree-ocl{background-position:0 0!important}.jstree-default-responsive .jstree-closed>.jstree-ocl{background-position:0 -40px!important}.jstree-default-responsive.jstree-rtl .jstree-closed>.jstree-ocl{background-position:-40px 0!important}.jstree-default-responsive .jstree-themeicon{background-position:-40px -40px}.jstree-default-responsive .jstree-checkbox,.jstree-default-responsive .jstree-checkbox:hover{background-position:-40px -80px}.jstree-default-responsive .jstree-checked>.jstree-checkbox,.jstree-default-responsive .jstree-checked>.jstree-checkbox:hover,.jstree-default-responsive.jstree-checkbox-selection .jstree-clicked>.jstree-checkbox,.jstree-default-responsive.jstree-checkbox-selection .jstree-clicked>.jstree-checkbox:hover{background-position:0 -80px}.jstree-default-responsive .jstree-anchor>.jstree-undetermined,.jstree-default-responsive .jstree-anchor>.jstree-undetermined:hover{background-position:0 -120px}.jstree-default-responsive .jstree-anchor{font-weight:700;font-size:1.1em;text-shadow:1px 1px #fff}.jstree-default-responsive>.jstree-striped{background:0 0}.jstree-default-responsive .jstree-wholerow{border-top:1px solid rgba(255,255,255,.7);border-bottom:1px solid rgba(64,64,64,.2);background:#ebebeb;height:40px}.jstree-default-responsive .jstree-wholerow-hovered{background:#e7f4f9}.jstree-default-responsive .jstree-wholerow-clicked{background:#beebff}.jstree-default-responsive .jstree-children .jstree-last>.jstree-wholerow{box-shadow:inset 0 -6px 3px -5px #666}.jstree-default-responsive .jstree-children .jstree-open>.jstree-wholerow{box-shadow:inset 0 6px 3px -5px #666;border-top:0}.jstree-default-responsive .jstree-children .jstree-open+.jstree-open{box-shadow:none}.jstree-default-responsive .jstree-checkbox,.jstree-default-responsive .jstree-icon,.jstree-default-responsive .jstree-node,.jstree-default-responsive .jstree-node>.jstree-ocl,.jstree-default-responsive .jstree-themeicon{background-image:url(src/../node_modules/jstree/dist/themes/default/40px.png);background-size:120px 240px}.jstree-default-responsive .jstree-node{background-position:-80px 0;background-repeat:repeat-y}.jstree-default-responsive .jstree-last{background:0 0}.jstree-default-responsive .jstree-leaf>.jstree-ocl{background-position:-40px -120px}.jstree-default-responsive .jstree-last>.jstree-ocl{background-position:-40px -160px}.jstree-default-responsive .jstree-themeicon-custom{background-color:transparent;background-image:none;background-position:0 0}.jstree-default-responsive .jstree-file{background:url(src/../node_modules/jstree/dist/themes/default/40px.png) 0 -160px no-repeat;background-size:120px 240px}.jstree-default-responsive .jstree-folder{background:url(src/../node_modules/jstree/dist/themes/default/40px.png) -40px -40px no-repeat;background-size:120px 240px}.jstree-default-responsive>.jstree-container-ul>.jstree-node{margin-left:0;margin-right:0}}.CodeMirror{font-family:monospace;height:300px;color:#000;direction:ltr}.CodeMirror-lines{padding:4px 0}.CodeMirror pre.CodeMirror-line,.CodeMirror pre.CodeMirror-line-like{padding:0 4px;-moz-border-radius:0;-webkit-border-radius:0;border-radius:0;border-width:0;background:0 0;font-family:inherit;font-size:inherit;margin:0;white-space:pre;word-wrap:normal;line-height:inherit;color:inherit;z-index:2;position:relative;overflow:visible;-webkit-tap-highlight-color:transparent;-webkit-font-variant-ligatures:contextual;font-variant-ligatures:contextual}.CodeMirror-gutter-filler,.CodeMirror-scrollbar-filler{background-color:#fff}.CodeMirror-gutters{border-right:1px solid #ddd;background-color:#f7f7f7;white-space:nowrap}.CodeMirror-linenumber{padding:0 3px 0 5px;min-width:20px;text-align:right;color:#999;white-space:nowrap}.CodeMirror-guttermarker{color:#000}.CodeMirror-guttermarker-subtle{color:#999}.CodeMirror-cursor{border-left:1px solid #000;border-right:none;width:0}.CodeMirror div.CodeMirror-secondarycursor{border-left:1px solid silver}.cm-fat-cursor .CodeMirror-cursor{width:auto;border:0!important;background:#7e7}.cm-fat-cursor div.CodeMirror-cursors{z-index:1}.cm-animate-fat-cursor,.cm-fat-cursor-mark{-webkit-animation:blink 1.06s steps(1) infinite;-moz-animation:blink 1.06s steps(1) infinite;animation:blink 1.06s steps(1) infinite}.cm-fat-cursor-mark{background-color:rgba(20,255,20,.5)}.cm-animate-fat-cursor{width:auto;border:0;background-color:#7e7}.cm-tab{display:inline-block;text-decoration:inherit}.CodeMirror-rulers{position:absolute;left:0;right:0;top:-50px;bottom:0;overflow:hidden}.CodeMirror-ruler{border-left:1px solid #ccc;top:0;bottom:0;position:absolute}.cm-s-default .cm-header{color:#00f}.cm-s-default .cm-quote{color:#090}.cm-negative{color:#d44}.cm-positive{color:#292}.cm-header,.cm-strong{font-weight:700}.cm-em{font-style:italic}.cm-link{text-decoration:underline}.cm-strikethrough{text-decoration:line-through}.cm-s-default .cm-keyword{color:#708}.cm-s-default .cm-atom{color:#219}.cm-s-default .cm-number{color:#164}.cm-s-default .cm-def{color:#00f}.cm-s-default .cm-variable-2{color:#05a}.cm-s-default .cm-type,.cm-s-default .cm-variable-3{color:#085}.cm-s-default .cm-comment{color:#a50}.cm-s-default .cm-string{color:#a11}.cm-s-default .cm-string-2{color:#f50}.cm-s-default .cm-meta,.cm-s-default .cm-qualifier{color:#555}.cm-s-default .cm-builtin{color:#30a}.cm-s-default .cm-bracket{color:#997}.cm-s-default .cm-tag{color:#170}.cm-s-default .cm-attribute{color:#00c}.cm-s-default .cm-hr{color:#999}.cm-s-default .cm-link{color:#00c}.cm-invalidchar,.cm-s-default .cm-error{color:red}.CodeMirror-composing{border-bottom:2px solid}div.CodeMirror span.CodeMirror-matchingbracket{color:#0b0}div.CodeMirror span.CodeMirror-nonmatchingbracket{color:#a22}.CodeMirror-matchingtag{background:rgba(255,150,0,.3)}.CodeMirror-activeline-background{background:#e8f2ff}.CodeMirror{position:relative;overflow:hidden;background:#fff}.CodeMirror-scroll{overflow:scroll!important;margin-bottom:-50px;margin-right:-50px;padding-bottom:50px;height:100%;outline:0;position:relative}.CodeMirror-sizer{position:relative;border-right:50px solid transparent}.CodeMirror-gutter-filler,.CodeMirror-hscrollbar,.CodeMirror-scrollbar-filler,.CodeMirror-vscrollbar{position:absolute;z-index:6;display:none;outline:0}.CodeMirror-vscrollbar{right:0;top:0;overflow-x:hidden;overflow-y:scroll}.CodeMirror-hscrollbar{bottom:0;left:0;overflow-y:hidden;overflow-x:scroll}.CodeMirror-scrollbar-filler{right:0;bottom:0}.CodeMirror-gutter-filler{left:0;bottom:0}.CodeMirror-gutters{position:absolute;left:0;top:0;min-height:100%;z-index:3}.CodeMirror-gutter{white-space:normal;height:100%;display:inline-block;vertical-align:top;margin-bottom:-50px}.CodeMirror-gutter-wrapper{position:absolute;z-index:4;background:0 0!important;border:0!important}.CodeMirror-gutter-background{position:absolute;top:0;bottom:0;z-index:4}.CodeMirror-gutter-elt{position:absolute;cursor:default;z-index:4}.CodeMirror-gutter-wrapper ::selection{background-color:transparent}.CodeMirror-gutter-wrapper ::-moz-selection{background-color:transparent}.CodeMirror-lines{cursor:text;min-height:1px}.CodeMirror-wrap pre.CodeMirror-line,.CodeMirror-wrap pre.CodeMirror-line-like{word-wrap:break-word;white-space:pre-wrap;word-break:normal}.CodeMirror-linebackground{position:absolute;left:0;right:0;top:0;bottom:0;z-index:0}.CodeMirror-linewidget{position:relative;z-index:2;padding:.1px}.CodeMirror-rtl pre{direction:rtl}.CodeMirror-code{outline:0}.CodeMirror-gutter,.CodeMirror-gutters,.CodeMirror-linenumber,.CodeMirror-scroll,.CodeMirror-sizer{-moz-box-sizing:content-box;box-sizing:content-box}.CodeMirror-measure{position:absolute;width:100%;height:0;overflow:hidden;visibility:hidden}.CodeMirror-cursor{position:absolute;pointer-events:none}.CodeMirror-measure pre{position:static}div.CodeMirror-cursors{visibility:hidden;position:relative;z-index:3}.CodeMirror-focused div.CodeMirror-cursors,div.CodeMirror-dragcursors{visibility:visible}.CodeMirror-selected{background:#d9d9d9}.CodeMirror-focused .CodeMirror-selected{background:#d7d4f0}.CodeMirror-crosshair{cursor:crosshair}.CodeMirror-line::selection,.CodeMirror-line>span::selection,.CodeMirror-line>span>span::selection{background:#d7d4f0}.CodeMirror-line::-moz-selection,.CodeMirror-line>span::-moz-selection,.CodeMirror-line>span>span::-moz-selection{background:#d7d4f0}.cm-searching{background-color:#ffa;background-color:rgba(255,255,0,.4)}.cm-force-border{padding-right:.1px}@media print{.CodeMirror div.CodeMirror-cursors{visibility:hidden}}.cm-tab-wrap-hack:after{content:''}#yui3-css-stamp.skin-sam-widget-base,.yui3-widget-hidden{display:none}.yui3-widget-content{overflow:hidden}.yui3-widget-content-expanded{-moz-box-sizing:border-box;-webkit-box-sizing:border-box;-ms-box-sizing:border-box;box-sizing:border-box;height:100%}.yui3-widget-tmp-forcesize{overflow:hidden!important}.yui3-button{display:inline-block;*display:inline;zoom:1;font-size:100%;*font-size:90%;*overflow:visible;padding:.4em 1em .45em;line-height:normal;white-space:nowrap;vertical-align:baseline;text-align:center;cursor:pointer;-webkit-user-drag:none;-webkit-user-select:none;-moz-user-select:none;user-select:none;*color:#444;border:transparent;background-color:#e6e6e6;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#80ffffff',endColorstr='#00ffffff',GradientType=0);background-image:-webkit-gradient(linear,0 0,0 100%,from(rgba(255,255,255,.3)),color-stop(40%,rgba(255,255,255,.15)),to(transparent));background-image:-webkit-linear-gradient(rgba(255,255,255,.3),rgba(255,255,255,.15) 40%,transparent);background-image:-moz-linear-gradient(top,rgba(255,255,255,.3),rgba(255,255,255,.15) 40%,transparent);background-image:-ms-linear-gradient(rgba(255,255,255,.3),rgba(255,255,255,.15) 40%,transparent);background-image:-o-linear-gradient(rgba(255,255,255,.3),rgba(255,255,255,.15) 40%,transparent);background-image:linear-gradient(rgba(255,255,255,.3),rgba(255,255,255,.15) 40%,transparent);-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;-webkit-box-shadow:0 0 0 1px rgba(0,0,0,.25) inset,0 2px 0 rgba(255,255,255,.3) inset,0 1px 2px rgba(0,0,0,.15);-moz-box-shadow:0 0 0 1px rgba(0,0,0,.25) inset,0 2px 0 rgba(255,255,255,.3) inset,0 1px 2px rgba(0,0,0,.15);box-shadow:0 0 0 1px rgba(0,0,0,.25) inset,0 2px 0 rgba(255,255,255,.3) inset,0 1px 2px rgba(0,0,0,.15);-webkit-transition:.1s linear -webkit-box-shadow;-moz-transition:.1s linear -moz-box-shadow;-ms-transition:.1s linear box-shadow;-o-transition:.1s linear box-shadow;transition:.1s linear box-shadow}.yui3-button,a.yui3-button{color:rgba(0,0,0,.8);color:#444;text-decoration:none}.yui3-button-hover,.yui3-button:hover{filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#00000000',endColorstr='#26000000',GradientType=0);background-image:-webkit-gradient(linear,0 0,0 100%,from(transparent),color-stop(40%,rgba(0,0,0,.05)),to(rgba(0,0,0,.15)));background-image:-webkit-linear-gradient(transparent,rgba(0,0,0,.05) 40%,rgba(0,0,0,.15));background-image:-moz-linear-gradient(top,transparent,rgba(0,0,0,.05) 40%,rgba(0,0,0,.15));background-image:-ms-linear-gradient(transparent,rgba(0,0,0,.05) 40%,rgba(0,0,0,.15));background-image:-o-linear-gradient(transparent,rgba(0,0,0,.05) 40%,rgba(0,0,0,.15));background-image:linear-gradient(transparent,rgba(0,0,0,.05) 40%,rgba(0,0,0,.15))}.yui3-button-active,.yui3-button:active{border:transparent;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#1A000000',endColorstr='#26000000',GradientType=0);background-image:-webkit-gradient(linear,0 0,0 100%,from(rgba(0,0,0,.1)),to(rgba(0,0,0,.15)));background-image:-webkit-linear-gradient(rgba(0,0,0,.1),rgba(0,0,0,.15));background-image:-moz-linear-gradient(top,rgba(0,0,0,.1),rgba(0,0,0,.15));background-image:-ms-linear-gradient(rgba(0,0,0,.1),rgba(0,0,0,.15));background-image:-o-linear-gradient(rgba(0,0,0,.1),rgba(0,0,0,.15));background-image:linear-gradient(rgba(0,0,0,.1),rgba(0,0,0,.15));-webkit-box-shadow:0 0 0 1px rgba(0,0,0,.25) inset,0 2px 4px rgba(0,0,0,.3) inset;-moz-box-shadow:0 0 0 1px rgba(0,0,0,.25) inset,0 2px 4px rgba(0,0,0,.3) inset;box-shadow:0 0 0 1px rgba(0,0,0,.25) inset,0 2px 4px rgba(0,0,0,.3) inset}.yui3-button-disabled,.yui3-button-disabled:active,.yui3-button-disabled:hover,.yui3-button[disabled]{cursor:default;background-image:none;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);filter:alpha(opacity=55);-khtml-opacity:.55;-moz-opacity:.55;opacity:.55;-webkit-box-shadow:0 0 0 1px rgba(0,0,0,.25) inset;-moz-box-shadow:0 0 0 1px rgba(0,0,0,.25) inset;box-shadow:0 0 0 1px rgba(0,0,0,.25) inset}#yui3-css-stamp.cssbutton,.yui3-button-hidden{display:none}.yui3-button::-moz-focus-inner{padding:0;border:0}.yui3-button:-moz-focusring{outline:thin dotted}.yui3-skin-sam .yui3-button-primary,.yui3-skin-sam .yui3-button-selected{background-color:#345fcb;color:#fff;-webkit-box-shadow:0 0 0 1px rgba(0,0,0,.25) inset,0 2px 0 rgba(255,255,255,.17) inset,0 1px 2px rgba(0,0,0,.15);-moz-box-shadow:0 0 0 1px rgba(0,0,0,.25) inset,0 2px 0 rgba(255,255,255,.17) inset,0 1px 2px rgba(0,0,0,.15);box-shadow:0 0 0 1px rgba(0,0,0,.25) inset,0 2px 0 rgba(255,255,255,.17) inset,0 1px 2px rgba(0,0,0,.15)}.yui3-skin-sam .yui3-button:-moz-focusring{outline-color:rgba(0,0,0,.85)}.yui3-skin-night .yui3-button{border:0;background-color:#343536;color:#dcdcdc;-webkit-box-shadow:0 0 0 1px rgba(0,0,0,.25) inset,0 2px 0 rgba(255,255,255,.15) inset,0 1px 2px rgba(0,0,0,.15);-moz-box-shadow:0 0 0 1px rgba(0,0,0,.25) inset,0 2px 0 rgba(255,255,255,.15) inset,0 1px 2px rgba(0,0,0,.15);box-shadow:0 0 0 1px rgba(0,0,0,.25) inset,0 2px 0 rgba(255,255,255,.15) inset,0 1px 2px rgba(0,0,0,.15)}.yui3-skin-night .yui3-button-primary,.yui3-skin-night .yui3-button-selected{background-color:#747576;text-shadow:0 1px 2px rgba(0,0,0,.7)}.yui3-skin-night .yui3-button:-moz-focusring{outline-color:rgba(255,255,255,.85)}.atwho-view{position:absolute;top:0;left:0;display:none;margin-top:18px;background:#fff;color:#000;border:1px solid #ddd;border-radius:3px;box-shadow:0 0 5px rgba(0,0,0,.1);min-width:120px;z-index:11110!important}.atwho-view .atwho-header{padding:5px;margin:5px;cursor:pointer;border-bottom:solid 1px #eaeff1;color:#6f8092;font-size:11px;font-weight:700}.atwho-view .atwho-header .small{color:#6f8092;float:right;padding-top:2px;margin-right:-5px;font-size:12px;font-weight:400}.atwho-view .atwho-header:hover{cursor:default}.atwho-view .cur{background:#36f;color:#fff}.atwho-view strong{color:#36f}.atwho-view .cur strong{color:#fff;font:700}.atwho-view ul{list-style:none;padding:0;margin:auto;max-height:200px;overflow-y:auto}.atwho-view ul li{display:block;padding:5px 10px;border-bottom:1px solid #ddd;cursor:pointer}.atwho-view small{font-size:smaller;color:#777;font-weight:400} \ No newline at end of file +@-moz-keyframes blink{50%{background-color:transparent}}@-webkit-keyframes blink{50%{background-color:transparent}}@keyframes blink{50%{background-color:transparent}}.jstree-children,.jstree-container-ul,.jstree-node{display:block;margin:0;padding:0;list-style-type:none;list-style-image:none}.jstree-anchor,.jstree-node{white-space:nowrap}.jstree-anchor{display:inline-block;padding:0 4px 0 1px;margin:0;vertical-align:top}.jstree-anchor:focus{outline:0}.jstree-anchor,.jstree-anchor:active,.jstree-anchor:hover,.jstree-anchor:link,.jstree-anchor:visited{text-decoration:none;color:inherit}.jstree-icon{display:inline-block;text-decoration:none;margin:0;padding:0;vertical-align:top;text-align:center}.jstree-icon:empty{display:inline-block;text-decoration:none;margin:0;padding:0;vertical-align:top;text-align:center}.jstree-ocl{cursor:pointer}.jstree-leaf>.jstree-ocl{cursor:default}.jstree .jstree-open>.jstree-children{display:block}.jstree-anchor>.jstree-themeicon{margin-right:2px}.jstree .jstree-closed>.jstree-children,.jstree .jstree-leaf>.jstree-children,.jstree-anchor>.jstree-themeicon-hidden,.jstree-hidden,.jstree-no-icons .jstree-themeicon,.jstree-node.jstree-hidden{display:none}.jstree-rtl .jstree-anchor{padding:0 1px 0 4px}.jstree-rtl .jstree-anchor>.jstree-themeicon{margin-left:2px;margin-right:0}.jstree-rtl .jstree-node{margin-left:0}.jstree-rtl .jstree-container-ul>.jstree-node{margin-right:0}.jstree-wholerow-ul{position:relative;display:inline-block;min-width:100%}.jstree-wholerow-ul .jstree-leaf>.jstree-ocl{cursor:pointer}.jstree-wholerow-ul .jstree-anchor,.jstree-wholerow-ul .jstree-icon{position:relative}.jstree-wholerow-ul .jstree-wholerow{width:100%;cursor:pointer;position:absolute;left:0;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.jstree-contextmenu .jstree-anchor{-webkit-user-select:none;-webkit-touch-callout:none}.jstree-default .jstree-no-icons .jstree-anchor>.jstree-themeicon,.vakata-context{display:none}.vakata-context,.vakata-context ul{margin:0;padding:2px;position:absolute;background:#f5f5f5;border:1px solid #979797;box-shadow:2px 2px 2px #999}.vakata-context ul{list-style:none;left:100%;margin:-2.7em 0 0 -4px}.vakata-context .vakata-context-right ul,.vakata-context-rtl ul{left:auto;right:100%;margin-left:auto;margin-right:-4px}.vakata-context li{list-style:none}.vakata-context li>a{display:block;padding:0 2em;text-decoration:none;width:auto;color:#000;white-space:nowrap;line-height:2.4em;text-shadow:1px 1px 0 #fff;border-radius:1px}.vakata-context .vakata-context-hover>a,.vakata-context li>a:hover{position:relative;background-color:#e8eff7;box-shadow:0 0 2px #0a6aa1}.vakata-context li>a.vakata-context-parent{background-image:url(data:image/gif;base64,R0lGODlhCwAHAIAAACgoKP///yH5BAEAAAEALAAAAAALAAcAAAIORI4JlrqN1oMSnmmZDQUAOw==);background-position:right center;background-repeat:no-repeat}.vakata-context li>a:focus{outline:0}.vakata-context .vakata-context-separator>a,.vakata-context .vakata-context-separator>a:hover{background:#fff;border:0;border-top:1px solid #e2e3e3;height:1px;min-height:1px;max-height:1px;padding:0;margin:0 0 0 2.4em;border-left:1px solid #e0e0e0;text-shadow:0 0 0 transparent;box-shadow:0 0 0 transparent;border-radius:0}.vakata-context .vakata-contextmenu-disabled a,.vakata-context .vakata-contextmenu-disabled a:hover{color:silver;background-color:transparent;border:0;box-shadow:0 0 0}.vakata-context .vakata-contextmenu-disabled>a>i{filter:grayscale(100%)}.vakata-context li>a>i{text-decoration:none;display:inline-block;width:2.4em;height:2.4em;background:0 0;margin:0 0 0 -2em;vertical-align:top;text-align:center;line-height:2.4em}.vakata-context li>a>i:empty{width:2.4em;line-height:2.4em}.vakata-context li>a .vakata-contextmenu-sep{display:inline-block;width:1px;height:2.4em;background:#fff;margin:0 .5em 0 0;border-left:1px solid #e2e3e3}.vakata-context .vakata-contextmenu-shortcut{font-size:.8em;color:silver;opacity:.5;display:none}.vakata-context-rtl li>a.vakata-context-parent{background-image:url(data:image/gif;base64,R0lGODlhCwAHAIAAACgoKP///yH5BAEAAAEALAAAAAALAAcAAAINjI+AC7rWHIsPtmoxLAA7);background-position:left center;background-repeat:no-repeat}.vakata-context-rtl .vakata-context-separator>a{margin:0 2.4em 0 0;border-left:0;border-right:1px solid #e2e3e3}.vakata-context-rtl .vakata-context-left ul{right:auto;left:100%;margin-left:-4px;margin-right:auto}.vakata-context-rtl li>a>i{margin:0 -2em 0 0}.vakata-context-rtl li>a .vakata-contextmenu-sep{margin:0 0 0 .5em;border-left-color:#fff;background:#e2e3e3}#jstree-marker{position:absolute;top:0;left:0;margin:-5px 0 0;padding:0;border-right:0;border-top:5px solid transparent;border-bottom:5px solid transparent;border-left:5px solid;width:0;height:0;font-size:0;line-height:0}#jstree-dnd{line-height:16px;margin:0;padding:4px}#jstree-dnd .jstree-icon{margin:0 2px 0 0}#jstree-dnd .jstree-copy,#jstree-dnd .jstree-icon{display:inline-block;text-decoration:none;padding:0;width:16px;height:16px}#jstree-dnd .jstree-ok{background:green}#jstree-dnd .jstree-er{background:red}#jstree-dnd .jstree-copy{margin:0 2px}.jstree-default .jstree-node{background-color:transparent}.jstree-default .jstree-icon{background-repeat:no-repeat;background-color:transparent}.jstree-default .jstree-anchor,.jstree-default .jstree-animated,.jstree-default .jstree-wholerow{transition:background-color .15s,box-shadow .15s}.jstree-default .jstree-context,.jstree-default .jstree-hovered{background:#e7f4f9;border-radius:2px;box-shadow:inset 0 0 1px #ccc}.jstree-default .jstree-clicked{background:#beebff;border-radius:2px;box-shadow:inset 0 0 1px #999}.jstree-default .jstree-disabled{color:#666}.jstree-default .jstree-disabled.jstree-hovered{box-shadow:none}.jstree-default .jstree-disabled>.jstree-icon{opacity:.8;filter:gray;-webkit-filter:grayscale(100%)}.jstree-default .jstree-search{font-style:italic;color:#8b0000;font-weight:700}.jstree-default .jstree-no-checkboxes .jstree-checkbox{display:none!important}.jstree-default.jstree-checkbox-no-clicked .jstree-clicked{background:0 0;box-shadow:none}.jstree-default.jstree-checkbox-no-clicked .jstree-clicked.jstree-hovered,.jstree-default.jstree-checkbox-no-clicked>.jstree-wholerow-ul .jstree-wholerow-clicked.jstree-wholerow-hovered{background:#e7f4f9}.jstree-default.jstree-checkbox-no-clicked>.jstree-wholerow-ul .jstree-wholerow-clicked{background:0 0}.jstree-default>.jstree-striped{min-width:100%;display:inline-block;background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAAkCAMAAAB/qqA+AAAABlBMVEUAAAAAAAClZ7nPAAAAAnRSTlMNAMM9s3UAAAAXSURBVHjajcEBAQAAAIKg/H/aCQZ70AUBjAATb6YPDgAAAABJRU5ErkJggg==) left top}.jstree-default>.jstree-wholerow-ul .jstree-clicked,.jstree-default>.jstree-wholerow-ul .jstree-hovered{background:0 0;box-shadow:none;border-radius:0}.jstree-default .jstree-wholerow{-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box}.jstree-default .jstree-wholerow-hovered{background:#e7f4f9}.jstree-default .jstree-wholerow-clicked{background:#beebff;background:-webkit-linear-gradient(top,#beebff 0,#a8e4ff 100%);background:linear-gradient(to bottom,#beebff 0,#a8e4ff 100%)}.jstree-default .jstree-node{min-height:24px;line-height:24px;margin-left:24px;min-width:24px}.jstree-default .jstree-anchor{line-height:24px;height:24px}.jstree-default .jstree-icon{width:24px;height:24px;line-height:24px}.jstree-default .jstree-icon:empty{width:24px;height:24px;line-height:24px}.jstree-default.jstree-rtl .jstree-node{margin-right:24px}.jstree-default .jstree-wholerow{height:24px}#jstree-dnd.jstree-default .jstree-er,#jstree-dnd.jstree-default .jstree-ok,.jstree-default .jstree-icon,.jstree-default .jstree-node{background-image:url(src/../node_modules/jstree/dist/themes/default/32px.png)}.jstree-default .jstree-node{background-position:-292px -4px;background-repeat:repeat-y}.jstree-default .jstree-last{background:0 0}.jstree-default .jstree-open>.jstree-ocl{background-position:-132px -4px}.jstree-default .jstree-closed>.jstree-ocl{background-position:-100px -4px}.jstree-default .jstree-leaf>.jstree-ocl{background-position:-68px -4px}.jstree-default .jstree-themeicon{background-position:-260px -4px}.jstree-default .jstree-disabled,.jstree-default .jstree-disabled.jstree-hovered,.jstree-default>.jstree-no-dots .jstree-leaf>.jstree-ocl,.jstree-default>.jstree-no-dots .jstree-node{background:0 0}.jstree-default>.jstree-no-dots .jstree-open>.jstree-ocl{background-position:-36px -4px}.jstree-default>.jstree-no-dots .jstree-closed>.jstree-ocl{background-position:-4px -4px}.jstree-default .jstree-disabled.jstree-clicked{background:#efefef}.jstree-default .jstree-checkbox{background-position:-164px -4px}.jstree-default .jstree-checkbox:hover{background-position:-164px -36px}.jstree-default .jstree-checked>.jstree-checkbox,.jstree-default.jstree-checkbox-selection .jstree-clicked>.jstree-checkbox{background-position:-228px -4px}.jstree-default .jstree-checked>.jstree-checkbox:hover,.jstree-default.jstree-checkbox-selection .jstree-clicked>.jstree-checkbox:hover{background-position:-228px -36px}.jstree-default .jstree-anchor>.jstree-undetermined{background-position:-196px -4px}.jstree-default .jstree-anchor>.jstree-undetermined:hover{background-position:-196px -36px}.jstree-default .jstree-checkbox-disabled{opacity:.8;filter:gray;-webkit-filter:grayscale(100%)}.jstree-default>.jstree-striped{background-size:auto 48px}.jstree-default.jstree-rtl .jstree-node{background-position:100% 1px;background-repeat:repeat-y}.jstree-default.jstree-rtl .jstree-open>.jstree-ocl{background-position:-132px -36px}.jstree-default.jstree-rtl .jstree-closed>.jstree-ocl{background-position:-100px -36px}.jstree-default.jstree-rtl .jstree-leaf>.jstree-ocl{background-position:-68px -36px}.jstree-default.jstree-rtl>.jstree-no-dots .jstree-leaf>.jstree-ocl,.jstree-default.jstree-rtl>.jstree-no-dots .jstree-node{background:0 0}.jstree-default.jstree-rtl>.jstree-no-dots .jstree-open>.jstree-ocl{background-position:-36px -36px}.jstree-default.jstree-rtl>.jstree-no-dots .jstree-closed>.jstree-ocl{background-position:-4px -36px}.jstree-default .jstree-themeicon-custom{background-color:transparent;background-image:none;background-position:0 0}.jstree-default>.jstree-container-ul .jstree-loading>.jstree-ocl{background:url(src/../node_modules/jstree/dist/themes/default/throbber.gif) center center no-repeat}.jstree-default .jstree-file{background:url(src/../node_modules/jstree/dist/themes/default/32px.png) -100px -68px no-repeat}.jstree-default .jstree-folder{background:url(src/../node_modules/jstree/dist/themes/default/32px.png) -260px -4px no-repeat}.jstree-default>.jstree-container-ul>.jstree-node{margin-left:0;margin-right:0}#jstree-dnd.jstree-default{line-height:24px;padding:0 4px}#jstree-dnd.jstree-default .jstree-er,#jstree-dnd.jstree-default .jstree-ok{background-repeat:no-repeat;background-color:transparent}#jstree-dnd.jstree-default i{background:0 0;width:24px;height:24px;line-height:24px}#jstree-dnd.jstree-default .jstree-ok{background-position:-4px -68px}#jstree-dnd.jstree-default .jstree-er{background-position:-36px -68px}.jstree-default .jstree-ellipsis{overflow:hidden}.jstree-default .jstree-ellipsis .jstree-anchor{width:calc(100% - 29px);text-overflow:ellipsis;overflow:hidden}.jstree-default.jstree-rtl .jstree-node{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAACAQMAAAB49I5GAAAABlBMVEUAAAAdHRvEkCwcAAAAAXRSTlMAQObYZgAAAAxJREFUCNdjAAMOBgAAGAAJMwQHdQAAAABJRU5ErkJggg==)}.jstree-default.jstree-rtl .jstree-last{background:0 0}.jstree-default-small .jstree-node{min-height:18px;line-height:18px;margin-left:18px;min-width:18px}.jstree-default-small .jstree-anchor{line-height:18px;height:18px}.jstree-default-small .jstree-icon{width:18px;height:18px;line-height:18px}.jstree-default-small .jstree-icon:empty{width:18px;height:18px;line-height:18px}.jstree-default-small.jstree-rtl .jstree-node{margin-right:18px}.jstree-default-small .jstree-wholerow{height:18px}.jstree-default-small .jstree-icon,.jstree-default-small .jstree-node{background-image:url(src/../node_modules/jstree/dist/themes/default/32px.png)}.jstree-default-small .jstree-node{background-position:-295px -7px;background-repeat:repeat-y}.jstree-default-small .jstree-last{background:0 0}.jstree-default-small .jstree-open>.jstree-ocl{background-position:-135px -7px}.jstree-default-small .jstree-closed>.jstree-ocl{background-position:-103px -7px}.jstree-default-small .jstree-leaf>.jstree-ocl{background-position:-71px -7px}.jstree-default-small .jstree-themeicon{background-position:-263px -7px}.jstree-default-small .jstree-disabled,.jstree-default-small .jstree-disabled.jstree-hovered,.jstree-default-small>.jstree-no-dots .jstree-leaf>.jstree-ocl,.jstree-default-small>.jstree-no-dots .jstree-node{background:0 0}.jstree-default-small>.jstree-no-dots .jstree-open>.jstree-ocl{background-position:-39px -7px}.jstree-default-small>.jstree-no-dots .jstree-closed>.jstree-ocl{background-position:-7px -7px}.jstree-default-small .jstree-disabled.jstree-clicked{background:#efefef}.jstree-default-small .jstree-checkbox{background-position:-167px -7px}.jstree-default-small .jstree-checkbox:hover{background-position:-167px -39px}.jstree-default-small .jstree-checked>.jstree-checkbox,.jstree-default-small.jstree-checkbox-selection .jstree-clicked>.jstree-checkbox{background-position:-231px -7px}.jstree-default-small .jstree-checked>.jstree-checkbox:hover,.jstree-default-small.jstree-checkbox-selection .jstree-clicked>.jstree-checkbox:hover{background-position:-231px -39px}.jstree-default-small .jstree-anchor>.jstree-undetermined{background-position:-199px -7px}.jstree-default-small .jstree-anchor>.jstree-undetermined:hover{background-position:-199px -39px}.jstree-default-small .jstree-checkbox-disabled{opacity:.8;filter:gray;-webkit-filter:grayscale(100%)}.jstree-default-small>.jstree-striped{background-size:auto 36px}.jstree-default-small.jstree-rtl .jstree-node{background-position:100% 1px;background-repeat:repeat-y}.jstree-default-small.jstree-rtl .jstree-open>.jstree-ocl{background-position:-135px -39px}.jstree-default-small.jstree-rtl .jstree-closed>.jstree-ocl{background-position:-103px -39px}.jstree-default-small.jstree-rtl .jstree-leaf>.jstree-ocl{background-position:-71px -39px}.jstree-default-small.jstree-rtl>.jstree-no-dots .jstree-leaf>.jstree-ocl,.jstree-default-small.jstree-rtl>.jstree-no-dots .jstree-node{background:0 0}.jstree-default-small.jstree-rtl>.jstree-no-dots .jstree-open>.jstree-ocl{background-position:-39px -39px}.jstree-default-small.jstree-rtl>.jstree-no-dots .jstree-closed>.jstree-ocl{background-position:-7px -39px}.jstree-default-small .jstree-themeicon-custom{background-color:transparent;background-image:none;background-position:0 0}.jstree-default-small>.jstree-container-ul .jstree-loading>.jstree-ocl{background:url(src/../node_modules/jstree/dist/themes/default/throbber.gif) center center no-repeat}.jstree-default-small .jstree-file{background:url(src/../node_modules/jstree/dist/themes/default/32px.png) -103px -71px no-repeat}.jstree-default-small .jstree-folder{background:url(src/../node_modules/jstree/dist/themes/default/32px.png) -263px -7px no-repeat}.jstree-default-small>.jstree-container-ul>.jstree-node{margin-left:0;margin-right:0}#jstree-dnd.jstree-default-small{line-height:18px;padding:0 4px}#jstree-dnd.jstree-default-small .jstree-er,#jstree-dnd.jstree-default-small .jstree-ok{background-image:url(src/../node_modules/jstree/dist/themes/default/32px.png);background-repeat:no-repeat;background-color:transparent}#jstree-dnd.jstree-default-small i{background:0 0;width:18px;height:18px;line-height:18px}#jstree-dnd.jstree-default-small .jstree-ok{background-position:-7px -71px}#jstree-dnd.jstree-default-small .jstree-er{background-position:-39px -71px}.jstree-default-small .jstree-ellipsis{overflow:hidden}.jstree-default-small .jstree-ellipsis .jstree-anchor{width:calc(100% - 23px);text-overflow:ellipsis;overflow:hidden}.jstree-default-small.jstree-rtl .jstree-node{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABIAAAACAQMAAABv1h6PAAAABlBMVEUAAAAdHRvEkCwcAAAAAXRSTlMAQObYZgAAAAxJREFUCNdjAAMHBgAAiABBI4gz9AAAAABJRU5ErkJggg==)}.jstree-default-small.jstree-rtl .jstree-last{background:0 0}.jstree-default-large .jstree-node{min-height:32px;line-height:32px;margin-left:32px;min-width:32px}.jstree-default-large .jstree-anchor{line-height:32px;height:32px}.jstree-default-large .jstree-icon{width:32px;height:32px;line-height:32px}.jstree-default-large .jstree-icon:empty{width:32px;height:32px;line-height:32px}.jstree-default-large.jstree-rtl .jstree-node{margin-right:32px}.jstree-default-large .jstree-wholerow{height:32px}.jstree-default-large .jstree-icon,.jstree-default-large .jstree-node{background-image:url(src/../node_modules/jstree/dist/themes/default/32px.png)}.jstree-default-large .jstree-node{background-position:-288px 0;background-repeat:repeat-y}.jstree-default-large .jstree-last{background:0 0}.jstree-default-large .jstree-open>.jstree-ocl{background-position:-128px 0}.jstree-default-large .jstree-closed>.jstree-ocl{background-position:-96px 0}.jstree-default-large .jstree-leaf>.jstree-ocl{background-position:-64px 0}.jstree-default-large .jstree-themeicon{background-position:-256px 0}.jstree-default-large .jstree-disabled,.jstree-default-large .jstree-disabled.jstree-hovered,.jstree-default-large>.jstree-no-dots .jstree-leaf>.jstree-ocl,.jstree-default-large>.jstree-no-dots .jstree-node{background:0 0}.jstree-default-large>.jstree-no-dots .jstree-open>.jstree-ocl{background-position:-32px 0}.jstree-default-large>.jstree-no-dots .jstree-closed>.jstree-ocl{background-position:0 0}.jstree-default-large .jstree-disabled.jstree-clicked{background:#efefef}.jstree-default-large .jstree-checkbox{background-position:-160px 0}.jstree-default-large .jstree-checkbox:hover{background-position:-160px -32px}.jstree-default-large .jstree-checked>.jstree-checkbox,.jstree-default-large.jstree-checkbox-selection .jstree-clicked>.jstree-checkbox{background-position:-224px 0}.jstree-default-large .jstree-checked>.jstree-checkbox:hover,.jstree-default-large.jstree-checkbox-selection .jstree-clicked>.jstree-checkbox:hover{background-position:-224px -32px}.jstree-default-large .jstree-anchor>.jstree-undetermined{background-position:-192px 0}.jstree-default-large .jstree-anchor>.jstree-undetermined:hover{background-position:-192px -32px}.jstree-default-large .jstree-checkbox-disabled{opacity:.8;filter:gray;-webkit-filter:grayscale(100%)}.jstree-default-large>.jstree-striped{background-size:auto 64px}.jstree-default-large.jstree-rtl .jstree-node{background-position:100% 1px;background-repeat:repeat-y}.jstree-default-large.jstree-rtl .jstree-open>.jstree-ocl{background-position:-128px -32px}.jstree-default-large.jstree-rtl .jstree-closed>.jstree-ocl{background-position:-96px -32px}.jstree-default-large.jstree-rtl .jstree-leaf>.jstree-ocl{background-position:-64px -32px}.jstree-default-large.jstree-rtl>.jstree-no-dots .jstree-leaf>.jstree-ocl,.jstree-default-large.jstree-rtl>.jstree-no-dots .jstree-node{background:0 0}.jstree-default-large.jstree-rtl>.jstree-no-dots .jstree-open>.jstree-ocl{background-position:-32px -32px}.jstree-default-large.jstree-rtl>.jstree-no-dots .jstree-closed>.jstree-ocl{background-position:0 -32px}.jstree-default-large .jstree-themeicon-custom{background-color:transparent;background-image:none;background-position:0 0}.jstree-default-large>.jstree-container-ul .jstree-loading>.jstree-ocl{background:url(src/../node_modules/jstree/dist/themes/default/throbber.gif) center center no-repeat}.jstree-default-large .jstree-file{background:url(src/../node_modules/jstree/dist/themes/default/32px.png) -96px -64px no-repeat}.jstree-default-large .jstree-folder{background:url(src/../node_modules/jstree/dist/themes/default/32px.png) -256px 0 no-repeat}.jstree-default-large>.jstree-container-ul>.jstree-node{margin-left:0;margin-right:0}#jstree-dnd.jstree-default-large{line-height:32px;padding:0 4px}#jstree-dnd.jstree-default-large .jstree-er,#jstree-dnd.jstree-default-large .jstree-ok{background-image:url(src/../node_modules/jstree/dist/themes/default/32px.png);background-repeat:no-repeat;background-color:transparent}#jstree-dnd.jstree-default-large i{background:0 0;width:32px;height:32px;line-height:32px}#jstree-dnd.jstree-default-large .jstree-ok{background-position:0 -64px}#jstree-dnd.jstree-default-large .jstree-er{background-position:-32px -64px}.jstree-default-large .jstree-ellipsis{overflow:hidden}.jstree-default-large .jstree-ellipsis .jstree-anchor{width:calc(100% - 37px);text-overflow:ellipsis;overflow:hidden}.jstree-default-large.jstree-rtl .jstree-node{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAACAQMAAAAD0EyKAAAABlBMVEUAAAAdHRvEkCwcAAAAAXRSTlMAQObYZgAAAAxJREFUCNdjgIIGBgABCgCBvVLXcAAAAABJRU5ErkJggg==)}.jstree-default-large.jstree-rtl .jstree-last,span.CodeMirror-selectedtext{background:0 0}@media (max-width:768px){#jstree-dnd.jstree-dnd-responsive{line-height:40px;font-weight:700;font-size:1.1em;text-shadow:1px 1px #fff}#jstree-dnd.jstree-dnd-responsive>i{background:0 0;width:40px;height:40px}#jstree-dnd.jstree-dnd-responsive>.jstree-er,#jstree-dnd.jstree-dnd-responsive>.jstree-ok{background-image:url(src/../node_modules/jstree/dist/themes/default/40px.png);background-position:0 -200px;background-size:120px 240px}#jstree-dnd.jstree-dnd-responsive>.jstree-er{background-position:-40px -200px}#jstree-marker.jstree-dnd-responsive{border-left-width:10px;border-top-width:10px;border-bottom-width:10px;margin-top:-10px}.jstree-default-responsive .jstree-node{background:0 0;min-height:40px;line-height:40px;margin-left:40px;min-width:40px;white-space:nowrap}.jstree-default-responsive .jstree-anchor{line-height:40px;height:40px}.jstree-default-responsive .jstree-icon,.jstree-default-responsive .jstree-icon:empty{width:40px;height:40px;line-height:40px}.jstree-default-responsive.jstree-rtl .jstree-node{margin-left:0;margin-right:40px;background:0 0}.jstree-default-responsive.jstree-rtl .jstree-container-ul>.jstree-node{margin-right:0}.jstree-default-responsive .jstree-ocl{background-size:120px 240px}.jstree-default-responsive .jstree-leaf>.jstree-ocl,.jstree-default-responsive.jstree-rtl .jstree-leaf>.jstree-ocl{background:0 0}.jstree-default-responsive .jstree-open>.jstree-ocl{background-position:0 0!important}.jstree-default-responsive .jstree-closed>.jstree-ocl{background-position:0 -40px!important}.jstree-default-responsive.jstree-rtl .jstree-closed>.jstree-ocl{background-position:-40px 0!important}.jstree-default-responsive .jstree-themeicon{background-position:-40px -40px}.jstree-default-responsive .jstree-checkbox,.jstree-default-responsive .jstree-checkbox:hover{background-position:-40px -80px}.jstree-default-responsive .jstree-checked>.jstree-checkbox,.jstree-default-responsive .jstree-checked>.jstree-checkbox:hover,.jstree-default-responsive.jstree-checkbox-selection .jstree-clicked>.jstree-checkbox,.jstree-default-responsive.jstree-checkbox-selection .jstree-clicked>.jstree-checkbox:hover{background-position:0 -80px}.jstree-default-responsive .jstree-anchor>.jstree-undetermined,.jstree-default-responsive .jstree-anchor>.jstree-undetermined:hover{background-position:0 -120px}.jstree-default-responsive .jstree-anchor{font-weight:700;font-size:1.1em;text-shadow:1px 1px #fff}.jstree-default-responsive>.jstree-striped{background:0 0}.jstree-default-responsive .jstree-wholerow{border-top:1px solid rgba(255,255,255,.7);border-bottom:1px solid rgba(64,64,64,.2);background:#ebebeb;height:40px}.jstree-default-responsive .jstree-wholerow-hovered{background:#e7f4f9}.jstree-default-responsive .jstree-wholerow-clicked{background:#beebff}.jstree-default-responsive .jstree-children .jstree-last>.jstree-wholerow{box-shadow:inset 0 -6px 3px -5px #666}.jstree-default-responsive .jstree-children .jstree-open>.jstree-wholerow{box-shadow:inset 0 6px 3px -5px #666;border-top:0}.jstree-default-responsive .jstree-children .jstree-open+.jstree-open{box-shadow:none}.jstree-default-responsive .jstree-checkbox,.jstree-default-responsive .jstree-icon,.jstree-default-responsive .jstree-node,.jstree-default-responsive .jstree-node>.jstree-ocl,.jstree-default-responsive .jstree-themeicon{background-image:url(src/../node_modules/jstree/dist/themes/default/40px.png);background-size:120px 240px}.jstree-default-responsive .jstree-node{background-position:-80px 0;background-repeat:repeat-y}.jstree-default-responsive .jstree-last{background:0 0}.jstree-default-responsive .jstree-leaf>.jstree-ocl{background-position:-40px -120px}.jstree-default-responsive .jstree-last>.jstree-ocl{background-position:-40px -160px}.jstree-default-responsive .jstree-themeicon-custom{background-color:transparent;background-image:none;background-position:0 0}.jstree-default-responsive .jstree-file{background:url(src/../node_modules/jstree/dist/themes/default/40px.png) 0 -160px no-repeat;background-size:120px 240px}.jstree-default-responsive .jstree-folder{background:url(src/../node_modules/jstree/dist/themes/default/40px.png) -40px -40px no-repeat;background-size:120px 240px}.jstree-default-responsive>.jstree-container-ul>.jstree-node{margin-left:0;margin-right:0}}.CodeMirror{font-family:monospace;height:300px;color:#000;direction:ltr}.CodeMirror-lines{padding:4px 0}.CodeMirror pre.CodeMirror-line,.CodeMirror pre.CodeMirror-line-like{padding:0 4px;-moz-border-radius:0;-webkit-border-radius:0;border-radius:0;border-width:0;background:0 0;font-family:inherit;font-size:inherit;margin:0;white-space:pre;word-wrap:normal;line-height:inherit;color:inherit;z-index:2;position:relative;overflow:visible;-webkit-tap-highlight-color:transparent;-webkit-font-variant-ligatures:contextual;font-variant-ligatures:contextual}.CodeMirror-gutter-filler,.CodeMirror-scrollbar-filler{background-color:#fff}.CodeMirror-gutters{border-right:1px solid #ddd;background-color:#f7f7f7;white-space:nowrap}.CodeMirror-linenumber{padding:0 3px 0 5px;min-width:20px;text-align:right;color:#999;white-space:nowrap}.CodeMirror-guttermarker{color:#000}.CodeMirror-guttermarker-subtle{color:#999}.CodeMirror-cursor{border-left:1px solid #000;border-right:none;width:0}.CodeMirror div.CodeMirror-secondarycursor{border-left:1px solid silver}.cm-fat-cursor .CodeMirror-cursor{width:auto;border:0!important;background:#7e7}.cm-fat-cursor div.CodeMirror-cursors{z-index:1}.cm-animate-fat-cursor,.cm-fat-cursor-mark{-webkit-animation:blink 1.06s steps(1) infinite;-moz-animation:blink 1.06s steps(1) infinite;animation:blink 1.06s steps(1) infinite}.cm-fat-cursor-mark{background-color:rgba(20,255,20,.5)}.cm-animate-fat-cursor{width:auto;border:0;background-color:#7e7}.cm-tab{display:inline-block;text-decoration:inherit}.CodeMirror-rulers{position:absolute;left:0;right:0;top:-50px;bottom:0;overflow:hidden}.CodeMirror-ruler{border-left:1px solid #ccc;top:0;bottom:0;position:absolute}.cm-s-default .cm-header{color:#00f}.cm-s-default .cm-quote{color:#090}.cm-negative{color:#d44}.cm-positive{color:#292}.cm-header,.cm-strong{font-weight:700}.cm-em{font-style:italic}.cm-link{text-decoration:underline}.cm-strikethrough{text-decoration:line-through}.cm-s-default .cm-keyword{color:#708}.cm-s-default .cm-atom{color:#219}.cm-s-default .cm-number{color:#164}.cm-s-default .cm-def{color:#00f}.cm-s-default .cm-variable-2{color:#05a}.cm-s-default .cm-type,.cm-s-default .cm-variable-3{color:#085}.cm-s-default .cm-comment{color:#a50}.cm-s-default .cm-string{color:#a11}.cm-s-default .cm-string-2{color:#f50}.cm-s-default .cm-meta,.cm-s-default .cm-qualifier{color:#555}.cm-s-default .cm-builtin{color:#30a}.cm-s-default .cm-bracket{color:#997}.cm-s-default .cm-tag{color:#170}.cm-s-default .cm-attribute{color:#00c}.cm-s-default .cm-hr{color:#999}.cm-s-default .cm-link{color:#00c}.cm-invalidchar,.cm-s-default .cm-error{color:red}.CodeMirror-composing{border-bottom:2px solid}div.CodeMirror span.CodeMirror-matchingbracket{color:#0b0}div.CodeMirror span.CodeMirror-nonmatchingbracket{color:#a22}.CodeMirror-matchingtag{background:rgba(255,150,0,.3)}.CodeMirror-activeline-background{background:#e8f2ff}.CodeMirror{position:relative;overflow:hidden;background:#fff}.CodeMirror-scroll{overflow:scroll!important;margin-bottom:-50px;margin-right:-50px;padding-bottom:50px;height:100%;outline:0;position:relative}.CodeMirror-sizer{position:relative;border-right:50px solid transparent}.CodeMirror-gutter-filler,.CodeMirror-hscrollbar,.CodeMirror-scrollbar-filler,.CodeMirror-vscrollbar{position:absolute;z-index:6;display:none;outline:0}.CodeMirror-vscrollbar{right:0;top:0;overflow-x:hidden;overflow-y:scroll}.CodeMirror-hscrollbar{bottom:0;left:0;overflow-y:hidden;overflow-x:scroll}.CodeMirror-scrollbar-filler{right:0;bottom:0}.CodeMirror-gutter-filler{left:0;bottom:0}.CodeMirror-gutters{position:absolute;left:0;top:0;min-height:100%;z-index:3}.CodeMirror-gutter{white-space:normal;height:100%;display:inline-block;vertical-align:top;margin-bottom:-50px}.CodeMirror-gutter-wrapper{position:absolute;z-index:4;background:0 0!important;border:0!important}.CodeMirror-gutter-background{position:absolute;top:0;bottom:0;z-index:4}.CodeMirror-gutter-elt{position:absolute;cursor:default;z-index:4}.CodeMirror-gutter-wrapper ::selection{background-color:transparent}.CodeMirror-gutter-wrapper ::-moz-selection{background-color:transparent}.CodeMirror-lines{cursor:text;min-height:1px}.CodeMirror-wrap pre.CodeMirror-line,.CodeMirror-wrap pre.CodeMirror-line-like{word-wrap:break-word;white-space:pre-wrap;word-break:normal}.CodeMirror-linebackground{position:absolute;left:0;right:0;top:0;bottom:0;z-index:0}.CodeMirror-linewidget{position:relative;z-index:2;padding:.1px}.CodeMirror-rtl pre{direction:rtl}.CodeMirror-code{outline:0}.CodeMirror-gutter,.CodeMirror-gutters,.CodeMirror-linenumber,.CodeMirror-scroll,.CodeMirror-sizer{-moz-box-sizing:content-box;box-sizing:content-box}.CodeMirror-measure{position:absolute;width:100%;height:0;overflow:hidden;visibility:hidden}.CodeMirror-cursor{position:absolute;pointer-events:none}.CodeMirror-measure pre{position:static}div.CodeMirror-cursors{visibility:hidden;position:relative;z-index:3}.CodeMirror-focused div.CodeMirror-cursors,div.CodeMirror-dragcursors{visibility:visible}.CodeMirror-selected{background:#d9d9d9}.CodeMirror-focused .CodeMirror-selected{background:#d7d4f0}.CodeMirror-crosshair{cursor:crosshair}.CodeMirror-line::selection,.CodeMirror-line>span::selection,.CodeMirror-line>span>span::selection{background:#d7d4f0}.CodeMirror-line::-moz-selection,.CodeMirror-line>span::-moz-selection,.CodeMirror-line>span>span::-moz-selection{background:#d7d4f0}.cm-searching{background-color:#ffa;background-color:rgba(255,255,0,.4)}.cm-force-border{padding-right:.1px}@media print{.CodeMirror div.CodeMirror-cursors{visibility:hidden}}.cm-tab-wrap-hack:after{content:''}.atwho-view{position:absolute;top:0;left:0;display:none;margin-top:18px;background:#fff;color:#000;border:1px solid #ddd;border-radius:3px;box-shadow:0 0 5px rgba(0,0,0,.1);min-width:120px;z-index:11110!important}.atwho-view .atwho-header{padding:5px;margin:5px;cursor:pointer;border-bottom:solid 1px #eaeff1;color:#6f8092;font-size:11px;font-weight:700}.atwho-view .atwho-header .small{color:#6f8092;float:right;padding-top:2px;margin-right:-5px;font-size:12px;font-weight:400}.atwho-view .atwho-header:hover{cursor:default}.atwho-view .cur{background:#36f;color:#fff}.atwho-view .cur small{color:#fff}.atwho-view strong{color:#36f}.atwho-view .cur strong{color:#fff;font:700}.atwho-view ul{list-style:none;padding:0;margin:auto;max-height:200px;overflow-y:auto}.atwho-view ul li{display:block;padding:5px 10px;border-bottom:1px solid #ddd;cursor:pointer}.atwho-view small{font-size:smaller;color:#777;font-weight:400}@-moz-keyframes blink{50%{background-color:transparent}}@-webkit-keyframes blink{50%{background-color:transparent}}@keyframes blink{50%{background-color:transparent}}.atwho-view ul{overflow:hidden}.atwho-jrtext{padding-left:1em;color:gray}.cur>.atwho-jrtext{padding-left:1em;color:#fff}.dropdown-menu a>i{display:inline-block;width:16px}.checklist i.fa-check{display:none;width:auto}.checklist .selected i.fa-check{display:inline-block;margin-left:-14px;margin-right:2px}.dropdown-submenu,.fd-xpath-editor .fd-xpath-editor-content fieldset{position:relative}.dropdown-submenu>a:after{display:block;content:" ";float:right;width:0;height:0;border-color:transparent transparent transparent #ccc;border-style:solid;border-width:5px 0 5px 5px;margin-top:5px;margin-right:-10px}.dropdown-submenu>.dropdown-menu{top:0;left:100%;margin-top:-6px;margin-left:-1px;border-radius:0 6px 6px 6px}.dropdown-submenu:hover>.dropdown-menu{display:block}.dropdown-submenu:hover>a:after{border-left-color:#fff}.fd-input{-moz-appearance:textfield;-webkit-appearance:textfield;border:1px solid #ccc;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);-moz-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 linear .2s,box-shadow linear .2s;-moz-transition:border linear .2s,box-shadow linear .2s;-o-transition:border linear .2s,box-shadow linear .2s;transition:border linear .2s,box-shadow linear .2s;height:28px;padding:6px 12px;font-size:12px;background:#fff;vertical-align:middle;color:#555;white-space:nowrap;overflow:hidden}.fd-input:focus,.fd-textarea:focus{border-color:rgba(82,168,236,.8);outline:0;outline:thin dotted \9;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(82,168,236,.6);-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(82,168,236,.6);box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(82,168,236,.6)}.fd-input p,.fd-textarea p{margin:0}.fd-textarea{-webkit-appearance:textfield;border:1px solid #ccc;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);-moz-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 linear .2s,box-shadow linear .2s;-moz-transition:border linear .2s,box-shadow linear .2s;-o-transition:border linear .2s,box-shadow linear .2s;transition:border linear .2s,box-shadow linear .2s;padding:6px 12px;font-size:12px;background:#fff;vertical-align:middle;color:#555;-moz-appearance:textfield-multiline;min-height:4em;height:4.5em;overflow:auto;resize:both;white-space:normal;word-break:break-word}.fd-textarea.fd-xpath-editor-text{height:13em;font-family:monospace}.fd-search{background-color:#f2f2f1;margin-bottom:5px}.fd-search>.form-inline,.formdesigner .fd-ui-container .fd-external-sources-container .fd-external-resource-search>form{position:relative;padding:0 12px}.fd-search>.form-inline i,.formdesigner .fd-ui-container .fd-external-sources-container .fd-external-resource-search>form i{line-height:42px}.fd-search .control-label{padding-top:0}.fd-search .fd-search-control{position:absolute;top:5px;margin-left:18px;width:100%}.fd-commander{background-color:#f2f2f1;padding:5px}.fd-commander input{border:1px solid #d6d6d4;height:19px;width:calc(100% - 15px)}.fd-commander .fd-commander-close{background:0 0;border:0;color:#373534;position:absolute;top:8px;right:8px;cursor:pointer}.label-datanode{text-shadow:none;line-height:16px;padding:0 2px;margin:0 2px 2px;font-size:12px;border:1px solid;vertical-align:middle;font-weight:400}.label-datanode:hover{cursor:pointer;color:#fff}.label-datanode .close{color:#00799a;opacity:.4;font-weight:500;line-height:13px;font-size:18px;padding:0 5px 3px;margin-right:-3px}.label-datanode .close:hover{opacity:.9}.label-datanode .fcc{padding:0 3px;font-size:.8em}.label-datanode-internal{color:#00799a;border-color:#88d0d2;background-color:#d2edee}.label-datanode-internal .close{color:#00799a}.label-datanode-internal:hover{background-color:#1ea2a7;border-color:#1a8d92}.label-datanode-internal:hover .close{color:#d2edee}.label-datanode-external{color:#373534;border-color:#c1c1bc;background-color:#e6e6e4}.label-datanode-external .close{color:#373534}.label-datanode-external:hover{background-color:#685c53}.formdesigner .fd-ui-container .fd-content .fd-head .fd-head-max-indicator i,.label-datanode-external:hover .close{color:#d6d6d4}.label-datanode-external-unknown{color:#685300;border-color:#eed161;background-color:#f6e5a6}.label-datanode-external-unknown .close{color:#685300}.label-datanode-external-unknown:hover{background-color:#f9c700}.label-datanode-external-unknown:hover .close{color:#f8ecbd}.label-datanode-unknown{color:#812627;border-color:#c6948e;background-color:#e8d4d2}.label-datanode-unknown .close{color:#812627}.label-datanode-unknown:hover{background-color:#e53e30}.label-datanode-unknown:hover .close{color:#efcfcb}.datanode-tree-bubble{font-size:11px;color:#fff;line-height:18px;display:inline-block;padding:0 5px;border-radius:3px}.datanode-tree-bubble .fcc{font-size:9px}.datanode-tree-bubble-internal{color:#00799a;background-color:#ccf3f4}.datanode-tree-bubble-external{color:#373534;background-color:#f2f2f1}.datanode-tree-bubble-internal.on{background-color:#00bdc5;color:#fff}.datanode-tree-bubble-external.on{background-color:#685c53;color:#fff}.cke_widget_wrapper:hover>.label-datanode{outline:0!important;-webkit-box-shadow:0 0 8px #004ebc;-moz-box-shadow:0 0 8px #004ebc;box-shadow:0 0 8px #004ebc}.cke_widget_focused .label-datanode{outline:0!important;-webkit-box-shadow:0 0 8px #002c5f;-moz-box-shadow:0 0 8px #002c5f;box-shadow:0 0 8px #002c5f;border-color:#0073f8}.cke_widget_drag_handler_container{top:-2px!important;background:0 0!important}.cke_widget_drag_handler{width:100%!important;height:100%!important}.itext-block-container.has-markdown .markdown-group{display:block!important}.itext-block-container.has-markdown .fd-help,.itext-block-container.has-markdown .markdown-output:not(:empty),.itext-block-container.has-markdown .turn-markdown-off{display:inline-block!important}.itext-block-container.has-markdown .turn-markdown-on{display:none!important}.itext-block-container:not(.has-markdown) .markdown-group,.itext-block-container:not(.has-markdown) .markdown-output,.itext-block-container:not(.has-markdown) .turn-markdown-off{display:none!important}.itext-block-container:not(.has-markdown) .fd-help,.itext-block-container:not(.has-markdown) .turn-markdown-on{display:inline-block!important}.itext-block-container.markdown-ignorant .fd-help,.itext-block-container.markdown-ignorant .markdown-output,.itext-block-container.markdown-ignorant .turn-markdown-off,.itext-block-container.markdown-ignorant .turn-markdown-on{display:none!important}.markdown-output{width:100%;margin:0}.markdown-output table{padding:0}.markdown-output table tr{border-top:1px solid #ccc;background-color:#fff;margin:0;padding:0}.markdown-output table tr th{font-weight:700;border:1px solid #ccc;text-align:left;margin:0;padding:6px 13px}.markdown-output table tr td:first-child,.markdown-output table tr th:first-child{margin-top:0}.markdown-output table tr td:last-child,.markdown-output table tr th:last-child{margin-bottom:0}.markdown-output table tr td{border:1px solid #ccc;text-align:left;margin:0;padding:6px 13px}.markdown-output table tr:nth-child(2n){background-color:#f8f8f8}.fd-valid-alert-icon{color:#d83a2e}.fd-form-saving{position:fixed;top:0;bottom:0;left:0;right:0;opacity:.8;background-color:#000;z-index:2000}.fd-form-saving>div{opacity:1;position:fixed;top:calc(50% - 24px);left:calc(50% - 24px);-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;width:48px;height:48px;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;background-color:#fff;padding:8px}.fd-form-saving>div>div{width:32px;height:32px;background-image:url(images/ajax-loader.gif)}.fd-full-screen-modal .modal-dialog{position:fixed;left:0;right:0;top:0;bottom:0;margin:0;width:auto}.fd-full-screen-modal .modal-dialog .modal-content{position:absolute;top:20px;bottom:20px;left:20px;right:20px}.fd-full-screen-modal .modal-dialog .modal-content .modal-body{overflow-y:auto}.formdesigner .fd-ui-container .fd-mm-preview-container{text-align:center;width:115px;float:left}.formdesigner .fd-ui-container .fd-mm-preview-container .fd-mm-no-ref,.formdesigner .fd-ui-container .fd-mm-preview-container img{border:1px solid #eee}.formdesigner .fd-ui-container .fd-mm-preview-container img{padding:.5em;background-color:#fff;margin-bottom:10px}.formdesigner .fd-ui-container .fd-mm-preview-container .fd-mm-no-ref{color:#999;background-color:#fff;padding:10px}.formdesigner .fd-ui-container .fd-mm-preview-container .fd-mm-no-ref i{display:block;font-size:56px}.formdesigner .fd-ui-container .fd-mm-upload-container{margin-left:125px}.formdesigner .fd-ui-container .fd-mm-upload-container>.control-row{margin:0 0 10px}.formdesigner .fd-ui-container .fd-mm-upload-container>.control-row:first-child{height:25px}.formdesigner .fd-ui-container .fd-mm-upload-container .fd-mm-path-input{margin-right:92px}.rich-text-popover{-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px;word-wrap:break-word;min-width:236px;max-width:276px}.rich-text-popover .popover-title h3{font-weight:600;font-size:14px;margin:0}.rich-text-popover .popover-title .text-muted{margin-top:5px;line-height:1.3em}.rich-text-popover.bottom,.rich-text-popover.left,.rich-text-popover.right,.rich-text-popover.top{margin:0}.rich-text-popover.bottom{margin-top:5px}.rich-text-popover.top{margin-bottom:-10px}.rich-text-popover.right{margin-left:5px}.rich-text-popover .arrow,.rich-text-popover .arrow:after{display:none}.popover-content .alert{margin-bottom:0}.formdesigner .fd-ui-container .fd-props-toolbar{margin-bottom:5px;border-bottom:1px solid #f4f4f4;padding:12px}.formdesigner .fd-ui-container .fd-props-toolbar .fd-question-comment{margin-top:10px;white-space:pre-line}.formdesigner .fd-ui-container .fd-props-content{padding:0 12px}.formdesigner .fd-ui-container .fd-props-content .fd-help{width:25px;font-size:21px}.formdesigner .fd-ui-container .fd-props-content .fd-help a:hover{text-decoration:none;color:#46a546}.formdesigner .fd-ui-container .fd-props-content .fd-copy-paste-help .row{padding:0 2em;margin-bottom:2em}.formdesigner .fd-ui-container .fd-props-content .fd-copy-paste-help .copy-paste-box textarea{width:100%;height:100px}.formdesigner .fd-ui-container .fd-props-content .fd-question-fieldset{position:relative;min-width:0;display:table-column}.formdesigner .fd-ui-container .fd-props-content .fd-question-fieldset:first-child{margin-top:20px}.formdesigner .fd-ui-container .fd-props-content .fd-question-fieldset:first-child legend{display:none}.formdesigner .fd-ui-container .fd-props-content .fd-question-fieldset legend{min-height:30px}.formdesigner .fd-ui-container .fd-props-content .fd-question-fieldset legend .fd-help{right:0;top:0}.formdesigner .fd-ui-container .fd-props-content .fd-question-fieldset .fd-fieldset-content .control-label .fd-help{position:relative;top:-8px;height:15px;display:inline-block}.formdesigner .fd-ui-container .fd-props-content .fd-question-fieldset .fd-fieldset-content .control-label label{vertical-align:top}.formdesigner .fd-ui-container .fd-props-content .fd-question-fieldset .fd-fieldset-content .messages .alert{margin:10px 0 0}.formdesigner .fd-ui-container .fd-props-content .fd-question-fieldset .fd-fieldset-content .itext-block-container .btn-danger{margin:10px}.formdesigner .fd-ui-container .fd-props-content .fd-question-fieldset .fd-itextID-checkbox-container{width:55px;padding:0 5px;background-color:#f1f9f1;-webkit-border-radius:5px;-moz-border-radius:5px;border-radius:5px}.formdesigner .fd-ui-container .fd-props-content .fd-question-fieldset .fd-kv{margin-bottom:0}.formdesigner .fd-ui-container .fd-props-content .fd-question-fieldset .fd-kv .fd-kv-arrow{text-align:center}.formdesigner .fd-ui-container .fd-props-content .fd-question-fieldset .fd-kv .fd-kv-arrow i{margin-top:8px}body.vellum-full-screen{overflow-y:hidden}.formdesigner .fd-ui-container{top:0;width:100%;background-color:#fff}.formdesigner .fd-ui-container.full-screen{z-index:1031}.formdesigner .fd-ui-container .fd-content{float:left}.formdesigner .fd-ui-container .fd-content.fd-content-left{width:30%}.formdesigner .fd-ui-container .fd-content.fd-content-left .fd-add-question{width:100%;border-radius:0;text-align:left;border:0}.formdesigner .fd-ui-container .fd-content.fd-content-left .fd-accessory-pane{overflow-x:hidden;overflow-y:auto}.formdesigner .fd-ui-container .fd-content.fd-content-right .fd-head{height:31px}.formdesigner .fd-ui-container .fd-content.fd-content-right .fd-head h2{line-height:30px}.formdesigner .fd-ui-container .fd-content.fd-content-right .well{padding:10px}.formdesigner .fd-ui-container .fd-content.fd-content-right .well .col-sm-1{padding:0}.formdesigner .fd-ui-container .fd-content.fd-content-right .fd-form-actions{background-color:#004ebc!important;padding:5px 8px 8px}.formdesigner .fd-ui-container .fd-content .fd-default-panel{padding-left:12px}.formdesigner .fd-ui-container .fd-content .fd-head{color:#fff;background-color:#002c5f;font-size:17px;height:25px;position:relative}.formdesigner .fd-ui-container .fd-content .fd-head .fd-head-max-indicator{position:absolute;right:10px}.atwho-view .cur small,.formdesigner .fd-ui-container .fd-content .fd-head:hover .fd-head-max-indicator i{color:#fff}.formdesigner .fd-ui-container .fd-content .fd-head>h2{font-size:12.6px;padding:1px 12px 0;margin:0;font-weight:400;line-height:23px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;position:absolute;left:0;right:38px}.formdesigner .fd-ui-container .fd-content .fd-head .fd-head-menu-container{position:absolute;right:0;top:0;line-height:23px;font-size:12.6px;min-width:50px}.formdesigner .fd-ui-container .fd-content .fd-head .fd-head-menu-container .dropdown .dropdown-toggle{color:#fff;cursor:pointer;display:block;padding:0 12px;text-decoration:none;background-color:#002c5f}.formdesigner .fd-ui-container .fd-content .fd-head .fd-head-menu-container .dropdown .dropdown-toggle:hover{text-decoration:none;background-color:#004ebc}.formdesigner .fd-ui-container .fd-content .fd-head .fd-head-menu-container .dropdown .dropdown-menu a{min-width:170px}.formdesigner .fd-ui-container .fd-content .fd-head .fd-head-menu-container .dropdown .dropdown-menu a>.hotkey{float:right}.formdesigner .fd-ui-container .fd-content-vertical-divider{width:5px;background:#004ebc}.formdesigner .fd-ui-container .fd-content-horizontal-divider{height:5px;margin:1px 0;background:#f4f4f4;background-repeat:no-repeat;background-position:center center;background-image:url(images/ellipsis.png);background-size:auto 80%}.formdesigner .fd-ui-container .fd-messages{position:fixed;bottom:40px;left:0;width:100%}.formdesigner .fd-ui-container .fd-messages .alert{-webkit-box-shadow:0 0 10px rgba(0,0,0,.4);-moz-box-shadow:0 0 10px rgba(0,0,0,.4);box-shadow:0 0 10px rgba(0,0,0,.4);margin:20px;height:auto;overflow:auto;max-height:200px}.formdesigner .fd-ui-container .fd-scrollable,.formdesigner .fd-ui-container .fd-scrollable-minimal{overflow-x:hidden;overflow-y:auto;transform:translate3d(0,0,0)}.formdesigner .fd-ui-container .fd-scrollable{height:606px;width:100%}.formdesigner .fd-ui-container .fd-scrollable-minimal{max-height:606px}.formdesigner .fd-ui-container .jstree .jstree-node .jstree-anchor{color:#37475d;line-height:27px;height:26px}.formdesigner .fd-ui-container .jstree .jstree-node .jstree-anchor.jstree-clicked,.formdesigner .fd-ui-container .jstree .jstree-node .jstree-anchor.jstree-hovered{border:0;background:#eaeff5}.formdesigner .fd-ui-container .jstree .jstree-node .jstree-anchor.jstree-clicked{-webkit-box-shadow:0 0 4px rgba(21,87,162,.6);-moz-box-shadow:0 0 4px rgba(21,87,162,.6);box-shadow:0 0 4px rgba(21,87,162,.6)}.formdesigner .fd-ui-container .jstree .jstree-node .jstree-anchor>.jstree-icon{background:0 0;font-size:.85em;color:#004ebc}.formdesigner .fd-ui-container .jstree .jstree-node .add_choice:before{background:0 0;color:#004ebc;margin-right:6px;font:14px/1 FontAwesome}.formdesigner .fd-ui-container .jstree .jstree-node .add_choice{display:block;margin-left:50px;cursor:pointer;padding:0 5px;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;line-height:24px;height:24px}.formdesigner .fd-ui-container .jstree .jstree-node .add_choice:hover{border:0;background-color:#eaeff5;width:95px}.formdesigner .fd-ui-container .jstree .jstree-node.jstree-closed .add_choice{display:none}.formdesigner .fd-ui-container .jstree .jstree-node .fd-valid-alert-icon{margin-right:3px;margin-left:-3px}.formdesigner .fd-ui-container .fd-tree .fd-head{height:46px}.formdesigner .fd-ui-container .fd-tree .fd-head h2{line-height:46px;font-size:14px}.formdesigner .fd-ui-container .fd-tree .fd-head .fd-head-menu-container{line-height:46px}.formdesigner .fd-ui-container .fd-tree .fd-scrollable{overflow-x:auto}.formdesigner .fd-ui-container .fd-tree .fd-scrollable .jstree{margin:5px 0}.formdesigner .fd-ui-container .fd-tree .fd-undo-delete{margin-bottom:0}.formdesigner .fd-ui-container .fd-external-sources-container .fd-head.fd-head-external-sources{cursor:pointer}.formdesigner .fd-ui-container .fd-external-sources-container .fd-head.fd-head-external-sources h2{font-size:12px}.formdesigner .fd-ui-container .fd-external-sources-container .fd-external-resource-search{background-color:#f2f2f1;margin-bottom:5px}.formdesigner .fd-ui-container .fd-external-sources-container .fd-external-resource-search .fd-search-control{position:absolute;top:5px;margin-left:18px;width:100%}.formdesigner .fd-ui-container .fd-external-sources-container .fd-external-sources-tree .jstree-anchor{color:#373534}.formdesigner .fd-ui-container .fd-external-sources-container .fd-external-sources-tree .jstree-anchor.jstree-clicked{background-color:#f2f2f1;-webkit-box-shadow:0 0 4px rgba(104,92,83,.8);-moz-box-shadow:0 0 4px rgba(104,92,83,.8);box-shadow:0 0 4px rgba(104,92,83,.8)}.formdesigner .fd-ui-container .fd-external-sources-container .fd-external-sources-tree .jstree-anchor>.jstree-icon{color:#685c53}.formdesigner .fd-ui-container .fd-undo-delete p{margin-top:1em}#jstree-dnd{max-width:300px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.clearfix,.fd-xpath-editor .fd-xpath-editor-content fieldset legend{*zoom:1}.clearfix:after,.clearfix:before,.fd-xpath-editor .fd-xpath-editor-content fieldset legend:after,.fd-xpath-editor .fd-xpath-editor-content fieldset legend:before{display:table;content:"";line-height:0}.clearfix:after,.fd-xpath-editor .fd-xpath-editor-content fieldset legend:after{clear:both}.hide-text{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.input-block-level{display:block;width:100%;min-height:30px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.fd-xpath-editor .fd-xpath-editor-content{padding:20px}.fd-xpath-editor .fd-xpath-editor-content fieldset legend button{margin-bottom:5px}.fd-xpath-editor .fd-xpath-editor-content fieldset .fd-xpath-editor-expressions .xpath-expression-group:last-child{margin-bottom:0}.fd-xpath-editor .fd-xpath-editor-content fieldset .fd-xpath-editor-expressions .xpath-expression-group .validation-results{display:inline-block;padding:5px 25px;margin-bottom:0}.jstree-children,.jstree-container-ul,.jstree-node{display:block;margin:0;padding:0;list-style-type:none;list-style-image:none}.jstree-anchor,.jstree-node{white-space:nowrap}.jstree-anchor{display:inline-block;padding:0 4px 0 1px;margin:0;vertical-align:top}.jstree-anchor:focus{outline:0}.jstree-anchor,.jstree-anchor:active,.jstree-anchor:hover,.jstree-anchor:link,.jstree-anchor:visited{text-decoration:none;color:inherit}.jstree-icon{display:inline-block;text-decoration:none;margin:0;padding:0;vertical-align:top;text-align:center}.jstree-icon:empty{display:inline-block;text-decoration:none;margin:0;padding:0;vertical-align:top;text-align:center}.jstree-ocl{cursor:pointer}.jstree-leaf>.jstree-ocl{cursor:default}.jstree .jstree-open>.jstree-children{display:block}.jstree-anchor>.jstree-themeicon{margin-right:2px}.jstree .jstree-closed>.jstree-children,.jstree .jstree-leaf>.jstree-children,.jstree-anchor>.jstree-themeicon-hidden,.jstree-hidden,.jstree-no-icons .jstree-themeicon,.jstree-node.jstree-hidden{display:none}.jstree-rtl .jstree-anchor{padding:0 1px 0 4px}.jstree-rtl .jstree-anchor>.jstree-themeicon{margin-left:2px;margin-right:0}.jstree-rtl .jstree-node{margin-left:0}.jstree-rtl .jstree-container-ul>.jstree-node{margin-right:0}.jstree-wholerow-ul{position:relative;display:inline-block;min-width:100%}.jstree-wholerow-ul .jstree-leaf>.jstree-ocl{cursor:pointer}.jstree-wholerow-ul .jstree-anchor,.jstree-wholerow-ul .jstree-icon{position:relative}.jstree-wholerow-ul .jstree-wholerow{width:100%;cursor:pointer;position:absolute;left:0;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.jstree-contextmenu .jstree-anchor{-webkit-user-select:none;-webkit-touch-callout:none}.jstree-default .jstree-no-icons .jstree-anchor>.jstree-themeicon,.vakata-context{display:none}.vakata-context,.vakata-context ul{margin:0;padding:2px;position:absolute;background:#f5f5f5;border:1px solid #979797;box-shadow:2px 2px 2px #999}.vakata-context ul{list-style:none;left:100%;margin:-2.7em 0 0 -4px}.vakata-context .vakata-context-right ul,.vakata-context-rtl ul{left:auto;right:100%;margin-left:auto;margin-right:-4px}.vakata-context li{list-style:none}.vakata-context li>a{display:block;padding:0 2em;text-decoration:none;width:auto;color:#000;white-space:nowrap;line-height:2.4em;text-shadow:1px 1px 0 #fff;border-radius:1px}.vakata-context .vakata-context-hover>a,.vakata-context li>a:hover{position:relative;background-color:#e8eff7;box-shadow:0 0 2px #0a6aa1}.vakata-context li>a.vakata-context-parent{background-image:url(data:image/gif;base64,R0lGODlhCwAHAIAAACgoKP///yH5BAEAAAEALAAAAAALAAcAAAIORI4JlrqN1oMSnmmZDQUAOw==);background-position:right center;background-repeat:no-repeat}.vakata-context li>a:focus{outline:0}.vakata-context .vakata-context-separator>a,.vakata-context .vakata-context-separator>a:hover{background:#fff;border:0;border-top:1px solid #e2e3e3;height:1px;min-height:1px;max-height:1px;padding:0;margin:0 0 0 2.4em;border-left:1px solid #e0e0e0;text-shadow:0 0 0 transparent;box-shadow:0 0 0 transparent;border-radius:0}.vakata-context .vakata-contextmenu-disabled a,.vakata-context .vakata-contextmenu-disabled a:hover{color:silver;background-color:transparent;border:0;box-shadow:0 0 0}.vakata-context .vakata-contextmenu-disabled>a>i{filter:grayscale(100%)}.vakata-context li>a>i{text-decoration:none;display:inline-block;width:2.4em;height:2.4em;background:0 0;margin:0 0 0 -2em;vertical-align:top;text-align:center;line-height:2.4em}.vakata-context li>a>i:empty{width:2.4em;line-height:2.4em}.vakata-context li>a .vakata-contextmenu-sep{display:inline-block;width:1px;height:2.4em;background:#fff;margin:0 .5em 0 0;border-left:1px solid #e2e3e3}.vakata-context .vakata-contextmenu-shortcut{font-size:.8em;color:silver;opacity:.5;display:none}.vakata-context-rtl li>a.vakata-context-parent{background-image:url(data:image/gif;base64,R0lGODlhCwAHAIAAACgoKP///yH5BAEAAAEALAAAAAALAAcAAAINjI+AC7rWHIsPtmoxLAA7);background-position:left center;background-repeat:no-repeat}.vakata-context-rtl .vakata-context-separator>a{margin:0 2.4em 0 0;border-left:0;border-right:1px solid #e2e3e3}.vakata-context-rtl .vakata-context-left ul{right:auto;left:100%;margin-left:-4px;margin-right:auto}.vakata-context-rtl li>a>i{margin:0 -2em 0 0}.vakata-context-rtl li>a .vakata-contextmenu-sep{margin:0 0 0 .5em;border-left-color:#fff;background:#e2e3e3}#jstree-marker{position:absolute;top:0;left:0;margin:-5px 0 0;padding:0;border-right:0;border-top:5px solid transparent;border-bottom:5px solid transparent;border-left:5px solid;width:0;height:0;font-size:0;line-height:0}#jstree-dnd{line-height:16px;margin:0;padding:4px}#jstree-dnd .jstree-icon{margin:0 2px 0 0}#jstree-dnd .jstree-copy,#jstree-dnd .jstree-icon{display:inline-block;text-decoration:none;padding:0;width:16px;height:16px}#jstree-dnd .jstree-ok{background:green}#jstree-dnd .jstree-er{background:red}#jstree-dnd .jstree-copy{margin:0 2px}.jstree-default .jstree-node{background-color:transparent}.jstree-default .jstree-icon{background-repeat:no-repeat;background-color:transparent}.jstree-default .jstree-anchor,.jstree-default .jstree-animated,.jstree-default .jstree-wholerow{transition:background-color .15s,box-shadow .15s}.jstree-default .jstree-context,.jstree-default .jstree-hovered{background:#e7f4f9;border-radius:2px;box-shadow:inset 0 0 1px #ccc}.jstree-default .jstree-clicked{background:#beebff;border-radius:2px;box-shadow:inset 0 0 1px #999}.jstree-default .jstree-disabled{color:#666}.jstree-default .jstree-disabled.jstree-hovered{box-shadow:none}.jstree-default .jstree-disabled>.jstree-icon{opacity:.8;filter:gray;-webkit-filter:grayscale(100%)}.jstree-default .jstree-search{font-style:italic;color:#8b0000;font-weight:700}.jstree-default .jstree-no-checkboxes .jstree-checkbox{display:none!important}.jstree-default.jstree-checkbox-no-clicked .jstree-clicked{background:0 0;box-shadow:none}.jstree-default.jstree-checkbox-no-clicked .jstree-clicked.jstree-hovered,.jstree-default.jstree-checkbox-no-clicked>.jstree-wholerow-ul .jstree-wholerow-clicked.jstree-wholerow-hovered{background:#e7f4f9}.jstree-default.jstree-checkbox-no-clicked>.jstree-wholerow-ul .jstree-wholerow-clicked{background:0 0}.jstree-default>.jstree-striped{min-width:100%;display:inline-block;background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAAkCAMAAAB/qqA+AAAABlBMVEUAAAAAAAClZ7nPAAAAAnRSTlMNAMM9s3UAAAAXSURBVHjajcEBAQAAAIKg/H/aCQZ70AUBjAATb6YPDgAAAABJRU5ErkJggg==) left top}.jstree-default>.jstree-wholerow-ul .jstree-clicked,.jstree-default>.jstree-wholerow-ul .jstree-hovered{background:0 0;box-shadow:none;border-radius:0}.jstree-default .jstree-wholerow{-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box}.jstree-default .jstree-wholerow-hovered{background:#e7f4f9}.jstree-default .jstree-wholerow-clicked{background:#beebff;background:-webkit-linear-gradient(top,#beebff 0,#a8e4ff 100%);background:linear-gradient(to bottom,#beebff 0,#a8e4ff 100%)}.jstree-default .jstree-node{min-height:24px;line-height:24px;margin-left:24px;min-width:24px}.jstree-default .jstree-anchor{line-height:24px;height:24px}.jstree-default .jstree-icon{width:24px;height:24px;line-height:24px}.jstree-default .jstree-icon:empty{width:24px;height:24px;line-height:24px}.jstree-default.jstree-rtl .jstree-node{margin-right:24px}.jstree-default .jstree-wholerow{height:24px}#jstree-dnd.jstree-default .jstree-er,#jstree-dnd.jstree-default .jstree-ok,.jstree-default .jstree-icon,.jstree-default .jstree-node{background-image:url(src/../node_modules/jstree/dist/themes/default/32px.png)}.jstree-default .jstree-node{background-position:-292px -4px;background-repeat:repeat-y}.jstree-default .jstree-last{background:0 0}.jstree-default .jstree-open>.jstree-ocl{background-position:-132px -4px}.jstree-default .jstree-closed>.jstree-ocl{background-position:-100px -4px}.jstree-default .jstree-leaf>.jstree-ocl{background-position:-68px -4px}.jstree-default .jstree-themeicon{background-position:-260px -4px}.jstree-default .jstree-disabled,.jstree-default .jstree-disabled.jstree-hovered,.jstree-default>.jstree-no-dots .jstree-leaf>.jstree-ocl,.jstree-default>.jstree-no-dots .jstree-node{background:0 0}.jstree-default>.jstree-no-dots .jstree-open>.jstree-ocl{background-position:-36px -4px}.jstree-default>.jstree-no-dots .jstree-closed>.jstree-ocl{background-position:-4px -4px}.jstree-default .jstree-disabled.jstree-clicked{background:#efefef}.jstree-default .jstree-checkbox{background-position:-164px -4px}.jstree-default .jstree-checkbox:hover{background-position:-164px -36px}.jstree-default .jstree-checked>.jstree-checkbox,.jstree-default.jstree-checkbox-selection .jstree-clicked>.jstree-checkbox{background-position:-228px -4px}.jstree-default .jstree-checked>.jstree-checkbox:hover,.jstree-default.jstree-checkbox-selection .jstree-clicked>.jstree-checkbox:hover{background-position:-228px -36px}.jstree-default .jstree-anchor>.jstree-undetermined{background-position:-196px -4px}.jstree-default .jstree-anchor>.jstree-undetermined:hover{background-position:-196px -36px}.jstree-default .jstree-checkbox-disabled{opacity:.8;filter:gray;-webkit-filter:grayscale(100%)}.jstree-default>.jstree-striped{background-size:auto 48px}.jstree-default.jstree-rtl .jstree-node{background-position:100% 1px;background-repeat:repeat-y}.jstree-default.jstree-rtl .jstree-open>.jstree-ocl{background-position:-132px -36px}.jstree-default.jstree-rtl .jstree-closed>.jstree-ocl{background-position:-100px -36px}.jstree-default.jstree-rtl .jstree-leaf>.jstree-ocl{background-position:-68px -36px}.jstree-default.jstree-rtl>.jstree-no-dots .jstree-leaf>.jstree-ocl,.jstree-default.jstree-rtl>.jstree-no-dots .jstree-node{background:0 0}.jstree-default.jstree-rtl>.jstree-no-dots .jstree-open>.jstree-ocl{background-position:-36px -36px}.jstree-default.jstree-rtl>.jstree-no-dots .jstree-closed>.jstree-ocl{background-position:-4px -36px}.jstree-default .jstree-themeicon-custom{background-color:transparent;background-image:none;background-position:0 0}.jstree-default>.jstree-container-ul .jstree-loading>.jstree-ocl{background:url(src/../node_modules/jstree/dist/themes/default/throbber.gif) center center no-repeat}.jstree-default .jstree-file{background:url(src/../node_modules/jstree/dist/themes/default/32px.png) -100px -68px no-repeat}.jstree-default .jstree-folder{background:url(src/../node_modules/jstree/dist/themes/default/32px.png) -260px -4px no-repeat}.jstree-default>.jstree-container-ul>.jstree-node{margin-left:0;margin-right:0}#jstree-dnd.jstree-default{line-height:24px;padding:0 4px}#jstree-dnd.jstree-default .jstree-er,#jstree-dnd.jstree-default .jstree-ok{background-repeat:no-repeat;background-color:transparent}#jstree-dnd.jstree-default i{background:0 0;width:24px;height:24px;line-height:24px}#jstree-dnd.jstree-default .jstree-ok{background-position:-4px -68px}#jstree-dnd.jstree-default .jstree-er{background-position:-36px -68px}.jstree-default .jstree-ellipsis{overflow:hidden}.jstree-default .jstree-ellipsis .jstree-anchor{width:calc(100% - 29px);text-overflow:ellipsis;overflow:hidden}.jstree-default.jstree-rtl .jstree-node{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAACAQMAAAB49I5GAAAABlBMVEUAAAAdHRvEkCwcAAAAAXRSTlMAQObYZgAAAAxJREFUCNdjAAMOBgAAGAAJMwQHdQAAAABJRU5ErkJggg==)}.jstree-default.jstree-rtl .jstree-last{background:0 0}.jstree-default-small .jstree-node{min-height:18px;line-height:18px;margin-left:18px;min-width:18px}.jstree-default-small .jstree-anchor{line-height:18px;height:18px}.jstree-default-small .jstree-icon{width:18px;height:18px;line-height:18px}.jstree-default-small .jstree-icon:empty{width:18px;height:18px;line-height:18px}.jstree-default-small.jstree-rtl .jstree-node{margin-right:18px}.jstree-default-small .jstree-wholerow{height:18px}.jstree-default-small .jstree-icon,.jstree-default-small .jstree-node{background-image:url(src/../node_modules/jstree/dist/themes/default/32px.png)}.jstree-default-small .jstree-node{background-position:-295px -7px;background-repeat:repeat-y}.jstree-default-small .jstree-last{background:0 0}.jstree-default-small .jstree-open>.jstree-ocl{background-position:-135px -7px}.jstree-default-small .jstree-closed>.jstree-ocl{background-position:-103px -7px}.jstree-default-small .jstree-leaf>.jstree-ocl{background-position:-71px -7px}.jstree-default-small .jstree-themeicon{background-position:-263px -7px}.jstree-default-small .jstree-disabled,.jstree-default-small .jstree-disabled.jstree-hovered,.jstree-default-small>.jstree-no-dots .jstree-leaf>.jstree-ocl,.jstree-default-small>.jstree-no-dots .jstree-node{background:0 0}.jstree-default-small>.jstree-no-dots .jstree-open>.jstree-ocl{background-position:-39px -7px}.jstree-default-small>.jstree-no-dots .jstree-closed>.jstree-ocl{background-position:-7px -7px}.jstree-default-small .jstree-disabled.jstree-clicked{background:#efefef}.jstree-default-small .jstree-checkbox{background-position:-167px -7px}.jstree-default-small .jstree-checkbox:hover{background-position:-167px -39px}.jstree-default-small .jstree-checked>.jstree-checkbox,.jstree-default-small.jstree-checkbox-selection .jstree-clicked>.jstree-checkbox{background-position:-231px -7px}.jstree-default-small .jstree-checked>.jstree-checkbox:hover,.jstree-default-small.jstree-checkbox-selection .jstree-clicked>.jstree-checkbox:hover{background-position:-231px -39px}.jstree-default-small .jstree-anchor>.jstree-undetermined{background-position:-199px -7px}.jstree-default-small .jstree-anchor>.jstree-undetermined:hover{background-position:-199px -39px}.jstree-default-small .jstree-checkbox-disabled{opacity:.8;filter:gray;-webkit-filter:grayscale(100%)}.jstree-default-small>.jstree-striped{background-size:auto 36px}.jstree-default-small.jstree-rtl .jstree-node{background-position:100% 1px;background-repeat:repeat-y}.jstree-default-small.jstree-rtl .jstree-open>.jstree-ocl{background-position:-135px -39px}.jstree-default-small.jstree-rtl .jstree-closed>.jstree-ocl{background-position:-103px -39px}.jstree-default-small.jstree-rtl .jstree-leaf>.jstree-ocl{background-position:-71px -39px}.jstree-default-small.jstree-rtl>.jstree-no-dots .jstree-leaf>.jstree-ocl,.jstree-default-small.jstree-rtl>.jstree-no-dots .jstree-node{background:0 0}.jstree-default-small.jstree-rtl>.jstree-no-dots .jstree-open>.jstree-ocl{background-position:-39px -39px}.jstree-default-small.jstree-rtl>.jstree-no-dots .jstree-closed>.jstree-ocl{background-position:-7px -39px}.jstree-default-small .jstree-themeicon-custom{background-color:transparent;background-image:none;background-position:0 0}.jstree-default-small>.jstree-container-ul .jstree-loading>.jstree-ocl{background:url(src/../node_modules/jstree/dist/themes/default/throbber.gif) center center no-repeat}.jstree-default-small .jstree-file{background:url(src/../node_modules/jstree/dist/themes/default/32px.png) -103px -71px no-repeat}.jstree-default-small .jstree-folder{background:url(src/../node_modules/jstree/dist/themes/default/32px.png) -263px -7px no-repeat}.jstree-default-small>.jstree-container-ul>.jstree-node{margin-left:0;margin-right:0}#jstree-dnd.jstree-default-small{line-height:18px;padding:0 4px}#jstree-dnd.jstree-default-small .jstree-er,#jstree-dnd.jstree-default-small .jstree-ok{background-image:url(src/../node_modules/jstree/dist/themes/default/32px.png);background-repeat:no-repeat;background-color:transparent}#jstree-dnd.jstree-default-small i{background:0 0;width:18px;height:18px;line-height:18px}#jstree-dnd.jstree-default-small .jstree-ok{background-position:-7px -71px}#jstree-dnd.jstree-default-small .jstree-er{background-position:-39px -71px}.jstree-default-small .jstree-ellipsis{overflow:hidden}.jstree-default-small .jstree-ellipsis .jstree-anchor{width:calc(100% - 23px);text-overflow:ellipsis;overflow:hidden}.jstree-default-small.jstree-rtl .jstree-node{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABIAAAACAQMAAABv1h6PAAAABlBMVEUAAAAdHRvEkCwcAAAAAXRSTlMAQObYZgAAAAxJREFUCNdjAAMHBgAAiABBI4gz9AAAAABJRU5ErkJggg==)}.jstree-default-small.jstree-rtl .jstree-last{background:0 0}.jstree-default-large .jstree-node{min-height:32px;line-height:32px;margin-left:32px;min-width:32px}.jstree-default-large .jstree-anchor{line-height:32px;height:32px}.jstree-default-large .jstree-icon{width:32px;height:32px;line-height:32px}.jstree-default-large .jstree-icon:empty{width:32px;height:32px;line-height:32px}.jstree-default-large.jstree-rtl .jstree-node{margin-right:32px}.jstree-default-large .jstree-wholerow{height:32px}.jstree-default-large .jstree-icon,.jstree-default-large .jstree-node{background-image:url(src/../node_modules/jstree/dist/themes/default/32px.png)}.jstree-default-large .jstree-node{background-position:-288px 0;background-repeat:repeat-y}.jstree-default-large .jstree-last{background:0 0}.jstree-default-large .jstree-open>.jstree-ocl{background-position:-128px 0}.jstree-default-large .jstree-closed>.jstree-ocl{background-position:-96px 0}.jstree-default-large .jstree-leaf>.jstree-ocl{background-position:-64px 0}.jstree-default-large .jstree-themeicon{background-position:-256px 0}.jstree-default-large .jstree-disabled,.jstree-default-large .jstree-disabled.jstree-hovered,.jstree-default-large>.jstree-no-dots .jstree-leaf>.jstree-ocl,.jstree-default-large>.jstree-no-dots .jstree-node{background:0 0}.jstree-default-large>.jstree-no-dots .jstree-open>.jstree-ocl{background-position:-32px 0}.jstree-default-large>.jstree-no-dots .jstree-closed>.jstree-ocl{background-position:0 0}.jstree-default-large .jstree-disabled.jstree-clicked{background:#efefef}.jstree-default-large .jstree-checkbox{background-position:-160px 0}.jstree-default-large .jstree-checkbox:hover{background-position:-160px -32px}.jstree-default-large .jstree-checked>.jstree-checkbox,.jstree-default-large.jstree-checkbox-selection .jstree-clicked>.jstree-checkbox{background-position:-224px 0}.jstree-default-large .jstree-checked>.jstree-checkbox:hover,.jstree-default-large.jstree-checkbox-selection .jstree-clicked>.jstree-checkbox:hover{background-position:-224px -32px}.jstree-default-large .jstree-anchor>.jstree-undetermined{background-position:-192px 0}.jstree-default-large .jstree-anchor>.jstree-undetermined:hover{background-position:-192px -32px}.jstree-default-large .jstree-checkbox-disabled{opacity:.8;filter:gray;-webkit-filter:grayscale(100%)}.jstree-default-large>.jstree-striped{background-size:auto 64px}.jstree-default-large.jstree-rtl .jstree-node{background-position:100% 1px;background-repeat:repeat-y}.jstree-default-large.jstree-rtl .jstree-open>.jstree-ocl{background-position:-128px -32px}.jstree-default-large.jstree-rtl .jstree-closed>.jstree-ocl{background-position:-96px -32px}.jstree-default-large.jstree-rtl .jstree-leaf>.jstree-ocl{background-position:-64px -32px}.jstree-default-large.jstree-rtl>.jstree-no-dots .jstree-leaf>.jstree-ocl,.jstree-default-large.jstree-rtl>.jstree-no-dots .jstree-node{background:0 0}.jstree-default-large.jstree-rtl>.jstree-no-dots .jstree-open>.jstree-ocl{background-position:-32px -32px}.jstree-default-large.jstree-rtl>.jstree-no-dots .jstree-closed>.jstree-ocl{background-position:0 -32px}.jstree-default-large .jstree-themeicon-custom{background-color:transparent;background-image:none;background-position:0 0}.jstree-default-large>.jstree-container-ul .jstree-loading>.jstree-ocl{background:url(src/../node_modules/jstree/dist/themes/default/throbber.gif) center center no-repeat}.jstree-default-large .jstree-file{background:url(src/../node_modules/jstree/dist/themes/default/32px.png) -96px -64px no-repeat}.jstree-default-large .jstree-folder{background:url(src/../node_modules/jstree/dist/themes/default/32px.png) -256px 0 no-repeat}.jstree-default-large>.jstree-container-ul>.jstree-node{margin-left:0;margin-right:0}#jstree-dnd.jstree-default-large{line-height:32px;padding:0 4px}#jstree-dnd.jstree-default-large .jstree-er,#jstree-dnd.jstree-default-large .jstree-ok{background-image:url(src/../node_modules/jstree/dist/themes/default/32px.png);background-repeat:no-repeat;background-color:transparent}#jstree-dnd.jstree-default-large i{background:0 0;width:32px;height:32px;line-height:32px}#jstree-dnd.jstree-default-large .jstree-ok{background-position:0 -64px}#jstree-dnd.jstree-default-large .jstree-er{background-position:-32px -64px}.jstree-default-large .jstree-ellipsis{overflow:hidden}.jstree-default-large .jstree-ellipsis .jstree-anchor{width:calc(100% - 37px);text-overflow:ellipsis;overflow:hidden}.jstree-default-large.jstree-rtl .jstree-node{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAACAQMAAAAD0EyKAAAABlBMVEUAAAAdHRvEkCwcAAAAAXRSTlMAQObYZgAAAAxJREFUCNdjgIIGBgABCgCBvVLXcAAAAABJRU5ErkJggg==)}.jstree-default-large.jstree-rtl .jstree-last,span.CodeMirror-selectedtext{background:0 0}@media (max-width:768px){#jstree-dnd.jstree-dnd-responsive{line-height:40px;font-weight:700;font-size:1.1em;text-shadow:1px 1px #fff}#jstree-dnd.jstree-dnd-responsive>i{background:0 0;width:40px;height:40px}#jstree-dnd.jstree-dnd-responsive>.jstree-er,#jstree-dnd.jstree-dnd-responsive>.jstree-ok{background-image:url(src/../node_modules/jstree/dist/themes/default/40px.png);background-position:0 -200px;background-size:120px 240px}#jstree-dnd.jstree-dnd-responsive>.jstree-er{background-position:-40px -200px}#jstree-marker.jstree-dnd-responsive{border-left-width:10px;border-top-width:10px;border-bottom-width:10px;margin-top:-10px}.jstree-default-responsive .jstree-node{background:0 0;min-height:40px;line-height:40px;margin-left:40px;min-width:40px;white-space:nowrap}.jstree-default-responsive .jstree-anchor{line-height:40px;height:40px}.jstree-default-responsive .jstree-icon,.jstree-default-responsive .jstree-icon:empty{width:40px;height:40px;line-height:40px}.jstree-default-responsive.jstree-rtl .jstree-node{margin-left:0;margin-right:40px;background:0 0}.jstree-default-responsive.jstree-rtl .jstree-container-ul>.jstree-node{margin-right:0}.jstree-default-responsive .jstree-ocl{background-size:120px 240px}.jstree-default-responsive .jstree-leaf>.jstree-ocl,.jstree-default-responsive.jstree-rtl .jstree-leaf>.jstree-ocl{background:0 0}.jstree-default-responsive .jstree-open>.jstree-ocl{background-position:0 0!important}.jstree-default-responsive .jstree-closed>.jstree-ocl{background-position:0 -40px!important}.jstree-default-responsive.jstree-rtl .jstree-closed>.jstree-ocl{background-position:-40px 0!important}.jstree-default-responsive .jstree-themeicon{background-position:-40px -40px}.jstree-default-responsive .jstree-checkbox,.jstree-default-responsive .jstree-checkbox:hover{background-position:-40px -80px}.jstree-default-responsive .jstree-checked>.jstree-checkbox,.jstree-default-responsive .jstree-checked>.jstree-checkbox:hover,.jstree-default-responsive.jstree-checkbox-selection .jstree-clicked>.jstree-checkbox,.jstree-default-responsive.jstree-checkbox-selection .jstree-clicked>.jstree-checkbox:hover{background-position:0 -80px}.jstree-default-responsive .jstree-anchor>.jstree-undetermined,.jstree-default-responsive .jstree-anchor>.jstree-undetermined:hover{background-position:0 -120px}.jstree-default-responsive .jstree-anchor{font-weight:700;font-size:1.1em;text-shadow:1px 1px #fff}.jstree-default-responsive>.jstree-striped{background:0 0}.jstree-default-responsive .jstree-wholerow{border-top:1px solid rgba(255,255,255,.7);border-bottom:1px solid rgba(64,64,64,.2);background:#ebebeb;height:40px}.jstree-default-responsive .jstree-wholerow-hovered{background:#e7f4f9}.jstree-default-responsive .jstree-wholerow-clicked{background:#beebff}.jstree-default-responsive .jstree-children .jstree-last>.jstree-wholerow{box-shadow:inset 0 -6px 3px -5px #666}.jstree-default-responsive .jstree-children .jstree-open>.jstree-wholerow{box-shadow:inset 0 6px 3px -5px #666;border-top:0}.jstree-default-responsive .jstree-children .jstree-open+.jstree-open{box-shadow:none}.jstree-default-responsive .jstree-checkbox,.jstree-default-responsive .jstree-icon,.jstree-default-responsive .jstree-node,.jstree-default-responsive .jstree-node>.jstree-ocl,.jstree-default-responsive .jstree-themeicon{background-image:url(src/../node_modules/jstree/dist/themes/default/40px.png);background-size:120px 240px}.jstree-default-responsive .jstree-node{background-position:-80px 0;background-repeat:repeat-y}.jstree-default-responsive .jstree-last{background:0 0}.jstree-default-responsive .jstree-leaf>.jstree-ocl{background-position:-40px -120px}.jstree-default-responsive .jstree-last>.jstree-ocl{background-position:-40px -160px}.jstree-default-responsive .jstree-themeicon-custom{background-color:transparent;background-image:none;background-position:0 0}.jstree-default-responsive .jstree-file{background:url(src/../node_modules/jstree/dist/themes/default/40px.png) 0 -160px no-repeat;background-size:120px 240px}.jstree-default-responsive .jstree-folder{background:url(src/../node_modules/jstree/dist/themes/default/40px.png) -40px -40px no-repeat;background-size:120px 240px}.jstree-default-responsive>.jstree-container-ul>.jstree-node{margin-left:0;margin-right:0}}.CodeMirror{font-family:monospace;height:300px;color:#000;direction:ltr}.CodeMirror-lines{padding:4px 0}.CodeMirror pre.CodeMirror-line,.CodeMirror pre.CodeMirror-line-like{padding:0 4px;-moz-border-radius:0;-webkit-border-radius:0;border-radius:0;border-width:0;background:0 0;font-family:inherit;font-size:inherit;margin:0;white-space:pre;word-wrap:normal;line-height:inherit;color:inherit;z-index:2;position:relative;overflow:visible;-webkit-tap-highlight-color:transparent;-webkit-font-variant-ligatures:contextual;font-variant-ligatures:contextual}.CodeMirror-gutter-filler,.CodeMirror-scrollbar-filler{background-color:#fff}.CodeMirror-gutters{border-right:1px solid #ddd;background-color:#f7f7f7;white-space:nowrap}.CodeMirror-linenumber{padding:0 3px 0 5px;min-width:20px;text-align:right;color:#999;white-space:nowrap}.CodeMirror-guttermarker{color:#000}.CodeMirror-guttermarker-subtle{color:#999}.CodeMirror-cursor{border-left:1px solid #000;border-right:none;width:0}.CodeMirror div.CodeMirror-secondarycursor{border-left:1px solid silver}.cm-fat-cursor .CodeMirror-cursor{width:auto;border:0!important;background:#7e7}.cm-fat-cursor div.CodeMirror-cursors{z-index:1}.cm-animate-fat-cursor,.cm-fat-cursor-mark{-webkit-animation:blink 1.06s steps(1) infinite;-moz-animation:blink 1.06s steps(1) infinite;animation:blink 1.06s steps(1) infinite}.cm-fat-cursor-mark{background-color:rgba(20,255,20,.5)}.cm-animate-fat-cursor{width:auto;border:0;background-color:#7e7}.cm-tab{display:inline-block;text-decoration:inherit}.CodeMirror-rulers{position:absolute;left:0;right:0;top:-50px;bottom:0;overflow:hidden}.CodeMirror-ruler{border-left:1px solid #ccc;top:0;bottom:0;position:absolute}.cm-s-default .cm-header{color:#00f}.cm-s-default .cm-quote{color:#090}.cm-negative{color:#d44}.cm-positive{color:#292}.cm-header,.cm-strong{font-weight:700}.cm-em{font-style:italic}.cm-link{text-decoration:underline}.cm-strikethrough{text-decoration:line-through}.cm-s-default .cm-keyword{color:#708}.cm-s-default .cm-atom{color:#219}.cm-s-default .cm-number{color:#164}.cm-s-default .cm-def{color:#00f}.cm-s-default .cm-variable-2{color:#05a}.cm-s-default .cm-type,.cm-s-default .cm-variable-3{color:#085}.cm-s-default .cm-comment{color:#a50}.cm-s-default .cm-string{color:#a11}.cm-s-default .cm-string-2{color:#f50}.cm-s-default .cm-meta,.cm-s-default .cm-qualifier{color:#555}.cm-s-default .cm-builtin{color:#30a}.cm-s-default .cm-bracket{color:#997}.cm-s-default .cm-tag{color:#170}.cm-s-default .cm-attribute{color:#00c}.cm-s-default .cm-hr{color:#999}.cm-s-default .cm-link{color:#00c}.cm-invalidchar,.cm-s-default .cm-error{color:red}.CodeMirror-composing{border-bottom:2px solid}div.CodeMirror span.CodeMirror-matchingbracket{color:#0b0}div.CodeMirror span.CodeMirror-nonmatchingbracket{color:#a22}.CodeMirror-matchingtag{background:rgba(255,150,0,.3)}.CodeMirror-activeline-background{background:#e8f2ff}.CodeMirror{position:relative;overflow:hidden;background:#fff}.CodeMirror-scroll{overflow:scroll!important;margin-bottom:-50px;margin-right:-50px;padding-bottom:50px;height:100%;outline:0;position:relative}.CodeMirror-sizer{position:relative;border-right:50px solid transparent}.CodeMirror-gutter-filler,.CodeMirror-hscrollbar,.CodeMirror-scrollbar-filler,.CodeMirror-vscrollbar{position:absolute;z-index:6;display:none;outline:0}.CodeMirror-vscrollbar{right:0;top:0;overflow-x:hidden;overflow-y:scroll}.CodeMirror-hscrollbar{bottom:0;left:0;overflow-y:hidden;overflow-x:scroll}.CodeMirror-scrollbar-filler{right:0;bottom:0}.CodeMirror-gutter-filler{left:0;bottom:0}.CodeMirror-gutters{position:absolute;left:0;top:0;min-height:100%;z-index:3}.CodeMirror-gutter{white-space:normal;height:100%;display:inline-block;vertical-align:top;margin-bottom:-50px}.CodeMirror-gutter-wrapper{position:absolute;z-index:4;background:0 0!important;border:0!important}.CodeMirror-gutter-background{position:absolute;top:0;bottom:0;z-index:4}.CodeMirror-gutter-elt{position:absolute;cursor:default;z-index:4}.CodeMirror-gutter-wrapper ::selection{background-color:transparent}.CodeMirror-gutter-wrapper ::-moz-selection{background-color:transparent}.CodeMirror-lines{cursor:text;min-height:1px}.CodeMirror-wrap pre.CodeMirror-line,.CodeMirror-wrap pre.CodeMirror-line-like{word-wrap:break-word;white-space:pre-wrap;word-break:normal}.CodeMirror-linebackground{position:absolute;left:0;right:0;top:0;bottom:0;z-index:0}.CodeMirror-linewidget{position:relative;z-index:2;padding:.1px}.CodeMirror-rtl pre{direction:rtl}.CodeMirror-code{outline:0}.CodeMirror-gutter,.CodeMirror-gutters,.CodeMirror-linenumber,.CodeMirror-scroll,.CodeMirror-sizer{-moz-box-sizing:content-box;box-sizing:content-box}.CodeMirror-measure{position:absolute;width:100%;height:0;overflow:hidden;visibility:hidden}.CodeMirror-cursor{position:absolute;pointer-events:none}.CodeMirror-measure pre{position:static}div.CodeMirror-cursors{visibility:hidden;position:relative;z-index:3}.CodeMirror-focused div.CodeMirror-cursors,div.CodeMirror-dragcursors{visibility:visible}.CodeMirror-selected{background:#d9d9d9}.CodeMirror-focused .CodeMirror-selected{background:#d7d4f0}.CodeMirror-crosshair{cursor:crosshair}.CodeMirror-line::selection,.CodeMirror-line>span::selection,.CodeMirror-line>span>span::selection{background:#d7d4f0}.CodeMirror-line::-moz-selection,.CodeMirror-line>span::-moz-selection,.CodeMirror-line>span>span::-moz-selection{background:#d7d4f0}.cm-searching{background-color:#ffa;background-color:rgba(255,255,0,.4)}.cm-force-border{padding-right:.1px}@media print{.CodeMirror div.CodeMirror-cursors{visibility:hidden}}.cm-tab-wrap-hack:after{content:''}.atwho-view{position:absolute;top:0;left:0;display:none;margin-top:18px;background:#fff;color:#000;border:1px solid #ddd;border-radius:3px;box-shadow:0 0 5px rgba(0,0,0,.1);min-width:120px;z-index:11110!important}.atwho-view .atwho-header{padding:5px;margin:5px;cursor:pointer;border-bottom:solid 1px #eaeff1;color:#6f8092;font-size:11px;font-weight:700}.atwho-view .atwho-header .small{color:#6f8092;float:right;padding-top:2px;margin-right:-5px;font-size:12px;font-weight:400}.atwho-view .atwho-header:hover{cursor:default}.atwho-view .cur{background:#36f;color:#fff}.atwho-view strong{color:#36f}.atwho-view .cur strong{color:#fff;font:700}.atwho-view ul{list-style:none;padding:0;margin:auto;max-height:200px;overflow-y:auto}.atwho-view ul li{display:block;padding:5px 10px;border-bottom:1px solid #ddd;cursor:pointer}.atwho-view small{font-size:smaller;color:#777;font-weight:400} \ No newline at end of file diff --git a/corehq/apps/app_manager/static/app_manager/js/vellum/version.txt b/corehq/apps/app_manager/static/app_manager/js/vellum/version.txt index 342e26a79aa6..ae5e11ffd4b3 100644 --- a/corehq/apps/app_manager/static/app_manager/js/vellum/version.txt +++ b/corehq/apps/app_manager/static/app_manager/js/vellum/version.txt @@ -1 +1 @@ -4cab4ebc583f2aa63d5e03875ebaedfbfe6d2c3b +81a02d4222d41dad1b32ca2230c40e366f7c0a37 diff --git a/corehq/apps/app_manager/static/app_manager/json/commcare-app-settings.yml b/corehq/apps/app_manager/static/app_manager/json/commcare-app-settings.yml index 5fcf2b47a724..fd8817d99965 100644 --- a/corehq/apps/app_manager/static/app_manager/json/commcare-app-settings.yml +++ b/corehq/apps/app_manager/static/app_manager/json/commcare-app-settings.yml @@ -154,10 +154,11 @@ description: Version of mobile UCRs to use. Read more on the Help Site toggle: MOBILE_UCR values: - - ['1.0', '1.0'] - - ['1.5', '1.5'] - ['2.0', '2.0'] - default: '1.0' + default: '2.0' + disabled: true + disabled_txt: This setting has been discontinued. We recommend you change this setting to Version 2. Upon doing so this setting will no longer appear on this page. + - id: location_fixture_restore name: App Aware Location Fixture Format diff --git a/corehq/apps/app_manager/static/app_manager/json/commcare-profile-settings.yml b/corehq/apps/app_manager/static/app_manager/json/commcare-profile-settings.yml index fd59b44dee60..e0a3fd09d3ad 100644 --- a/corehq/apps/app_manager/static/app_manager/json/commcare-profile-settings.yml +++ b/corehq/apps/app_manager/static/app_manager/json/commcare-profile-settings.yml @@ -356,7 +356,11 @@ values: - ['org.commcare.dalvik.reminders', 'CommCare Reminders'] - ['callout.commcare.org.sendussd', 'CommCare USSD'] - - ['org.commcare.dalvik.abha', 'CommCare ABHA'] + - ['com.dimagi.biometric', 'Biometrics Capture'] + - ['org.rdtoolkit', 'CommCare Toolkit'] + - ['richard.chard.lu.android.areamapper', 'Area Calculator for CommCare'] + - ['org.commcare.respiratory', 'Breath Counter'] + - ['com.simprints.id', 'Simprints ID'] default: [] # multiSelect default takes a list - since: '2.53' + since: '2.54' force: true diff --git a/corehq/apps/app_manager/static_strings.py b/corehq/apps/app_manager/static_strings.py index faa24c7b592e..53ad3ce391d8 100644 --- a/corehq/apps/app_manager/static_strings.py +++ b/corehq/apps/app_manager/static_strings.py @@ -142,6 +142,8 @@ gettext_noop('Only Flat Fixture'), gettext_noop('Only Hierarchical Fixture'), gettext_noop('Oops! This setting has been discontinued. We recommend you change this setting to Version 2, and it will no longer appear on your settings page.'), + gettext_noop('This setting has been discontinued. We recommend you change this setting to Version 2.' + ' Upon doing so this setting will no longer appear on this page.'), gettext_noop('Practice Mobile Worker'), gettext_noop('Prevents mobile workers from using a CommCare app until the ' 'Android apps that it needs have been installed on the ' diff --git a/corehq/apps/app_manager/templates/app_manager/app_view.html b/corehq/apps/app_manager/templates/app_manager/app_view.html index 7b145d2aeb8e..34d8bf7f7ec5 100644 --- a/corehq/apps/app_manager/templates/app_manager/app_view.html +++ b/corehq/apps/app_manager/templates/app_manager/app_view.html @@ -5,10 +5,6 @@ {% load i18n %} {% load xforms_extras %} -{% block head %}{{ block.super }} - {% include 'analytics/fullstory.html' %} -{% endblock %} - {% block js %}{{ block.super }} {% compress js %} @@ -20,7 +16,6 @@ - @@ -76,8 +71,7 @@ {% block modals %}{{ block.super }} {% for uploader in uploaders %} - {% include 'hqmedia/partials/multimedia_uploader.html' %} + {% include 'hqmedia/partials/multimedia_uploader.html' with id=uploader.slug type=uploader.media_type %} {% endfor %} - {% include 'app_manager/partials/settings/password_setter_modal.html' %} {% include 'app_manager/partials/toggle_diff_modal.html' %} {% endblock %} diff --git a/corehq/apps/app_manager/templates/app_manager/form_designer.html b/corehq/apps/app_manager/templates/app_manager/form_designer.html index 6c58ebd06540..02762848b7ab 100644 --- a/corehq/apps/app_manager/templates/app_manager/form_designer.html +++ b/corehq/apps/app_manager/templates/app_manager/form_designer.html @@ -5,9 +5,6 @@ {% load xforms_extras %} {% block head %}{{ block.super }} - {% if include_fullstory %} - {% include 'analytics/fullstory.html' %} - {% endif %} {% if not vellum_debug %} {% elif vellum_debug == "dev-min" %} diff --git a/corehq/apps/app_manager/templates/app_manager/form_view.html b/corehq/apps/app_manager/templates/app_manager/form_view.html index d704184e8f2b..65935e5997d7 100644 --- a/corehq/apps/app_manager/templates/app_manager/form_view.html +++ b/corehq/apps/app_manager/templates/app_manager/form_view.html @@ -14,10 +14,6 @@ {% endblock %} -{% block head %}{{ block.super }} - {% include 'analytics/fullstory.html' %} -{% endblock %} - {% block js %}{{ block.super }} {% compress js %} @@ -312,5 +308,6 @@ {% block modals %}{{ block.super }} {% include "app_manager/partials/forms/form_view_modals.html" %} - {% include "app_manager/partials/nav_menu_media_modals.html" %} + {% include "hqmedia/partials/multimedia_uploader.html" with id=multimedia.upload_managers.icon.slug type="image" %} + {% include "hqmedia/partials/multimedia_uploader.html" with id=multimedia.upload_managers.audio.slug type="audio" %} {% endblock modals %} diff --git a/corehq/apps/app_manager/templates/app_manager/module_view.html b/corehq/apps/app_manager/templates/app_manager/module_view.html index ff998f6b2707..b5156fcfddc9 100644 --- a/corehq/apps/app_manager/templates/app_manager/module_view.html +++ b/corehq/apps/app_manager/templates/app_manager/module_view.html @@ -5,10 +5,6 @@ {% load i18n %} {% load xforms_extras %} -{% block head %}{{ block.super }} - {% include 'analytics/fullstory.html' %} -{% endblock %} - {% block title %}{{ module.name|clean_trans:langs }} - {% trans 'Menu Settings' %}{% endblock %} {% block stylesheets %}{{ block.super }} @@ -197,10 +193,11 @@ {% endblock %} {% block modals %}{{ block.super }} - {% include "app_manager/partials/nav_menu_media_modals.html" %} + {% include "hqmedia/partials/multimedia_uploader.html" with id=multimedia.upload_managers.icon.slug type="image" %} + {% include "hqmedia/partials/multimedia_uploader.html" with id=multimedia.upload_managers.audio.slug type="audio" %} {% if request|toggle_enabled:"CASE_DETAIL_PRINT" %} {% with print_uploader as uploader %} - {% include 'hqmedia/partials/multimedia_uploader.html' %} + {% include 'hqmedia/partials/multimedia_uploader.html' with id=uploader.slug type=uploader.media_type %} {% endwith %} {% endif %} {% endblock modals %} diff --git a/corehq/apps/app_manager/templates/app_manager/module_view_report.html b/corehq/apps/app_manager/templates/app_manager/module_view_report.html index 8ce309802c7f..55aaed76cec8 100644 --- a/corehq/apps/app_manager/templates/app_manager/module_view_report.html +++ b/corehq/apps/app_manager/templates/app_manager/module_view_report.html @@ -41,6 +41,7 @@ {% endblock %} {% block modals %}{{ block.super }} - {% include "app_manager/partials/nav_menu_media_modals.html" %} + {% include "hqmedia/partials/multimedia_uploader.html" with id=multimedia.upload_managers.icon.slug type="image" %} + {% include "hqmedia/partials/multimedia_uploader.html" with id=multimedia.upload_managers.audio.slug type="audio" %} {% include 'app_manager/partials/modules/graph_configuration_modal.html' %} {% endblock modals %} diff --git a/corehq/apps/app_manager/templates/app_manager/partials/mobile_ucr_v1_warning.html b/corehq/apps/app_manager/templates/app_manager/partials/mobile_ucr_v1_warning.html new file mode 100644 index 000000000000..d8c460b22300 --- /dev/null +++ b/corehq/apps/app_manager/templates/app_manager/partials/mobile_ucr_v1_warning.html @@ -0,0 +1,12 @@ +{% load i18n %} +{% load hq_shared_tags %} +{% load xforms_extras %} + +
+

+ + {% trans "Warning" %}

+ + {{ warning_message }} + +
diff --git a/corehq/apps/app_manager/templates/app_manager/partials/nav_menu_media_modals.html b/corehq/apps/app_manager/templates/app_manager/partials/nav_menu_media_modals.html deleted file mode 100644 index 68c072a46e50..000000000000 --- a/corehq/apps/app_manager/templates/app_manager/partials/nav_menu_media_modals.html +++ /dev/null @@ -1,81 +0,0 @@ -{% load hq_shared_tags %} -{% load i18n %} - - - diff --git a/corehq/apps/app_manager/templates/app_manager/partials/nav_menu_media_single_type.html b/corehq/apps/app_manager/templates/app_manager/partials/nav_menu_media_single_type.html index 47e35ad25333..280feb8d71e6 100644 --- a/corehq/apps/app_manager/templates/app_manager/partials/nav_menu_media_single_type.html +++ b/corehq/apps/app_manager/templates/app_manager/partials/nav_menu_media_single_type.html @@ -51,16 +51,6 @@ {% trans 'Set Path' %} - {% if type == "audio" %} -

- - {% blocktrans %} - To hear audio on Java Phones, you must be in CommCare Sense - mode or Numeric Selection Mode. (On Android it will always work.) - {% endblocktrans %} -

- {% endif %} {% if app.langs|length > 1%}
diff --git a/corehq/apps/cloudcare/templates/cloudcare/partials/grid_view/landing_page_app.html b/corehq/apps/cloudcare/templates/cloudcare/partials/grid_view/landing_page_app.html deleted file mode 100644 index c13910315e33..000000000000 --- a/corehq/apps/cloudcare/templates/cloudcare/partials/grid_view/landing_page_app.html +++ /dev/null @@ -1,17 +0,0 @@ - diff --git a/corehq/apps/cloudcare/templates/cloudcare/partials/menu/breadcrumbs.html b/corehq/apps/cloudcare/templates/cloudcare/partials/menu/breadcrumbs.html index db01c111ba2d..7c3a2d46528a 100644 --- a/corehq/apps/cloudcare/templates/cloudcare/partials/menu/breadcrumbs.html +++ b/corehq/apps/cloudcare/templates/cloudcare/partials/menu/breadcrumbs.html @@ -1,17 +1,17 @@ {% load i18n %} diff --git a/corehq/apps/cloudcare/templates/cloudcare/partials/menu/dropdown.html b/corehq/apps/cloudcare/templates/cloudcare/partials/menu/dropdown.html index 6af06c205794..f88811e9121c 100644 --- a/corehq/apps/cloudcare/templates/cloudcare/partials/menu/dropdown.html +++ b/corehq/apps/cloudcare/templates/cloudcare/partials/menu/dropdown.html @@ -2,12 +2,12 @@ + + diff --git a/corehq/apps/cloudcare/templates/cloudcare/partials/sessions/list.html b/corehq/apps/cloudcare/templates/cloudcare/partials/sessions/list.html index 259ff5f35e9b..fb60765a3490 100644 --- a/corehq/apps/cloudcare/templates/cloudcare/partials/sessions/list.html +++ b/corehq/apps/cloudcare/templates/cloudcare/partials/sessions/list.html @@ -1,7 +1,7 @@ {% load i18n %} + + diff --git a/corehq/apps/cloudcare/templates/cloudcare/preview_app.html b/corehq/apps/cloudcare/templates/cloudcare/preview_app.html index 1de3beb6e50d..939f830bded7 100644 --- a/corehq/apps/cloudcare/templates/cloudcare/preview_app.html +++ b/corehq/apps/cloudcare/templates/cloudcare/preview_app.html @@ -72,12 +72,8 @@ {% if request.couch_user.can_edit_data %} -
+
{% endif %} {% endblock %} diff --git a/corehq/apps/cloudcare/tests/test_session.py b/corehq/apps/cloudcare/tests/test_session.py index 735cc256aa25..5852549afdda 100644 --- a/corehq/apps/cloudcare/tests/test_session.py +++ b/corehq/apps/cloudcare/tests/test_session.py @@ -70,6 +70,7 @@ def test_user_data_profile(self): def test_load_session_data_for_web_user(self): user = WebUser.create(None, 'web-user@example.com', '123', None, None) + self.addCleanup(user.delete, None, None) data = get_user_contributions_to_touchforms_session('cloudcare-tests', user) self.assertEqual('web-user@example.com', data['username']) self.assertEqual(user._id, data['user_id']) diff --git a/corehq/apps/commtrack/static/commtrack/images/goodstock.png b/corehq/apps/commtrack/static/commtrack/images/goodstock.png deleted file mode 100644 index 89c8129a490b..000000000000 Binary files a/corehq/apps/commtrack/static/commtrack/images/goodstock.png and /dev/null differ diff --git a/corehq/apps/commtrack/static/commtrack/images/no_data.png b/corehq/apps/commtrack/static/commtrack/images/no_data.png deleted file mode 100644 index 041bdbf735fb..000000000000 Binary files a/corehq/apps/commtrack/static/commtrack/images/no_data.png and /dev/null differ diff --git a/corehq/apps/commtrack/static/commtrack/images/overstock.png b/corehq/apps/commtrack/static/commtrack/images/overstock.png deleted file mode 100644 index 64181d236ed2..000000000000 Binary files a/corehq/apps/commtrack/static/commtrack/images/overstock.png and /dev/null differ diff --git a/corehq/apps/commtrack/static/commtrack/images/stockout.png b/corehq/apps/commtrack/static/commtrack/images/stockout.png deleted file mode 100644 index ab6808fba554..000000000000 Binary files a/corehq/apps/commtrack/static/commtrack/images/stockout.png and /dev/null differ diff --git a/corehq/apps/commtrack/static/commtrack/images/warning.png b/corehq/apps/commtrack/static/commtrack/images/warning.png deleted file mode 100644 index 81e9ed29a560..000000000000 Binary files a/corehq/apps/commtrack/static/commtrack/images/warning.png and /dev/null differ diff --git a/corehq/apps/custom_data_fields/edit_entity.py b/corehq/apps/custom_data_fields/edit_entity.py index 2852fa56ffca..67354e97852e 100644 --- a/corehq/apps/custom_data_fields/edit_entity.py +++ b/corehq/apps/custom_data_fields/edit_entity.py @@ -33,6 +33,11 @@ def with_prefix(string, prefix): return "{}-{}".format(prefix, string) +def without_prefix(string, prefix): + prefix_len = len(prefix) + 1 + return string[prefix_len:] if string.startswith(prefix) else string + + def add_prefix(field_dict, prefix): """ Prefix all keys in the dict. @@ -131,13 +136,45 @@ def _make_field(self, field): else: return forms.CharField(label=safe_label, required=field.is_required) + def make_fieldsets(self, form_fields, is_post, field_name_includes_prefix=False): + if self.ko_model: + field_names = [] + for field_name, field in form_fields.items(): + data_bind_field_name = ( + without_prefix(field_name, self.prefix) if field_name_includes_prefix else field_name) + data_binds = [ + f"value: {self.ko_model}.{data_bind_field_name}.value", + f"disable: {self.ko_model}.{data_bind_field_name}.disable", + ] + if hasattr(field, 'choices') or without_prefix(field_name, self.prefix) == PROFILE_SLUG: + data_binds.append("select2: " + json.dumps([ + {"id": id, "text": text} for id, text in field.widget.choices + ])) + field_names.append(Field( + field_name, + data_bind=", ".join(data_binds) + )) + else: + field_names = list(form_fields) + + form_fieldsets = [] + if field_names: + form_fieldsets.append(Fieldset( + _("Additional Information"), + *field_names, + css_class="custom-data-fieldset" + )) + if not is_post: + form_fieldsets.append(self.uncategorized_form) + return form_fieldsets + @property @memoized def fields(self): return list(self.model.get_fields(required_only=self.required_only)) def init_form(self, post_dict=None): - fields = OrderedDict() + form_fields = OrderedDict() from corehq.apps.users.views.mobile import UserFieldsView has_profile_privilege_and_is_user_fields_view = ( @@ -167,7 +204,7 @@ def validate_profile_slug(value): } if not self.ko_model: attrs.update({'class': 'hqwebapp-select2'}) - fields[PROFILE_SLUG] = forms.IntegerField( + form_fields[PROFILE_SLUG] = forms.IntegerField( label=_('Profile'), required=False, widget=Select(choices=[ @@ -177,74 +214,49 @@ def validate_profile_slug(value): validators=[validate_profile_slug], ) for field in self.fields: - fields[field.slug] = self._make_field(field) - - if self.ko_model: - field_names = [] - for field_name, field in fields.items(): - data_binds = [ - f"value: {self.ko_model}.{field_name}.value", - f"disable: {self.ko_model}.{field_name}.disable", - ] - if hasattr(field, 'choices') or field_name == PROFILE_SLUG: - data_binds.append("select2: " + json.dumps([ - {"id": id, "text": text} for id, text in field.widget.choices - ])) - field_names.append(Field( - field_name, - data_bind=", ".join(data_binds) - )) - else: - field_names = list(fields) + form_fields[field.slug] = self._make_field(field) - CustomDataForm = type('CustomDataForm', (forms.Form,), fields) + CustomDataForm = type('CustomDataForm', (forms.Form,), form_fields.copy()) if self.ko_model: CustomDataForm.helper = HQModalFormHelper() else: CustomDataForm.helper = HQFormHelper() CustomDataForm.helper.form_tag = False - additional_fields = [] - if field_names: - additional_fields.append(Fieldset( - _("Additional Information"), - *field_names, - css_class="custom-data-fieldset" - )) - if post_dict is None: - additional_fields.append(self.uncategorized_form) + form_fieldsets = self.make_fieldsets(form_fields, post_dict is not None) + CustomDataForm.helper.layout = Layout( - *additional_fields + *form_fieldsets ) CustomDataForm._has_uncategorized = bool(self.uncategorized_form) and post_dict is None if post_dict: - fields = post_dict.copy() # make mutable + form_data = post_dict.copy() # make mutable elif self.existing_custom_data is not None: - fields = add_prefix(self.existing_custom_data, self.prefix) + form_data = add_prefix(self.existing_custom_data, self.prefix) else: - fields = None + form_data = None # Add profile fields so that form validation passes - if fields and has_profile_privilege_and_is_user_fields_view: + if form_data and has_profile_privilege_and_is_user_fields_view: # When a field is disabled via knockout, it is not included in POST so this # adds it back if (post_dict and (with_prefix(PROFILE_SLUG, self.prefix)) not in post_dict and not can_edit_original_profile): - fields.update({with_prefix(PROFILE_SLUG, self.prefix): original_profile_id}) + form_data.update({with_prefix(PROFILE_SLUG, self.prefix): original_profile_id}) try: profile_fields = CustomDataFieldsProfile.objects.get( - id=int(fields.get(with_prefix(PROFILE_SLUG, self.prefix))), + id=int(form_data.get(with_prefix(PROFILE_SLUG, self.prefix))), definition__field_type=self.field_view.field_type, definition__domain=self.domain, ).fields except (ValueError, TypeError, CustomDataFieldsProfile.DoesNotExist): profile_fields = {} - fields.update(add_prefix(profile_fields, self.prefix)) + form_data.update(add_prefix(profile_fields, self.prefix)) - self.form = CustomDataForm(fields, prefix=self.prefix) + self.form = CustomDataForm(form_data, prefix=self.prefix) return self.form @property diff --git a/corehq/apps/dashboard/static/dashboard/js/dashboard.js b/corehq/apps/dashboard/static/dashboard/js/dashboard.js index 5f345232a4ec..ccc45ffca4c5 100644 --- a/corehq/apps/dashboard/static/dashboard/js/dashboard.js +++ b/corehq/apps/dashboard/static/dashboard/js/dashboard.js @@ -4,7 +4,7 @@ hqDefine("dashboard/js/dashboard", [ 'knockout', 'underscore', 'hqwebapp/js/initial_page_data', - 'hqwebapp/js/bootstrap5/components.ko', // pagination widget + 'hqwebapp/js/components/pagination', 'hqwebapp/js/bootstrap5/main', // post-link function 'hqwebapp/js/bootstrap5/knockout_bindings.ko', // popover ], function ( diff --git a/corehq/apps/data_dictionary/static/data_dictionary/js/data_dictionary.js b/corehq/apps/data_dictionary/static/data_dictionary/js/data_dictionary.js index 011536975ca2..fda23e481f50 100644 --- a/corehq/apps/data_dictionary/static/data_dictionary/js/data_dictionary.js +++ b/corehq/apps/data_dictionary/static/data_dictionary/js/data_dictionary.js @@ -122,6 +122,7 @@ hqDefine("data_dictionary/js/data_dictionary", [ self.description = ko.observable(description); self.caseType = caseType; self.properties = ko.observableArray(); + self.newPropertyName = ko.observable(); self.expanded = ko.observable(true); self.toggleExpanded = () => self.expanded(!self.expanded()); self.deprecated = deprecated; @@ -139,6 +140,27 @@ hqDefine("data_dictionary/js/data_dictionary", [ return self.toBeDeprecated() && !deprecated && self.properties().length > 0; }); + self.newCaseProperty = function () { + if (self.newPropertyName().trim()) { + const prop = { + 'name': self.newPropertyName(), + 'label': self.newPropertyName(), + 'allowedValues': {}, + }; + let propObj = propertyListItem( + prop, + false, + self.name(), + self.caseType, + false, + self.name(), + changeSaveButton + ); + self.newPropertyName(undefined); + self.properties.push(propObj); + } + }; + self.name.subscribe(changeSaveButton); self.description.subscribe(changeSaveButton); self.toBeDeprecated.subscribe(changeSaveButton); @@ -521,19 +543,19 @@ hqDefine("data_dictionary/js/data_dictionary", [ return pattern.test(nameStr); } - self.newPropertyNameValid = ko.computed(function () { - if (!self.newPropertyName()) { + self.newPropertyNameValid = function (name) { + if (!name) { return true; } - return isNameValid(self.newPropertyName()); - }); + return isNameValid(name); + }; - self.newPropertyNameUnique = ko.computed(function () { - if (!self.newPropertyName()) { + self.newPropertyNameUnique = function (name) { + if (!name) { return true; } - const propertyNameFormatted = self.newPropertyName().toLowerCase().trim(); + const propertyNameFormatted = name.toLowerCase().trim(); const activeCaseTypeData = self.activeCaseTypeData(); for (const group of activeCaseTypeData) { if (group.properties().find(v => v.name.toLowerCase() === propertyNameFormatted)) { @@ -541,7 +563,7 @@ hqDefine("data_dictionary/js/data_dictionary", [ } } return true; - }); + }; self.newGroupNameValid = ko.computed(function () { if (!self.newGroupName()) { @@ -565,28 +587,6 @@ hqDefine("data_dictionary/js/data_dictionary", [ return true; }); - self.newCaseProperty = function () { - if (_.isString(self.newPropertyName()) && self.newPropertyName().trim()) { - let lastGroup = self.activeCaseTypeData()[self.activeCaseTypeData().length - 1]; - const prop = { - 'name': self.newPropertyName(), - 'label': self.newPropertyName(), - 'allowedValues': {}, - }; - let propObj = propertyListItem( - prop, - false, - lastGroup.name(), - self.activeCaseType(), - false, - lastGroup.name(), - changeSaveButton - ); - self.newPropertyName(undefined); - lastGroup.properties.push(propObj); - } - }; - self.newGroup = function () { if (_.isString(self.newGroupName()) && self.newGroupName().trim()) { var group = groupsViewModel( diff --git a/corehq/apps/data_dictionary/templates/data_dictionary/base.html b/corehq/apps/data_dictionary/templates/data_dictionary/base.html index 9c347d361f44..594ee88330f9 100644 --- a/corehq/apps/data_dictionary/templates/data_dictionary/base.html +++ b/corehq/apps/data_dictionary/templates/data_dictionary/base.html @@ -93,7 +93,8 @@ {% trans "Description" %}
- +
@@ -200,10 +201,11 @@

{% trans "Case Property" %}
+
{% trans "Label" %}
{% if request|toggle_enabled:"CASE_IMPORT_DATA_DICTIONARY_VALIDATION" %}
{% trans "Data Type" %}
{% endif %} -
{% trans "Description" %}
+
{% trans "Description" %}
{% if fhir_integration_enabled %}
{% trans "FHIR Resource Property Path" %}
{% endif %} @@ -215,12 +217,16 @@

{% endif %} -
+
@@ -239,15 +245,17 @@

+
+  {# Empty cell where "Label" is in case property rows #} +
{% if request|toggle_enabled:"CASE_IMPORT_DATA_DICTIONARY_VALIDATION" %}
{% trans "Case Property Group" %}
{% endif %} -
+
- +
{% if fhir_integration_enabled %} @@ -278,17 +286,15 @@

-
- - - - -
+
+ +
{% if request|toggle_enabled:"CASE_IMPORT_DATA_DICTIONARY_VALIDATION" %}
+
+
{% if fhir_integration_enabled %}
@@ -363,30 +369,51 @@

+ + {% if not request.is_view_only %} +
+
+
+ + +
+ + {% blocktrans %} + A case property with this name already exists. + If you don’t see it on the page, please click ‘Show Deprecated’ button to reveal deprecated + properties. + {% endblocktrans %} + + + {% trans "Invalid case property name. It should start with a letter, and only contain letters, numbers, '-', and '_'" %} + +
+ +
+
+
+ {% endif %} +
+ {% if not request.is_view_only %} -
- - -
- - {% blocktrans %} - A case property with this name already exists. - If you don’t see it on the page, please click ‘Show Deprecated’ button to reveal deprecated - properties. - {% endblocktrans %} - - - {% trans "Invalid case property name. It should start with a letter, and only contain letters, numbers, '-', and '_'" %} - -
-
-
+ {% else %} +
{{ report.subtitle|default:" " }}
+ {% endif %}

@@ -32,4 +38,6 @@

{% endfor %}
+ + {% include 'enterprise/partials/date_range_modal.html' %} {% endblock %} diff --git a/corehq/apps/enterprise/templates/enterprise/partials/date_range_modal.html b/corehq/apps/enterprise/templates/enterprise/partials/date_range_modal.html new file mode 100644 index 000000000000..7118a7aec50a --- /dev/null +++ b/corehq/apps/enterprise/templates/enterprise/partials/date_range_modal.html @@ -0,0 +1,26 @@ +{% load hq_shared_tags %} +{% load i18n %} + + diff --git a/corehq/apps/enterprise/tests/test_enterprise.py b/corehq/apps/enterprise/tests/test_enterprise.py index 79a34c8c21f8..1f0725dac311 100644 --- a/corehq/apps/enterprise/tests/test_enterprise.py +++ b/corehq/apps/enterprise/tests/test_enterprise.py @@ -3,11 +3,15 @@ from freezegun import freeze_time from unittest.mock import patch, MagicMock +from corehq.apps.enterprise.exceptions import TooMuchRequestedDataError from corehq.apps.export.models.new import FormExportInstance from corehq.apps.accounting.models import BillingAccount from corehq.apps.domain.models import Domain from corehq.apps.export.dbaccessors import ODataExportFetcher -from corehq.apps.enterprise.enterprise import EnterpriseODataReport, EnterpriseFormReport +from corehq.apps.enterprise.enterprise import ( + EnterpriseODataReport, + EnterpriseFormReport, +) @override_settings(BASE_ADDRESS='localhost:8000') @@ -169,7 +173,7 @@ def test_constructor_with_only_end_date_uses_num_days(self): def test_specifying_timespan_greater_than_90_days_throws_error(self): end_date = datetime(month=10, day=1, year=2020) - with self.assertRaises(ValueError): + with self.assertRaises(TooMuchRequestedDataError): EnterpriseFormReport(self.billing_account, None, end_date=end_date, num_days=91) def test_specifying_timespans_up_to_90_days_works(self): diff --git a/corehq/apps/enterprise/tests/test_iterators.py b/corehq/apps/enterprise/tests/test_iterators.py new file mode 100644 index 000000000000..3ffc80c12a7c --- /dev/null +++ b/corehq/apps/enterprise/tests/test_iterators.py @@ -0,0 +1,19 @@ +from django.test import SimpleTestCase + +from corehq.apps.enterprise.iterators import raise_after_max_elements + + +class TestRaiseAfterMaxElements(SimpleTestCase): + def test_iterating_beyond_max_items_will_raise_the_default_exception(self): + it = raise_after_max_elements([1, 2, 3], 2) + with self.assertRaisesMessage(Exception, 'Too Many Elements'): + list(it) + + def test_iterating_beyond_max_items_will_raise_provided_exception(self): + it = raise_after_max_elements([1, 2, 3], 2, Exception('Test Message')) + with self.assertRaisesMessage(Exception, 'Test Message'): + list(it) + + def test_can_iterate_through_all_elements_with_no_exception(self): + it = raise_after_max_elements([1, 2, 3], 3) + self.assertEqual(list(it), [1, 2, 3]) diff --git a/corehq/apps/enterprise/tests/test_permissions.py b/corehq/apps/enterprise/tests/test_permissions.py index bca8ff69f1b6..cd460fc127f4 100644 --- a/corehq/apps/enterprise/tests/test_permissions.py +++ b/corehq/apps/enterprise/tests/test_permissions.py @@ -7,6 +7,7 @@ from .utils import create_enterprise_permissions from corehq.apps.domain.models import Domain from corehq.apps.domain.shortcuts import create_domain +from corehq.apps.enterprise.models import EnterprisePermissions from corehq.apps.fixtures.resources.v0_1 import InternalFixtureResource from corehq.apps.users.models import ( HQApiKey, @@ -68,6 +69,36 @@ def tearDownClass(cls): Domain.get_by_name('staging').delete() super().tearDownClass() + def test_get_by_domain(self): + # Any domain in the account can be used to get the config + configs = [ + EnterprisePermissions.get_by_domain('state'), + EnterprisePermissions.get_by_domain('county'), + EnterprisePermissions.get_by_domain('staging'), + ] + for config in configs: + self.assertTrue(config.is_enabled) + self.assertEqual(config.source_domain, 'state') + self.assertListEqual(config.domains, ['county']) + + empty_config = EnterprisePermissions.get_by_domain('not-a-domain') + self.assertFalse(empty_config.is_enabled) + + def test_get_source_domain(self): + self.assertEqual(EnterprisePermissions.get_source_domain('state'), None) + self.assertEqual(EnterprisePermissions.get_source_domain('county'), 'state') + self.assertEqual(EnterprisePermissions.get_source_domain('staging'), None) + + def test_get_domains(self): + self.assertListEqual(EnterprisePermissions.get_domains('state'), ['county']) + self.assertListEqual(EnterprisePermissions.get_domains('county'), []) + self.assertListEqual(EnterprisePermissions.get_domains('staging'), []) + + def test_is_source_domain(self): + self.assertTrue(EnterprisePermissions.is_source_domain('state')) + self.assertFalse(EnterprisePermissions.is_source_domain('county')) + self.assertFalse(EnterprisePermissions.is_source_domain('staging')) + def test_permission_mirroring(self): for domain in ('state', 'county'): self.assertTrue(self.web_user_admin.is_domain_admin(domain)) diff --git a/corehq/apps/enterprise/tests/test_views.py b/corehq/apps/enterprise/tests/test_views.py index 0f97389f5a96..84e7a298b6d0 100644 --- a/corehq/apps/enterprise/tests/test_views.py +++ b/corehq/apps/enterprise/tests/test_views.py @@ -1,12 +1,17 @@ -from django.test import SimpleTestCase, RequestFactory +from django.test import SimpleTestCase, TestCase, RequestFactory +from datetime import datetime from importlib import reload from unittest.mock import patch +from corehq.apps.accounting.tests.generator import billing_account from corehq.apps.enterprise import views +from corehq.apps.enterprise.enterprise import EnterpriseReport from corehq.apps.enterprise import decorators as enterprise_decorators from corehq.apps.domain import decorators as domain_decorators +from corehq.apps.users.models import WebUser + from codecs import BOM_UTF8 @@ -58,3 +63,48 @@ def _patch_decorators(cls): domain_decorators, 'login_and_domain_required', lambda x: x) login_and_domain_required_patcher.start() cls.addClassCleanup(login_and_domain_required_patcher.stop) + + +class EnterpriseDashboardEmailTests(TestCase): + def test_custom_date_range_is_not_required(self): + request = RequestFactory().get('/') + request.couch_user = WebUser(username='test-user') + request.account = billing_account(request.couch_user, request.couch_user) + + with patch.object(views, 'email_enterprise_report') as mocked: + views.enterprise_dashboard_email(request, 'test-domain', EnterpriseReport.FORM_SUBMISSIONS) + kwargs = mocked.delay.call_args[1] + self.assertNotIn('start_date', kwargs) + self.assertNotIn('end_date', kwargs) + + def test_custom_date_range_is_sent_to_celery(self): + request = RequestFactory().get('/', data={ + 'start_date': '2015-04-08T00:00:00.000000Z', + 'end_date': '2015-04-10T00:00:00.000000Z' + }) + request.couch_user = WebUser(username='test-user') + request.account = billing_account(request.couch_user, request.couch_user) + + with patch.object(views, 'email_enterprise_report') as mocked: + views.enterprise_dashboard_email(request, 'test-domain', EnterpriseReport.FORM_SUBMISSIONS) + kwargs = mocked.delay.call_args[1] + self.assertEqual(kwargs['start_date'], datetime(year=2015, month=4, day=8)) + self.assertEqual(kwargs['end_date'], datetime(year=2015, month=4, day=10)) + + @classmethod + def setUpClass(cls): + super().setUpClass() + cls._patch_decorators() + reload(views) + + @classmethod + def _patch_decorators(cls): + require_enterprise_admin_patcher = patch.object( + enterprise_decorators, 'require_enterprise_admin', lambda x: x) + require_enterprise_admin_patcher.start() + cls.addClassCleanup(require_enterprise_admin_patcher.stop) + + login_and_domain_required_patcher = patch.object( + domain_decorators, 'login_and_domain_required', lambda x: x) + login_and_domain_required_patcher.start() + cls.addClassCleanup(login_and_domain_required_patcher.stop) diff --git a/corehq/apps/enterprise/views.py b/corehq/apps/enterprise/views.py index ec850e0084e6..7883da63ffb1 100644 --- a/corehq/apps/enterprise/views.py +++ b/corehq/apps/enterprise/views.py @@ -1,4 +1,5 @@ import json +from datetime import datetime from django.conf import settings from django.contrib import messages @@ -23,11 +24,13 @@ from corehq.apps.accounting.decorators import always_allow_project_access from corehq.apps.enterprise.decorators import require_enterprise_admin +from corehq.apps.enterprise.exceptions import TooMuchRequestedDataError from corehq.apps.enterprise.mixins import ManageMobileWorkersMixin from corehq.apps.enterprise.models import EnterprisePermissions from corehq.apps.enterprise.tasks import clear_enterprise_permissions_cache_for_all_users from couchexport.export import Format from dimagi.utils.couch.cache.cache_core import get_redis_client +from dimagi.utils.parsing import ISO_DATETIME_FORMAT from corehq import privileges from corehq.apps.accounting.models import ( @@ -44,20 +47,21 @@ from corehq.apps.domain.views.accounting import PAYMENT_ERROR_MESSAGES, InvoiceStripePaymentView, \ BulkStripePaymentView, WireInvoiceView, BillingStatementPdfView -from corehq.apps.enterprise.enterprise import EnterpriseReport +from corehq.apps.enterprise.enterprise import EnterpriseReport, EnterpriseFormReport from corehq.apps.enterprise.forms import EnterpriseSettingsForm from corehq.apps.enterprise.tasks import email_enterprise_report from corehq.apps.export.utils import get_default_export_settings_if_available -from corehq.apps.hqwebapp.decorators import use_bootstrap5 +from corehq.apps.hqwebapp.decorators import use_bootstrap5, use_tempusdominus from corehq.apps.hqwebapp.views import CRUDPaginatedViewMixin from corehq.apps.users.decorators import require_can_edit_or_view_web_users from corehq.const import USER_DATE_FORMAT +@use_tempusdominus @use_bootstrap5 @always_allow_project_access @require_enterprise_admin @@ -69,6 +73,7 @@ def enterprise_dashboard(request, domain): context = { 'account': request.account, 'domain': domain, + 'max_date_range_days': EnterpriseFormReport.MAX_DATE_RANGE_DAYS, 'reports': [EnterpriseReport.create(slug, request.account.id, request.couch_user) for slug in ( EnterpriseReport.DOMAINS, EnterpriseReport.WEB_USERS, @@ -87,7 +92,16 @@ def enterprise_dashboard(request, domain): @require_enterprise_admin @login_and_domain_required def enterprise_dashboard_total(request, domain, slug): - report = EnterpriseReport.create(slug, request.account.id, request.couch_user) + kwargs = {} + if slug == EnterpriseReport.FORM_SUBMISSIONS: + kwargs = get_form_submission_report_kwargs(request) + try: + report = EnterpriseReport.create(slug, request.account.id, request.couch_user, **kwargs) + except TooMuchRequestedDataError as e: + response = JsonResponse({'message': str(e)}) + response.status_code = 400 + return response + return JsonResponse({'total': report.total}) @@ -126,8 +140,17 @@ def _get_export_filename(request, slug): @require_enterprise_admin @login_and_domain_required def enterprise_dashboard_email(request, domain, slug): - report = EnterpriseReport.create(slug, request.account.id, request.couch_user) - email_enterprise_report.delay(domain, slug, request.couch_user) + kwargs = {} + if slug == EnterpriseReport.FORM_SUBMISSIONS: + kwargs = get_form_submission_report_kwargs(request) + try: + report = EnterpriseReport.create(slug, request.account.id, request.couch_user, **kwargs) + except TooMuchRequestedDataError as e: + response = JsonResponse({'message': str(e)}) + response.status_code = 400 + return response + + email_enterprise_report.delay(domain, slug, request.couch_user, **kwargs) message = _("Generating {title} report, will email to {email} when complete.").format(**{ 'title': report.title, 'email': request.couch_user.username, @@ -135,6 +158,17 @@ def enterprise_dashboard_email(request, domain, slug): return JsonResponse({'message': message}) +def get_form_submission_report_kwargs(request): + kwargs = {} + start_date = request.GET.get('start_date') + end_date = request.GET.get('end_date') + if start_date and end_date: + kwargs['start_date'] = datetime.strptime(start_date, ISO_DATETIME_FORMAT) + kwargs['end_date'] = datetime.strptime(end_date, ISO_DATETIME_FORMAT) + + return kwargs + + @use_bootstrap5 @require_enterprise_admin @login_and_domain_required diff --git a/corehq/apps/es/case_search.py b/corehq/apps/es/case_search.py index 6251e0631bdb..858884d859c2 100644 --- a/corehq/apps/es/case_search.py +++ b/corehq/apps/es/case_search.py @@ -233,7 +233,7 @@ def multiplex_to_adapter(domain): return None -def case_property_query(case_property_name, value, fuzzy=False, multivalue_mode=None): +def case_property_query(case_property_name, value, fuzzy=False, multivalue_mode=None, boost_first=False): """ Search for all cases where case property with name `case_property_name`` has text value `value` """ @@ -254,6 +254,15 @@ def case_property_query(case_property_name, value, fuzzy=False, multivalue_mode= queries.match(value, PROPERTY_VALUE, operator=multivalue_mode) ), ) + if boost_first: + return _base_property_query( + case_property_name, + filters.OR( + filters.term(PROPERTY_VALUE, value), + queries.match(value[0], PROPERTY_VALUE) + ) + + ) if not fuzzy and multivalue_mode in ['or', 'and']: return case_property_text_query(case_property_name, value, operator=multivalue_mode) return exact_case_property_text_query(case_property_name, value) diff --git a/corehq/apps/es/client.py b/corehq/apps/es/client.py index c3f1cbf51336..1a8a2267fe08 100644 --- a/corehq/apps/es/client.py +++ b/corehq/apps/es/client.py @@ -90,22 +90,18 @@ def index_exists(self, index): """ self._validate_single_index(index) try: - if self._es.indices.get(index, feature="_aliases", - expand_wildcards="none"): + if self._es.indices.get(index, expand_wildcards="none"): return True except NotFoundError: pass return False - def get_indices(self, full_info=False): + def get_indices(self): """Return the cluster index information of active indices. - :param full_info: ``bool`` whether to return the full index info - (default ``False``) :returns: ``dict`` """ - feature = "" if full_info else "_aliases,_settings" - return self._es.indices.get("_all", feature=feature) + return self._es.indices.get("_all") def get_aliases(self): """Return the cluster aliases information. @@ -439,8 +435,19 @@ def reindex( "conflicts": "proceed" } - # Should be removed after ES 5-6 migration - if copy_doc_ids: + # Should be removed after ES 5-6 migration + if copy_doc_ids and source == const.HQ_USERS_INDEX_NAME: + # Remove password from form index + reindex_body["script"] = { + "lang": "painless", + "source": """ + ctx._source.remove('password'); + if (!ctx._source.containsKey('doc_id')) { + ctx._source['doc_id'] = ctx._id; + } + """ + } + elif copy_doc_ids: reindex_body["script"] = { "lang": "painless", "source": """ @@ -646,7 +653,7 @@ def search(self, query, **kw): try: result = self._search(query, **kw) self._fix_hits_in_result(result) - self._report_and_fail_on_shard_failures(result) + self._report_and_fail_on_shard_failures(result, {"index": self.canonical_name}) except ElasticsearchException as exc: raise ESError(exc) return result @@ -687,7 +694,7 @@ def scroll(self, query, scroll=SCROLL_KEEPALIVE, size=None): # TODO: standardize all result collections returned by this class. try: for result in self._scroll(query, scroll, size): - self._report_and_fail_on_shard_failures(result) + self._report_and_fail_on_shard_failures(result, {"index": self.canonical_name}) self._fix_hits_in_result(result) for hit in result["hits"]["hits"]: yield hit @@ -752,7 +759,7 @@ def _scroll(self, query, scroll, size): # resulting in this method fetching a maximum `size * 2` # documents. # see: https://stackoverflow.com/a/63911571 - result = self._es.scroll(scroll_id, scroll=scroll) + result = self._es.scroll(scroll_id=scroll_id, scroll=scroll) scroll_id = result.get("_scroll_id") yield result if scroll_id is None or not result["hits"]["hits"]: @@ -991,7 +998,7 @@ def _fix_hits_in_result(self, result): self._fix_hit(hit) @staticmethod - def _report_and_fail_on_shard_failures(result): + def _report_and_fail_on_shard_failures(result, tags): """ Raise an ESShardFailure if there are shard failures in a search result (JSON) and report to datadog. @@ -1004,7 +1011,7 @@ def _report_and_fail_on_shard_failures(result): if not isinstance(result, dict): raise ValueError(f"invalid Elastic result object: {result}") if result.get("_shards", {}).get("failed"): - metrics_counter("commcare.es.partial_results") + metrics_counter("commcare.es.partial_results", tags=tags) # Example message: # "_shards: {"successful": 4, "failed": 1, "total": 5}" shard_info = json.dumps(result["_shards"]) diff --git a/corehq/apps/es/mappings/user_mapping.py b/corehq/apps/es/mappings/user_mapping.py index 28dfdf966490..aed7ebcfc77e 100644 --- a/corehq/apps/es/mappings/user_mapping.py +++ b/corehq/apps/es/mappings/user_mapping.py @@ -297,6 +297,7 @@ "location_id": { "type": "keyword" }, + # TODO: Remove password field when creating new mappings for this index. "password": { "type": "text" }, diff --git a/corehq/apps/es/tests/test_case_search_es.py b/corehq/apps/es/tests/test_case_search_es.py index 1215945b3d46..d0bd82c58c17 100644 --- a/corehq/apps/es/tests/test_case_search_es.py +++ b/corehq/apps/es/tests/test_case_search_es.py @@ -8,6 +8,7 @@ from couchforms.geopoint import GeoPoint +from corehq.privileges import DATA_DICTIONARY from corehq.apps.case_search.const import RELEVANCE_SCORE from corehq.apps.case_search.models import CaseSearchConfig from corehq.apps.case_search.xpath_functions.comparison import adjust_input_date_by_timezone @@ -29,7 +30,7 @@ from corehq.form_processor.models import CommCareCaseIndex from corehq.form_processor.tests.utils import FormProcessorTestUtils from corehq.pillows.case_search import CaseSearchReindexerFactory -from corehq.util.test_utils import create_and_save_a_case, flag_enabled +from corehq.util.test_utils import create_and_save_a_case, flag_enabled, privilege_enabled @es_test @@ -390,10 +391,11 @@ def _bootstrap_cases_in_es_for_domain(self, domain, input_cases): def _assert_query_runs_correctly(self, domain, input_cases, query, xpath_query, output): self._bootstrap_cases_in_es_for_domain(domain, input_cases) - self.assertItemsEqual( - query.get_ids(), - output - ) + if query: + self.assertItemsEqual( + query.get_ids(), + output + ) if xpath_query: self.assertItemsEqual( CaseSearchES().xpath_query(self.domain, xpath_query).get_ids(), @@ -434,6 +436,20 @@ def test_fuzzy_case_property_query(self): ['c3'] ) + def test_fuzzy_date(self): + self._assert_query_runs_correctly( + self.domain, + [ + {'_id': 'c1', 'dob': date(2020, 3, 1)}, + {'_id': 'c2', 'dob': date(2020, 1, 3)}, + {'_id': 'c3', 'dob': date(2002, 3, 1)}, + {'_id': 'c4', 'dob': date(2020, 3, 4)}, + ], + None, + "fuzzy-date(dob, '2020-03-01')", + ['c1', 'c2', 'c3'] + ) + def test_multiple_case_search_queries(self): query = (CaseSearchES().domain(self.domain) .case_property_query("foo", "redbeard") @@ -535,8 +551,8 @@ def test_case_property_query(self): ) ) - @flag_enabled('USH_CASE_CLAIM_UPDATES') @patch('corehq.pillows.case_search.get_gps_properties', return_value={'coords'}) + @privilege_enabled(DATA_DICTIONARY) def test_geopoint_query_for_gps_properties(self, _): self._bootstrap_cases_in_es_for_domain(self.domain, [ {'_id': 'c1', 'coords': "42.373611 -71.110558 0 0"}, diff --git a/corehq/apps/es/tests/test_client.py b/corehq/apps/es/tests/test_client.py index 9a17a95c6cd4..5f99d22335a9 100644 --- a/corehq/apps/es/tests/test_client.py +++ b/corehq/apps/es/tests/test_client.py @@ -11,6 +11,7 @@ from corehq.apps.es import const from corehq.apps.es.utils import check_task_progress, get_es_reindex_setting_value +from corehq.apps.users.models import CommCareUser from corehq.util.es.elasticsearch import ( BulkIndexError, Elasticsearch, @@ -268,21 +269,14 @@ def _clear_cluster_routing(self, verify=False): a transient setting once its set without restarting the cluster, so we explicitly set the default value (`all`) instead. """ - self.adapter.cluster_routing(enabled=True) # default value + try: + self.adapter._cluster_put_settings({"cluster.routing.allocation.enable": None}) + except TransportError: + # TransportError(400, 'action_request_validation_exception', 'Validation Failed: 1: no settings to update;') # noqa: E501 + pass if verify: settings = self.adapter._es.cluster.get_settings(flat_settings=True) - self.assertEqual(settings["transient"]["cluster.routing.allocation.enable"], "all") - # - # The code below is better. Use it instead when able Elastic v5+ - # - #try: - # self.adapter._cluster_put_settings({"cluster.routing.allocation.enable": None}) - #except TransportError: - # # TransportError(400, 'action_request_validation_exception', 'Validation Failed: 1: no settings to update;') # noqa: E501 - # pass - #if verify: - # settings = self.adapter._es.cluster.get_settings(flat_settings=True) - # self.assertIsNone(settings["transient"].get("cluster.routing.allocation.enable")) + self.assertIsNone(settings["transient"].get("cluster.routing.allocation.enable")) def test_get_node_info(self): info = self.adapter._es.nodes.info() @@ -584,6 +578,59 @@ def test_reindex_with_query_parameter_set(self): self.assertEqual(list(self._get_all_doc_ids_in_index(SUBINDEX)), ['7']) + def test_reindex_for_users_index(self): + from corehq.apps.es.users import user_adapter + + SECONDARY_INDEX = 'secondary_user_index' + domain = 'es_reindex_users_index' + + # Setup Indices + with temporary_index(user_adapter.index_name, user_adapter.type, user_adapter.mapping): + with temporary_index(SECONDARY_INDEX, user_adapter.type, user_adapter.mapping): + + mobile_user = CommCareUser( + _id='1', username="amazing_user", domain=domain, password='**************', + created_by=None, created_via=None + ) + + # Save user to the source index + with patch('corehq.apps.groups.dbaccessors.get_group_id_name_map_by_user', return_value=[]), \ + patch.object(user_adapter.model_cls, 'get_user_data', return_value={}): + + id, source = user_adapter.from_python(mobile_user) + # Manually set password field because now it is removed in from_python + source['password'] = '12345678' + manager._es.index( + user_adapter.index_name, + user_adapter.type, + source, + id, + refresh=True + ) + + # Get the saved user from ES + user_es = user_adapter.get(mobile_user._id) + + # Ensure that password field exists in the user dict + assert 'password' in user_es, "password does not exist in source index" + self.assertEqual(user_es['password'], '12345678') + + # Reindex the user index to the secondary index + with patch.object(const, 'HQ_USERS_INDEX_NAME', user_adapter.index_name): + manager.reindex( + user_adapter.index_name, SECONDARY_INDEX, + wait_for_completion=True, + refresh=True, + requests_per_second=2, + ) + + # Get the saved user from the secondary index + user = manager._es.search(index=SECONDARY_INDEX, body={})['hits']['hits'][0]['_source'] + # Ensure that password field does not exist in the user dict + print(user) + self.assertEqual(user['doc_id'], '1') + assert 'password' not in user, "password exists in source index" + def _index_test_docs_for_reindex(self): all_ids = set([str(i) for i in range(1, 10)]) @@ -643,7 +690,10 @@ def test_index_close(self): self.adapter.index_close(test_adapter.index_name) with self.assertRaises(TransportError) as test: test_adapter.index(TestDoc("2", "test")) - self.assertEqual(test.exception.status_code, 403) + if test_adapter.elastic_major_version <= 5: + self.assertEqual(test.exception.status_code, 403) + else: + self.assertEqual(test.exception.status_code, 400) self.assertEqual(test.exception.error, "index_closed_exception") def test_index_put_alias(self): @@ -771,7 +821,11 @@ def test_index_put_mapping_clears_existing_mapping_metadata(self): } self.adapter.index_create(self.index, {"mappings": {type_: mapping}}) self.assertEqual(self.adapter.index_get_mapping(self.index, type_), mapping) - del mapping["_meta"] + # To remove meta in Elastic 6.x, we have to pass an empty _meta field + # but in Elastic 5.x, we have to remove it entirely from the object + mapping["_meta"] = {} + if manager.elastic_major_version < 6: + del mapping["_meta"] self.adapter.index_put_mapping(self.index, type_, mapping) self.assertEqual(self.adapter.index_get_mapping(self.index, type_), mapping) diff --git a/corehq/apps/es/tests/test_migration_operations.py b/corehq/apps/es/tests/test_migration_operations.py index d3c0f6e3f21b..00c23a927e92 100644 --- a/corehq/apps/es/tests/test_migration_operations.py +++ b/corehq/apps/es/tests/test_migration_operations.py @@ -140,7 +140,10 @@ def test_fails_if_index_exists(self): migration = TestMigration(CreateIndex(*self.create_index_args)) with self.assertRaises(RequestError) as context: migration.apply() - self.assertEqual(context.exception.error, "index_already_exists_exception") + if manager.elastic_major_version >= 6: + self.assertEqual(context.exception.error, "resource_already_exists_exception") + else: + self.assertEqual(context.exception.error, "index_already_exists_exception") def test_reverse_deletes_index(self): migration = TestMigration(CreateIndex(*self.create_index_args)) @@ -473,7 +476,10 @@ def test_reverse_fails_if_index_exists(self): ) with self.assertRaises(RequestError) as context: migration.unapply() - self.assertEqual(context.exception.error, "index_already_exists_exception") + if manager.elastic_major_version >= 6: + self.assertEqual(context.exception.error, "resource_already_exists_exception") + else: + self.assertEqual(context.exception.error, "index_already_exists_exception") def test_describe(self): operation = DeleteIndex(self.index) @@ -637,8 +643,9 @@ def test_fails_for_existing_property_type_change(self): self.type, {"prop": {"type": "integer"}}, )) + error_type = "RequestError" if manager.elastic_major_version >= 6 else "TransportError" literal = ( - "TransportError(400, 'illegal_argument_exception', 'mapper [prop] " + f"{error_type}(400, 'illegal_argument_exception', 'mapper [prop] " "of different type, current_type [text], merged_type [integer]')" ) with self.assertRaisesRegex(RequestError, f"^{re.escape(literal)}$"): @@ -654,8 +661,9 @@ def test_fails_for_changing_existing_property_index_values(self): self.type, {"prop": {"type": "keyword"}}, )) + error_type = "RequestError" if manager.elastic_major_version >= 6 else "TransportError" literal = ( - "TransportError(400, 'illegal_argument_exception', " + f"{error_type}(400, 'illegal_argument_exception', " "'mapper [prop] of different type, current_type [text], merged_type [keyword]')" ) with self.assertRaisesRegex(RequestError, f"^{re.escape(literal)}$"): diff --git a/corehq/apps/es/tests/test_test_utils.py b/corehq/apps/es/tests/test_test_utils.py index 612efd45c2a3..22b490e9311c 100644 --- a/corehq/apps/es/tests/test_test_utils.py +++ b/corehq/apps/es/tests/test_test_utils.py @@ -1,5 +1,8 @@ +import re +from contextlib import nullcontext + +import pytest from django.test import SimpleTestCase -from nose.tools import assert_raises_regex from testil import assert_raises from unittest.mock import patch @@ -121,17 +124,14 @@ def test_only_dog_index_exists(self): @es_test_attr -def test_index_state_with_function_decorator(): - - @es_test(requires=[pigs_adapter]) - def test_pig_index_exists(): - assert_index_exists(pigs_adapter) +@es_test(requires=[pigs_adapter]) +def test_pig_index_exists(): + assert_index_exists(pigs_adapter) - def test_pig_index_does_not_exist(): - assert_not_index_exists(pigs_adapter) - yield test_pig_index_exists, - yield test_pig_index_does_not_exist, +@es_test_attr +def test_pig_index_does_not_exist(): + assert_not_index_exists(pigs_adapter) def assert_index_exists(adapter): @@ -148,47 +148,46 @@ def assert_not_index_exists(adapter): @es_test_attr def test_setup_class_expects_classmethod(): - with assert_raises_regex(ValueError, "^'setup_class' expects a classmethod"): + with assert_raises(ValueError, msg=re.compile("^'setup_class' expects a classmethod")): @es_test(requires=[pigs_adapter], setup_class=True) class TestExpectsClassmethod: def setUpClass(self): pass +@pytest.mark.parametrize("args", [ + (), # without type/mapping + ("test_doc", {"_meta": {}}), # with type/mapping +]) @es_test -def test_temporary_index(): +def test_temporary_index(args): index = "test_index" + with temporary_index(index, *args): + assert manager.index_exists(index) + assert not manager.index_exists(index) - def test_temporary_index_with_args(*args): - with temporary_index(index, *args): - assert manager.index_exists(index) - assert not manager.index_exists(index) - - yield test_temporary_index_with_args, # without type/mapping - yield test_temporary_index_with_args, "test_doc", {"_meta": {}} # with type/mapping +@pytest.mark.parametrize("has_index, type_, mapping", [ + # test while index exists + (True, "test_doc", None), # no mapping + (True, None, {}), # no type + # test while index does not exist + (False, "test_doc", None), # no mapping + (False, None, {}), # no type +]) @es_test -def test_temporary_index_fails_with_invalid_args(): +def test_temporary_index_fails_with_invalid_args(has_index, type_, mapping): index = "test_index" + with (temporary_index(index) if has_index else nullcontext()): + if has_index: + assert manager.index_exists(index) + else: + assert not manager.index_exists(index) - def test_temporary_index_with_args(type_, mapping): index_was_present = manager.index_exists(index) with assert_raises(ValueError): with temporary_index(index, type_, mapping): pass assert index_was_present == manager.index_exists(index), \ "unexpected index existence change" - - no_mapping = ("test_doc", None) - no_type = (None, {}) - - with temporary_index(index): - # test while index exists - assert manager.index_exists(index) - yield test_temporary_index_with_args, *no_mapping - yield test_temporary_index_with_args, *no_type - # test while index does not exist - assert not manager.index_exists(index) - yield test_temporary_index_with_args, *no_mapping - yield test_temporary_index_with_args, *no_type diff --git a/corehq/apps/es/tests/test_user_adapter.py b/corehq/apps/es/tests/test_user_adapter.py index 93974f62658f..8059a43f851f 100644 --- a/corehq/apps/es/tests/test_user_adapter.py +++ b/corehq/apps/es/tests/test_user_adapter.py @@ -33,6 +33,18 @@ def test_from_python_works_with_user_dicts(self): user_adapter.from_python(self.user.to_json()) user_adapter.from_python(self.web_user.to_json()) + def test_from_python_removes_password_field(self): + user_obj = self.user.to_json() + self.assertIn('password', user_obj) + user_es_obj = user_adapter.from_python(user_obj) + self.assertNotIn('password', user_es_obj) + + def test_from_python_works_fine_if_password_field_not_present(self): + user_obj = self.user.to_json() + user_obj.pop('password') + user_es_obj = user_adapter.from_python(user_obj) + self.assertNotIn('password', user_es_obj) + def test_from_python_raises_for_other_objects(self): self.assertRaises(TypeError, user_adapter.from_python, set) diff --git a/corehq/apps/es/tests/test_utils.py b/corehq/apps/es/tests/test_utils.py index 57128ba17d5e..5b4dd50f6abd 100644 --- a/corehq/apps/es/tests/test_utils.py +++ b/corehq/apps/es/tests/test_utils.py @@ -1,5 +1,6 @@ from datetime import date, datetime +import pytest from django.test.testcases import SimpleTestCase from pytz import UTC, timezone @@ -15,24 +16,21 @@ @es_test -def test_es_format_datetime(): - def _assert_returns(date_or_datetime, expected): - actual = es_format_datetime(date_or_datetime) - assert actual == expected, f"Expected {expected}, got {actual}" - - for date_or_datetime, expected in [ - ("04/28/21", "04/28/21"), - (date(2021, 4, 28), "2021-04-28"), - (datetime(2021, 4, 28), "2021-04-28T00:00:00"), - (datetime(2021, 4, 28, 11, 47, 22), "2021-04-28T11:47:22"), - (datetime(2021, 4, 28, 11, 47, 22, 3), "2021-04-28T11:47:22.000003"), - (datetime(2021, 4, 28, 11, 47, 22, 300000), "2021-04-28T11:47:22.300000"), - (datetime(2021, 4, 28, 11, tzinfo=UTC), "2021-04-28T11:00:00+00:00"), - (ET.localize(datetime(2021, 4, 28, 11)), "2021-04-28T11:00:00-04:00"), - # 2021-04-28T11:00:00.000001-04:00 isn't supported in ES, so convert to server time - (ET.localize(datetime(2021, 4, 28, 11, microsecond=1)), "2021-04-28T15:00:00.000001"), - ]: - yield _assert_returns, date_or_datetime, expected +@pytest.mark.parametrize("date_or_datetime, expected", [ + ("04/28/21", "04/28/21"), + (date(2021, 4, 28), "2021-04-28"), + (datetime(2021, 4, 28), "2021-04-28T00:00:00"), + (datetime(2021, 4, 28, 11, 47, 22), "2021-04-28T11:47:22"), + (datetime(2021, 4, 28, 11, 47, 22, 3), "2021-04-28T11:47:22.000003"), + (datetime(2021, 4, 28, 11, 47, 22, 300000), "2021-04-28T11:47:22.300000"), + (datetime(2021, 4, 28, 11, tzinfo=UTC), "2021-04-28T11:00:00+00:00"), + (ET.localize(datetime(2021, 4, 28, 11)), "2021-04-28T11:00:00-04:00"), + # 2021-04-28T11:00:00.000001-04:00 isn't supported in ES, so convert to server time + (ET.localize(datetime(2021, 4, 28, 11, microsecond=1)), "2021-04-28T15:00:00.000001"), +]) +def test_es_format_datetime(date_or_datetime, expected): + actual = es_format_datetime(date_or_datetime) + assert actual == expected, f"Expected {expected}, got {actual}" @es_test diff --git a/corehq/apps/es/tests/utils.py b/corehq/apps/es/tests/utils.py index a56865e0264d..15a227cb3d13 100644 --- a/corehq/apps/es/tests/utils.py +++ b/corehq/apps/es/tests/utils.py @@ -4,14 +4,14 @@ from functools import wraps from inspect import isclass -from nose.plugins.attrib import attr -from nose.tools import nottest +import pytest from pillowtop.es_utils import initialize_index_and_mapping from pillowtop.tests.utils import get_pillow_doc_adapter from corehq.apps.es.client import ElasticMultiplexAdapter from corehq.apps.es.migration_operations import CreateIndex +from corehq.tests.tools import nottest from corehq.tests.util.warnings import filter_warnings from corehq.util.elastic import ensure_index_deleted from corehq.util.es.elasticsearch import NotFoundError @@ -26,7 +26,7 @@ }, "properties": { "doc_type": { - "index": "not_analyzed", "type": "string" + "type": "keyword" }, } } @@ -39,7 +39,7 @@ UserWarning, ) -es_test_attr = attr(es_test=True) +es_test_attr = pytest.mark.es_test class TEST_ES_INFO: diff --git a/corehq/apps/es/transient_util.py b/corehq/apps/es/transient_util.py index 75dd2b4fce27..35e2cc16ee73 100644 --- a/corehq/apps/es/transient_util.py +++ b/corehq/apps/es/transient_util.py @@ -88,6 +88,7 @@ def populate_doc_adapter_map(): from pillowtop.tests.utils import TEST_ES_TYPE, TEST_ES_MAPPING, TEST_ES_INDEX add_dynamic_adapter("PillowTop", TEST_ES_INDEX, TEST_ES_TYPE, TEST_ES_MAPPING) + import corehq.tests.pytest_compat # noqa: F401 - to be removed after switch to pytest from corehq.apps.es.tests.utils import TEST_ES_INFO, TEST_ES_MAPPING add_dynamic_adapter("UtilES", TEST_ES_INFO.alias, TEST_ES_INFO.type, TEST_ES_MAPPING) diff --git a/corehq/apps/es/users.py b/corehq/apps/es/users.py index a1835e4b44cb..90c7a12aed41 100644 --- a/corehq/apps/es/users.py +++ b/corehq/apps/es/users.py @@ -104,6 +104,7 @@ def _from_dict(self, user_dict): user_dict['__group_ids'] = [res.id for res in results] user_dict['__group_names'] = [res.name for res in results] user_dict['user_data_es'] = [] + user_dict.pop('password', None) if user_dict.get('base_doc') == 'CouchUser' and user_dict['doc_type'] == 'CommCareUser': user_obj = self.model_cls.wrap_correctly(user_dict) user_data = user_obj.get_user_data(user_obj.domain) @@ -127,9 +128,9 @@ def domain(domain, allow_enterprise=False): domain_list = [domain] if allow_enterprise: from corehq.apps.enterprise.models import EnterprisePermissions - config = EnterprisePermissions.get_by_domain(domain) - if config.is_enabled and domain in config.domains: - domain_list.append(config.source_domain) + source_domain = EnterprisePermissions.get_source_domain(domain) + if source_domain: + domain_list.append(source_domain) return domains(domain_list) diff --git a/corehq/apps/events/static/events/js/event_attendees.js b/corehq/apps/events/static/events/js/event_attendees.js index 20b3324de464..336c49e6d7e0 100644 --- a/corehq/apps/events/static/events/js/event_attendees.js +++ b/corehq/apps/events/static/events/js/event_attendees.js @@ -6,7 +6,8 @@ hqDefine("events/js/event_attendees",[ 'jquery.rmi/jquery.rmi', 'locations/js/widgets', "hqwebapp/js/bootstrap3/widgets", - "hqwebapp/js/bootstrap3/components.ko", // for pagination + "hqwebapp/js/components/pagination", + "hqwebapp/js/components/search_box", ], function ( $, ko, @@ -111,24 +112,24 @@ hqDefine("events/js/event_attendees",[ return self; }; - var mobileWorkerAttendees = function() { + var mobileWorkerAttendees = function () { self.mobileWorkerAttendeesEnabled = ko.observable(false); self.buttonText = ko.observable(""); - self.toggleButtonText = function() { + self.toggleButtonText = function () { var button = document.getElementById("mobileWorkerAttendeeButton"); - if(self.mobileWorkerAttendeesEnabled()) { + if (self.mobileWorkerAttendeesEnabled()) { button.innerHTML = gettext("Disable Mobile Worker Attendees"); // Appending btn-danger will override btn-default - button.classList.add("btn-danger") - }else{ + button.classList.add("btn-danger"); + } else { button.innerHTML = gettext("Enable Mobile Worker Attendees"); // Simply removing btn-danger will effectively enable btn-default - button.classList.remove("btn-danger") - }; + button.classList.remove("btn-danger"); + } }; - self.loadMobileWorkerAttendeeConfig = function() { + self.loadMobileWorkerAttendeeConfig = function () { $.ajax({ method: 'GET', url: initialPageData.reverse('attendees_config'), diff --git a/corehq/apps/export/forms.py b/corehq/apps/export/forms.py index 9ef5382e4221..00d81a5cf988 100644 --- a/corehq/apps/export/forms.py +++ b/corehq/apps/export/forms.py @@ -9,7 +9,6 @@ import dateutil from crispy_forms import layout as crispy from crispy_forms.helper import FormHelper -from corehq.apps.hqwebapp import crispy as hqcrispy from crispy_forms.bootstrap import StrictButton from corehq import privileges @@ -933,9 +932,6 @@ def __init__(self, domain_object, *args, **kwargs): self.domain_object = domain_object super(EmwfFilterFormExport, self).__init__(domain_object, *args, **kwargs) - self.helper.label_class = 'col-sm-3 col-md-2 col-lg-2' - self.helper.field_class = 'col-sm-9 col-md-8 col-lg-3' - def get_model_filter(self, mobile_user_and_group_slugs, can_access_all_locations, accessible_location_ids): """ :param mobile_user_and_group_slugs: slug from request like @@ -989,8 +985,6 @@ def __init__(self, domain_object, timezone, *args, **kwargs): self.timezone = timezone super(FilterCaseESExportDownloadForm, self).__init__(domain_object, *args, **kwargs) - self.helper.label_class = 'col-sm-3 col-md-2 col-lg-2' - self.helper.field_class = 'col-sm-9 col-md-8 col-lg-3' # update date_range filter's initial values to span the entirety of # the domain's submission range default_datespan = datespan_from_beginning(self.domain_object, self.timezone) @@ -1047,8 +1041,6 @@ def __init__(self, domain_object, timezone, *args, **kwargs): self.timezone = timezone super(FilterSmsESExportDownloadForm, self).__init__(domain_object, *args, **kwargs) - self.helper.label_class = 'col-sm-3 col-md-2 col-lg-2' - self.helper.field_class = 'col-sm-9 col-md-8 col-lg-3' # update date_range filter's initial values to span the entirety of # the domain's submission range default_datespan = datespan_from_beginning(self.domain_object, self.timezone) @@ -1087,8 +1079,6 @@ class DatasourceExportDownloadForm(forms.Form): def __init__(self, domain, *args, **kwargs): super(DatasourceExportDownloadForm, self).__init__(*args, **kwargs) self.helper = FormHelper() - self.helper.label_class = 'col-sm-3 col-md-2 col-lg-2' - self.helper.field_class = 'col-sm-9 col-md-8 col-lg-3' self.fields['data_source'].choices = self.domain_datasources(domain) @@ -1104,14 +1094,12 @@ def __init__(self, domain, *args, **kwargs): data_bind='visible: haveDatasources' ), ), - hqcrispy.FormActions( - StrictButton( - _("Download Data Export Tool query file"), - type="submit", - css_class="btn-primary", - data_bind="enable: haveDatasources" - ), - ) + StrictButton( + _("Download Data Export Tool query file"), + type="submit", + css_class="btn-primary", + data_bind="enable: haveDatasources" + ), ) @staticmethod diff --git a/corehq/apps/export/models/new.py b/corehq/apps/export/models/new.py index 74dba4e0d090..dd94f03cd70c 100644 --- a/corehq/apps/export/models/new.py +++ b/corehq/apps/export/models/new.py @@ -1771,6 +1771,7 @@ def generate_schema_from_builds( only_process_current_builds=False, task=None, for_new_export_instance=False, + is_identifier_case_type=False, ): """ Builds a schema from Application builds for a given identifier @@ -1787,6 +1788,7 @@ def generate_schema_from_builds( processed. :param task: A celery task to update the progress of the build :param for_new_export_instance: Flag to be set if generating schema for a new export instance + :param is_identifier_case_type: boolean, if True, some optimizations are applied specific to case type :returns: Returns a ExportDataSchema instance """ @@ -1809,7 +1811,8 @@ def generate_schema_from_builds( ) app_build_ids.extend(app_ids_for_domain) current_schema = cls._process_apps_for_export(domain, current_schema, identifier, app_build_ids, task, - for_new_export_instance=for_new_export_instance) + for_new_export_instance=for_new_export_instance, + is_identifier_case_type=is_identifier_case_type) inferred_schema = cls._get_inferred_schema(domain, app_id, identifier) if inferred_schema: @@ -1955,7 +1958,7 @@ def _save_export_schema(current_schema, original_id, original_rev): @classmethod def _process_apps_for_export(cls, domain, schema, identifier, app_build_ids, task, - for_new_export_instance=False): + for_new_export_instance=False, is_identifier_case_type=False): apps_processed = 0 for app_doc in iter_docs(Application.get_db(), app_build_ids, chunksize=10): doc_type = app_doc.get('doc_type', '') @@ -1974,6 +1977,9 @@ def _process_apps_for_export(cls, domain, schema, identifier, app_build_ids, tas ) continue + if is_identifier_case_type and not app.case_type_exists(identifier): + continue + try: schema = cls._process_app_build( schema, @@ -2313,18 +2319,6 @@ def _get_stock_items_from_question(question, app_id, app_version, repeats): return items - @classmethod - def _process_apps_for_export(cls, domain, schema, identifier, app_build_ids, task, - for_new_export_instance=False): - return super(FormExportDataSchema, cls)._process_apps_for_export( - domain, - schema, - identifier, - app_build_ids, - task, - for_new_export_instance=for_new_export_instance - ) - class CaseExportDataSchema(ExportDataSchema): @@ -2544,7 +2538,7 @@ def _add_to_group_schema(group_schema, path_start, prop, app_id, app_version): @classmethod def _process_apps_for_export(cls, domain, schema, identifier, app_build_ids, task, - for_new_export_instance=False): + for_new_export_instance=False, is_identifier_case_type=False): if identifier == ALL_CASE_TYPE_EXPORT: return cls._process_apps_for_bulk_export(domain, schema, app_build_ids, task) else: @@ -2554,7 +2548,8 @@ def _process_apps_for_export(cls, domain, schema, identifier, app_build_ids, tas identifier, app_build_ids, task, - for_new_export_instance=for_new_export_instance + for_new_export_instance=for_new_export_instance, + is_identifier_case_type=is_identifier_case_type ) @classmethod @@ -2623,17 +2618,6 @@ def schema_version(cls): def get_latest_export_schema(domain, include_metadata, identifier=None): return SMSExportDataSchema(domain=domain, include_metadata=include_metadata) - def _process_apps_for_export(cls, domain, schema, identifier, app_build_ids, task, - for_new_export_instance=False): - return super(SMSExportDataSchema, cls)._process_apps_for_export( - domain, - schema, - identifier, - app_build_ids, - task, - for_new_export_instance=for_new_export_instance - ) - def _string_path_to_list(path): return path if path is None else path[1:].split('/') diff --git a/corehq/apps/export/static/export/js/create_export.js b/corehq/apps/export/static/export/js/create_export.js index 65530e88c13a..c01a2355d428 100644 --- a/corehq/apps/export/static/export/js/create_export.js +++ b/corehq/apps/export/static/export/js/create_export.js @@ -131,6 +131,7 @@ hqDefine("export/js/create_export", [ $formElem.select2({ data: self._app_types || [], width: '100%', + dropdownParent: $("#createExportOptionsModal"), }).val(drilldownDefaults.app_type).trigger('change'); } }, @@ -152,6 +153,7 @@ hqDefine("export/js/create_export", [ $formElem.select2({ data: fieldData || [], width: '100%', + dropdownParent: $("#createExportOptionsModal"), }).val(drilldownDefaults[fieldSlug]).trigger('change'); } } diff --git a/corehq/apps/export/static/export/js/customize_export_new.js b/corehq/apps/export/static/export/js/customize_export_new.js index ad36e80e2137..5aed55dbfd95 100644 --- a/corehq/apps/export/static/export/js/customize_export_new.js +++ b/corehq/apps/export/static/export/js/customize_export_new.js @@ -1,6 +1,7 @@ hqDefine('export/js/customize_export_new', [ 'jquery', 'knockout', + 'es6!hqwebapp/js/bootstrap5_loader', 'hqwebapp/js/initial_page_data', 'export/js/models', 'hqwebapp/js/toggles', @@ -8,6 +9,7 @@ hqDefine('export/js/customize_export_new', [ ], function ( $, ko, + bootstrap, initialPageData, models, toggles, @@ -31,7 +33,9 @@ hqDefine('export/js/customize_export_new', [ "build_schema", "/a/---/data/export/build_full_schema/" ); $('#customize-export').koApplyBindings(customExportView); - $('.export-tooltip').tooltip(); + $('.export-tooltip').each(function (index, trigger) { + new bootstrap.Tooltip(trigger); + }); if (toggles.toggleEnabled('SUPPORT_GEO_JSON_EXPORT')) { const exportFormat = initialPageData.get('export_instance').export_format; diff --git a/corehq/apps/export/static/export/js/download_data_files.js b/corehq/apps/export/static/export/js/download_data_files.js index 6452332a800c..e85cc1282eb7 100644 --- a/corehq/apps/export/static/export/js/download_data_files.js +++ b/corehq/apps/export/static/export/js/download_data_files.js @@ -1,6 +1,6 @@ hqDefine("export/js/download_data_files",[ 'jquery', - 'hqwebapp/js/bootstrap3/alert_user', + 'hqwebapp/js/bootstrap5/alert_user', 'hqwebapp/js/initial_page_data', 'hqwebapp/js/assert_properties', ], function ($, alertUserModule, initialPageData, assertProperties) { diff --git a/corehq/apps/export/static/export/js/download_export.js b/corehq/apps/export/static/export/js/download_export.js index 2c9dc3dbc729..c4ce890b62d4 100644 --- a/corehq/apps/export/static/export/js/download_export.js +++ b/corehq/apps/export/static/export/js/download_export.js @@ -13,12 +13,12 @@ hqDefine('export/js/download_export', [ 'underscore', 'hqwebapp/js/assert_properties', 'hqwebapp/js/initial_page_data', + 'hqwebapp/js/tempus_dominus', 'analytix/js/google', 'analytix/js/kissmetrix', - 'reports/js/filters/bootstrap3/main', + 'reports/js/filters/bootstrap5/main', 'reports/js/reports.util', 'export/js/utils', - 'hqwebapp/js/daterangepicker.config', // createDateRangePicker 'jquery.cookie/jquery.cookie', // for resuming export downloads on refresh ], function ( $, @@ -26,6 +26,7 @@ hqDefine('export/js/download_export', [ _, assertProperties, initialPageData, + hqTempusDominus, googleAnalytics, kissmetricsAnalytics, reportFilters, @@ -435,12 +436,7 @@ hqDefine('export/js/download_export', [ $(".hqwebapp-datespan").each(function () { var $el = $(this).find("input"); - $el.createDateRangePicker( - $el.data("labels"), - $el.data("separator"), - $el.data('startDate'), - $el.data('endDate') - ); + hqTempusDominus.createDateRangePicker($el.get(0), $el.data("separator")); }); }); }); diff --git a/corehq/apps/export/static/export/js/export_list.js b/corehq/apps/export/static/export/js/export_list.js index a56d048268d7..d7811c1cc313 100644 --- a/corehq/apps/export/static/export/js/export_list.js +++ b/corehq/apps/export/static/export/js/export_list.js @@ -16,18 +16,22 @@ hqDefine("export/js/export_list", [ 'knockout', 'underscore', 'hqwebapp/js/assert_properties', + 'es6!hqwebapp/js/bootstrap5_loader', 'clipboard/dist/clipboard', 'analytix/js/google', 'analytix/js/kissmetrix', 'export/js/utils', - 'hqwebapp/js/bootstrap3/validators.ko', // needed for validation of startDate and endDate - 'hqwebapp/js/bootstrap3/components.ko', // pagination & feedback widget + 'hqwebapp/js/bootstrap5/validators.ko', // needed for validation of startDate and endDate + 'hqwebapp/js/components/inline_edit', + 'hqwebapp/js/components/pagination', + 'hqwebapp/js/components/bootstrap5/feedback', 'select2/dist/js/select2.full.min', ], function ( $, ko, _, assertProperties, + bootstrap, Clipboard, googleAnalytics, kissmetricsAnalytics, @@ -181,7 +185,8 @@ hqDefine("export/js/export_list", [ self.isAutoRebuildEnabled(data.isAutoRebuildEnabled); } $button.enableButton(); - $('#modalEnableDisableAutoRefresh-' + self.id() + '-' + self.emailedExport.groupId()).modal('hide'); + const modalId = 'modalEnableDisableAutoRefresh-' + self.id() + '-' + self.emailedExport.groupId(); + bootstrap.Modal.getInstance('#' + modalId).hide(); }, }); }; @@ -261,7 +266,9 @@ hqDefine("export/js/export_list", [ }; self.updateData = function () { - $('#modalRefreshExportConfirm-' + exportId + '-' + self.groupId()).modal('hide'); + const modalId = 'modalRefreshExportConfirm-' + exportId + '-' + self.groupId(); + bootstrap.Modal.getInstance('#' + modalId).hide(); + self.updatingData(true); $.ajax({ method: 'POST', @@ -462,29 +469,12 @@ hqDefine("export/js/export_list", [ return true; }; - var tooltipText = ""; - if (self.isOData || self.isFeed) { - tooltipText = gettext("All of the selected feeds will be deleted."); - } else { - tooltipText = gettext("All of the selected exports will be deleted."); - } - - $(function () { - $('[data-toggle="tooltip-bulkExport"]').attr('title', - gettext("All of the selected exports will be collected for download to a " + - "single Excel file, with each export as a separate sheet.")).tooltip(); - }); - - $(function () { - $('[data-toggle="tooltip-bulkDelete"]').attr('title', tooltipText).tooltip({trigger: 'hover'}); - }); - self.isMultiple = ko.computed(function () { if (self.bulkDeleteList().length > 1) { return true; } return false; }); - self.BulkExportDelete = function (observable, event) { + self.BulkExportDelete = function () { var count = self.bulkExportDownloadCount; self.panels().forEach(panel => panel.isBulkDeleting(true)); var bulkDelete = function () { @@ -680,7 +670,7 @@ hqDefine("export/js/export_list", [ if (export_.hasEmailedExport) { export_.emailedExport.pollProgressBar(); } - self.$filterModal.modal('hide'); + bootstrap.Modal.getInstance(self.$filterModal.get(0)).hide(); } else { self.formSubmitErrorMessage(data.error); } diff --git a/corehq/apps/export/static/export/js/export_list_main.js b/corehq/apps/export/static/export/js/export_list_main.js index fc0a07f5c3d4..1d67953ed1ef 100644 --- a/corehq/apps/export/static/export/js/export_list_main.js +++ b/corehq/apps/export/static/export/js/export_list_main.js @@ -2,7 +2,7 @@ hqDefine("export/js/export_list_main", [ 'jquery', 'hqwebapp/js/initial_page_data', 'analytix/js/kissmetrix', - 'hqwebapp/js/bootstrap3/main', + 'hqwebapp/js/bootstrap5/main', 'export/js/create_export', 'export/js/export_list', 'hqwebapp/js/select_2_ajax_widget', // for case owner & user filters in DashboardFeedFilterForm diff --git a/corehq/apps/export/static/export/js/incremental_export.js b/corehq/apps/export/static/export/js/incremental_export.js index 491c5b25dabd..3327df92fbd4 100644 --- a/corehq/apps/export/static/export/js/incremental_export.js +++ b/corehq/apps/export/static/export/js/incremental_export.js @@ -1,7 +1,7 @@ hqDefine('export/js/incremental_export', [ "jquery", "hqwebapp/js/initial_page_data", - "hqwebapp/js/bootstrap3/crud_paginated_list_init", + "hqwebapp/js/bootstrap5/crud_paginated_list_init", ], function ($, initialPageData, CRUDPaginatedListInit) { $(function () { var viewModel = CRUDPaginatedListInit.paginatedListModel; diff --git a/corehq/apps/export/static/export/js/models.js b/corehq/apps/export/static/export/js/models.js index d898e01d53bb..8b0fbd1ea585 100644 --- a/corehq/apps/export/static/export/js/models.js +++ b/corehq/apps/export/static/export/js/models.js @@ -8,18 +8,20 @@ hqDefine('export/js/models', [ 'jquery', 'knockout', 'underscore', + 'es6!hqwebapp/js/bootstrap5_loader', 'hqwebapp/js/initial_page_data', 'hqwebapp/js/toggles', 'analytix/js/google', 'analytix/js/kissmetrix', 'export/js/const', 'export/js/utils', - 'hqwebapp/js/bootstrap3/validators.ko', // needed for validation of customPathString - 'hqwebapp/js/bootstrap3/knockout_bindings.ko', // needed for multirow_sortable binding + 'hqwebapp/js/bootstrap5/validators.ko', // needed for validation of customPathString + 'hqwebapp/js/bootstrap5/knockout_bindings.ko', // needed for multirow_sortable binding ], function ( $, ko, _, + bootstrap, initialPageData, toggles, googleAnalytics, @@ -451,7 +453,7 @@ hqDefine('export/js/models', [ table.showDeleted(!table.showDeleted()); if (this.numberOfAppsToProcess > 0 && table.showDeleted()) { - $('#export-process-deleted-applications').modal('show'); + bootstrap.Modal.getOrCreateInstance('#export-process-deleted-applications').show(); } }; @@ -576,7 +578,7 @@ hqDefine('export/js/models', [ const queryString = window.location.search; const urlParams = new URLSearchParams(queryString); if (urlParams.get('load_deprecated') !== 'True' && table.showDeprecated()) { - $('#export-process-deprecated-properties').modal('show'); + bootstrap.Modal.getOrCreateInstance('#export-process-deprecated-properties').show(); } }; diff --git a/corehq/apps/export/static/export/js/utils.js b/corehq/apps/export/static/export/js/utils.js index f9914d37e54c..6efad48bc6e2 100644 --- a/corehq/apps/export/static/export/js/utils.js +++ b/corehq/apps/export/static/export/js/utils.js @@ -10,11 +10,11 @@ hqDefine('export/js/utils', [ constants ) { var getTagCSSClass = function (tag) { - var cls = 'label'; + var cls = 'badge'; if (tag === constants.TAG_DELETED) { - return cls + ' label-warning'; + return cls + ' text-bg-warning'; } else { - return cls + ' label-default'; + return cls + ' text-bg-secondary'; } }; diff --git a/corehq/apps/export/static/export/spec/Exports.Utils.spec.js b/corehq/apps/export/static/export/spec/Exports.Utils.spec.js index cf4c0380e48d..cacf6badb1d3 100644 --- a/corehq/apps/export/static/export/spec/Exports.Utils.spec.js +++ b/corehq/apps/export/static/export/spec/Exports.Utils.spec.js @@ -14,12 +14,12 @@ hqDefine("export/spec/Exports.Utils.spec", [ describe('#getTagCSSClass', function () { it('Should get regular tag class', function () { var cls = utils.getTagCSSClass('random-tag'); - assert.equal(cls, 'label label-default'); + assert.equal(cls, 'badge text-bg-secondary'); }); it('Should get warning tag class', function () { var cls = utils.getTagCSSClass(constants.TAG_DELETED); - assert.equal(cls, 'label label-warning'); + assert.equal(cls, 'badge text-bg-warning'); }); }); diff --git a/corehq/apps/export/templates/export/customize_export_new.html b/corehq/apps/export/templates/export/customize_export_new.html index 857425601a48..74ee9fa955e2 100644 --- a/corehq/apps/export/templates/export/customize_export_new.html +++ b/corehq/apps/export/templates/export/customize_export_new.html @@ -1,8 +1,8 @@ -{% extends "hqwebapp/bootstrap3/base_section.html" %} +{% extends "hqwebapp/bootstrap5/base_section.html" %} {% load hq_shared_tags %} {% load i18n %} -{% requirejs_main 'export/js/customize_export_new' %} +{% requirejs_main_b5 'export/js/customize_export_new' %} {% block page_content %} {% initial_page_data 'number_of_apps_to_process' number_of_apps_to_process %} @@ -15,10 +15,10 @@ {% initial_page_data 'export_instance' export_instance %} {% initial_page_data 'geo_properties' geo_properties %} -

+ -
-