From 0aad65605435839f115b2651a5119dc7c6ce3b10 Mon Sep 17 00:00:00 2001 From: joetsoi Date: Mon, 9 Sep 2013 16:28:18 +0100 Subject: [PATCH 01/77] [#790] Tutorial for custom fields in packages --- doc/extensions/adding-custom-fields.rst | 154 ++++++++++++++++++++++++ 1 file changed, 154 insertions(+) create mode 100644 doc/extensions/adding-custom-fields.rst diff --git a/doc/extensions/adding-custom-fields.rst b/doc/extensions/adding-custom-fields.rst new file mode 100644 index 00000000000..6a2c5acac38 --- /dev/null +++ b/doc/extensions/adding-custom-fields.rst @@ -0,0 +1,154 @@ +============================ +Adding Custom Fields to CKAN +============================ + +CKAN by default allows users to enter custom fields and values into datasets in the "Additional Information" step when creating datasets and when editing datasets as additional key-value pairs. This tutorial shows you how to customize this handling so that your metadata is more integrated with the form and API. In this tutorial we are assuming that you have read the :doc:`/extensions/tutorial` + +Adding Custom Fields to Packages +-------------------------------- + +Create a new plugin named ``ckanext-extrafields`` and create a class named ``ExtraFieldsPlugins`` inside ``ckanext-extrafields/ckanext/extrafields/plugins.py`` that implements the ``IDatasetForm`` interface and inherits from ``SingletonPlugin`` and ``DefaultDatasetForm``, we will want to implement that functions that allow us to update CKAN's default package schema to include our custom field. + +.. code-block:: python + + import ckan.plugins as p + import ckan.plugins.toolkit as tk + + class ExtraFieldsPlugin(p.SingletonPlugin, tk.DefaultDatasetForm): + p.implements(p.IDatasetForm) + + +Updating the CKAN Schema +^^^^^^^^^^^^^^^^^^^^^^^^ + +The ``create_package_schema`` function is used whenever a new package is created, we'll want update the default schema and insert our custom field here. We will fetch the default schema defined in ``in default_create_package_schema`` by running ``create_package_schema``'s super function and update it. + +.. code-block:: python + + def create_package_schema(self): + # let's grab the default schema in our plugin + schema = super(ExtraFieldsPlugin, self).create_package_schema() + #our custom field + schema.update({ + 'custom_text': [tk.get_validator('ignore_missing'), tk.get_converter('convert_to_extras')] + }) + return schema + +The CKAN schema is a dictionary where the key is the name of the field and the value is a list of validators and converters. Here we have a validator to tell CKAN to not raise a validation error if the value is missing and a converter to convert the value to and save as an extra. We will want to change the ``update_package_schema`` function with the same update code + +.. code-block:: python + + def update_package_schema(self): + schema = super(ExtraFieldsPlugin, self).update_package_schema() + #our custom field + schema.update({ + 'custom_text': [tk.get_validator('ignore_missing'), + tk.get_converter('convert_to_extras')] + }) + return schema + +The ``show_package_schema`` is used when the ``package_show`` action is called, we want the default_show_package_schema to be updated to include our custom field. This time, instead of converting to an an extras field. We want our field to be converted *from* an extras field. So we want to use the ``convert_from_extras`` converter. + + +.. code-block:: python + :emphasize-lines: 4 + + def show_package_schema(self): + schema = super(CustomFieldsPlugins, self).show_package_schema() + schema.update({ + 'custom_text': [tk.get_converter('convert_from_extras'), + tk.get_validator('ignore_missing')] + }) + return schema + +.. topic :: Database Details + + By default CKAN is saving the custom values to the package_extra table. When a call to ``package_show`` is made, normally the results in package_extra are returned as a nested dictionary named 'extras'. By editing the schema in our plugin we are moving the field into the top-level of the dictionary returned from ``package_show``. Our custom_field will seemlessly appear as part of the schema. This means it appears as a top level attribute for our package in our templates and API calls whilst letting CKAN handle the conversion and saving to the package_extra table. + + +Package Types +^^^^^^^^^^^^^ + +The ``package_types`` function defines a list of package types that this plugin handles. Each package has a field containing it's type. Plugins can register to handle specific types of packages and ignore others. Since our plugin is not for any specific type of package and we want our plugin to be the default handler, we update the plugin code to contain the following + +.. code-block:: python + + def is_fallback(self): + # Return True to register this plugin as the default handler for + # package types not handled by any other IDatasetForm plugin. + return True + + def package_types(self): + # This plugin doesn't handle any special package types, it just + # registers itself as the default (above). + return [] + +Updating Templates +^^^^^^^^^^^^^^^^^^ + +In order for our new field to be visible on the CKAN front-end, we need to update the templates. Add an additional line to make the plugin implement the IConfigurer interface + +.. code-block:: python + + plugins.implements(plugins.IConfigurer) + +This interface allows to implement a function ``update_config`` that allows us to update the CKAN config, in our case we want to add an additional location for CKAN to look for templates. Add the following code to your plugin. +.. code-block:: python + + def update_config(self, config): + # Add this plugin's templates dir to CKAN's extra_template_paths, so + # that CKAN will use this plugin's custom templates. + tk.add_template_directory(config, 'templates') + +You will also need to add a directory under your extension directory to store the templates. Create a directory called ``ckanext-extrafields/ckanext/extrafields/templates/`` and the subdirectories ``ckanext-extrafields/ckanext/extrafields/templates/package/snippets/``. + +We need to override a few templates in order to get our custom field rendered. Firstly we need to remove the default custom field handling. Create a template file in our templates directory called ``package/snippets/package_metadata_fields.html`` containing + + +.. code-block:: jinja + + {% ckan_extends %} + + {# Remove 'free extras' from the package form. If you're using + convert_to/from_extras() as we are with our 'custom_text' field below then + you need to remove free extras from the form, or editing your custom field + won't work. #} + {% block custom_fields %} + {% endblock %} + +This overrides the custom_fields block with an empty block so the default CKAN custom fields form does not render. Next add a template in our template directory called ``package/snippets/package_basic_fields.html`` containing + +.. code-block:: jinja + + {% ckan_extends %} + + {% block package_basic_fields_custom %} + {{ form.input('custom_text', label=_('Custom Text'), id='field-custom_text', placeholder=_('custom text'), value=data.custom_text, error=errors.custom_text, classes=['control-medium']) }} + {% endblock %} + +This adds our custom_text field to the editing form. Finally we want to display our custom_text field on the dataset page. Add another file called ``package/snippets/additional_info.html`` containing + + +.. code-block:: jinja + + {% ckan_extends %} + + {% block extras %} + {% if pkg_dict.custom_text %} + + {{ _("Custom Text") }} + {{ pkg_dict.custom_text }} + + {% endif %} + {% endblock %} + +This template overrides the the default extras rendering on the dataset page and replaces it to just display our custom field. + +You're done! Make sure you have your plugin installed and setup as in the Writing Extensions tutorial. Then run a development server and you should now have an additional field called "Custom Text" when displaying and adding/editing a dataset. + + +.. todo:: resouces below + +--------------------------------- +Adding Custom Fields to Resources +--------------------------------- From b5646618e801d2d1a1db25416c71375e84da044a Mon Sep 17 00:00:00 2001 From: joetsoi Date: Mon, 9 Sep 2013 16:29:52 +0100 Subject: [PATCH 02/77] [#790] add custom fields tutorial to extensions index --- doc/extensions/index.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/extensions/index.rst b/doc/extensions/index.rst index a4752dcfa47..07db220bbe0 100644 --- a/doc/extensions/index.rst +++ b/doc/extensions/index.rst @@ -29,6 +29,7 @@ extensions. custom-config-settings testing-extensions best-practices + adding-custom-fields plugin-interfaces plugins-toolkit converters From c9038d91ab2e172960868604f3c2bbae5bddc128 Mon Sep 17 00:00:00 2001 From: joetsoi Date: Mon, 9 Sep 2013 16:36:42 +0100 Subject: [PATCH 03/77] [#790] clean up formatting --- doc/extensions/adding-custom-fields.rst | 84 ++++++++++++++++++++----- 1 file changed, 68 insertions(+), 16 deletions(-) diff --git a/doc/extensions/adding-custom-fields.rst b/doc/extensions/adding-custom-fields.rst index 6a2c5acac38..ba239da26ff 100644 --- a/doc/extensions/adding-custom-fields.rst +++ b/doc/extensions/adding-custom-fields.rst @@ -2,12 +2,22 @@ Adding Custom Fields to CKAN ============================ -CKAN by default allows users to enter custom fields and values into datasets in the "Additional Information" step when creating datasets and when editing datasets as additional key-value pairs. This tutorial shows you how to customize this handling so that your metadata is more integrated with the form and API. In this tutorial we are assuming that you have read the :doc:`/extensions/tutorial` +CKAN by default allows users to enter custom fields and values into datasets in +the "Additional Information" step when creating datasets and when editing +datasets as additional key-value pairs. This tutorial shows you how to +customize this handling so that your metadata is more integrated with the form +and API. In this tutorial we are assuming that you have read the +:doc:`/extensions/tutorial` Adding Custom Fields to Packages -------------------------------- -Create a new plugin named ``ckanext-extrafields`` and create a class named ``ExtraFieldsPlugins`` inside ``ckanext-extrafields/ckanext/extrafields/plugins.py`` that implements the ``IDatasetForm`` interface and inherits from ``SingletonPlugin`` and ``DefaultDatasetForm``, we will want to implement that functions that allow us to update CKAN's default package schema to include our custom field. +Create a new plugin named ``ckanext-extrafields`` and create a class named +``ExtraFieldsPlugins`` inside +``ckanext-extrafields/ckanext/extrafields/plugins.py`` that implements the +``IDatasetForm`` interface and inherits from ``SingletonPlugin`` and +``DefaultDatasetForm``, we will want to implement that functions that allow us +to update CKAN's default package schema to include our custom field. .. code-block:: python @@ -21,7 +31,11 @@ Create a new plugin named ``ckanext-extrafields`` and create a class named ``Ext Updating the CKAN Schema ^^^^^^^^^^^^^^^^^^^^^^^^ -The ``create_package_schema`` function is used whenever a new package is created, we'll want update the default schema and insert our custom field here. We will fetch the default schema defined in ``in default_create_package_schema`` by running ``create_package_schema``'s super function and update it. +The ``create_package_schema`` function is used whenever a new package is +created, we'll want update the default schema and insert our custom field here. +We will fetch the default schema defined in +``in default_create_package_schema`` by running ``create_package_schema``'s +super function and update it. .. code-block:: python @@ -30,11 +44,16 @@ The ``create_package_schema`` function is used whenever a new package is created schema = super(ExtraFieldsPlugin, self).create_package_schema() #our custom field schema.update({ - 'custom_text': [tk.get_validator('ignore_missing'), tk.get_converter('convert_to_extras')] + 'custom_text': [tk.get_validator('ignore_missing'), + tk.get_converter('convert_to_extras')] }) return schema -The CKAN schema is a dictionary where the key is the name of the field and the value is a list of validators and converters. Here we have a validator to tell CKAN to not raise a validation error if the value is missing and a converter to convert the value to and save as an extra. We will want to change the ``update_package_schema`` function with the same update code +The CKAN schema is a dictionary where the key is the name of the field and the +value is a list of validators and converters. Here we have a validator to tell +CKAN to not raise a validation error if the value is missing and a converter to +convert the value to and save as an extra. We will want to change the +``update_package_schema`` function with the same update code .. code-block:: python @@ -47,7 +66,11 @@ The CKAN schema is a dictionary where the key is the name of the field and the v }) return schema -The ``show_package_schema`` is used when the ``package_show`` action is called, we want the default_show_package_schema to be updated to include our custom field. This time, instead of converting to an an extras field. We want our field to be converted *from* an extras field. So we want to use the ``convert_from_extras`` converter. +The ``show_package_schema`` is used when the ``package_show`` action is called, +we want the default_show_package_schema to be updated to include our custom +field. This time, instead of converting to an an extras field. We want our +field to be converted *from* an extras field. So we want to use the +``convert_from_extras`` converter. .. code-block:: python @@ -63,13 +86,24 @@ The ``show_package_schema`` is used when the ``package_show`` action is called, .. topic :: Database Details - By default CKAN is saving the custom values to the package_extra table. When a call to ``package_show`` is made, normally the results in package_extra are returned as a nested dictionary named 'extras'. By editing the schema in our plugin we are moving the field into the top-level of the dictionary returned from ``package_show``. Our custom_field will seemlessly appear as part of the schema. This means it appears as a top level attribute for our package in our templates and API calls whilst letting CKAN handle the conversion and saving to the package_extra table. + By default CKAN is saving the custom values to the package_extra table. + When a call to ``package_show`` is made, normally the results in + package_extra are returned as a nested dictionary named 'extras'. + By editing the schema in our plugin we are moving the field into the top + level of the dictionary returned from ``package_show``. Our custom_field + will seemlessly appear as part of the schema. This means it appears as a + top level attribute for our package in our templates and API calls whilst + letting CKAN handle the conversion and saving to the package_extra table. Package Types ^^^^^^^^^^^^^ -The ``package_types`` function defines a list of package types that this plugin handles. Each package has a field containing it's type. Plugins can register to handle specific types of packages and ignore others. Since our plugin is not for any specific type of package and we want our plugin to be the default handler, we update the plugin code to contain the following +The ``package_types`` function defines a list of package types that this plugin +handles. Each package has a field containing it's type. Plugins can register to +handle specific types of packages and ignore others. Since our plugin is not +for any specific type of package and we want our plugin to be the default +handler, we update the plugin code to contain the following .. code-block:: python @@ -86,13 +120,17 @@ The ``package_types`` function defines a list of package types that this plugin Updating Templates ^^^^^^^^^^^^^^^^^^ -In order for our new field to be visible on the CKAN front-end, we need to update the templates. Add an additional line to make the plugin implement the IConfigurer interface +In order for our new field to be visible on the CKAN front-end, we need to +update the templates. Add an additional line to make the plugin implement the +IConfigurer interface .. code-block:: python plugins.implements(plugins.IConfigurer) -This interface allows to implement a function ``update_config`` that allows us to update the CKAN config, in our case we want to add an additional location for CKAN to look for templates. Add the following code to your plugin. +This interface allows to implement a function ``update_config`` that allows us +to update the CKAN config, in our case we want to add an additional location +for CKAN to look for templates. Add the following code to your plugin. .. code-block:: python def update_config(self, config): @@ -100,9 +138,15 @@ This interface allows to implement a function ``update_config`` that allows us t # that CKAN will use this plugin's custom templates. tk.add_template_directory(config, 'templates') -You will also need to add a directory under your extension directory to store the templates. Create a directory called ``ckanext-extrafields/ckanext/extrafields/templates/`` and the subdirectories ``ckanext-extrafields/ckanext/extrafields/templates/package/snippets/``. +You will also need to add a directory under your extension directory to store +the templates. Create a directory called +``ckanext-extrafields/ckanext/extrafields/templates/`` and the subdirectories +``ckanext-extrafields/ckanext/extrafields/templates/package/snippets/``. -We need to override a few templates in order to get our custom field rendered. Firstly we need to remove the default custom field handling. Create a template file in our templates directory called ``package/snippets/package_metadata_fields.html`` containing +We need to override a few templates in order to get our custom field rendered. +Firstly we need to remove the default custom field handling. Create a template +file in our templates directory called +``package/snippets/package_metadata_fields.html`` containing .. code-block:: jinja @@ -116,7 +160,9 @@ We need to override a few templates in order to get our custom field rendered. F {% block custom_fields %} {% endblock %} -This overrides the custom_fields block with an empty block so the default CKAN custom fields form does not render. Next add a template in our template directory called ``package/snippets/package_basic_fields.html`` containing +This overrides the custom_fields block with an empty block so the default CKAN +custom fields form does not render. Next add a template in our template +directory called ``package/snippets/package_basic_fields.html`` containing .. code-block:: jinja @@ -126,7 +172,9 @@ This overrides the custom_fields block with an empty block so the default CKAN c {{ form.input('custom_text', label=_('Custom Text'), id='field-custom_text', placeholder=_('custom text'), value=data.custom_text, error=errors.custom_text, classes=['control-medium']) }} {% endblock %} -This adds our custom_text field to the editing form. Finally we want to display our custom_text field on the dataset page. Add another file called ``package/snippets/additional_info.html`` containing +This adds our custom_text field to the editing form. Finally we want to display +our custom_text field on the dataset page. Add another file called +``package/snippets/additional_info.html`` containing .. code-block:: jinja @@ -142,9 +190,13 @@ This adds our custom_text field to the editing form. Finally we want to display {% endif %} {% endblock %} -This template overrides the the default extras rendering on the dataset page and replaces it to just display our custom field. +This template overrides the the default extras rendering on the dataset page +and replaces it to just display our custom field. -You're done! Make sure you have your plugin installed and setup as in the Writing Extensions tutorial. Then run a development server and you should now have an additional field called "Custom Text" when displaying and adding/editing a dataset. +You're done! Make sure you have your plugin installed and setup as in the +`extension/tutorial`. Then run a development server and you should now have +an additional field called "Custom Text" when displaying and adding/editing a +dataset. .. todo:: resouces below From 96233ece26929af181147bd61bd8755f5137577c Mon Sep 17 00:00:00 2001 From: joetsoi Date: Wed, 2 Oct 2013 10:12:02 +0100 Subject: [PATCH 04/77] [#790] resource customization tutorial also added resource example to idataset form example --- ckanext/example_idatasetform/plugin.py | 7 +++ doc/extensions/adding-custom-fields.rst | 80 +++++++++++++++++++++++-- 2 files changed, 82 insertions(+), 5 deletions(-) diff --git a/ckanext/example_idatasetform/plugin.py b/ckanext/example_idatasetform/plugin.py index de3aa86692b..12542a3f252 100644 --- a/ckanext/example_idatasetform/plugin.py +++ b/ckanext/example_idatasetform/plugin.py @@ -92,6 +92,10 @@ def _modify_package_schema(self, schema): 'custom_text': [tk.get_validator('ignore_missing'), tk.get_converter('convert_to_extras')] }) + # Add our custom_resource_text metadata field to the schema + schema['resources'].update({ + 'custom_resource_text' : [ tk.get_validator('ignore_missing') ] + }) return schema def create_package_schema(self): @@ -124,6 +128,9 @@ def show_package_schema(self): tk.get_validator('ignore_missing')] }) + schema['resources'].update({ + 'custom_resource_text' : [ tk.get_validator('ignore_missing') ] + }) return schema # These methods just record how many times they're called, for testing diff --git a/doc/extensions/adding-custom-fields.rst b/doc/extensions/adding-custom-fields.rst index ba239da26ff..c782c8ece20 100644 --- a/doc/extensions/adding-custom-fields.rst +++ b/doc/extensions/adding-custom-fields.rst @@ -125,12 +125,16 @@ update the templates. Add an additional line to make the plugin implement the IConfigurer interface .. code-block:: python - - plugins.implements(plugins.IConfigurer) + :emphasize-lines: 3 + + class ExtraFieldsPlugin(p.SingletonPlugin, tk.DefaultDatasetForm): + p.implements(p.IDatasetForm) + p.implements(p.IConfigurer) This interface allows to implement a function ``update_config`` that allows us to update the CKAN config, in our case we want to add an additional location for CKAN to look for templates. Add the following code to your plugin. + .. code-block:: python def update_config(self, config): @@ -198,9 +202,75 @@ You're done! Make sure you have your plugin installed and setup as in the an additional field called "Custom Text" when displaying and adding/editing a dataset. +Tag Vocabularies +---------------- +If you need to add a custom field where the input options are restrcited to a +provide list of options, you can use tag vocabularies `/tag-vocabularies` -.. todo:: resouces below - ---------------------------------- Adding Custom Fields to Resources --------------------------------- + +In order to customize the fields in a resource the schema for resources needs +to be modified in a similar way to the packages. Before we do, we can clean up +the ``create_package_schema`` and ``update_package_schema``. There is a bit of +duplication that we could remove. Replace the two functions with + +.. code-block:: python + + def _modify_package_schema(self, schema): + schema.update({ + 'custom_text': [tk.get_validator('ignore_missing'), + tk.get_converter('convert_to_extras')] + }) + return schema + + def create_package_schema(self): + schema = super(ExtraFieldsPlugin, self).create_package_schema() + schema = self._modify_package_schema(schema) + return schema + + def update_package_schema(self): + schema = super(ExtraFieldsPlugin, self).update_package_schema() + schema = self._modify_package_schema(schema) + return schema + +Now we can add our additional field to the resource schema. The resource schema +is nested in the package dict as package['resources']. We modify this dict in +a similar way to the package schema. Change ``_modify_package_schema`` to the +following. + +.. code-block:: python + + def _modify_package_schema(self, schema): + schema.update({ + 'custom_text': [tk.get_validator('ignore_missing'), + tk.get_converter('convert_to_extras')] + }) + schema['resources'].update({ + 'custom_resource_text' : [ tk.get_validator('ignore_missing') ] + }) + return schema + +Update ``show_package_schema`` similarly + +.. code-block:: python + + def show_package_schema(self): + schema = super(CustomFieldsPlugins, self).show_package_schema() + schema.update({ + 'custom_text': [tk.get_converter('convert_from_extras'), + tk.get_validator('ignore_missing')] + }) + schema['resources'].update({ + 'custom_resource_text' : [ tk.get_validator('ignore_missing') ] + }) + return schema + +Save and reload your development server + +.. topic:: Details + + CKAN will take any additional keys from the resource schema and save + them the it's extras field. This is a Postgres Json datatype field, any + additional keys get saved there. The templates will automatically check + this field and display them in the resource_read page. From 3a60326db6fb10307e7302fe330186a9a26abed8 Mon Sep 17 00:00:00 2001 From: joetsoi Date: Wed, 23 Oct 2013 11:26:09 +0100 Subject: [PATCH 05/77] [#790] add tag-vocabularies to custom-fields tutorial --- doc/extensions/adding-custom-fields.rst | 160 +++++++++++++++++++++--- 1 file changed, 143 insertions(+), 17 deletions(-) diff --git a/doc/extensions/adding-custom-fields.rst b/doc/extensions/adding-custom-fields.rst index c782c8ece20..91f321ae5c6 100644 --- a/doc/extensions/adding-custom-fields.rst +++ b/doc/extensions/adding-custom-fields.rst @@ -27,7 +27,6 @@ to update CKAN's default package schema to include our custom field. class ExtraFieldsPlugin(p.SingletonPlugin, tk.DefaultDatasetForm): p.implements(p.IDatasetForm) - Updating the CKAN Schema ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -95,7 +94,6 @@ field to be converted *from* an extras field. So we want to use the top level attribute for our package in our templates and API calls whilst letting CKAN handle the conversion and saving to the package_extra table. - Package Types ^^^^^^^^^^^^^ @@ -202,18 +200,12 @@ You're done! Make sure you have your plugin installed and setup as in the an additional field called "Custom Text" when displaying and adding/editing a dataset. -Tag Vocabularies ----------------- -If you need to add a custom field where the input options are restrcited to a -provide list of options, you can use tag vocabularies `/tag-vocabularies` - -Adding Custom Fields to Resources ---------------------------------- +Cleaning up the code +^^^^^^^^^^^^^^^^^^^^ -In order to customize the fields in a resource the schema for resources needs -to be modified in a similar way to the packages. Before we do, we can clean up -the ``create_package_schema`` and ``update_package_schema``. There is a bit of -duplication that we could remove. Replace the two functions with +Before we continue further, we can clean up the ``create_package_schema`` +and ``update_package_schema``. There is a bit of duplication that we could +remove. Replace the two functions with .. code-block:: python @@ -234,7 +226,141 @@ duplication that we could remove. Replace the two functions with schema = self._modify_package_schema(schema) return schema -Now we can add our additional field to the resource schema. The resource schema +Tag Vocabularies +---------------- +If you need to add a custom field where the input options are restrcited to a +provide list of options, you can use tag vocabularies `/tag-vocabularies`. We +will need to create our vocabulary first. By calling vocabulary_create. Add a +function to your plugin.py above your plugin class. + +.. code-block:: python + + def create_country_codes(): + user = tk.get_action('get_site_user')({'ignore_auth': True}, {}) + context = {'user': user['name']} + try: + data = {'id': 'country_codes'} + tk.get_action('vocabulary_show')(context, data) + except tk.ObjectNotFound: + data = {'name': 'country_codes'} + vocab = tk.get_action('vocabulary_create')(context, data) + for tag in (u'uk', u'ie', u'de', u'fr', u'es'): + data = {'name': tag, 'vocabulary_id': vocab['id']} + tk.get_action('tag_create')(context, data) + +This codeblock is taken from the ``example_idatsetform plugin``. +``create_country_codes`` tries to fetch the vocabulary country_codes using +``vocabulary_show``. If it is not found it will create it and iterate over +the list of countries 'uk', 'ie', 'de', 'fr', 'es'. For each of these +a vocabulary tag is created using ``tag_create``, belonging to the vocabulary +``country_code``. + +Although we have only defined five tags here, additional tags can be created +at any point by a sysadmin user by calling ``tag_create`` using the API or action +functions. Add a second function below ``create_country_codes`` + +.. code-block:: python + + def country_codes(): + create_country_codes() + try: + country_codes = tk.get_action('tag_list')( + data_dict={'vocabulary_id': 'country_codes'}) + return country_codes + except tk.ObjectNotFound: + return None + +country_codes will call ``create_country_codes`` so that the ``country_codes`` +vocabulary is created if it does not exist. Then it calls tag_list to return +all of our vocabulary tags together. Now we have a way of retrieving our tag +vocabularies and creating them if they do not exist. We just need our plugin +to call this code. + +Adding Tags to the Schema +^^^^^^^^^^^^^^^^^^^^^^^^^ +Update ``_modify_package_schema`` and ``show_package_schema`` + +.. code-block:: python + :emphasize-lines: 8,19-24 + + def _modify_package_schema(self, schema): + schema.update({ + 'custom_text': [tk.get_validator('ignore_missing'), + tk.get_converter('convert_to_extras')] + }) + schema.update({ + 'country_code': [tk.get_validator('ignore_missing'), + tk.get_converter('convert_to_tags')('country_codes')] + }) + return schema + + def show_package_schema(self): + schema = super(CustomFieldsPlugins, self).show_package_schema() + schema.update({ + 'custom_text': [tk.get_converter('convert_from_extras'), + tk.get_validator('ignore_missing')] + }) + + schema['tags']['__extras'].append(tk.get_converter('free_tags_only')) + schema.update({ + 'country_code': [ + tk.get_converter('convert_from_tags')('country_codes'), + tk.get_validator('ignore_missing')] + }) + return schema + +We are adding our tag to our plugin's schema. A converter is required to +convert the field in to our tag in a similar way to how we converted our field +to extras earlier. In ``show_package_schema`` we convert from the tag back again +but we have an additional line with another converter containing +``free_tags_only``. We include this line so that vocab tags are not shown mixed +with normal free tags. + +Adding Tags to Templates +^^^^^^^^^^^^^^^^^^^^^^^^ + +Add an additional plugin.implements line to to your plugin +to implement the ``ITemplateHelpers``, we will need to add a ``get_helpers`` +function defined for this interface. + +.. code-block:: python + + plugins.implements(plugins.ITemplateHelpers, inherit=False) + + def get_helpers(self): + return {'country_codes': country_codes} + +Our intention here is to tie our country_code fetching/creation to when they +are used in the templates. Add the code below to +``package/snippets/package_metadata_fields.html`` + +.. code-block:: jinja + + {% block package_metadata_fields %} + +
+ +
+ +
+
+ + {{ super() }} + + {% endblock %} + +This adds our country code to our template, here we are using the additional +helper country_codes that we defined in our get_helpers function in our plugin. + +Adding Custom Fields to Resources +--------------------------------- + +In order to customize the fields in a resource the schema for resources needs +to be modified in a similar way to the packages. The resource schema is nested in the package dict as package['resources']. We modify this dict in a similar way to the package schema. Change ``_modify_package_schema`` to the following. @@ -271,6 +397,6 @@ Save and reload your development server .. topic:: Details CKAN will take any additional keys from the resource schema and save - them the it's extras field. This is a Postgres Json datatype field, any - additional keys get saved there. The templates will automatically check - this field and display them in the resource_read page. + them the it's extras field. This is a Postgres Json datatype field, + The templates will automatically check this field and display them in the + resource_read page. From 68cc993368f81347f326c7abeed72c42c45f450d Mon Sep 17 00:00:00 2001 From: joetsoi Date: Wed, 23 Oct 2013 11:32:06 +0100 Subject: [PATCH 06/77] [#790] fix titles to match docs style guidelines --- doc/extensions/adding-custom-fields.rst | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/doc/extensions/adding-custom-fields.rst b/doc/extensions/adding-custom-fields.rst index 91f321ae5c6..ab8c6f0ad83 100644 --- a/doc/extensions/adding-custom-fields.rst +++ b/doc/extensions/adding-custom-fields.rst @@ -1,5 +1,5 @@ ============================ -Adding Custom Fields to CKAN +Adding custom fields to CKAN ============================ CKAN by default allows users to enter custom fields and values into datasets in @@ -9,7 +9,7 @@ customize this handling so that your metadata is more integrated with the form and API. In this tutorial we are assuming that you have read the :doc:`/extensions/tutorial` -Adding Custom Fields to Packages +Adding custom fields to packages -------------------------------- Create a new plugin named ``ckanext-extrafields`` and create a class named @@ -27,7 +27,7 @@ to update CKAN's default package schema to include our custom field. class ExtraFieldsPlugin(p.SingletonPlugin, tk.DefaultDatasetForm): p.implements(p.IDatasetForm) -Updating the CKAN Schema +Updating the CKAN schema ^^^^^^^^^^^^^^^^^^^^^^^^ The ``create_package_schema`` function is used whenever a new package is @@ -94,7 +94,7 @@ field to be converted *from* an extras field. So we want to use the top level attribute for our package in our templates and API calls whilst letting CKAN handle the conversion and saving to the package_extra table. -Package Types +Package types ^^^^^^^^^^^^^ The ``package_types`` function defines a list of package types that this plugin @@ -115,7 +115,7 @@ handler, we update the plugin code to contain the following # registers itself as the default (above). return [] -Updating Templates +Updating templates ^^^^^^^^^^^^^^^^^^ In order for our new field to be visible on the CKAN front-end, we need to @@ -226,7 +226,7 @@ remove. Replace the two functions with schema = self._modify_package_schema(schema) return schema -Tag Vocabularies +Tag vocabularies ---------------- If you need to add a custom field where the input options are restrcited to a provide list of options, you can use tag vocabularies `/tag-vocabularies`. We @@ -276,7 +276,7 @@ all of our vocabulary tags together. Now we have a way of retrieving our tag vocabularies and creating them if they do not exist. We just need our plugin to call this code. -Adding Tags to the Schema +Adding tags to the schema ^^^^^^^^^^^^^^^^^^^^^^^^^ Update ``_modify_package_schema`` and ``show_package_schema`` @@ -316,7 +316,7 @@ but we have an additional line with another converter containing ``free_tags_only``. We include this line so that vocab tags are not shown mixed with normal free tags. -Adding Tags to Templates +Adding tags to templates ^^^^^^^^^^^^^^^^^^^^^^^^ Add an additional plugin.implements line to to your plugin @@ -356,7 +356,7 @@ are used in the templates. Add the code below to This adds our country code to our template, here we are using the additional helper country_codes that we defined in our get_helpers function in our plugin. -Adding Custom Fields to Resources +Adding custom fields to resources --------------------------------- In order to customize the fields in a resource the schema for resources needs From 92516d1e917b056a4102560d4ad04a502ebd679f Mon Sep 17 00:00:00 2001 From: joetsoi Date: Sun, 15 Dec 2013 17:11:03 +0000 Subject: [PATCH 07/77] [#790] custom fields tutorial move source for tutorial into it's own files --- ckanext/example_idatasetform/plugin_v1.py | 42 +++ ckanext/example_idatasetform/plugin_v2.py | 41 +++ ckanext/example_idatasetform/plugin_v3.py | 42 +++ ckanext/example_idatasetform/plugin_v4.py | 85 ++++++ ckanext/example_idatasetform/plugin_v5.py | 91 ++++++ .../package/snippets/additional_info.html | 10 + .../package/snippets/resource_form.html | 7 + doc/_themes/sphinx-theme-okfn | 2 +- doc/extensions/adding-custom-fields.rst | 266 ++++-------------- 9 files changed, 367 insertions(+), 219 deletions(-) create mode 100644 ckanext/example_idatasetform/plugin_v1.py create mode 100644 ckanext/example_idatasetform/plugin_v2.py create mode 100644 ckanext/example_idatasetform/plugin_v3.py create mode 100644 ckanext/example_idatasetform/plugin_v4.py create mode 100644 ckanext/example_idatasetform/plugin_v5.py create mode 100644 ckanext/example_idatasetform/templates/package/snippets/additional_info.html create mode 100644 ckanext/example_idatasetform/templates/package/snippets/resource_form.html diff --git a/ckanext/example_idatasetform/plugin_v1.py b/ckanext/example_idatasetform/plugin_v1.py new file mode 100644 index 00000000000..b971d202d77 --- /dev/null +++ b/ckanext/example_idatasetform/plugin_v1.py @@ -0,0 +1,42 @@ +import ckan.plugins as p +import ckan.plugins.toolkit as tk + +class ExampleIDatasetForm(p.SingletonPlugin, tk.DefaultDatasetForm): + p.implements(p.IDatasetForm) + + def create_package_schema(self): + # let's grab the default schema in our plugin + schema = super(ExampleIDatasetForm, self).create_package_schema() + #our custom field + schema.update({ + 'custom_text': [tk.get_validator('ignore_missing'), + tk.get_converter('convert_to_extras')] + }) + return schema + + def update_package_schema(self): + schema = super(ExampleIDatasetForm, self).update_package_schema() + #our custom field + schema.update({ + 'custom_text': [tk.get_validator('ignore_missing'), + tk.get_converter('convert_to_extras')] + }) + return schema + + def show_package_schema(self): + schema = super(ExampleIDatasetForm, self).show_package_schema() + schema.update({ + 'custom_text': [tk.get_converter('convert_from_extras'), + tk.get_validator('ignore_missing')] + }) + return schema + + def is_fallback(self): + # Return True to register this plugin as the default handler for + # package types not handled by any other IDatasetForm plugin. + return True + + def package_types(self): + # This plugin doesn't handle any special package types, it just + # registers itself as the default (above). + return [] diff --git a/ckanext/example_idatasetform/plugin_v2.py b/ckanext/example_idatasetform/plugin_v2.py new file mode 100644 index 00000000000..f3b146bc627 --- /dev/null +++ b/ckanext/example_idatasetform/plugin_v2.py @@ -0,0 +1,41 @@ +import ckan.plugins as p +import ckan.plugins.toolkit as tk + +class ExampleIDatasetForm(p.SingletonPlugin, tk.DefaultDatasetForm): + p.implements(p.IDatasetForm) + p.implements(p.IConfigurer) + + def create_package_schema(self): + # let's grab the default schema in our plugin + schema = super(ExampleIDatasetForm, self).create_package_schema() + #our custom field + schema.update({ + 'custom_text': [tk.get_validator('ignore_missing'), + tk.get_converter('convert_to_extras')] + }) + return schema + + def update_package_schema(self): + schema = super(ExampleIDatasetForm, self).update_package_schema() + #our custom field + schema.update({ + 'custom_text': [tk.get_validator('ignore_missing'), + tk.get_converter('convert_to_extras')] + }) + return schema + + #is fall back + def is_fallback(self): + # Return True to register this plugin as the default handler for + # package types not handled by any other IDatasetForm plugin. + return True + + def package_types(self): + # This plugin doesn't handle any special package types, it just + # registers itself as the default (above). + return [] + + def update_config(self, config): + # Add this plugin's templates dir to CKAN's extra_template_paths, so + # that CKAN will use this plugin's custom templates. + tk.add_template_directory(config, 'templates') diff --git a/ckanext/example_idatasetform/plugin_v3.py b/ckanext/example_idatasetform/plugin_v3.py new file mode 100644 index 00000000000..78212636445 --- /dev/null +++ b/ckanext/example_idatasetform/plugin_v3.py @@ -0,0 +1,42 @@ +'''Example IDatasetFormPlugin''' +import ckan.plugins as p +import ckan.plugins.toolkit as tk + +class ExtraFieldsPlugin(p.SingletonPlugin, tk.DefaultDatasetForm): + p.implements(p.IDatasetForm) + + def _modify_package_schema(self, schema): + schema.update({ + 'custom_text': [tk.get_validator('ignore_missing'), + tk.get_converter('convert_to_extras')] + }) + return schema + + def create_package_schema(self): + schema = super(ExtraFieldsPlugin, self).create_package_schema() + schema = self._modify_package_schema(schema) + return schema + + def update_package_schema(self): + schema = super(ExtraFieldsPlugin, self).update_package_schema() + schema = self._modify_package_schema(schema) + return schema + + def show_package_schema(self): + schema = super(ExtraFieldsPlugin, self).show_package_schema() + schema.update({ + 'custom_text': [tk.get_converter('convert_from_extras'), + tk.get_validator('ignore_missing')] + }) + return schema + + #is fall back + def is_fallback(self): + # Return True to register this plugin as the default handler for + # package types not handled by any other IDatasetForm plugin. + return True + + def package_types(self): + # This plugin doesn't handle any special package types, it just + # registers itself as the default (above). + return [] diff --git a/ckanext/example_idatasetform/plugin_v4.py b/ckanext/example_idatasetform/plugin_v4.py new file mode 100644 index 00000000000..2b0e99927dc --- /dev/null +++ b/ckanext/example_idatasetform/plugin_v4.py @@ -0,0 +1,85 @@ +import ckan.plugins as p +import ckan.plugins.toolkit as tk + +def create_country_codes(): + user = tk.get_action('get_site_user')({'ignore_auth': True}, {}) + context = {'user': user['name']} + try: + data = {'id': 'country_codes'} + tk.get_action('vocabulary_show')(context, data) + except tk.ObjectNotFound: + data = {'name': 'country_codes'} + vocab = tk.get_action('vocabulary_create')(context, data) + for tag in (u'uk', u'ie', u'de', u'fr', u'es'): + data = {'name': tag, 'vocabulary_id': vocab['id']} + tk.get_action('tag_create')(context, data) + +def country_codes(): + create_country_codes() + try: + country_codes = tk.get_action('tag_list')( + data_dict={'vocabulary_id': 'country_codes'}) + return country_codes + except tk.ObjectNotFound: + return None + +class ExampleIDatasetForm(p.SingletonPlugin, tk.DefaultDatasetForm): + p.implements(p.IDatasetForm) + p.implements(p.IConfigurer) + p.implements(p.ITemplateHelpers) + + def get_helpers(self): + return {'country_codes': country_codes} + + def _modify_package_schema(self, schema): + schema.update({ + 'custom_text': [tk.get_validator('ignore_missing'), + tk.get_converter('convert_to_extras')] + }) + schema.update({ + 'country_code': [tk.get_validator('ignore_missing'), + tk.get_converter('convert_to_tags')('country_codes')] + }) + return schema + + def show_package_schema(self): + schema = super(ExampleIDatasetForm, self).show_package_schema() + schema.update({ + 'custom_text': [tk.get_converter('convert_from_extras'), + tk.get_validator('ignore_missing')] + }) + + schema['tags']['__extras'].append(tk.get_converter('free_tags_only')) + schema.update({ + 'country_code': [ + tk.get_converter('convert_from_tags')('country_codes'), + tk.get_validator('ignore_missing')] + }) + return schema + + def create_package_schema(self): + schema = super(ExampleIDatasetForm, self).create_package_schema() + schema = self._modify_package_schema(schema) + return schema + + def update_package_schema(self): + schema = super(ExampleIDatasetForm, self).update_package_schema() + schema = self._modify_package_schema(schema) + return schema + + #is fall back + def is_fallback(self): + # Return True to register this plugin as the default handler for + # package types not handled by any other IDatasetForm plugin. + return True + + def package_types(self): + # This plugin doesn't handle any special package types, it just + # registers itself as the default (above). + return [] + + #update config + def update_config(self, config): + # Add this plugin's templates dir to CKAN's extra_template_paths, so + # that CKAN will use this plugin's custom templates. + tk.add_template_directory(config, 'templates') diff --git a/ckanext/example_idatasetform/plugin_v5.py b/ckanext/example_idatasetform/plugin_v5.py new file mode 100644 index 00000000000..d4f60ee52ac --- /dev/null +++ b/ckanext/example_idatasetform/plugin_v5.py @@ -0,0 +1,91 @@ +import ckan.plugins as p +import ckan.plugins.toolkit as tk + +def create_country_codes(): + user = tk.get_action('get_site_user')({'ignore_auth': True}, {}) + context = {'user': user['name']} + try: + data = {'id': 'country_codes'} + tk.get_action('vocabulary_show')(context, data) + except tk.ObjectNotFound: + data = {'name': 'country_codes'} + vocab = tk.get_action('vocabulary_create')(context, data) + for tag in (u'uk', u'ie', u'de', u'fr', u'es'): + data = {'name': tag, 'vocabulary_id': vocab['id']} + tk.get_action('tag_create')(context, data) + +def country_codes(): + create_country_codes() + try: + country_codes = tk.get_action('tag_list')( + data_dict={'vocabulary_id': 'country_codes'}) + return country_codes + except tk.ObjectNotFound: + return None + +class ExampleIDatasetForm(p.SingletonPlugin, tk.DefaultDatasetForm): + p.implements(p.IDatasetForm) + p.implements(p.IConfigurer) + p.implements(p.ITemplateHelpers) + + def get_helpers(self): + return {'country_codes': country_codes} + + def _modify_package_schema(self, schema): + schema.update({ + 'custom_text': [tk.get_validator('ignore_missing'), + tk.get_converter('convert_to_extras')] + }) + schema.update({ + 'country_code': [tk.get_validator('ignore_missing'), + tk.get_converter('convert_to_tags')('country_codes')] + }) + schema['resources'].update({ + 'custom_resource_text' : [ tk.get_validator('ignore_missing') ] + }) + return schema + + def show_package_schema(self): + schema = super(ExampleIDatasetForm, self).show_package_schema() + schema.update({ + 'custom_text': [tk.get_converter('convert_from_extras'), + tk.get_validator('ignore_missing')] + }) + + schema['tags']['__extras'].append(tk.get_converter('free_tags_only')) + schema.update({ + 'country_code': [ + tk.get_converter('convert_from_tags')('country_codes'), + tk.get_validator('ignore_missing')] + }) + schema['resources'].update({ + 'custom_resource_text' : [ tk.get_validator('ignore_missing') ] + }) + return schema + + def create_package_schema(self): + schema = super(ExampleIDatasetForm, self).create_package_schema() + schema = self._modify_package_schema(schema) + return schema + + def update_package_schema(self): + schema = super(ExampleIDatasetForm, self).update_package_schema() + schema = self._modify_package_schema(schema) + return schema + + #is fall back + def is_fallback(self): + # Return True to register this plugin as the default handler for + # package types not handled by any other IDatasetForm plugin. + return True + + def package_types(self): + # This plugin doesn't handle any special package types, it just + # registers itself as the default (above). + return [] + + #update config + def update_config(self, config): + # Add this plugin's templates dir to CKAN's extra_template_paths, so + # that CKAN will use this plugin's custom templates. + tk.add_template_directory(config, 'templates') diff --git a/ckanext/example_idatasetform/templates/package/snippets/additional_info.html b/ckanext/example_idatasetform/templates/package/snippets/additional_info.html new file mode 100644 index 00000000000..c48488e5cc4 --- /dev/null +++ b/ckanext/example_idatasetform/templates/package/snippets/additional_info.html @@ -0,0 +1,10 @@ +{% ckan_extends %} + +{% block extras %} + {% if pkg_dict.custom_text %} + + {{ _("Custom Text") }} + {{ pkg_dict.custom_text }} + + {% endif %} +{% endblock %} diff --git a/ckanext/example_idatasetform/templates/package/snippets/resource_form.html b/ckanext/example_idatasetform/templates/package/snippets/resource_form.html new file mode 100644 index 00000000000..5e36126ac62 --- /dev/null +++ b/ckanext/example_idatasetform/templates/package/snippets/resource_form.html @@ -0,0 +1,7 @@ +{% ckan_extends %} + +{% block basic_fields_url %} +{{ super() }} + + {{ form.input('custom_resource_text', label=_('Custom Text'), id='field-custom_resource_text', placeholder=_('custom resource text'), value=data.custom_resource_text, error=errors.custom_resource_text, classes=['control-medium']) }} +{% endblock %} diff --git a/doc/_themes/sphinx-theme-okfn b/doc/_themes/sphinx-theme-okfn index 4628f26abf4..320555990b6 160000 --- a/doc/_themes/sphinx-theme-okfn +++ b/doc/_themes/sphinx-theme-okfn @@ -1 +1 @@ -Subproject commit 4628f26abf401fdb63ec099384bff44a27dcda4c +Subproject commit 320555990b639c99ac3bcc79024140c9588e2bdf diff --git a/doc/extensions/adding-custom-fields.rst b/doc/extensions/adding-custom-fields.rst index ab8c6f0ad83..1b86ccb0553 100644 --- a/doc/extensions/adding-custom-fields.rst +++ b/doc/extensions/adding-custom-fields.rst @@ -13,19 +13,14 @@ Adding custom fields to packages -------------------------------- Create a new plugin named ``ckanext-extrafields`` and create a class named -``ExtraFieldsPlugins`` inside +``ExampleIDatasetForms`` inside ``ckanext-extrafields/ckanext/extrafields/plugins.py`` that implements the ``IDatasetForm`` interface and inherits from ``SingletonPlugin`` and ``DefaultDatasetForm``, we will want to implement that functions that allow us to update CKAN's default package schema to include our custom field. -.. code-block:: python - - import ckan.plugins as p - import ckan.plugins.toolkit as tk - - class ExtraFieldsPlugin(p.SingletonPlugin, tk.DefaultDatasetForm): - p.implements(p.IDatasetForm) +.. literalinclude:: ../../ckanext/example_idatasetform/plugin_v1.py + :end-before: def create_package_schema(self): Updating the CKAN schema ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -36,17 +31,8 @@ We will fetch the default schema defined in ``in default_create_package_schema`` by running ``create_package_schema``'s super function and update it. -.. code-block:: python - - def create_package_schema(self): - # let's grab the default schema in our plugin - schema = super(ExtraFieldsPlugin, self).create_package_schema() - #our custom field - schema.update({ - 'custom_text': [tk.get_validator('ignore_missing'), - tk.get_converter('convert_to_extras')] - }) - return schema +.. literalinclude:: ../../ckanext/example_idatasetform/plugin_v1.py + :pyobject: ExampleIDatasetForm.create_package_schema The CKAN schema is a dictionary where the key is the name of the field and the value is a list of validators and converters. Here we have a validator to tell @@ -54,16 +40,8 @@ CKAN to not raise a validation error if the value is missing and a converter to convert the value to and save as an extra. We will want to change the ``update_package_schema`` function with the same update code -.. code-block:: python - - def update_package_schema(self): - schema = super(ExtraFieldsPlugin, self).update_package_schema() - #our custom field - schema.update({ - 'custom_text': [tk.get_validator('ignore_missing'), - tk.get_converter('convert_to_extras')] - }) - return schema +.. literalinclude:: ../../ckanext/example_idatasetform/plugin_v1.py + :pyobject: ExampleIDatasetForm.update_package_schema The ``show_package_schema`` is used when the ``package_show`` action is called, we want the default_show_package_schema to be updated to include our custom @@ -71,28 +49,10 @@ field. This time, instead of converting to an an extras field. We want our field to be converted *from* an extras field. So we want to use the ``convert_from_extras`` converter. +.. literalinclude:: ../../ckanext/example_idatasetform/plugin_v1.py + :emphasize-lines: 4 + :pyobject: ExampleIDatasetForm.show_package_schema -.. code-block:: python - :emphasize-lines: 4 - - def show_package_schema(self): - schema = super(CustomFieldsPlugins, self).show_package_schema() - schema.update({ - 'custom_text': [tk.get_converter('convert_from_extras'), - tk.get_validator('ignore_missing')] - }) - return schema - -.. topic :: Database Details - - By default CKAN is saving the custom values to the package_extra table. - When a call to ``package_show`` is made, normally the results in - package_extra are returned as a nested dictionary named 'extras'. - By editing the schema in our plugin we are moving the field into the top - level of the dictionary returned from ``package_show``. Our custom_field - will seemlessly appear as part of the schema. This means it appears as a - top level attribute for our package in our templates and API calls whilst - letting CKAN handle the conversion and saving to the package_extra table. Package types ^^^^^^^^^^^^^ @@ -103,17 +63,8 @@ handle specific types of packages and ignore others. Since our plugin is not for any specific type of package and we want our plugin to be the default handler, we update the plugin code to contain the following -.. code-block:: python - - def is_fallback(self): - # Return True to register this plugin as the default handler for - # package types not handled by any other IDatasetForm plugin. - return True - - def package_types(self): - # This plugin doesn't handle any special package types, it just - # registers itself as the default (above). - return [] +.. literalinclude:: ../../ckanext/example_idatasetform/plugin_v1.py + :lines: 34- Updating templates ^^^^^^^^^^^^^^^^^^ @@ -122,23 +73,17 @@ In order for our new field to be visible on the CKAN front-end, we need to update the templates. Add an additional line to make the plugin implement the IConfigurer interface -.. code-block:: python - :emphasize-lines: 3 - - class ExtraFieldsPlugin(p.SingletonPlugin, tk.DefaultDatasetForm): - p.implements(p.IDatasetForm) - p.implements(p.IConfigurer) +.. literalinclude:: ../../ckanext/example_idatasetform/plugin_v2.py + :emphasize-lines: 3 + :start-after: import ckan.plugins.toolkit as tk + :end-before: def create_package_schema(self): This interface allows to implement a function ``update_config`` that allows us to update the CKAN config, in our case we want to add an additional location for CKAN to look for templates. Add the following code to your plugin. -.. code-block:: python - - def update_config(self, config): - # Add this plugin's templates dir to CKAN's extra_template_paths, so - # that CKAN will use this plugin's custom templates. - tk.add_template_directory(config, 'templates') +.. literalinclude:: ../../ckanext/example_idatasetform/plugin_v2.py + :pyobject: ExampleIDatasetForm.update_config You will also need to add a directory under your extension directory to store the templates. Create a directory called @@ -151,46 +96,24 @@ file in our templates directory called ``package/snippets/package_metadata_fields.html`` containing -.. code-block:: jinja - - {% ckan_extends %} - - {# Remove 'free extras' from the package form. If you're using - convert_to/from_extras() as we are with our 'custom_text' field below then - you need to remove free extras from the form, or editing your custom field - won't work. #} - {% block custom_fields %} - {% endblock %} +.. literalinclude:: ../../ckanext/example_idatasetform/templates/package/snippets/package_metadata_fields.html + :language: jinja + :end-before: {% block package_metadata_fields %} This overrides the custom_fields block with an empty block so the default CKAN custom fields form does not render. Next add a template in our template directory called ``package/snippets/package_basic_fields.html`` containing -.. code-block:: jinja - - {% ckan_extends %} - - {% block package_basic_fields_custom %} - {{ form.input('custom_text', label=_('Custom Text'), id='field-custom_text', placeholder=_('custom text'), value=data.custom_text, error=errors.custom_text, classes=['control-medium']) }} - {% endblock %} +.. literalinclude:: ../../ckanext/example_idatasetform/templates/package/snippets/package_basic_fields.html + :language: jinja This adds our custom_text field to the editing form. Finally we want to display our custom_text field on the dataset page. Add another file called ``package/snippets/additional_info.html`` containing -.. code-block:: jinja - - {% ckan_extends %} - - {% block extras %} - {% if pkg_dict.custom_text %} - - {{ _("Custom Text") }} - {{ pkg_dict.custom_text }} - - {% endif %} - {% endblock %} +.. literalinclude:: ../../ckanext/example_idatasetform/templates/package/snippets/additional_info.html + :language: jinja This template overrides the the default extras rendering on the dataset page and replaces it to just display our custom field. @@ -207,24 +130,9 @@ Before we continue further, we can clean up the ``create_package_schema`` and ``update_package_schema``. There is a bit of duplication that we could remove. Replace the two functions with -.. code-block:: python - - def _modify_package_schema(self, schema): - schema.update({ - 'custom_text': [tk.get_validator('ignore_missing'), - tk.get_converter('convert_to_extras')] - }) - return schema - - def create_package_schema(self): - schema = super(ExtraFieldsPlugin, self).create_package_schema() - schema = self._modify_package_schema(schema) - return schema - - def update_package_schema(self): - schema = super(ExtraFieldsPlugin, self).update_package_schema() - schema = self._modify_package_schema(schema) - return schema +.. literalinclude:: ../../ckanext/example_idatasetform/plugin_v3.py + :start-after: p.implements(p.IDatasetForm) + :end-before: def show_package_schema(self): Tag vocabularies ---------------- @@ -233,20 +141,8 @@ provide list of options, you can use tag vocabularies `/tag-vocabularies`. We will need to create our vocabulary first. By calling vocabulary_create. Add a function to your plugin.py above your plugin class. -.. code-block:: python - - def create_country_codes(): - user = tk.get_action('get_site_user')({'ignore_auth': True}, {}) - context = {'user': user['name']} - try: - data = {'id': 'country_codes'} - tk.get_action('vocabulary_show')(context, data) - except tk.ObjectNotFound: - data = {'name': 'country_codes'} - vocab = tk.get_action('vocabulary_create')(context, data) - for tag in (u'uk', u'ie', u'de', u'fr', u'es'): - data = {'name': tag, 'vocabulary_id': vocab['id']} - tk.get_action('tag_create')(context, data) +.. literalinclude:: ../../ckanext/example_idatasetform/plugin_v4.py + :pyobject: create_country_codes This codeblock is taken from the ``example_idatsetform plugin``. ``create_country_codes`` tries to fetch the vocabulary country_codes using @@ -259,16 +155,8 @@ Although we have only defined five tags here, additional tags can be created at any point by a sysadmin user by calling ``tag_create`` using the API or action functions. Add a second function below ``create_country_codes`` -.. code-block:: python - - def country_codes(): - create_country_codes() - try: - country_codes = tk.get_action('tag_list')( - data_dict={'vocabulary_id': 'country_codes'}) - return country_codes - except tk.ObjectNotFound: - return None +.. literalinclude:: ../../ckanext/example_idatasetform/plugin_v4.py + :pyobject: country_codes country_codes will call ``create_country_codes`` so that the ``country_codes`` vocabulary is created if it does not exist. Then it calls tag_list to return @@ -280,34 +168,10 @@ Adding tags to the schema ^^^^^^^^^^^^^^^^^^^^^^^^^ Update ``_modify_package_schema`` and ``show_package_schema`` -.. code-block:: python - :emphasize-lines: 8,19-24 - - def _modify_package_schema(self, schema): - schema.update({ - 'custom_text': [tk.get_validator('ignore_missing'), - tk.get_converter('convert_to_extras')] - }) - schema.update({ - 'country_code': [tk.get_validator('ignore_missing'), - tk.get_converter('convert_to_tags')('country_codes')] - }) - return schema - - def show_package_schema(self): - schema = super(CustomFieldsPlugins, self).show_package_schema() - schema.update({ - 'custom_text': [tk.get_converter('convert_from_extras'), - tk.get_validator('ignore_missing')] - }) - - schema['tags']['__extras'].append(tk.get_converter('free_tags_only')) - schema.update({ - 'country_code': [ - tk.get_converter('convert_from_tags')('country_codes'), - tk.get_validator('ignore_missing')] - }) - return schema +.. literalinclude:: ../../ckanext/example_idatasetform/plugin_v4.py + :start-after: return {'country_codes': country_codes} + :end-before: def create_package_schema(self): + :emphasize-lines: 8,19-24 We are adding our tag to our plugin's schema. A converter is required to convert the field in to our tag in a similar way to how we converted our field @@ -323,35 +187,18 @@ Add an additional plugin.implements line to to your plugin to implement the ``ITemplateHelpers``, we will need to add a ``get_helpers`` function defined for this interface. -.. code-block:: python - - plugins.implements(plugins.ITemplateHelpers, inherit=False) - - def get_helpers(self): - return {'country_codes': country_codes} +.. literalinclude:: ../../ckanext/example_idatasetform/plugin_v4.py + :start-after: p.implements(p.IConfigurer) + :end-before: def _modify_package_schema(self, schema): Our intention here is to tie our country_code fetching/creation to when they are used in the templates. Add the code below to ``package/snippets/package_metadata_fields.html`` -.. code-block:: jinja - - {% block package_metadata_fields %} +.. literalinclude:: ../../ckanext/example_idatasetform/templates/package/snippets/package_metadata_fields.html + :language: jinja + :start-after: {% endblock %} -
- -
- -
-
- - {{ super() }} - - {% endblock %} This adds our country code to our template, here we are using the additional helper country_codes that we defined in our get_helpers function in our plugin. @@ -365,32 +212,15 @@ is nested in the package dict as package['resources']. We modify this dict in a similar way to the package schema. Change ``_modify_package_schema`` to the following. -.. code-block:: python - - def _modify_package_schema(self, schema): - schema.update({ - 'custom_text': [tk.get_validator('ignore_missing'), - tk.get_converter('convert_to_extras')] - }) - schema['resources'].update({ - 'custom_resource_text' : [ tk.get_validator('ignore_missing') ] - }) - return schema +.. literalinclude:: ../../ckanext/example_idatasetform/plugin_v5.py + :pyobject: ExampleIDatasetForm._modify_package_schema + :emphasize-lines: 10-12 Update ``show_package_schema`` similarly -.. code-block:: python - - def show_package_schema(self): - schema = super(CustomFieldsPlugins, self).show_package_schema() - schema.update({ - 'custom_text': [tk.get_converter('convert_from_extras'), - tk.get_validator('ignore_missing')] - }) - schema['resources'].update({ - 'custom_resource_text' : [ tk.get_validator('ignore_missing') ] - }) - return schema +.. literalinclude:: ../../ckanext/example_idatasetform/plugin_v5.py + :pyobject: ExampleIDatasetForm.show_package_schema + :emphasize-lines: 14-16 Save and reload your development server From 1dd533613e9393c74cbe9e87c64142675dee26b1 Mon Sep 17 00:00:00 2001 From: joetsoi Date: Mon, 6 Jan 2014 19:36:39 +0000 Subject: [PATCH 08/77] [#790] custom fields tutorial * Add tests to example_idatasetform plugin. * Split out source from tutorial into plugins so they can be tested * Use sphinx referencing * Add section on validators and conveters * Minor rewrites, fix titles, etc. --- .../new_tests/__init__.py | 0 .../new_tests/test_example_idatasetform.py | 174 ++++++++++++++++++ ckanext/example_idatasetform/plugin_v1.py | 8 +- ckanext/example_idatasetform/plugin_v2.py | 14 +- ckanext/example_idatasetform/plugin_v3.py | 8 +- ckanext/example_idatasetform/plugin_v4.py | 8 +- doc/extensions/adding-custom-fields.rst | 169 +++++++++++------ setup.py | 4 + 8 files changed, 309 insertions(+), 76 deletions(-) create mode 100644 ckanext/example_idatasetform/new_tests/__init__.py create mode 100644 ckanext/example_idatasetform/new_tests/test_example_idatasetform.py diff --git a/ckanext/example_idatasetform/new_tests/__init__.py b/ckanext/example_idatasetform/new_tests/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/ckanext/example_idatasetform/new_tests/test_example_idatasetform.py b/ckanext/example_idatasetform/new_tests/test_example_idatasetform.py new file mode 100644 index 00000000000..5784264b231 --- /dev/null +++ b/ckanext/example_idatasetform/new_tests/test_example_idatasetform.py @@ -0,0 +1,174 @@ +import nose.tools as nt +import ckan.model as model +import ckan.plugins as plugins +import ckan.new_tests.helpers as helpers + +import ckanext.example_idatasetform.plugin_v4 as v4 +import ckanext.example_idatasetform.plugin as v5 + +class ExampleIDatasetFormPluginBase(object): + '''Version 1, 2 and 3 of the plugin are basically the same, so this class + provides the tests that all three versions of the plugins will run''' + def teardown(self): + model.repo.rebuild_db() + + @classmethod + def teardown_class(cls): + helpers.reset_db() + + def test_package_create(self): + result = helpers.call_action('package_create', name='test_package', + custom_text='this is my custom text') + nt.assert_equals('this is my custom text', result['custom_text']) + + def test_package_update(self): + helpers.call_action('package_create', name='test_package', + custom_text='this is my custom text') + result = helpers.call_action('package_update', name='test_package', + custom_text='this is my updated text') + nt.assert_equals('this is my updated text', result['custom_text']) + + def test_package_show(self): + helpers.call_action('package_create', name='test_package', + custom_text='this is my custom text') + result = helpers.call_action('package_show', name_or_id='test_package') + nt.assert_equals('this is my custom text', result['custom_text']) + + +class TestVersion1(ExampleIDatasetFormPluginBase): + @classmethod + def setup_class(cls): + plugins.load('example_idatasetform_v1') + + @classmethod + def teardown_class(cls): + super(TestVersion1, cls).teardown_class() + plugins.unload('example_idatasetform_v1') + + +class TestVersion2(ExampleIDatasetFormPluginBase): + @classmethod + def setup_class(cls): + plugins.load('example_idatasetform_v2') + + @classmethod + def teardown_class(cls): + super(TestVersion2, cls).teardown_class() + plugins.unload('example_idatasetform_v2') + + +class TestVersion3(ExampleIDatasetFormPluginBase): + @classmethod + def setup_class(cls): + plugins.load('example_idatasetform_v3') + + @classmethod + def teardown_class(cls): + super(TestVersion3, cls).teardown_class() + plugins.unload('example_idatasetform_v3') + +class TestIDatasetFormPluginVersion4(object): + @classmethod + def setup_class(cls): + plugins.load('example_idatasetform_v4') + + def teardown(self): + model.repo.rebuild_db() + + @classmethod + def teardown_class(cls): + plugins.unload('example_idatasetform_v4') + helpers.reset_db() + + def test_package_create(self): + v4.create_country_codes() + result = helpers.call_action('package_create', name='test_package', + custom_text='this is my custom text', + country_code='uk') + nt.assert_equals('this is my custom text', result['custom_text']) + nt.assert_equals([u'uk'], result['country_code']) + + def test_package_create_wrong_country_code(self): + v4.create_country_codes() + nt.assert_raises(plugins.toolkit.ValidationError, + helpers.call_action, + 'package_create', + name='test_package', + custom_text='this is my custom text', + country_code='notcode') + + def test_package_update(self): + v4.create_country_codes() + helpers.call_action('package_create', name='test_package', + custom_text='this is my custom text', + country_code='uk') + result = helpers.call_action('package_update', name='test_package', + custom_text='this is my updated text', + country_code='ie') + nt.assert_equals('this is my updated text', result['custom_text']) + nt.assert_equals([u'ie'], result['country_code']) + +class TestIDatasetFormPlugin(object): + @classmethod + def setup_class(cls): + plugins.load('example_idatasetform') + + def teardown(self): + model.repo.rebuild_db() + + @classmethod + def teardown_class(cls): + plugins.unload('example_idatasetform') + helpers.reset_db() + + def test_package_create(self): + v5.create_country_codes() + result = helpers.call_action( + 'package_create', name='test_package', + custom_text='this is my custom text', country_code='uk', + resources=[{ + 'url': 'http://test.com/', + 'custom_resource_text': 'my custom resource', + }]) + nt.assert_equals('my custom resource', + result['resources'][0]['custom_resource_text']) + + def test_package_update(self): + v5.create_country_codes() + helpers.call_action( + 'package_create', name='test_package', + custom_text='this is my custom text', country_code='uk', + resources=[{ + 'url': 'http://test.com/', + 'custom_resource_text': 'my custom resource', + }]) + result = helpers.call_action( + 'package_update', + name='test_package', + custom_text='this is my updated text', + country_code='ie', + resources=[{ + 'url': 'http://test.com/', + 'custom_resource_text': 'updated custom resource', + }] + ) + nt.assert_equals('this is my updated text', result['custom_text']) + nt.assert_equals([u'ie'], result['country_code']) + nt.assert_equals('updated custom resource', + result['resources'][0]['custom_resource_text']) + + def test_package_show(self): + v5.create_country_codes() + helpers.call_action( + 'package_create', name='test_package', + custom_text='this is my custom text', country_code='uk', + resources=[{ + 'url': 'http://test.com/', + 'custom_resource_text': 'my custom resource', + }] + ) + result = helpers.call_action('package_show', name_or_id='test_package') + nt.assert_equals('my custom resource', + result['resources'][0]['custom_resource_text']) + nt.assert_equals('my custom resource', + result['resources'][0]['custom_resource_text']) diff --git a/ckanext/example_idatasetform/plugin_v1.py b/ckanext/example_idatasetform/plugin_v1.py index b971d202d77..f3b7f76321d 100644 --- a/ckanext/example_idatasetform/plugin_v1.py +++ b/ckanext/example_idatasetform/plugin_v1.py @@ -1,12 +1,12 @@ import ckan.plugins as p import ckan.plugins.toolkit as tk -class ExampleIDatasetForm(p.SingletonPlugin, tk.DefaultDatasetForm): +class ExampleIDatasetFormPlugin(p.SingletonPlugin, tk.DefaultDatasetForm): p.implements(p.IDatasetForm) def create_package_schema(self): # let's grab the default schema in our plugin - schema = super(ExampleIDatasetForm, self).create_package_schema() + schema = super(ExampleIDatasetFormPlugin, self).create_package_schema() #our custom field schema.update({ 'custom_text': [tk.get_validator('ignore_missing'), @@ -15,7 +15,7 @@ def create_package_schema(self): return schema def update_package_schema(self): - schema = super(ExampleIDatasetForm, self).update_package_schema() + schema = super(ExampleIDatasetFormPlugin, self).update_package_schema() #our custom field schema.update({ 'custom_text': [tk.get_validator('ignore_missing'), @@ -24,7 +24,7 @@ def update_package_schema(self): return schema def show_package_schema(self): - schema = super(ExampleIDatasetForm, self).show_package_schema() + schema = super(ExampleIDatasetFormPlugin, self).show_package_schema() schema.update({ 'custom_text': [tk.get_converter('convert_from_extras'), tk.get_validator('ignore_missing')] diff --git a/ckanext/example_idatasetform/plugin_v2.py b/ckanext/example_idatasetform/plugin_v2.py index f3b146bc627..c1fa7f71f8a 100644 --- a/ckanext/example_idatasetform/plugin_v2.py +++ b/ckanext/example_idatasetform/plugin_v2.py @@ -1,13 +1,13 @@ import ckan.plugins as p import ckan.plugins.toolkit as tk -class ExampleIDatasetForm(p.SingletonPlugin, tk.DefaultDatasetForm): +class ExampleIDatasetFormPlugin(p.SingletonPlugin, tk.DefaultDatasetForm): p.implements(p.IDatasetForm) p.implements(p.IConfigurer) def create_package_schema(self): # let's grab the default schema in our plugin - schema = super(ExampleIDatasetForm, self).create_package_schema() + schema = super(ExampleIDatasetFormPlugin, self).create_package_schema() #our custom field schema.update({ 'custom_text': [tk.get_validator('ignore_missing'), @@ -16,7 +16,7 @@ def create_package_schema(self): return schema def update_package_schema(self): - schema = super(ExampleIDatasetForm, self).update_package_schema() + schema = super(ExampleIDatasetFormPlugin, self).update_package_schema() #our custom field schema.update({ 'custom_text': [tk.get_validator('ignore_missing'), @@ -24,6 +24,14 @@ def update_package_schema(self): }) return schema + def show_package_schema(self): + schema = super(ExampleIDatasetFormPlugin, self).show_package_schema() + schema.update({ + 'custom_text': [tk.get_converter('convert_from_extras'), + tk.get_validator('ignore_missing')] + }) + return schema + #is fall back def is_fallback(self): # Return True to register this plugin as the default handler for diff --git a/ckanext/example_idatasetform/plugin_v3.py b/ckanext/example_idatasetform/plugin_v3.py index 78212636445..a272ca538b5 100644 --- a/ckanext/example_idatasetform/plugin_v3.py +++ b/ckanext/example_idatasetform/plugin_v3.py @@ -2,7 +2,7 @@ import ckan.plugins as p import ckan.plugins.toolkit as tk -class ExtraFieldsPlugin(p.SingletonPlugin, tk.DefaultDatasetForm): +class ExampleIDatasetFormPlugin(p.SingletonPlugin, tk.DefaultDatasetForm): p.implements(p.IDatasetForm) def _modify_package_schema(self, schema): @@ -13,17 +13,17 @@ def _modify_package_schema(self, schema): return schema def create_package_schema(self): - schema = super(ExtraFieldsPlugin, self).create_package_schema() + schema = super(ExampleIDatasetFormPlugin, self).create_package_schema() schema = self._modify_package_schema(schema) return schema def update_package_schema(self): - schema = super(ExtraFieldsPlugin, self).update_package_schema() + schema = super(ExampleIDatasetFormPlugin, self).update_package_schema() schema = self._modify_package_schema(schema) return schema def show_package_schema(self): - schema = super(ExtraFieldsPlugin, self).show_package_schema() + schema = super(ExampleIDatasetFormPlugin, self).show_package_schema() schema.update({ 'custom_text': [tk.get_converter('convert_from_extras'), tk.get_validator('ignore_missing')] diff --git a/ckanext/example_idatasetform/plugin_v4.py b/ckanext/example_idatasetform/plugin_v4.py index 2b0e99927dc..437defaa9a1 100644 --- a/ckanext/example_idatasetform/plugin_v4.py +++ b/ckanext/example_idatasetform/plugin_v4.py @@ -23,7 +23,7 @@ def country_codes(): except tk.ObjectNotFound: return None -class ExampleIDatasetForm(p.SingletonPlugin, tk.DefaultDatasetForm): +class ExampleIDatasetFormPlugin(p.SingletonPlugin, tk.DefaultDatasetForm): p.implements(p.IDatasetForm) p.implements(p.IConfigurer) p.implements(p.ITemplateHelpers) @@ -43,7 +43,7 @@ def _modify_package_schema(self, schema): return schema def show_package_schema(self): - schema = super(ExampleIDatasetForm, self).show_package_schema() + schema = super(ExampleIDatasetFormPlugin, self).show_package_schema() schema.update({ 'custom_text': [tk.get_converter('convert_from_extras'), tk.get_validator('ignore_missing')] @@ -58,12 +58,12 @@ def show_package_schema(self): return schema def create_package_schema(self): - schema = super(ExampleIDatasetForm, self).create_package_schema() + schema = super(ExampleIDatasetFormPlugin, self).create_package_schema() schema = self._modify_package_schema(schema) return schema def update_package_schema(self): - schema = super(ExampleIDatasetForm, self).update_package_schema() + schema = super(ExampleIDatasetFormPlugin, self).update_package_schema() schema = self._modify_package_schema(schema) return schema diff --git a/doc/extensions/adding-custom-fields.rst b/doc/extensions/adding-custom-fields.rst index 1b86ccb0553..817f0124d86 100644 --- a/doc/extensions/adding-custom-fields.rst +++ b/doc/extensions/adding-custom-fields.rst @@ -2,22 +2,59 @@ Adding custom fields to CKAN ============================ -CKAN by default allows users to enter custom fields and values into datasets in -the "Additional Information" step when creating datasets and when editing -datasets as additional key-value pairs. This tutorial shows you how to -customize this handling so that your metadata is more integrated with the form -and API. In this tutorial we are assuming that you have read the -:doc:`/extensions/tutorial` - -Adding custom fields to packages --------------------------------- +Storing additional metadata for a dataset beyond the default metadata in CKAN +is a common scenario. CKAN provides a simple way to do this by allowing you to +abitrary key/value pairs against a dataset when creating or updating the +dataset, these appear under the "Additional Information" section on the web +interface and in 'extras' field of the JSON when accessed via in the API. + +These default extras can only take strings for their keys and values, no +validation is applied to the inputs and you cannot make them mandatory or +restrict the possible values you can take. By using CKAN's IDatasetForm plugin +interface, a CKAN plugin can add custom, first-class metadata fields to CKAN +datasets, and can do custom validation of these fields. In this tutorial we +are assuming that you have read the :doc:`/extensions/tutorial` + +CKAN schemas and validation +--------------------------- +When calls are made to the action functions, either via the web interface or +the CKAN API, the parameters passed to the action function usually have an +associated schema. For each parameter provided, the schema will contain a list +of functions that will take the value of the parameter and run it against each +function. These functions can provide validation, that can raise an error if +the value fails validation or it may be a converter that provides a lookup +for the action function to use. + +For example, the schemas can allow optional values by using the +:func:`~ckan.lib.navl.validators.ignore_missing` validator or check that a +dataset exists using :func:`~ckan.logic.validators.package_id_exists`. A list +of available validators and converters can be found at the :doc:`validators` +and :doc:`converters`. + +We will customizing these schemas to add our additional fields. The +:py:class:`~ckan.plugins.interfaces.IDatasetForm` interface allows us to +override the schemas for creation, updating and displaying of datasets. + +.. autosummary:: + + ~ckan.plugins.interfaces.IDatasetForm.create_package_schema + ~ckan.plugins.interfaces.IDatasetForm.update_package_schema + ~ckan.plugins.interfaces.IDatasetForm.show_package_schema + ~ckan.plugins.interfaces.IDatasetForm.is_fallback + ~ckan.plugins.interfaces.IDatasetForm.package_types + +The IDatasetForm also has other additional functions that allow you to +provide a custom template to be rendered for the CKAN frontend, but we will +not be using them for this tutorial. + +Adding custom fields to datasets +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Create a new plugin named ``ckanext-extrafields`` and create a class named -``ExampleIDatasetForms`` inside +``ExampleIDatasetFormPlugins`` inside ``ckanext-extrafields/ckanext/extrafields/plugins.py`` that implements the ``IDatasetForm`` interface and inherits from ``SingletonPlugin`` and -``DefaultDatasetForm``, we will want to implement that functions that allow us -to update CKAN's default package schema to include our custom field. +``DefaultDatasetForm``. .. literalinclude:: ../../ckanext/example_idatasetform/plugin_v1.py :end-before: def create_package_schema(self): @@ -25,43 +62,48 @@ to update CKAN's default package schema to include our custom field. Updating the CKAN schema ^^^^^^^^^^^^^^^^^^^^^^^^ -The ``create_package_schema`` function is used whenever a new package is -created, we'll want update the default schema and insert our custom field here. -We will fetch the default schema defined in -``in default_create_package_schema`` by running ``create_package_schema``'s +The :py:meth:`~ckan.plugins.interfaces.IDatasetForm.create_package_schema` +function is used whenever a new dataset is created, we'll want update the +default schema and insert our custom field here. We will fetch the default +schema defined in +:py:func:`~ckan.logic.schema.default_create_package_schema` by running +:py:meth:`~ckan.plugins.interfaces.IDatasetForm.create_package_schema`'s super function and update it. .. literalinclude:: ../../ckanext/example_idatasetform/plugin_v1.py - :pyobject: ExampleIDatasetForm.create_package_schema + :pyobject: ExampleIDatasetFormPlugin.create_package_schema The CKAN schema is a dictionary where the key is the name of the field and the value is a list of validators and converters. Here we have a validator to tell CKAN to not raise a validation error if the value is missing and a converter to convert the value to and save as an extra. We will want to change the -``update_package_schema`` function with the same update code +:py:meth:`~ckan.plugins.interfaces.IDatasetForm.update_package_schema` function +with the same update code. .. literalinclude:: ../../ckanext/example_idatasetform/plugin_v1.py - :pyobject: ExampleIDatasetForm.update_package_schema + :pyobject: ExampleIDatasetFormPlugin.update_package_schema -The ``show_package_schema`` is used when the ``package_show`` action is called, -we want the default_show_package_schema to be updated to include our custom -field. This time, instead of converting to an an extras field. We want our -field to be converted *from* an extras field. So we want to use the -``convert_from_extras`` converter. +The :py:meth:`~ckan.plugins.interfaces.IDatasetForm.show_package_schema` is used +when the :py:func:`~ckan.logic.action.get.package_show` action is called, we +want the default_show_package_schema to be updated to include our custom field. +This time, instead of converting to an an extras field. We want our field to be +converted *from* an extras field. So we want to use the +:py:meth:`~ckan.logic.converters.convert_from_extras` converter. .. literalinclude:: ../../ckanext/example_idatasetform/plugin_v1.py :emphasize-lines: 4 - :pyobject: ExampleIDatasetForm.show_package_schema + :pyobject: ExampleIDatasetFormPlugin.show_package_schema Package types ^^^^^^^^^^^^^ -The ``package_types`` function defines a list of package types that this plugin -handles. Each package has a field containing it's type. Plugins can register to -handle specific types of packages and ignore others. Since our plugin is not -for any specific type of package and we want our plugin to be the default -handler, we update the plugin code to contain the following +The :py:meth:`~ckan.plugins.interfaces.IDatasetForm.package_types` function +defines a list of package types that this plugin handles. Each package has a +field containing it's type. Plugins can register to handle specific types of +packages and ignore others. Since our plugin is not for any specific type of +package and we want our plugin to be the default handler, we update the plugin +code to contain the following: .. literalinclude:: ../../ckanext/example_idatasetform/plugin_v1.py :lines: 34- @@ -78,12 +120,13 @@ IConfigurer interface :start-after: import ckan.plugins.toolkit as tk :end-before: def create_package_schema(self): -This interface allows to implement a function ``update_config`` that allows us +This interface allows to implement a function +:py:meth:`~ckan.plugins.interfaces.IDatasetForm.update_config` that allows us to update the CKAN config, in our case we want to add an additional location for CKAN to look for templates. Add the following code to your plugin. .. literalinclude:: ../../ckanext/example_idatasetform/plugin_v2.py - :pyobject: ExampleIDatasetForm.update_config + :pyobject: ExampleIDatasetFormPlugin.update_config You will also need to add a directory under your extension directory to store the templates. Create a directory called @@ -126,9 +169,11 @@ dataset. Cleaning up the code ^^^^^^^^^^^^^^^^^^^^ -Before we continue further, we can clean up the ``create_package_schema`` -and ``update_package_schema``. There is a bit of duplication that we could -remove. Replace the two functions with +Before we continue further, we can clean up the +:py:meth:`~ckan.plugins.interfaces.IDatasetForm.create_package_schema` +and :py:meth:`~ckan.plugins.interfaces.IDatasetForm.update_package_schema`. +There is a bit of duplication that we could remove. Replace the two functions +with: .. literalinclude:: ../../ckanext/example_idatasetform/plugin_v3.py :start-after: p.implements(p.IDatasetForm) @@ -146,14 +191,16 @@ function to your plugin.py above your plugin class. This codeblock is taken from the ``example_idatsetform plugin``. ``create_country_codes`` tries to fetch the vocabulary country_codes using -``vocabulary_show``. If it is not found it will create it and iterate over -the list of countries 'uk', 'ie', 'de', 'fr', 'es'. For each of these -a vocabulary tag is created using ``tag_create``, belonging to the vocabulary +:func:`~ckan.logic.action.get.vocabulary_show`. If it is not found it will +create it and iterate over the list of countries 'uk', 'ie', 'de', 'fr', 'es'. +For each of these a vocabulary tag is created using +:func:`~ckan.logic.action.create.tag_create`, belonging to the vocabulary ``country_code``. Although we have only defined five tags here, additional tags can be created -at any point by a sysadmin user by calling ``tag_create`` using the API or action -functions. Add a second function below ``create_country_codes`` +at any point by a sysadmin user by calling +:func:`~ckan.logic.action.tag_create`` using the API or action functions. Add a +second function below ``create_country_codes`` .. literalinclude:: ../../ckanext/example_idatasetform/plugin_v4.py :pyobject: country_codes @@ -166,7 +213,8 @@ to call this code. Adding tags to the schema ^^^^^^^^^^^^^^^^^^^^^^^^^ -Update ``_modify_package_schema`` and ``show_package_schema`` +Update ``_modify_package_schema`` and +:py:meth:`~ckan.plugins.interfaces.IDatasetForm.show_package_schema` .. literalinclude:: ../../ckanext/example_idatasetform/plugin_v4.py :start-after: return {'country_codes': country_codes} @@ -175,16 +223,19 @@ Update ``_modify_package_schema`` and ``show_package_schema`` We are adding our tag to our plugin's schema. A converter is required to convert the field in to our tag in a similar way to how we converted our field -to extras earlier. In ``show_package_schema`` we convert from the tag back again -but we have an additional line with another converter containing -``free_tags_only``. We include this line so that vocab tags are not shown mixed -with normal free tags. +to extras earlier. In +:py:meth:`~ckan.plugins.interfaces.IDatasetForm.show_package_schema` we convert +from the tag back again but we have an additional line with another converter +containing +:py:func:`~ckan.logic.converters.free_tags_only`. We include this line so that +vocab tags are not shown mixed with normal free tags. Adding tags to templates ^^^^^^^^^^^^^^^^^^^^^^^^ Add an additional plugin.implements line to to your plugin -to implement the ``ITemplateHelpers``, we will need to add a ``get_helpers`` +to implement the :py:class:`~ckan.plugins.interfaces.ITemplateHelpers`, we will +need to add a :py:meth:`~ckan.plugins.interfaces.ITemplateHelpers.get_helpers` function defined for this interface. .. literalinclude:: ../../ckanext/example_idatasetform/plugin_v4.py @@ -212,21 +263,17 @@ is nested in the package dict as package['resources']. We modify this dict in a similar way to the package schema. Change ``_modify_package_schema`` to the following. -.. literalinclude:: ../../ckanext/example_idatasetform/plugin_v5.py - :pyobject: ExampleIDatasetForm._modify_package_schema - :emphasize-lines: 10-12 - -Update ``show_package_schema`` similarly - -.. literalinclude:: ../../ckanext/example_idatasetform/plugin_v5.py - :pyobject: ExampleIDatasetForm.show_package_schema +.. literalinclude:: ../../ckanext/example_idatasetform/plugin.py + :pyobject: ExampleIDatasetFormPlugin._modify_package_schema :emphasize-lines: 14-16 - -Save and reload your development server -.. topic:: Details +Update :py:meth:`~ckan.plugins.interfaces.IDatasetForm.show_package_schema` +similarly - CKAN will take any additional keys from the resource schema and save - them the it's extras field. This is a Postgres Json datatype field, - The templates will automatically check this field and display them in the - resource_read page. +.. literalinclude:: ../../ckanext/example_idatasetform/plugin.py + :pyobject: ExampleIDatasetFormPlugin.show_package_schema + :emphasize-lines: 20-23 + +Save and reload your development server CKAN will take any additional keys from +the resource schema and save them the it's extras field. The templates will +automatically check this field and display them in the resource_read page. diff --git a/setup.py b/setup.py index a020232b516..d76a1e3f02f 100644 --- a/setup.py +++ b/setup.py @@ -75,6 +75,10 @@ 'recline_preview = ckanext.reclinepreview.plugin:ReclinePreview', 'example_itemplatehelpers = ckanext.example_itemplatehelpers.plugin:ExampleITemplateHelpersPlugin', 'example_idatasetform = ckanext.example_idatasetform.plugin:ExampleIDatasetFormPlugin', + 'example_idatasetform_v1 = ckanext.example_idatasetform.plugin_v1:ExampleIDatasetFormPlugin', + 'example_idatasetform_v2 = ckanext.example_idatasetform.plugin_v2:ExampleIDatasetFormPlugin', + 'example_idatasetform_v3 = ckanext.example_idatasetform.plugin_v3:ExampleIDatasetFormPlugin', + 'example_idatasetform_v4 = ckanext.example_idatasetform.plugin_v4:ExampleIDatasetFormPlugin', 'example_iauthfunctions_v1 = ckanext.example_iauthfunctions.plugin_v1:ExampleIAuthFunctionsPlugin', 'example_iauthfunctions_v2 = ckanext.example_iauthfunctions.plugin_v2:ExampleIAuthFunctionsPlugin', 'example_iauthfunctions_v3 = ckanext.example_iauthfunctions.plugin_v3:ExampleIAuthFunctionsPlugin', From 453a18c69caf868d8492390add4a524591d87bcd Mon Sep 17 00:00:00 2001 From: joetsoi Date: Mon, 6 Jan 2014 19:44:05 +0000 Subject: [PATCH 09/77] [#790] undo doc subproject commits --- doc/_themes/sphinx-theme-okfn | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/_themes/sphinx-theme-okfn b/doc/_themes/sphinx-theme-okfn index 320555990b6..4628f26abf4 160000 --- a/doc/_themes/sphinx-theme-okfn +++ b/doc/_themes/sphinx-theme-okfn @@ -1 +1 @@ -Subproject commit 320555990b639c99ac3bcc79024140c9588e2bdf +Subproject commit 4628f26abf401fdb63ec099384bff44a27dcda4c From d7d7adcd65b6c79d1dfc0fa2bb23befd752e7b8f Mon Sep 17 00:00:00 2001 From: joetsoi Date: Mon, 6 Jan 2014 19:52:26 +0000 Subject: [PATCH 10/77] [#790] remove unused plugin version --- ckanext/example_idatasetform/plugin_v5.py | 91 ----------------------- doc/extensions/adding-custom-fields.rst | 3 + 2 files changed, 3 insertions(+), 91 deletions(-) delete mode 100644 ckanext/example_idatasetform/plugin_v5.py diff --git a/ckanext/example_idatasetform/plugin_v5.py b/ckanext/example_idatasetform/plugin_v5.py deleted file mode 100644 index d4f60ee52ac..00000000000 --- a/ckanext/example_idatasetform/plugin_v5.py +++ /dev/null @@ -1,91 +0,0 @@ -import ckan.plugins as p -import ckan.plugins.toolkit as tk - -def create_country_codes(): - user = tk.get_action('get_site_user')({'ignore_auth': True}, {}) - context = {'user': user['name']} - try: - data = {'id': 'country_codes'} - tk.get_action('vocabulary_show')(context, data) - except tk.ObjectNotFound: - data = {'name': 'country_codes'} - vocab = tk.get_action('vocabulary_create')(context, data) - for tag in (u'uk', u'ie', u'de', u'fr', u'es'): - data = {'name': tag, 'vocabulary_id': vocab['id']} - tk.get_action('tag_create')(context, data) - -def country_codes(): - create_country_codes() - try: - country_codes = tk.get_action('tag_list')( - data_dict={'vocabulary_id': 'country_codes'}) - return country_codes - except tk.ObjectNotFound: - return None - -class ExampleIDatasetForm(p.SingletonPlugin, tk.DefaultDatasetForm): - p.implements(p.IDatasetForm) - p.implements(p.IConfigurer) - p.implements(p.ITemplateHelpers) - - def get_helpers(self): - return {'country_codes': country_codes} - - def _modify_package_schema(self, schema): - schema.update({ - 'custom_text': [tk.get_validator('ignore_missing'), - tk.get_converter('convert_to_extras')] - }) - schema.update({ - 'country_code': [tk.get_validator('ignore_missing'), - tk.get_converter('convert_to_tags')('country_codes')] - }) - schema['resources'].update({ - 'custom_resource_text' : [ tk.get_validator('ignore_missing') ] - }) - return schema - - def show_package_schema(self): - schema = super(ExampleIDatasetForm, self).show_package_schema() - schema.update({ - 'custom_text': [tk.get_converter('convert_from_extras'), - tk.get_validator('ignore_missing')] - }) - - schema['tags']['__extras'].append(tk.get_converter('free_tags_only')) - schema.update({ - 'country_code': [ - tk.get_converter('convert_from_tags')('country_codes'), - tk.get_validator('ignore_missing')] - }) - schema['resources'].update({ - 'custom_resource_text' : [ tk.get_validator('ignore_missing') ] - }) - return schema - - def create_package_schema(self): - schema = super(ExampleIDatasetForm, self).create_package_schema() - schema = self._modify_package_schema(schema) - return schema - - def update_package_schema(self): - schema = super(ExampleIDatasetForm, self).update_package_schema() - schema = self._modify_package_schema(schema) - return schema - - #is fall back - def is_fallback(self): - # Return True to register this plugin as the default handler for - # package types not handled by any other IDatasetForm plugin. - return True - - def package_types(self): - # This plugin doesn't handle any special package types, it just - # registers itself as the default (above). - return [] - - #update config - def update_config(self, config): - # Add this plugin's templates dir to CKAN's extra_template_paths, so - # that CKAN will use this plugin's custom templates. - tk.add_template_directory(config, 'templates') diff --git a/doc/extensions/adding-custom-fields.rst b/doc/extensions/adding-custom-fields.rst index 817f0124d86..f8256052bda 100644 --- a/doc/extensions/adding-custom-fields.rst +++ b/doc/extensions/adding-custom-fields.rst @@ -277,3 +277,6 @@ similarly Save and reload your development server CKAN will take any additional keys from the resource schema and save them the it's extras field. The templates will automatically check this field and display them in the resource_read page. + +You can find the complete source for this tutorial in the +``ckanext/example_idatasetform`` directory. From 33d747091839b4b679b49e165cd80a67976f2e38 Mon Sep 17 00:00:00 2001 From: joetsoi Date: Tue, 7 Jan 2014 02:37:11 +0000 Subject: [PATCH 11/77] [#790] pep8, fix tests by preventing plugins from loading during import --- .../new_tests/test_example_idatasetform.py | 32 +++++++++++-------- ckanext/example_idatasetform/plugin_v1.py | 9 +++--- ckanext/example_idatasetform/plugin_v2.py | 11 ++++--- ckanext/example_idatasetform/plugin_v3.py | 5 +-- ckanext/example_idatasetform/plugin_v4.py | 21 +++++++----- doc/extensions/adding-custom-fields.rst | 2 +- 6 files changed, 46 insertions(+), 34 deletions(-) diff --git a/ckanext/example_idatasetform/new_tests/test_example_idatasetform.py b/ckanext/example_idatasetform/new_tests/test_example_idatasetform.py index 5784264b231..a7aaccf955f 100644 --- a/ckanext/example_idatasetform/new_tests/test_example_idatasetform.py +++ b/ckanext/example_idatasetform/new_tests/test_example_idatasetform.py @@ -3,8 +3,10 @@ import ckan.plugins as plugins import ckan.new_tests.helpers as helpers -import ckanext.example_idatasetform.plugin_v4 as v4 -import ckanext.example_idatasetform.plugin as v5 +import ckanext.example_idatasetform as idf +#do not import plugins classes (e.g example_idatasetform.plugin_v4) +#it causes the plugins to get registered and loaded before the tests are run + class ExampleIDatasetFormPluginBase(object): '''Version 1, 2 and 3 of the plugin are basically the same, so this class @@ -23,14 +25,14 @@ def test_package_create(self): def test_package_update(self): helpers.call_action('package_create', name='test_package', - custom_text='this is my custom text') + custom_text='this is my custom text') result = helpers.call_action('package_update', name='test_package', custom_text='this is my updated text') nt.assert_equals('this is my updated text', result['custom_text']) def test_package_show(self): helpers.call_action('package_create', name='test_package', - custom_text='this is my custom text') + custom_text='this is my custom text') result = helpers.call_action('package_show', name_or_id='test_package') nt.assert_equals('this is my custom text', result['custom_text']) @@ -67,6 +69,7 @@ def teardown_class(cls): super(TestVersion3, cls).teardown_class() plugins.unload('example_idatasetform_v3') + class TestIDatasetFormPluginVersion4(object): @classmethod def setup_class(cls): @@ -81,7 +84,7 @@ def teardown_class(cls): helpers.reset_db() def test_package_create(self): - v4.create_country_codes() + idf.plugin_v4.create_country_codes() result = helpers.call_action('package_create', name='test_package', custom_text='this is my custom text', country_code='uk') @@ -89,7 +92,7 @@ def test_package_create(self): nt.assert_equals([u'uk'], result['country_code']) def test_package_create_wrong_country_code(self): - v4.create_country_codes() + idf.plugin_v4.create_country_codes() nt.assert_raises(plugins.toolkit.ValidationError, helpers.call_action, 'package_create', @@ -98,7 +101,7 @@ def test_package_create_wrong_country_code(self): country_code='notcode') def test_package_update(self): - v4.create_country_codes() + idf.plugin_v4.create_country_codes() helpers.call_action('package_create', name='test_package', custom_text='this is my custom text', country_code='uk') @@ -108,6 +111,7 @@ def test_package_update(self): nt.assert_equals('this is my updated text', result['custom_text']) nt.assert_equals([u'ie'], result['country_code']) + class TestIDatasetFormPlugin(object): @classmethod def setup_class(cls): @@ -122,7 +126,7 @@ def teardown_class(cls): helpers.reset_db() def test_package_create(self): - v5.create_country_codes() + idf.plugin.create_country_codes() result = helpers.call_action( 'package_create', name='test_package', custom_text='this is my custom text', country_code='uk', @@ -131,10 +135,10 @@ def test_package_create(self): 'custom_resource_text': 'my custom resource', }]) nt.assert_equals('my custom resource', - result['resources'][0]['custom_resource_text']) + result['resources'][0]['custom_resource_text']) def test_package_update(self): - v5.create_country_codes() + idf.plugin.create_country_codes() helpers.call_action( 'package_create', name='test_package', custom_text='this is my custom text', country_code='uk', @@ -155,10 +159,10 @@ def test_package_update(self): nt.assert_equals('this is my updated text', result['custom_text']) nt.assert_equals([u'ie'], result['country_code']) nt.assert_equals('updated custom resource', - result['resources'][0]['custom_resource_text']) + result['resources'][0]['custom_resource_text']) def test_package_show(self): - v5.create_country_codes() + idf.plugin.create_country_codes() helpers.call_action( 'package_create', name='test_package', custom_text='this is my custom text', country_code='uk', @@ -169,6 +173,6 @@ def test_package_show(self): ) result = helpers.call_action('package_show', name_or_id='test_package') nt.assert_equals('my custom resource', - result['resources'][0]['custom_resource_text']) + result['resources'][0]['custom_resource_text']) nt.assert_equals('my custom resource', - result['resources'][0]['custom_resource_text']) + result['resources'][0]['custom_resource_text']) diff --git a/ckanext/example_idatasetform/plugin_v1.py b/ckanext/example_idatasetform/plugin_v1.py index f3b7f76321d..183e12ff28e 100644 --- a/ckanext/example_idatasetform/plugin_v1.py +++ b/ckanext/example_idatasetform/plugin_v1.py @@ -1,6 +1,7 @@ import ckan.plugins as p import ckan.plugins.toolkit as tk + class ExampleIDatasetFormPlugin(p.SingletonPlugin, tk.DefaultDatasetForm): p.implements(p.IDatasetForm) @@ -9,8 +10,8 @@ def create_package_schema(self): schema = super(ExampleIDatasetFormPlugin, self).create_package_schema() #our custom field schema.update({ - 'custom_text': [tk.get_validator('ignore_missing'), - tk.get_converter('convert_to_extras')] + 'custom_text': [tk.get_validator('ignore_missing'), + tk.get_converter('convert_to_extras')] }) return schema @@ -19,7 +20,7 @@ def update_package_schema(self): #our custom field schema.update({ 'custom_text': [tk.get_validator('ignore_missing'), - tk.get_converter('convert_to_extras')] + tk.get_converter('convert_to_extras')] }) return schema @@ -27,7 +28,7 @@ def show_package_schema(self): schema = super(ExampleIDatasetFormPlugin, self).show_package_schema() schema.update({ 'custom_text': [tk.get_converter('convert_from_extras'), - tk.get_validator('ignore_missing')] + tk.get_validator('ignore_missing')] }) return schema diff --git a/ckanext/example_idatasetform/plugin_v2.py b/ckanext/example_idatasetform/plugin_v2.py index c1fa7f71f8a..9741d8be7ff 100644 --- a/ckanext/example_idatasetform/plugin_v2.py +++ b/ckanext/example_idatasetform/plugin_v2.py @@ -1,6 +1,7 @@ import ckan.plugins as p import ckan.plugins.toolkit as tk + class ExampleIDatasetFormPlugin(p.SingletonPlugin, tk.DefaultDatasetForm): p.implements(p.IDatasetForm) p.implements(p.IConfigurer) @@ -10,8 +11,8 @@ def create_package_schema(self): schema = super(ExampleIDatasetFormPlugin, self).create_package_schema() #our custom field schema.update({ - 'custom_text': [tk.get_validator('ignore_missing'), - tk.get_converter('convert_to_extras')] + 'custom_text': [tk.get_validator('ignore_missing'), + tk.get_converter('convert_to_extras')] }) return schema @@ -20,7 +21,7 @@ def update_package_schema(self): #our custom field schema.update({ 'custom_text': [tk.get_validator('ignore_missing'), - tk.get_converter('convert_to_extras')] + tk.get_converter('convert_to_extras')] }) return schema @@ -28,7 +29,7 @@ def show_package_schema(self): schema = super(ExampleIDatasetFormPlugin, self).show_package_schema() schema.update({ 'custom_text': [tk.get_converter('convert_from_extras'), - tk.get_validator('ignore_missing')] + tk.get_validator('ignore_missing')] }) return schema @@ -42,7 +43,7 @@ def package_types(self): # This plugin doesn't handle any special package types, it just # registers itself as the default (above). return [] - + def update_config(self, config): # Add this plugin's templates dir to CKAN's extra_template_paths, so # that CKAN will use this plugin's custom templates. diff --git a/ckanext/example_idatasetform/plugin_v3.py b/ckanext/example_idatasetform/plugin_v3.py index a272ca538b5..6430becf7b7 100644 --- a/ckanext/example_idatasetform/plugin_v3.py +++ b/ckanext/example_idatasetform/plugin_v3.py @@ -2,13 +2,14 @@ import ckan.plugins as p import ckan.plugins.toolkit as tk + class ExampleIDatasetFormPlugin(p.SingletonPlugin, tk.DefaultDatasetForm): p.implements(p.IDatasetForm) def _modify_package_schema(self, schema): schema.update({ 'custom_text': [tk.get_validator('ignore_missing'), - tk.get_converter('convert_to_extras')] + tk.get_converter('convert_to_extras')] }) return schema @@ -26,7 +27,7 @@ def show_package_schema(self): schema = super(ExampleIDatasetFormPlugin, self).show_package_schema() schema.update({ 'custom_text': [tk.get_converter('convert_from_extras'), - tk.get_validator('ignore_missing')] + tk.get_validator('ignore_missing')] }) return schema diff --git a/ckanext/example_idatasetform/plugin_v4.py b/ckanext/example_idatasetform/plugin_v4.py index 437defaa9a1..1639459c069 100644 --- a/ckanext/example_idatasetform/plugin_v4.py +++ b/ckanext/example_idatasetform/plugin_v4.py @@ -1,6 +1,7 @@ import ckan.plugins as p import ckan.plugins.toolkit as tk + def create_country_codes(): user = tk.get_action('get_site_user')({'ignore_auth': True}, {}) context = {'user': user['name']} @@ -14,15 +15,17 @@ def create_country_codes(): data = {'name': tag, 'vocabulary_id': vocab['id']} tk.get_action('tag_create')(context, data) + def country_codes(): create_country_codes() try: - country_codes = tk.get_action('tag_list')( - data_dict={'vocabulary_id': 'country_codes'}) + tag_list = tk.get_action('tag_list') + country_codes = tag_list(data_dict={'vocabulary_id': 'country_codes'}) return country_codes except tk.ObjectNotFound: return None + class ExampleIDatasetFormPlugin(p.SingletonPlugin, tk.DefaultDatasetForm): p.implements(p.IDatasetForm) p.implements(p.IConfigurer) @@ -34,19 +37,21 @@ def get_helpers(self): def _modify_package_schema(self, schema): schema.update({ 'custom_text': [tk.get_validator('ignore_missing'), - tk.get_converter('convert_to_extras')] + tk.get_converter('convert_to_extras')] }) schema.update({ - 'country_code': [tk.get_validator('ignore_missing'), - tk.get_converter('convert_to_tags')('country_codes')] - }) + 'country_code': [ + tk.get_validator('ignore_missing'), + tk.get_converter('convert_to_tags')('country_codes') + ] + }) return schema def show_package_schema(self): schema = super(ExampleIDatasetFormPlugin, self).show_package_schema() schema.update({ 'custom_text': [tk.get_converter('convert_from_extras'), - tk.get_validator('ignore_missing')] + tk.get_validator('ignore_missing')] }) schema['tags']['__extras'].append(tk.get_converter('free_tags_only')) @@ -77,7 +82,7 @@ def package_types(self): # This plugin doesn't handle any special package types, it just # registers itself as the default (above). return [] - + #update config def update_config(self, config): # Add this plugin's templates dir to CKAN's extra_template_paths, so diff --git a/doc/extensions/adding-custom-fields.rst b/doc/extensions/adding-custom-fields.rst index f8256052bda..58aeec0fd17 100644 --- a/doc/extensions/adding-custom-fields.rst +++ b/doc/extensions/adding-custom-fields.rst @@ -219,7 +219,7 @@ Update ``_modify_package_schema`` and .. literalinclude:: ../../ckanext/example_idatasetform/plugin_v4.py :start-after: return {'country_codes': country_codes} :end-before: def create_package_schema(self): - :emphasize-lines: 8,19-24 + :emphasize-lines: 9,21-26 We are adding our tag to our plugin's schema. A converter is required to convert the field in to our tag in a similar way to how we converted our field From 3fca1af3714af5d204bfadcd82e417bb26412574 Mon Sep 17 00:00:00 2001 From: joetsoi Date: Thu, 30 Jan 2014 22:40:57 +0000 Subject: [PATCH 12/77] [#790] IDatasetForm tutorial cleanups --- .../new_tests/test_example_idatasetform.py | 4 +- doc/extensions/adding-custom-fields.rst | 85 +++++++++++-------- 2 files changed, 49 insertions(+), 40 deletions(-) diff --git a/ckanext/example_idatasetform/new_tests/test_example_idatasetform.py b/ckanext/example_idatasetform/new_tests/test_example_idatasetform.py index a7aaccf955f..c917b53f8df 100644 --- a/ckanext/example_idatasetform/new_tests/test_example_idatasetform.py +++ b/ckanext/example_idatasetform/new_tests/test_example_idatasetform.py @@ -1,11 +1,9 @@ import nose.tools as nt + import ckan.model as model import ckan.plugins as plugins import ckan.new_tests.helpers as helpers - import ckanext.example_idatasetform as idf -#do not import plugins classes (e.g example_idatasetform.plugin_v4) -#it causes the plugins to get registered and loaded before the tests are run class ExampleIDatasetFormPluginBase(object): diff --git a/doc/extensions/adding-custom-fields.rst b/doc/extensions/adding-custom-fields.rst index 58aeec0fd17..315bd87eb9d 100644 --- a/doc/extensions/adding-custom-fields.rst +++ b/doc/extensions/adding-custom-fields.rst @@ -1,37 +1,41 @@ -============================ -Adding custom fields to CKAN -============================ +=================================================================== +Customizing dataset and resource metadata fields using IDatasetForm +=================================================================== Storing additional metadata for a dataset beyond the default metadata in CKAN is a common scenario. CKAN provides a simple way to do this by allowing you to -abitrary key/value pairs against a dataset when creating or updating the -dataset, these appear under the "Additional Information" section on the web -interface and in 'extras' field of the JSON when accessed via in the API. +store arbitrary key/value pairs against a dataset when creating or updating the +dataset. These appear under the "Additional Information" section on the web +interface and in 'extras' field of the JSON when accessed via the API. -These default extras can only take strings for their keys and values, no +Default extras can only take strings for their keys and values, no validation is applied to the inputs and you cannot make them mandatory or -restrict the possible values you can take. By using CKAN's IDatasetForm plugin -interface, a CKAN plugin can add custom, first-class metadata fields to CKAN -datasets, and can do custom validation of these fields. In this tutorial we -are assuming that you have read the :doc:`/extensions/tutorial` +restrict the possible values to a defined list. By using CKAN's IDatasetForm +plugin interface, a CKAN plugin can add custom, first-class metadata fields to +CKAN datasets, and can do custom validation of these fields. + + .. seealso:: + In this tutorial we are assuming that you have read the + :doc:`/extensions/tutorial` CKAN schemas and validation --------------------------- -When calls are made to the action functions, either via the web interface or -the CKAN API, the parameters passed to the action function usually have an -associated schema. For each parameter provided, the schema will contain a list -of functions that will take the value of the parameter and run it against each -function. These functions can provide validation, that can raise an error if -the value fails validation or it may be a converter that provides a lookup -for the action function to use. +When a dataset is created, updated or viewed, the parameters passed to CKAN +(e.g. via the web form when creating or updating a dataset, or posted to an API +end point) are validated against a schema. For each parameter, the schema will +contain a corresponding list of functions that will be run against the value of +the parameter. Generally these functions are used to validate the value +(and raise an error if the value fails validation) or convert the value to a +different value. For example, the schemas can allow optional values by using the :func:`~ckan.lib.navl.validators.ignore_missing` validator or check that a dataset exists using :func:`~ckan.logic.validators.package_id_exists`. A list of available validators and converters can be found at the :doc:`validators` -and :doc:`converters`. +and :doc:`converters`. You can also define your own validators for custom +validation. -We will customizing these schemas to add our additional fields. The +We will be customizing these schemas to add our additional fields. The :py:class:`~ckan.plugins.interfaces.IDatasetForm` interface allows us to override the schemas for creation, updating and displaying of datasets. @@ -43,6 +47,12 @@ override the schemas for creation, updating and displaying of datasets. ~ckan.plugins.interfaces.IDatasetForm.is_fallback ~ckan.plugins.interfaces.IDatasetForm.package_types +CKAN allows you to have multiple IDatasetForm plugins, each handling different +dataset types. So you could customize the CKAN web front end, for different +types of datasets. In this tutorial we will be defining our plugin as the +fallback plugin. This plugin is used if no other IDatasetForm plugin is found +that handles that dataset's type. + The IDatasetForm also has other additional functions that allow you to provide a custom template to be rendered for the CKAN frontend, but we will not be using them for this tutorial. @@ -86,7 +96,7 @@ with the same update code. The :py:meth:`~ckan.plugins.interfaces.IDatasetForm.show_package_schema` is used when the :py:func:`~ckan.logic.action.get.package_show` action is called, we want the default_show_package_schema to be updated to include our custom field. -This time, instead of converting to an an extras field. We want our field to be +This time, instead of converting to an extras field, we want our field to be converted *from* an extras field. So we want to use the :py:meth:`~ckan.logic.converters.convert_from_extras` converter. @@ -100,7 +110,7 @@ Package types The :py:meth:`~ckan.plugins.interfaces.IDatasetForm.package_types` function defines a list of package types that this plugin handles. Each package has a -field containing it's type. Plugins can register to handle specific types of +field containing its type. Plugins can register to handle specific types of packages and ignore others. Since our plugin is not for any specific type of package and we want our plugin to be the default handler, we update the plugin code to contain the following: @@ -158,7 +168,7 @@ our custom_text field on the dataset page. Add another file called .. literalinclude:: ../../ckanext/example_idatasetform/templates/package/snippets/additional_info.html :language: jinja -This template overrides the the default extras rendering on the dataset page +This template overrides the default extras rendering on the dataset page and replaces it to just display our custom field. You're done! Make sure you have your plugin installed and setup as in the @@ -181,15 +191,16 @@ with: Tag vocabularies ---------------- -If you need to add a custom field where the input options are restrcited to a -provide list of options, you can use tag vocabularies `/tag-vocabularies`. We -will need to create our vocabulary first. By calling vocabulary_create. Add a -function to your plugin.py above your plugin class. +If you need to add a custom field where the input options are restricted to a +provided list of options, you can use tag vocabularies `/tag-vocabularies`. We +will need to create our vocabulary first. By calling +:func:`~ckan.logic.action.vocabulary_create`. Add a function to your plugin.py +above your plugin class. .. literalinclude:: ../../ckanext/example_idatasetform/plugin_v4.py :pyobject: create_country_codes -This codeblock is taken from the ``example_idatsetform plugin``. +This code block is taken from the ``example_idatsetform plugin``. ``create_country_codes`` tries to fetch the vocabulary country_codes using :func:`~ckan.logic.action.get.vocabulary_show`. If it is not found it will create it and iterate over the list of countries 'uk', 'ie', 'de', 'fr', 'es'. @@ -199,22 +210,22 @@ For each of these a vocabulary tag is created using Although we have only defined five tags here, additional tags can be created at any point by a sysadmin user by calling -:func:`~ckan.logic.action.tag_create`` using the API or action functions. Add a -second function below ``create_country_codes`` +:func:`~ckan.logic.action.create.tag_create` using the API or action functions. +Add a second function below ``create_country_codes`` .. literalinclude:: ../../ckanext/example_idatasetform/plugin_v4.py :pyobject: country_codes country_codes will call ``create_country_codes`` so that the ``country_codes`` -vocabulary is created if it does not exist. Then it calls tag_list to return -all of our vocabulary tags together. Now we have a way of retrieving our tag -vocabularies and creating them if they do not exist. We just need our plugin -to call this code. +vocabulary is created if it does not exist. Then it calls +:func:`~ckan.logic.action.get.tag_list` to return all of our vocabulary tags +together. Now we have a way of retrieving our tag vocabularies and creating +them if they do not exist. We just need our plugin to call this code. Adding tags to the schema ^^^^^^^^^^^^^^^^^^^^^^^^^ -Update ``_modify_package_schema`` and -:py:meth:`~ckan.plugins.interfaces.IDatasetForm.show_package_schema` +Update :py:meth:`~ckan.plugins.interfaces.IDatasetForm._modify_package_schema` +and :py:meth:`~ckan.plugins.interfaces.IDatasetForm.show_package_schema` .. literalinclude:: ../../ckanext/example_idatasetform/plugin_v4.py :start-after: return {'country_codes': country_codes} @@ -275,7 +286,7 @@ similarly :emphasize-lines: 20-23 Save and reload your development server CKAN will take any additional keys from -the resource schema and save them the it's extras field. The templates will +the resource schema and save them the its extras field. The templates will automatically check this field and display them in the resource_read page. You can find the complete source for this tutorial in the From ac9ceb194e48270f550d2899f58bc4d8fbf8728a Mon Sep 17 00:00:00 2001 From: joetsoi Date: Thu, 30 Jan 2014 23:31:59 +0000 Subject: [PATCH 13/77] [#790] IDatasetForm tutorial: add dataset search page sorting --- doc/extensions/adding-custom-fields.rst | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/doc/extensions/adding-custom-fields.rst b/doc/extensions/adding-custom-fields.rst index 315bd87eb9d..350c68e8002 100644 --- a/doc/extensions/adding-custom-fields.rst +++ b/doc/extensions/adding-custom-fields.rst @@ -289,5 +289,30 @@ Save and reload your development server CKAN will take any additional keys from the resource schema and save them the its extras field. The templates will automatically check this field and display them in the resource_read page. + +Sorting datasets by custom fields +--------------------------------- + +Now that we've added our custom field, we can customize the CKAN web front end +search page to sort datasets by our custom field. Add a new file called +``ckan/example_idatasetform/templates/package/search.html`` containing: + +.. literalinclude:: ../../ckanext/example_idatasetform/templates/package/search.html + :language: jinja + :emphasize-lines: 16-17 + +This overrides search ordering drop down box code block, the code is the same +as the default package search block but we are adding two additional lines that +define the display name of that search ordering (e.g. Custom Field Ascending) +and the SOLR sort ordering (e.g. custom_text asc). If you reload your development +server you should be able to see these two additional sorting options on the +dataset search page. + +The SOLR sort ordering can define arbitrary functions for custom sorting, but +this is beyond the scope of this tutorial for further details see +http://wiki.apache.org/solr/CommonQueryParameters#sort and +http://wiki.apache.org/solr/FunctionQuery + + You can find the complete source for this tutorial in the ``ckanext/example_idatasetform`` directory. From 689ab0a05f61a557ee956b03ca016c0e6f6bfa39 Mon Sep 17 00:00:00 2001 From: joetsoi Date: Thu, 30 Jan 2014 23:41:22 +0000 Subject: [PATCH 14/77] [#790] Add IDatasetForm search template --- .../templates/package/search.html | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 ckanext/example_idatasetform/templates/package/search.html diff --git a/ckanext/example_idatasetform/templates/package/search.html b/ckanext/example_idatasetform/templates/package/search.html new file mode 100644 index 00000000000..67cfe5229f1 --- /dev/null +++ b/ckanext/example_idatasetform/templates/package/search.html @@ -0,0 +1,21 @@ +{% ckan_extends %} + +{% block form %} + {% set facets = { + 'fields': c.fields_grouped, + 'search': c.search_facets, + 'titles': c.facet_titles, + 'translated_fields': c.translated_fields, + 'remove_field': c.remove_field } + %} + {% set sorting = [ + (_('Relevance'), 'score desc, metadata_modified desc'), + (_('Name Ascending'), 'title_string asc'), + (_('Name Descending'), 'title_string desc'), + (_('Last Modified'), 'metadata_modified desc'), + (_('Custom Field Ascending'), 'custom_text asc'), + (_('Custom Field Descending'), 'custom_text desc'), + (_('Popular'), 'views_recent desc') if g.tracking_enabled else (false, false) ] + %} + {% snippet 'snippets/search_form.html', type='dataset', query=c.q, sorting=sorting, sorting_selected=c.sort_by_selected, count=c.page.item_count, facets=facets, show_empty=request.params, error=c.query_error %} +{% endblock %} From cb1534b414e691eda8be12cc6c397ea1c4dbcede Mon Sep 17 00:00:00 2001 From: joetsoi Date: Fri, 31 Jan 2014 00:05:26 +0000 Subject: [PATCH 15/77] [#790] idatasetform tutorial cleanups --- doc/extensions/adding-custom-fields.rst | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/doc/extensions/adding-custom-fields.rst b/doc/extensions/adding-custom-fields.rst index 350c68e8002..f29a3392a16 100644 --- a/doc/extensions/adding-custom-fields.rst +++ b/doc/extensions/adding-custom-fields.rst @@ -290,8 +290,8 @@ the resource schema and save them the its extras field. The templates will automatically check this field and display them in the resource_read page. -Sorting datasets by custom fields ---------------------------------- +Sorting by custom fields on the dataset search page +--------------------------------------------------- Now that we've added our custom field, we can customize the CKAN web front end search page to sort datasets by our custom field. Add a new file called @@ -301,12 +301,12 @@ search page to sort datasets by our custom field. Add a new file called :language: jinja :emphasize-lines: 16-17 -This overrides search ordering drop down box code block, the code is the same -as the default package search block but we are adding two additional lines that -define the display name of that search ordering (e.g. Custom Field Ascending) -and the SOLR sort ordering (e.g. custom_text asc). If you reload your development -server you should be able to see these two additional sorting options on the -dataset search page. +This overrides the search ordering drop down code block, the code is the +same as the default package search block but we are adding two additional lines +that define the display name of that search ordering (e.g. Custom Field +Ascending) and the SOLR sort ordering (e.g. custom_text asc). If you reload your +development server you should be able to see these two additional sorting options +on the dataset search page. The SOLR sort ordering can define arbitrary functions for custom sorting, but this is beyond the scope of this tutorial for further details see From ecb70ec152bb4c771dae94b78a8daaa8c819b901 Mon Sep 17 00:00:00 2001 From: joetsoi Date: Fri, 31 Jan 2014 18:27:12 +0000 Subject: [PATCH 16/77] [#790] idatasetform tutorial cleanups --- doc/extensions/adding-custom-fields.rst | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/doc/extensions/adding-custom-fields.rst b/doc/extensions/adding-custom-fields.rst index f29a3392a16..85562592839 100644 --- a/doc/extensions/adding-custom-fields.rst +++ b/doc/extensions/adding-custom-fields.rst @@ -3,7 +3,7 @@ Customizing dataset and resource metadata fields using IDatasetForm =================================================================== Storing additional metadata for a dataset beyond the default metadata in CKAN -is a common scenario. CKAN provides a simple way to do this by allowing you to +is a common use case. CKAN provides a simple way to do this by allowing you to store arbitrary key/value pairs against a dataset when creating or updating the dataset. These appear under the "Additional Information" section on the web interface and in 'extras' field of the JSON when accessed via the API. @@ -51,7 +51,7 @@ CKAN allows you to have multiple IDatasetForm plugins, each handling different dataset types. So you could customize the CKAN web front end, for different types of datasets. In this tutorial we will be defining our plugin as the fallback plugin. This plugin is used if no other IDatasetForm plugin is found -that handles that dataset's type. +that handles that dataset type. The IDatasetForm also has other additional functions that allow you to provide a custom template to be rendered for the CKAN frontend, but we will @@ -105,14 +105,14 @@ converted *from* an extras field. So we want to use the :pyobject: ExampleIDatasetFormPlugin.show_package_schema -Package types +Dataset types ^^^^^^^^^^^^^ The :py:meth:`~ckan.plugins.interfaces.IDatasetForm.package_types` function -defines a list of package types that this plugin handles. Each package has a +defines a list of dataset types that this plugin handles. Each dataset has a field containing its type. Plugins can register to handle specific types of -packages and ignore others. Since our plugin is not for any specific type of -package and we want our plugin to be the default handler, we update the plugin +dataset and ignore others. Since our plugin is not for any specific type of +dataset and we want our plugin to be the default handler, we update the plugin code to contain the following: .. literalinclude:: ../../ckanext/example_idatasetform/plugin_v1.py @@ -269,9 +269,9 @@ Adding custom fields to resources --------------------------------- In order to customize the fields in a resource the schema for resources needs -to be modified in a similar way to the packages. The resource schema -is nested in the package dict as package['resources']. We modify this dict in -a similar way to the package schema. Change ``_modify_package_schema`` to the +to be modified in a similar way to the datasets. The resource schema +is nested in the dataset dict as package['resources']. We modify this dict in +a similar way to the dataset schema. Change ``_modify_package_schema`` to the following. .. literalinclude:: ../../ckanext/example_idatasetform/plugin.py @@ -289,20 +289,18 @@ Save and reload your development server CKAN will take any additional keys from the resource schema and save them the its extras field. The templates will automatically check this field and display them in the resource_read page. - Sorting by custom fields on the dataset search page --------------------------------------------------- - Now that we've added our custom field, we can customize the CKAN web front end search page to sort datasets by our custom field. Add a new file called -``ckan/example_idatasetform/templates/package/search.html`` containing: +``ckanext-extrafields/ckanext/extrafields/templates/package/search.html`` containing: .. literalinclude:: ../../ckanext/example_idatasetform/templates/package/search.html :language: jinja :emphasize-lines: 16-17 This overrides the search ordering drop down code block, the code is the -same as the default package search block but we are adding two additional lines +same as the default dataset search block but we are adding two additional lines that define the display name of that search ordering (e.g. Custom Field Ascending) and the SOLR sort ordering (e.g. custom_text asc). If you reload your development server you should be able to see these two additional sorting options From 7d1ac48ffba1bffdca709ad21c127f991d40f7e3 Mon Sep 17 00:00:00 2001 From: joetsoi Date: Mon, 3 Feb 2014 12:50:12 +0000 Subject: [PATCH 17/77] [#790] idatasetform tutorial cleanups --- ckanext/example_idatasetform/plugin_v3.py | 1 - ckanext/example_idatasetform/plugin_v4.py | 1 - doc/extensions/adding-custom-fields.rst | 14 +++++++------- 3 files changed, 7 insertions(+), 9 deletions(-) diff --git a/ckanext/example_idatasetform/plugin_v3.py b/ckanext/example_idatasetform/plugin_v3.py index 6430becf7b7..a80d26a46db 100644 --- a/ckanext/example_idatasetform/plugin_v3.py +++ b/ckanext/example_idatasetform/plugin_v3.py @@ -31,7 +31,6 @@ def show_package_schema(self): }) return schema - #is fall back def is_fallback(self): # Return True to register this plugin as the default handler for # package types not handled by any other IDatasetForm plugin. diff --git a/ckanext/example_idatasetform/plugin_v4.py b/ckanext/example_idatasetform/plugin_v4.py index 1639459c069..01f6ce5c430 100644 --- a/ckanext/example_idatasetform/plugin_v4.py +++ b/ckanext/example_idatasetform/plugin_v4.py @@ -72,7 +72,6 @@ def update_package_schema(self): schema = self._modify_package_schema(schema) return schema - #is fall back def is_fallback(self): # Return True to register this plugin as the default handler for # package types not handled by any other IDatasetForm plugin. diff --git a/doc/extensions/adding-custom-fields.rst b/doc/extensions/adding-custom-fields.rst index 85562592839..f7a5131f737 100644 --- a/doc/extensions/adding-custom-fields.rst +++ b/doc/extensions/adding-custom-fields.rst @@ -14,9 +14,9 @@ restrict the possible values to a defined list. By using CKAN's IDatasetForm plugin interface, a CKAN plugin can add custom, first-class metadata fields to CKAN datasets, and can do custom validation of these fields. - .. seealso:: - In this tutorial we are assuming that you have read the - :doc:`/extensions/tutorial` +.. seealso:: + In this tutorial we are assuming that you have read the + :doc:`/extensions/tutorial` CKAN schemas and validation --------------------------- @@ -192,8 +192,8 @@ with: Tag vocabularies ---------------- If you need to add a custom field where the input options are restricted to a -provided list of options, you can use tag vocabularies `/tag-vocabularies`. We -will need to create our vocabulary first. By calling +provided list of options, you can use tag vocabularies :doc:`/tag-vocabularies`. +We will need to create our vocabulary first. By calling :func:`~ckan.logic.action.vocabulary_create`. Add a function to your plugin.py above your plugin class. @@ -312,5 +312,5 @@ http://wiki.apache.org/solr/CommonQueryParameters#sort and http://wiki.apache.org/solr/FunctionQuery -You can find the complete source for this tutorial in the -``ckanext/example_idatasetform`` directory. +You can find the complete source for this tutorial at +https://github.com/ckan/ckan/tree/master/ckanext/example_idatasetform From 5bf5a534e11c4c275de3dec823ae575a6a16e88d Mon Sep 17 00:00:00 2001 From: Nigel Babu Date: Tue, 18 Mar 2014 10:55:06 +0530 Subject: [PATCH 18/77] Use the full organization dict to display orgs The package page uses only the bits of the organization dict that is returned from package_show, this doesn't have the image_display_url and therefore organization images are not shown anymore. This uses a new helper to get the full organization dict. --- ckan/lib/helpers.py | 10 ++++++++++ ckan/templates/package/read_base.html | 3 ++- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/ckan/lib/helpers.py b/ckan/lib/helpers.py index 91556fa5d7a..ac8d924b635 100644 --- a/ckan/lib/helpers.py +++ b/ckan/lib/helpers.py @@ -1757,6 +1757,15 @@ def get_site_statistics(): def check_config_permission(permission): return new_authz.check_config_permission(permission) + +def get_organization(org=None): + if org is None: + return {} + try: + return logic.get_action('organization_show')({}, {'id': org}) + except Exception: + return {} + # these are the functions that will end up in `h` template helpers __allowed_functions__ = [ # functions defined in ckan.lib.helpers @@ -1843,6 +1852,7 @@ def check_config_permission(permission): 'list_dict_filter', 'new_activities', 'time_ago_from_timestamp', + 'get_organization', # imported into ckan.lib.helpers 'literal', 'link_to', diff --git a/ckan/templates/package/read_base.html b/ckan/templates/package/read_base.html index 8cd14492cd9..559ca0b6972 100644 --- a/ckan/templates/package/read_base.html +++ b/ckan/templates/package/read_base.html @@ -56,7 +56,8 @@ {% block package_organization %} {% if pkg.organization %} - {% snippet "snippets/organization.html", organization=pkg.organization, has_context_title=true %} + {% set org = h.get_organization(pkg.organization.name) %} + {% snippet "snippets/organization.html", organization=org, has_context_title=true %} {% endif %} {% endblock %} From 03d8d70dd2262bc53f84cbce0551f57a1616a15c Mon Sep 17 00:00:00 2001 From: Vitor Baptista Date: Tue, 1 Apr 2014 20:57:43 -0300 Subject: [PATCH 19/77] [#1550] Show the file name when uploading a resource Hiding it is bad makes it hard for the user to check its URL (although it makes it more difficult for her to change it by mistake). When you first upload, some browsers have a safety feature to not disclosing the file's full path to the page so, instead of getting something like: ``` /home/vitor/datasets/unemployment.csv ``` You get: ``` C:\fakepath\unemployment.csv ``` To avoid bothering the user showing this ```fakepath``` stuff, we remove it, showing just the file name. This only happens when uploading a file. The next time you edit the resource, we'll have the entire URL, so that'll be shown instead. --- ckan/public/base/javascript/modules/image-upload.js | 9 +++------ ckan/public/base/less/forms.less | 3 +++ 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/ckan/public/base/javascript/modules/image-upload.js b/ckan/public/base/javascript/modules/image-upload.js index 47f38fb240e..4aa194750e6 100644 --- a/ckan/public/base/javascript/modules/image-upload.js +++ b/ckan/public/base/javascript/modules/image-upload.js @@ -130,11 +130,7 @@ this.ckan.module('image-upload', function($, _) { .add(this.button_url) .add(this.input) .show(); - } else if (state == this.state.attached) { - this.button_remove - .add(this.field_image) - .show(); - } else if (state == this.state.web) { + } else if (state == this.state.attached || state == this.state.web) { this.field_url .show(); } @@ -167,7 +163,8 @@ this.ckan.module('image-upload', function($, _) { * Returns nothing. */ _onInputChange: function() { - this.file_name = this.input.val(); + var file_name = this.input.val().split(/^C:\\fakepath\\/).pop(); + $('input', this.field_url).val(file_name); this.field_clear.val(''); this.changeState(this.state.attached); }, diff --git a/ckan/public/base/less/forms.less b/ckan/public/base/less/forms.less index bf45350340f..e85a25c72ce 100644 --- a/ckan/public/base/less/forms.less +++ b/ckan/public/base/less/forms.less @@ -681,6 +681,9 @@ textarea { } .js .image-upload { + #field-image-url { + padding-right: 29px; + } #field-image-upload { cursor: pointer; position: absolute; From 375264e28404e998f35dcf1aa878d9dd9edccdfc Mon Sep 17 00:00:00 2001 From: Vitor Baptista Date: Tue, 1 Apr 2014 21:57:13 -0300 Subject: [PATCH 20/77] [#1550] Merge the merge and attached states into filled state They're the same now. --- .../base/javascript/modules/image-upload.js | 21 ++++++++----------- 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/ckan/public/base/javascript/modules/image-upload.js b/ckan/public/base/javascript/modules/image-upload.js index 4aa194750e6..3e566be12e3 100644 --- a/ckan/public/base/javascript/modules/image-upload.js +++ b/ckan/public/base/javascript/modules/image-upload.js @@ -26,9 +26,8 @@ this.ckan.module('image-upload', function($, _) { }, state: { - attached: 1, - blank: 2, - web: 3 + blank: 1, + filled: 2 }, /* Initialises the module setting up elements and event listeners. @@ -102,10 +101,8 @@ this.ckan.module('image-upload', function($, _) { .add(this.field_image); // Setup the initial state - if (options.is_url) { - this.changeState(this.state.web); - } else if (options.is_upload) { - this.changeState(this.state.attached); + if (options.filled) { + this.changeState(this.state.filled); } else { this.changeState(this.state.blank); } @@ -118,7 +115,7 @@ this.ckan.module('image-upload', function($, _) { * * Examples * - * this.changeState(this.state.web); // Sets the state in URL mode + * this.changeState(this.state.filled); // Sets the state in Filled mode * * Returns nothing. */ @@ -130,7 +127,7 @@ this.ckan.module('image-upload', function($, _) { .add(this.button_url) .add(this.input) .show(); - } else if (state == this.state.attached || state == this.state.web) { + } else if (state == this.state.filled) { this.field_url .show(); } @@ -141,7 +138,7 @@ this.ckan.module('image-upload', function($, _) { * Returns nothing. */ _onFromWeb: function() { - this.changeState(this.state.web); + this.changeState(this.state.filled); $('input', this.field_url).focus(); if (this.options.is_upload) { this.field_clear.val('true'); @@ -166,7 +163,7 @@ this.ckan.module('image-upload', function($, _) { var file_name = this.input.val().split(/^C:\\fakepath\\/).pop(); $('input', this.field_url).val(file_name); this.field_clear.val(''); - this.changeState(this.state.attached); + this.changeState(this.state.filled); }, /* Event listener for when a user mouseovers the hidden file input @@ -185,5 +182,5 @@ this.ckan.module('image-upload', function($, _) { this.button_upload.removeClass('hover'); } - } + }; }); From 9ab79cf7c85d6877ee8f410ab2ed832908ba1f67 Mon Sep 17 00:00:00 2001 From: Vitor Baptista Date: Tue, 1 Apr 2014 22:02:27 -0300 Subject: [PATCH 21/77] [#1550] Refactor the state machine into a simpler architecture We just have two states now, so we can simplify stuff. --- .../base/javascript/modules/image-upload.js | 56 ++++++------------- 1 file changed, 17 insertions(+), 39 deletions(-) diff --git a/ckan/public/base/javascript/modules/image-upload.js b/ckan/public/base/javascript/modules/image-upload.js index 3e566be12e3..5ad37e01dc4 100644 --- a/ckan/public/base/javascript/modules/image-upload.js +++ b/ckan/public/base/javascript/modules/image-upload.js @@ -25,11 +25,6 @@ this.ckan.module('image-upload', function($, _) { ].join("\n") }, - state: { - blank: 1, - filled: 2 - }, - /* Initialises the module setting up elements and event listeners. * * Returns nothing. @@ -100,37 +95,6 @@ this.ckan.module('image-upload', function($, _) { .add(this.field_url) .add(this.field_image); - // Setup the initial state - if (options.filled) { - this.changeState(this.state.filled); - } else { - this.changeState(this.state.blank); - } - - }, - - /* Method to change the display state of the image fields - * - * state - Pseudo constant for passing the state we should be in now - * - * Examples - * - * this.changeState(this.state.filled); // Sets the state in Filled mode - * - * Returns nothing. - */ - changeState: function(state) { - this.fields.hide(); - if (state == this.state.blank) { - this.button_upload - .add(this.field_image) - .add(this.button_url) - .add(this.input) - .show(); - } else if (state == this.state.filled) { - this.field_url - .show(); - } }, /* Event listener for when someone sets the field to URL mode @@ -138,7 +102,7 @@ this.ckan.module('image-upload', function($, _) { * Returns nothing. */ _onFromWeb: function() { - this.changeState(this.state.filled); + _showOnlyFieldUrl(); $('input', this.field_url).focus(); if (this.options.is_upload) { this.field_clear.val('true'); @@ -150,7 +114,12 @@ this.ckan.module('image-upload', function($, _) { * Returns nothing. */ _onRemove: function() { - this.changeState(this.state.blank); + this.fields.hide(); + this.button_upload + .add(this.field_image) + .add(this.button_url) + .add(this.input) + .show(); $('input', this.field_url).val(''); this.field_clear.val('true'); }, @@ -163,7 +132,16 @@ this.ckan.module('image-upload', function($, _) { var file_name = this.input.val().split(/^C:\\fakepath\\/).pop(); $('input', this.field_url).val(file_name); this.field_clear.val(''); - this.changeState(this.state.filled); + _showOnlyFieldUrl(); + }, + + /* Show only the URL field, hiding all others + * + * Returns nothing. + */ + _showOnlyFieldUrl: function() { + this.fields.hide(); + this.field_url.show(); }, /* Event listener for when a user mouseovers the hidden file input From 5137d6e06693d0fbe954705ef608c5877d992d5e Mon Sep 17 00:00:00 2001 From: Vitor Baptista Date: Mon, 7 Apr 2014 23:52:25 -0300 Subject: [PATCH 22/77] [#1550] Initialize correctly the status of the image-upload --- .../base/javascript/modules/image-upload.js | 29 ++++++++++++++----- 1 file changed, 21 insertions(+), 8 deletions(-) diff --git a/ckan/public/base/javascript/modules/image-upload.js b/ckan/public/base/javascript/modules/image-upload.js index 5ad37e01dc4..cb6be362041 100644 --- a/ckan/public/base/javascript/modules/image-upload.js +++ b/ckan/public/base/javascript/modules/image-upload.js @@ -95,6 +95,11 @@ this.ckan.module('image-upload', function($, _) { .add(this.field_url) .add(this.field_image); + if (options.is_url || options.is_upload) { + this._showOnlyFieldUrl(); + } else { + this._showOnlyButtons(); + } }, /* Event listener for when someone sets the field to URL mode @@ -102,7 +107,7 @@ this.ckan.module('image-upload', function($, _) { * Returns nothing. */ _onFromWeb: function() { - _showOnlyFieldUrl(); + this._showOnlyFieldUrl(); $('input', this.field_url).focus(); if (this.options.is_upload) { this.field_clear.val('true'); @@ -114,12 +119,7 @@ this.ckan.module('image-upload', function($, _) { * Returns nothing. */ _onRemove: function() { - this.fields.hide(); - this.button_upload - .add(this.field_image) - .add(this.button_url) - .add(this.input) - .show(); + this._showOnlyButtons(); $('input', this.field_url).val(''); this.field_clear.val('true'); }, @@ -132,7 +132,20 @@ this.ckan.module('image-upload', function($, _) { var file_name = this.input.val().split(/^C:\\fakepath\\/).pop(); $('input', this.field_url).val(file_name); this.field_clear.val(''); - _showOnlyFieldUrl(); + this._showOnlyFieldUrl(); + }, + + /* Show only the buttons, hiding all others + * + * Returns nothing. + */ + _showOnlyButtons: function() { + this.fields.hide(); + this.button_upload + .add(this.field_image) + .add(this.button_url) + .add(this.input) + .show(); }, /* Show only the URL field, hiding all others From 1d43bc7bbce3b16d6f2de580adfce54ccf6ce97d Mon Sep 17 00:00:00 2001 From: Vitor Baptista Date: Mon, 7 Apr 2014 23:53:01 -0300 Subject: [PATCH 23/77] [#1550] Remove "Remove" button, as we now only use the "X" at the input --- ckan/public/base/javascript/modules/image-upload.js | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/ckan/public/base/javascript/modules/image-upload.js b/ckan/public/base/javascript/modules/image-upload.js index cb6be362041..212297ee032 100644 --- a/ckan/public/base/javascript/modules/image-upload.js +++ b/ckan/public/base/javascript/modules/image-upload.js @@ -17,8 +17,7 @@ this.ckan.module('image-upload', function($, _) { remove: _('Remove'), upload_label: _('Image'), upload_tooltip: _('Upload a file on your computer'), - url_tooltip: _('Link to a URL on the internet (you can also link to an API)'), - remove_tooltip: _('Reset this') + url_tooltip: _('Link to a URL on the internet (you can also link to an API)') }, template: [ '' @@ -63,15 +62,9 @@ this.ckan.module('image-upload', function($, _) { this.button_upload = $(''+this.i18n('upload')+'') .insertAfter(this.input); - // Button to reset the form back to the first from when there is a image uploaded - this.button_remove = $('') - .text(this.i18n('remove')) - .on('click', this._onRemove) - .insertAfter(this.button_upload); - // Button for resetting the form when there is a URL set $('') - .prop('title', this.i18n('remove_tooltip')) + .prop('title', this.i18n('remove')) .on('click', this._onRemove) .insertBefore($('input', this.field_url)); @@ -88,7 +81,6 @@ this.ckan.module('image-upload', function($, _) { // Fields storage. Used in this.changeState this.fields = $('') - .add(this.button_remove) .add(this.button_upload) .add(this.button_url) .add(this.input) From f90b85d21cf27a37d2ca6c1b6afb4783bf50c2fe Mon Sep 17 00:00:00 2001 From: nigelb Date: Fri, 11 Apr 2014 09:18:02 +0530 Subject: [PATCH 24/77] [#1617] Clean up templates/package/related_list Stop using the package dict unnecessarily --- ckan/controllers/related.py | 1 + ckan/logic/action/get.py | 16 ++++++++-------- ckan/templates/package/related_list.html | 5 ++--- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/ckan/controllers/related.py b/ckan/controllers/related.py index 3bc6b82acb8..b06a7add63e 100644 --- a/ckan/controllers/related.py +++ b/ckan/controllers/related.py @@ -116,6 +116,7 @@ def list(self, id): try: c.pkg_dict = logic.get_action('package_show')(context, data_dict) + c.related_list = logic.get_action('related_list')(context, data_dict) c.pkg = context['package'] c.resources_json = h.json.dumps(c.pkg_dict.get('resources', [])) except logic.NotFound: diff --git a/ckan/logic/action/get.py b/ckan/logic/action/get.py index 54a27b1c2fb..7ff687bff9d 100644 --- a/ckan/logic/action/get.py +++ b/ckan/logic/action/get.py @@ -64,7 +64,7 @@ def _filter_activity_by_user(activity_list, users=[]): return new_list -def _activity_stream_get_filtered_users(): +def _activity_stream_get_filtered_users(context): ''' Get the list of users from the :ref:`ckan.hide_activity_from_users` config option and return a list of their ids. If the config is not specified, @@ -74,7 +74,7 @@ def _activity_stream_get_filtered_users(): if users: users_list = users.split() else: - context = {'model': model, 'ignore_auth': True} + context['ignore_auth'] = True site_user = logic.get_action('get_site_user')(context) users_list = [site_user.get('name')] @@ -2196,7 +2196,7 @@ def user_activity_list(context, data_dict): _activity_objects = model.activity.user_activity_list(user.id, limit=limit, offset=offset) activity_objects = _filter_activity_by_user(_activity_objects, - _activity_stream_get_filtered_users()) + _activity_stream_get_filtered_users(context)) return model_dictize.activity_list_dictize(activity_objects, context) @@ -2238,7 +2238,7 @@ def package_activity_list(context, data_dict): _activity_objects = model.activity.package_activity_list(package.id, limit=limit, offset=offset) activity_objects = _filter_activity_by_user(_activity_objects, - _activity_stream_get_filtered_users()) + _activity_stream_get_filtered_users(context)) return model_dictize.activity_list_dictize(activity_objects, context) @@ -2279,7 +2279,7 @@ def group_activity_list(context, data_dict): _activity_objects = model.activity.group_activity_list(group_id, limit=limit, offset=offset) activity_objects = _filter_activity_by_user(_activity_objects, - _activity_stream_get_filtered_users()) + _activity_stream_get_filtered_users(context)) return model_dictize.activity_list_dictize(activity_objects, context) @@ -2311,7 +2311,7 @@ def organization_activity_list(context, data_dict): _activity_objects = model.activity.group_activity_list(org_id, limit=limit, offset=offset) activity_objects = _filter_activity_by_user(_activity_objects, - _activity_stream_get_filtered_users()) + _activity_stream_get_filtered_users(context)) return model_dictize.activity_list_dictize(activity_objects, context) @@ -2341,7 +2341,7 @@ def recently_changed_packages_activity_list(context, data_dict): _activity_objects = model.activity.recently_changed_packages_activity_list( limit=limit, offset=offset) activity_objects = _filter_activity_by_user(_activity_objects, - _activity_stream_get_filtered_users()) + _activity_stream_get_filtered_users(context)) return model_dictize.activity_list_dictize(activity_objects, context) @@ -3019,7 +3019,7 @@ def dashboard_activity_list(context, data_dict): limit=limit, offset=offset) activity_objects = _filter_activity_by_user(_activity_objects, - _activity_stream_get_filtered_users()) + _activity_stream_get_filtered_users(context)) activity_dicts = model_dictize.activity_list_dictize( activity_objects, context) diff --git a/ckan/templates/package/related_list.html b/ckan/templates/package/related_list.html index affdd974372..55ad318797d 100644 --- a/ckan/templates/package/related_list.html +++ b/ckan/templates/package/related_list.html @@ -1,14 +1,13 @@ {% extends "package/read_base.html" %} -{% set pkg = c.pkg %} {% block subtitle %}{{ _('Related') }} - {{ super() }}{% endblock %} {% block primary_content_inner %}

{% block page_heading %}{{ _('Related Media for {dataset}').format(dataset=h.dataset_display_name(c.pkg)) }}{% endblock %}

{% block related_list %} - {% if c.pkg.related %} - {% snippet "related/snippets/related_list.html", related_items=c.pkg.related, pkg_id=c.pkg.name %} + {% if c.related_list %} + {% snippet "related/snippets/related_list.html", related_items=c.related_list, pkg_id=c.pkg_dict.name %} {% else %}

{{ _('No related items') }}

{% endif %} From f69a81fdc5c41b03e50ec68102808128e5e874e0 Mon Sep 17 00:00:00 2001 From: nigelb Date: Fri, 11 Apr 2014 12:55:51 +0530 Subject: [PATCH 25/77] Fix pep8 --- ckan/controllers/related.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ckan/controllers/related.py b/ckan/controllers/related.py index b06a7add63e..ed24857aed1 100644 --- a/ckan/controllers/related.py +++ b/ckan/controllers/related.py @@ -116,7 +116,8 @@ def list(self, id): try: c.pkg_dict = logic.get_action('package_show')(context, data_dict) - c.related_list = logic.get_action('related_list')(context, data_dict) + c.related_list = logic.get_action('related_list')(context, + data_dict) c.pkg = context['package'] c.resources_json = h.json.dumps(c.pkg_dict.get('resources', [])) except logic.NotFound: From 567a0dbecb58b4321b37d184da3efa73ca123bf7 Mon Sep 17 00:00:00 2001 From: Vitor Baptista Date: Tue, 15 Apr 2014 16:21:12 -0300 Subject: [PATCH 26/77] [#1550] Disable URL field when uploading image --- ckan/public/base/javascript/modules/image-upload.js | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/ckan/public/base/javascript/modules/image-upload.js b/ckan/public/base/javascript/modules/image-upload.js index 212297ee032..6531b654ae5 100644 --- a/ckan/public/base/javascript/modules/image-upload.js +++ b/ckan/public/base/javascript/modules/image-upload.js @@ -40,6 +40,7 @@ this.ckan.module('image-upload', function($, _) { this.input = $(field_upload, this.el); this.field_url = $(field_url, this.el).parents('.control-group'); this.field_image = this.input.parents('.control-group'); + this.field_url_input = $('input', this.field_url); // Is there a clear checkbox on the form already? var checkbox = $(field_clear, this.el); @@ -66,7 +67,7 @@ this.ckan.module('image-upload', function($, _) { $('') .prop('title', this.i18n('remove')) .on('click', this._onRemove) - .insertBefore($('input', this.field_url)); + .insertBefore(this.field_url_input); // Update the main label $('label[for="field-image-upload"]').text(options.upload_label || this.i18n('upload_label')); @@ -100,7 +101,7 @@ this.ckan.module('image-upload', function($, _) { */ _onFromWeb: function() { this._showOnlyFieldUrl(); - $('input', this.field_url).focus(); + this.field_url_input.focus(); if (this.options.is_upload) { this.field_clear.val('true'); } @@ -112,7 +113,8 @@ this.ckan.module('image-upload', function($, _) { */ _onRemove: function() { this._showOnlyButtons(); - $('input', this.field_url).val(''); + this.field_url_input.val(''); + this.field_url_input.prop('disabled', false); this.field_clear.val('true'); }, @@ -122,7 +124,8 @@ this.ckan.module('image-upload', function($, _) { */ _onInputChange: function() { var file_name = this.input.val().split(/^C:\\fakepath\\/).pop(); - $('input', this.field_url).val(file_name); + this.field_url_input.val(file_name); + this.field_url_input.prop('disabled', true); this.field_clear.val(''); this._showOnlyFieldUrl(); }, From e70b9c352c68d07e15015ddb132d2c8c01edfeb3 Mon Sep 17 00:00:00 2001 From: Vitor Baptista Date: Tue, 15 Apr 2014 16:28:09 -0300 Subject: [PATCH 27/77] [#1550] Remove unused "template" option As far as I could see, this was never used. Maybe the structure of this code came from copy/pasting from somewhere else where it made sense, and it was left by mistake. --- ckan/public/base/javascript/modules/image-upload.js | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/ckan/public/base/javascript/modules/image-upload.js b/ckan/public/base/javascript/modules/image-upload.js index 6531b654ae5..516025f1293 100644 --- a/ckan/public/base/javascript/modules/image-upload.js +++ b/ckan/public/base/javascript/modules/image-upload.js @@ -18,10 +18,7 @@ this.ckan.module('image-upload', function($, _) { upload_label: _('Image'), upload_tooltip: _('Upload a file on your computer'), url_tooltip: _('Link to a URL on the internet (you can also link to an API)') - }, - template: [ - '' - ].join("\n") + } }, /* Initialises the module setting up elements and event listeners. From fa60dc947eb6db612218d8d89affec7d6df3b096 Mon Sep 17 00:00:00 2001 From: Vitor Baptista Date: Wed, 16 Apr 2014 22:52:16 -0300 Subject: [PATCH 28/77] [#291] Configure ckanext.stats as namespace packages --- ckanext/stats/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ckanext/stats/__init__.py b/ckanext/stats/__init__.py index b646540d6be..de40ea7ca05 100644 --- a/ckanext/stats/__init__.py +++ b/ckanext/stats/__init__.py @@ -1 +1 @@ -# empty file needed for pylons to find templates in this directory +__import__('pkg_resources').declare_namespace(__name__) From 73b1242d1c7f3f6d7956b2e598136bac67b299ba Mon Sep 17 00:00:00 2001 From: amercader Date: Thu, 17 Apr 2014 17:35:16 +0100 Subject: [PATCH 29/77] [#1652] Fix auth when creating a DataStore resource directly If you provided a dataset id on datastore_create to create the resource directly, the auth functions failed as they expected a resource. This changes the datastore_create auth function to use package_update instead of resource_update if that is the case. --- ckanext/datastore/logic/auth.py | 10 ++++++- ckanext/datastore/tests/test_create.py | 37 ++++++++++++++++++++++++++ 2 files changed, 46 insertions(+), 1 deletion(-) diff --git a/ckanext/datastore/logic/auth.py b/ckanext/datastore/logic/auth.py index d002d106fda..73d78e03b84 100644 --- a/ckanext/datastore/logic/auth.py +++ b/ckanext/datastore/logic/auth.py @@ -4,6 +4,7 @@ def datastore_auth(context, data_dict, privilege='resource_update'): if not 'id' in data_dict: data_dict['id'] = data_dict.get('resource_id') + user = context.get('user') authorized = p.toolkit.check_access(privilege, context, data_dict) @@ -19,7 +20,14 @@ def datastore_auth(context, data_dict, privilege='resource_update'): def datastore_create(context, data_dict): - return datastore_auth(context, data_dict) + + if 'resource' in data_dict and data_dict['resource'].get('package_id'): + data_dict['id'] = data_dict['resource'].get('package_id') + privilege = 'package_update' + else: + privilege = 'resource_update' + + return datastore_auth(context, data_dict, privilege=privilege) def datastore_upsert(context, data_dict): diff --git a/ckanext/datastore/tests/test_create.py b/ckanext/datastore/tests/test_create.py index f2db232af8a..3dcde2f694b 100644 --- a/ckanext/datastore/tests/test_create.py +++ b/ckanext/datastore/tests/test_create.py @@ -538,6 +538,43 @@ def test_create_basic(self): assert res_dict['success'] is True, res_dict + def test_create_datastore_resource_on_dataset(self): + pkg = model.Package.get('annakarenina') + + data = { + 'resource': { + 'package_id': pkg.id, + }, + 'fields': [{'id': 'boo%k', 'type': 'text'}, # column with percent + {'id': 'author', 'type': 'json'}], + 'indexes': [['boo%k', 'author'], 'author'], + 'records': [{'boo%k': 'crime', 'author': ['tolstoy', 'dostoevsky']}, + {'boo%k': 'annakarenina', 'author': ['tolstoy', 'putin']}, + {'boo%k': 'warandpeace'}] # treat author as null + } + + postparams = '%s=1' % json.dumps(data) + auth = {'Authorization': str(self.normal_user.apikey)} + res = self.app.post('/api/action/datastore_create', params=postparams, + extra_environ=auth) + res_dict = json.loads(res.body) + + assert res_dict['success'] is True + res = res_dict['result'] + assert res['fields'] == data['fields'], res['fields'] + assert res['records'] == data['records'] + + # Get resource details + data = { + 'id': res['resource_id'] + } + postparams = '%s=1' % json.dumps(data) + res = self.app.post('/api/action/resource_show', params=postparams) + res_dict = json.loads(res.body) + + assert res_dict['datastore_active'] is True + + def test_guess_types(self): resource = model.Package.get('annakarenina').resources[1] From 1808a81182e987923000b369f7e74b1ab7194d8c Mon Sep 17 00:00:00 2001 From: joetsoi Date: Tue, 22 Apr 2014 10:45:08 +0100 Subject: [PATCH 30/77] fix paster db clean again User.get() leaves an open transaction when the site user is added to the pylons context, commit here closes it so it does not lock tables when running paster db clean --- ckan/lib/cli.py | 1 + 1 file changed, 1 insertion(+) diff --git a/ckan/lib/cli.py b/ckan/lib/cli.py index 117ebfacd06..397c8870c68 100644 --- a/ckan/lib/cli.py +++ b/ckan/lib/cli.py @@ -115,6 +115,7 @@ def _load_config(self): pylons.c.user = self.site_user['name'] pylons.c.userobj = model.User.get(self.site_user['name']) + model.Session.commit() ## give routes enough information to run url_for parsed = urlparse.urlparse(conf.get('ckan.site_url', 'http://0.0.0.0')) From f31a1924bc8539ab73260771b31cd5174b19b1f9 Mon Sep 17 00:00:00 2001 From: joetsoi Date: Tue, 22 Apr 2014 10:56:13 +0100 Subject: [PATCH 31/77] fix paster db clean defer commit from get_site_user and attach it to pylons context first --- ckan/lib/cli.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/ckan/lib/cli.py b/ckan/lib/cli.py index 397c8870c68..ab314d6e8f3 100644 --- a/ckan/lib/cli.py +++ b/ckan/lib/cli.py @@ -111,11 +111,12 @@ def _load_config(self): self.registry.register(pylons.c, c) - self.site_user = logic.get_action('get_site_user')({'ignore_auth': True}, {}) + self.site_user = logic.get_action('get_site_user')({'ignore_auth': True, + 'defer_commit': True}, {}) pylons.c.user = self.site_user['name'] pylons.c.userobj = model.User.get(self.site_user['name']) - model.Session.commit() + model.repo.commit_and_remove() ## give routes enough information to run url_for parsed = urlparse.urlparse(conf.get('ckan.site_url', 'http://0.0.0.0')) From 7f0e59e05257e935b0a83d0bce50c0a05f8a8170 Mon Sep 17 00:00:00 2001 From: joetsoi Date: Tue, 22 Apr 2014 21:55:16 +0100 Subject: [PATCH 32/77] [#1656] add doc string about defer_commit to get_site_user --- ckan/logic/action/get.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/ckan/logic/action/get.py b/ckan/logic/action/get.py index 54a27b1c2fb..d089eac009b 100644 --- a/ckan/logic/action/get.py +++ b/ckan/logic/action/get.py @@ -2036,6 +2036,16 @@ def term_translation_show(context, data_dict): # Only internal services are allowed to call get_site_user. def get_site_user(context, data_dict): + '''Return the ckan site user + + :param defer_commit: by default (or if set to false) get_site_user will + commit and clean up the current transaction, it will also close and + discard the current session in the context. If set to true, caller + is responsible for commiting transaction after get_site_user is + called. Leaving open connections can cause cli commands to hang! + (optional, default: False) + :type defer_commit: boolean + ''' _check_access('get_site_user', context, data_dict) model = context['model'] site_id = config.get('ckan.site_id', 'ckan_site_user') From e9e3d818174c18cca11a80c25f0b86aef0ceaf9b Mon Sep 17 00:00:00 2001 From: Vitor Baptista Date: Thu, 24 Apr 2014 10:48:14 -0300 Subject: [PATCH 33/77] [#1550] Disable URL input if it belongs to an uploaded file --- ckan/public/base/javascript/modules/image-upload.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/ckan/public/base/javascript/modules/image-upload.js b/ckan/public/base/javascript/modules/image-upload.js index 516025f1293..9b3a15ab68f 100644 --- a/ckan/public/base/javascript/modules/image-upload.js +++ b/ckan/public/base/javascript/modules/image-upload.js @@ -85,8 +85,11 @@ this.ckan.module('image-upload', function($, _) { .add(this.field_url) .add(this.field_image); - if (options.is_url || options.is_upload) { + if (options.is_url) { this._showOnlyFieldUrl(); + } else if (options.is_upload) { + this._showOnlyFieldUrl(); + this.field_url_input.prop('disabled', true); } else { this._showOnlyButtons(); } From ac11f87037d5e383d75c2e1580ed50396e5d8417 Mon Sep 17 00:00:00 2001 From: Vitor Baptista Date: Fri, 25 Apr 2014 14:41:37 -0300 Subject: [PATCH 34/77] [#1674] Add policy that pull requests shouldn't lower the test coverage --- doc/contributing/pull-requests.rst | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/doc/contributing/pull-requests.rst b/doc/contributing/pull-requests.rst index 6909657b5c3..8452e0a5c53 100644 --- a/doc/contributing/pull-requests.rst +++ b/doc/contributing/pull-requests.rst @@ -64,7 +64,11 @@ This section will walk you through the steps for making a pull request. - Your branch should contain new or changed tests for any new or changed code, and all the CKAN tests should pass on your branch, see - :doc:`test`. + `Testing CKAN `_. + + - Your pull request shouldn't lower our test coverage. You can check it at + our `coveralls page `. If for some + reason you can't avoid lowering it, explain why on the pull request. - Your branch should contain new or updated documentation for any new or updated code, see :doc:`documentation`. From db1883a09bd64647f16f861a145c73d52be32f94 Mon Sep 17 00:00:00 2001 From: nigelb Date: Mon, 28 Apr 2014 11:21:26 +0530 Subject: [PATCH 35/77] Catch NotFound error in resource_proxy --- ckanext/resourceproxy/controller.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/ckanext/resourceproxy/controller.py b/ckanext/resourceproxy/controller.py index 0e8fd9bfd11..b22b0595092 100644 --- a/ckanext/resourceproxy/controller.py +++ b/ckanext/resourceproxy/controller.py @@ -20,7 +20,11 @@ def proxy_resource(context, data_dict): than the maximum file size. ''' resource_id = data_dict['resource_id'] log.info('Proxify resource {id}'.format(id=resource_id)) - resource = logic.get_action('resource_show')(context, {'id': resource_id}) + try: + resource = logic.get_action('resource_show')(context, {'id': + resource_id}) + except logic.NotFound: + base.abort(404, 'Resource not found') url = resource['url'] parts = urlparse.urlsplit(url) From 5c2c13bfcc7ca021c7acd92a1bf3cf2fa75ccd2f Mon Sep 17 00:00:00 2001 From: nigelb Date: Mon, 28 Apr 2014 11:43:59 +0530 Subject: [PATCH 36/77] Add tests for non-existent resource --- ckanext/resourceproxy/tests/test_proxy.py | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/ckanext/resourceproxy/tests/test_proxy.py b/ckanext/resourceproxy/tests/test_proxy.py index 52b96f373ff..f4d0dc3dbf5 100644 --- a/ckanext/resourceproxy/tests/test_proxy.py +++ b/ckanext/resourceproxy/tests/test_proxy.py @@ -31,7 +31,6 @@ def set_resource_url(url): 'session': model.Session, 'user': model.User.get('testsysadmin').name } - resource = logic.get_action('resource_show')(context, {'id': testpackage.resources[0].id}) package = logic.get_action('package_show')(context, {'id': testpackage.id}) @@ -138,7 +137,6 @@ def test_invalid_url(self): assert result.status == 409, result.status assert 'Invalid URL' in result.body, result.body - def test_non_existent_url(self): self.data_dict = set_resource_url('http://foo.bar') @@ -151,3 +149,12 @@ def f1(): result = self.app.get(proxied_url, status='*') assert result.status == 502, result.status assert 'connection error' in result.body, result.body + + def test_non_existent_resource(self): + self.data_dict = {'package': {'name': 'doesnotexist'}, + 'resource': {'id': 'doesnotexist'}} + + proxied_url = proxy.get_proxified_resource_url(self.data_dict) + result = self.app.get(proxied_url, status='*') + assert result.status == 404, result.status + assert 'Resource not found' in result.body, result.body From 1760033efaffdc706f9c38a34daf120160f64240 Mon Sep 17 00:00:00 2001 From: nigelb Date: Mon, 28 Apr 2014 16:05:53 +0530 Subject: [PATCH 37/77] Don't pass context around unnecessarily --- ckan/logic/action/get.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/ckan/logic/action/get.py b/ckan/logic/action/get.py index 7ff687bff9d..54a27b1c2fb 100644 --- a/ckan/logic/action/get.py +++ b/ckan/logic/action/get.py @@ -64,7 +64,7 @@ def _filter_activity_by_user(activity_list, users=[]): return new_list -def _activity_stream_get_filtered_users(context): +def _activity_stream_get_filtered_users(): ''' Get the list of users from the :ref:`ckan.hide_activity_from_users` config option and return a list of their ids. If the config is not specified, @@ -74,7 +74,7 @@ def _activity_stream_get_filtered_users(context): if users: users_list = users.split() else: - context['ignore_auth'] = True + context = {'model': model, 'ignore_auth': True} site_user = logic.get_action('get_site_user')(context) users_list = [site_user.get('name')] @@ -2196,7 +2196,7 @@ def user_activity_list(context, data_dict): _activity_objects = model.activity.user_activity_list(user.id, limit=limit, offset=offset) activity_objects = _filter_activity_by_user(_activity_objects, - _activity_stream_get_filtered_users(context)) + _activity_stream_get_filtered_users()) return model_dictize.activity_list_dictize(activity_objects, context) @@ -2238,7 +2238,7 @@ def package_activity_list(context, data_dict): _activity_objects = model.activity.package_activity_list(package.id, limit=limit, offset=offset) activity_objects = _filter_activity_by_user(_activity_objects, - _activity_stream_get_filtered_users(context)) + _activity_stream_get_filtered_users()) return model_dictize.activity_list_dictize(activity_objects, context) @@ -2279,7 +2279,7 @@ def group_activity_list(context, data_dict): _activity_objects = model.activity.group_activity_list(group_id, limit=limit, offset=offset) activity_objects = _filter_activity_by_user(_activity_objects, - _activity_stream_get_filtered_users(context)) + _activity_stream_get_filtered_users()) return model_dictize.activity_list_dictize(activity_objects, context) @@ -2311,7 +2311,7 @@ def organization_activity_list(context, data_dict): _activity_objects = model.activity.group_activity_list(org_id, limit=limit, offset=offset) activity_objects = _filter_activity_by_user(_activity_objects, - _activity_stream_get_filtered_users(context)) + _activity_stream_get_filtered_users()) return model_dictize.activity_list_dictize(activity_objects, context) @@ -2341,7 +2341,7 @@ def recently_changed_packages_activity_list(context, data_dict): _activity_objects = model.activity.recently_changed_packages_activity_list( limit=limit, offset=offset) activity_objects = _filter_activity_by_user(_activity_objects, - _activity_stream_get_filtered_users(context)) + _activity_stream_get_filtered_users()) return model_dictize.activity_list_dictize(activity_objects, context) @@ -3019,7 +3019,7 @@ def dashboard_activity_list(context, data_dict): limit=limit, offset=offset) activity_objects = _filter_activity_by_user(_activity_objects, - _activity_stream_get_filtered_users(context)) + _activity_stream_get_filtered_users()) activity_dicts = model_dictize.activity_list_dictize( activity_objects, context) From cc7e91743d179964dcf271875bc10db64b6fc0c9 Mon Sep 17 00:00:00 2001 From: Vitor Baptista Date: Thu, 1 May 2014 19:48:09 -0300 Subject: [PATCH 38/77] [#1697] Don't break PEP8 tests if test files have lines >79 chars MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit According to naming test methods [1] in our testing coding standards, we should make the test names clear "...even if it means your method name gets really long, since we don’t write code that calls our test methods there’s no advantage to having short test method names". Given this, we shouldn't validate E501 on our test suite. [1] https://ckan.readthedocs.org/en/latest/contributing/testing.html#naming-test-methods --- ckan/tests/test_coding_standards.py | 108 +++------------------------- 1 file changed, 11 insertions(+), 97 deletions(-) diff --git a/ckan/tests/test_coding_standards.py b/ckan/tests/test_coding_standards.py index 7e65f835d7e..a0de9792150 100644 --- a/ckan/tests/test_coding_standards.py +++ b/ckan/tests/test_coding_standards.py @@ -706,7 +706,6 @@ class TestPep8(object): 'ckan/model/tag.py', 'ckan/model/task_status.py', 'ckan/model/term_translation.py', - 'ckan/model/test_user.py', 'ckan/model/tracking.py', 'ckan/model/types.py', 'ckan/model/user.py', @@ -723,119 +722,27 @@ class TestPep8(object): 'ckan/tests/ckantestplugin/setup.py', 'ckan/tests/ckantestplugins.py', 'ckan/tests/functional/api/base.py', - 'ckan/tests/functional/api/model/test_group.py', - 'ckan/tests/functional/api/model/test_licenses.py', - 'ckan/tests/functional/api/model/test_package.py', - 'ckan/tests/functional/api/model/test_ratings.py', - 'ckan/tests/functional/api/model/test_relationships.py', - 'ckan/tests/functional/api/model/test_revisions.py', - 'ckan/tests/functional/api/model/test_tag.py', - 'ckan/tests/functional/api/model/test_vocabulary.py', - 'ckan/tests/functional/api/test_activity.py', - 'ckan/tests/functional/api/test_api.py', - 'ckan/tests/functional/api/test_dashboard.py', - 'ckan/tests/functional/api/test_email_notifications.py', - 'ckan/tests/functional/api/test_follow.py', - 'ckan/tests/functional/api/test_misc.py', - 'ckan/tests/functional/api/test_package_search.py', - 'ckan/tests/functional/api/test_resource.py', - 'ckan/tests/functional/api/test_resource_search.py', - 'ckan/tests/functional/api/test_revision_search.py', - 'ckan/tests/functional/api/test_user.py', - 'ckan/tests/functional/api/test_util.py', 'ckan/tests/functional/base.py', - 'ckan/tests/functional/test_activity.py', - 'ckan/tests/functional/test_admin.py', - 'ckan/tests/functional/test_cors.py', - 'ckan/tests/functional/test_error.py', - 'ckan/tests/functional/test_follow.py', - 'ckan/tests/functional/test_home.py', - 'ckan/tests/functional/test_package.py', - 'ckan/tests/functional/test_package_relationships.py', - 'ckan/tests/functional/test_pagination.py', - 'ckan/tests/functional/test_preview_interface.py', - 'ckan/tests/functional/test_related.py', - 'ckan/tests/functional/test_revision.py', - 'ckan/tests/functional/test_search.py', - 'ckan/tests/functional/test_storage.py', - 'ckan/tests/functional/test_tag.py', - 'ckan/tests/functional/test_tag_vocab.py', - 'ckan/tests/functional/test_upload.py', - 'ckan/tests/functional/test_user.py', 'ckan/tests/html_check.py', 'ckan/tests/lib/__init__.py', - 'ckan/tests/lib/test_accept.py', - 'ckan/tests/lib/test_alphabet_pagination.py', - 'ckan/tests/lib/test_cli.py', - 'ckan/tests/lib/test_datapreview.py', - 'ckan/tests/lib/test_dictization.py', - 'ckan/tests/lib/test_dictization_schema.py', - 'ckan/tests/lib/test_email_notifications.py', - 'ckan/tests/lib/test_field_types.py', - 'ckan/tests/lib/test_hash.py', - 'ckan/tests/lib/test_helpers.py', - 'ckan/tests/lib/test_i18n.py', - 'ckan/tests/lib/test_mailer.py', - 'ckan/tests/lib/test_munge.py', - 'ckan/tests/lib/test_navl.py', - 'ckan/tests/lib/test_resource_search.py', - 'ckan/tests/lib/test_simple_search.py', - 'ckan/tests/lib/test_solr_package_search.py', - 'ckan/tests/lib/test_solr_package_search_synchronous_update.py', - 'ckan/tests/lib/test_solr_schema_version.py', - 'ckan/tests/lib/test_solr_search_index.py', - 'ckan/tests/lib/test_tag_search.py', - 'ckan/tests/logic/test_action.py', - 'ckan/tests/logic/test_auth.py', - 'ckan/tests/logic/test_tag.py', - 'ckan/tests/logic/test_tag_vocab.py', - 'ckan/tests/logic/test_validators.py', - 'ckan/tests/misc/test_format_text.py', - 'ckan/tests/misc/test_mock_mail_server.py', - 'ckan/tests/misc/test_sync.py', 'ckan/tests/mock_mail_server.py', 'ckan/tests/mock_plugin.py', - 'ckan/tests/models/test_extras.py', - 'ckan/tests/models/test_group.py', - 'ckan/tests/models/test_license.py', - 'ckan/tests/models/test_misc.py', - 'ckan/tests/models/test_package.py', - 'ckan/tests/models/test_package_relationships.py', - 'ckan/tests/models/test_purge_revision.py', - 'ckan/tests/models/test_resource.py', - 'ckan/tests/models/test_revision.py', - 'ckan/tests/models/test_user.py', 'ckan/tests/monkey.py', 'ckan/tests/pylons_controller.py', - 'ckan/tests/schema/test_schema.py', - 'ckan/tests/test_dumper.py', - 'ckan/tests/test_plugins.py', - 'ckan/tests/test_versions.py', - 'ckan/tests/test_wsgi_ckanclient.py', 'ckan/tests/wsgi_ckanclient.py', 'ckan/websetup.py', 'ckanext/datastore/bin/datastore_setup.py', 'ckanext/datastore/logic/action.py', 'ckanext/datastore/plugin.py', - 'ckanext/datastore/tests/test_configure.py', - 'ckanext/datastore/tests/test_create.py', - 'ckanext/datastore/tests/test_delete.py', - 'ckanext/datastore/tests/test_search.py', - 'ckanext/datastore/tests/test_upsert.py', 'ckanext/example_idatasetform/plugin.py', 'ckanext/example_itemplatehelpers/plugin.py', 'ckanext/multilingual/plugin.py', 'ckanext/reclinepreview/plugin.py', - 'ckanext/reclinepreview/tests/test_preview.py', 'ckanext/resourceproxy/plugin.py', - 'ckanext/resourceproxy/tests/test_proxy.py', 'ckanext/stats/controller.py', 'ckanext/stats/plugin.py', 'ckanext/stats/stats.py', 'ckanext/stats/tests/__init__.py', - 'ckanext/stats/tests/test_stats_lib.py', - 'ckanext/stats/tests/test_stats_plugin.py', - 'ckanext/test_tag_vocab_plugin.py', 'ckanext/tests/plugin.py', 'doc/conf.py', 'fabfile.py', @@ -871,12 +778,15 @@ def test_pep8_pass(self): msg = 'The following files passed pep8 but are blacklisted' show_passing(msg, self.passes) - @staticmethod - def find_pep8_errors(filename=None, lines=None): - + @classmethod + def find_pep8_errors(cls, filename=None, lines=None): try: sys.stdout = cStringIO.StringIO() - checker = pep8.Checker(filename=filename, lines=lines) + config = {} + if cls._is_test(filename): + config['ignore'] = ['E501'] + checker = pep8.Checker(filename=filename, lines=lines, + **config) checker.check_all() output = sys.stdout.getvalue() finally: @@ -891,6 +801,10 @@ def find_pep8_errors(filename=None, lines=None): errors.append('%s ln:%s %s' % (error, line_no, desc)) return errors + @classmethod + def _is_test(cls, filename): + return not not re.search('(^|\W)test_.*\.py', filename, re.IGNORECASE) + class TestActionAuth(object): ''' These tests check the logic auth/action functions are compliant. The From 56857f20c819c5ac759b507cfcc312ef6eaccd4e Mon Sep 17 00:00:00 2001 From: Vitor Baptista Date: Thu, 1 May 2014 20:25:34 -0300 Subject: [PATCH 39/77] [#1697] Revert blacklisted files removed in cc7e917 They still fail even without validating E501. --- ckan/tests/test_coding_standards.py | 93 +++++++++++++++++++++++++++++ 1 file changed, 93 insertions(+) diff --git a/ckan/tests/test_coding_standards.py b/ckan/tests/test_coding_standards.py index a0de9792150..a1cf2bea1e6 100644 --- a/ckan/tests/test_coding_standards.py +++ b/ckan/tests/test_coding_standards.py @@ -706,6 +706,7 @@ class TestPep8(object): 'ckan/model/tag.py', 'ckan/model/task_status.py', 'ckan/model/term_translation.py', + 'ckan/model/test_user.py', 'ckan/model/tracking.py', 'ckan/model/types.py', 'ckan/model/user.py', @@ -722,27 +723,119 @@ class TestPep8(object): 'ckan/tests/ckantestplugin/setup.py', 'ckan/tests/ckantestplugins.py', 'ckan/tests/functional/api/base.py', + 'ckan/tests/functional/api/model/test_group.py', + 'ckan/tests/functional/api/model/test_licenses.py', + 'ckan/tests/functional/api/model/test_package.py', + 'ckan/tests/functional/api/model/test_ratings.py', + 'ckan/tests/functional/api/model/test_relationships.py', + 'ckan/tests/functional/api/model/test_revisions.py', + 'ckan/tests/functional/api/model/test_tag.py', + 'ckan/tests/functional/api/model/test_vocabulary.py', + 'ckan/tests/functional/api/test_activity.py', + 'ckan/tests/functional/api/test_api.py', + 'ckan/tests/functional/api/test_dashboard.py', + 'ckan/tests/functional/api/test_email_notifications.py', + 'ckan/tests/functional/api/test_follow.py', + 'ckan/tests/functional/api/test_misc.py', + 'ckan/tests/functional/api/test_package_search.py', + 'ckan/tests/functional/api/test_resource.py', + 'ckan/tests/functional/api/test_resource_search.py', + 'ckan/tests/functional/api/test_revision_search.py', + 'ckan/tests/functional/api/test_user.py', + 'ckan/tests/functional/api/test_util.py', 'ckan/tests/functional/base.py', + 'ckan/tests/functional/test_activity.py', + 'ckan/tests/functional/test_admin.py', + 'ckan/tests/functional/test_cors.py', + 'ckan/tests/functional/test_error.py', + 'ckan/tests/functional/test_follow.py', + 'ckan/tests/functional/test_home.py', + 'ckan/tests/functional/test_package.py', + 'ckan/tests/functional/test_package_relationships.py', + 'ckan/tests/functional/test_pagination.py', + 'ckan/tests/functional/test_preview_interface.py', + 'ckan/tests/functional/test_related.py', + 'ckan/tests/functional/test_revision.py', + 'ckan/tests/functional/test_search.py', + 'ckan/tests/functional/test_storage.py', + 'ckan/tests/functional/test_tag.py', + 'ckan/tests/functional/test_tag_vocab.py', + 'ckan/tests/functional/test_upload.py', + 'ckan/tests/functional/test_user.py', 'ckan/tests/html_check.py', 'ckan/tests/lib/__init__.py', + 'ckan/tests/lib/test_accept.py', + 'ckan/tests/lib/test_alphabet_pagination.py', + 'ckan/tests/lib/test_cli.py', + 'ckan/tests/lib/test_datapreview.py', + 'ckan/tests/lib/test_dictization.py', + 'ckan/tests/lib/test_dictization_schema.py', + 'ckan/tests/lib/test_email_notifications.py', + 'ckan/tests/lib/test_field_types.py', + 'ckan/tests/lib/test_hash.py', + 'ckan/tests/lib/test_helpers.py', + 'ckan/tests/lib/test_i18n.py', + 'ckan/tests/lib/test_mailer.py', + 'ckan/tests/lib/test_munge.py', + 'ckan/tests/lib/test_navl.py', + 'ckan/tests/lib/test_resource_search.py', + 'ckan/tests/lib/test_simple_search.py', + 'ckan/tests/lib/test_solr_package_search.py', + 'ckan/tests/lib/test_solr_package_search_synchronous_update.py', + 'ckan/tests/lib/test_solr_schema_version.py', + 'ckan/tests/lib/test_solr_search_index.py', + 'ckan/tests/lib/test_tag_search.py', + 'ckan/tests/logic/test_action.py', + 'ckan/tests/logic/test_auth.py', + 'ckan/tests/logic/test_tag.py', + 'ckan/tests/logic/test_tag_vocab.py', + 'ckan/tests/logic/test_validators.py', + 'ckan/tests/misc/test_format_text.py', + 'ckan/tests/misc/test_mock_mail_server.py', + 'ckan/tests/misc/test_sync.py', 'ckan/tests/mock_mail_server.py', 'ckan/tests/mock_plugin.py', + 'ckan/tests/models/test_extras.py', + 'ckan/tests/models/test_group.py', + 'ckan/tests/models/test_license.py', + 'ckan/tests/models/test_misc.py', + 'ckan/tests/models/test_package.py', + 'ckan/tests/models/test_package_relationships.py', + 'ckan/tests/models/test_purge_revision.py', + 'ckan/tests/models/test_resource.py', + 'ckan/tests/models/test_revision.py', + 'ckan/tests/models/test_user.py', 'ckan/tests/monkey.py', 'ckan/tests/pylons_controller.py', + 'ckan/tests/schema/test_schema.py', + 'ckan/tests/test_dumper.py', + 'ckan/tests/test_plugins.py', + 'ckan/tests/test_versions.py', + 'ckan/tests/test_wsgi_ckanclient.py', 'ckan/tests/wsgi_ckanclient.py', 'ckan/websetup.py', 'ckanext/datastore/bin/datastore_setup.py', 'ckanext/datastore/logic/action.py', 'ckanext/datastore/plugin.py', + 'ckanext/datastore/tests/test_configure.py', + 'ckanext/datastore/tests/test_create.py', + 'ckanext/datastore/tests/test_delete.py', + 'ckanext/datastore/tests/test_search.py', + 'ckanext/datastore/tests/test_upsert.py', 'ckanext/example_idatasetform/plugin.py', 'ckanext/example_itemplatehelpers/plugin.py', 'ckanext/multilingual/plugin.py', 'ckanext/reclinepreview/plugin.py', + 'ckanext/reclinepreview/tests/test_preview.py', 'ckanext/resourceproxy/plugin.py', + 'ckanext/resourceproxy/tests/test_proxy.py', 'ckanext/stats/controller.py', 'ckanext/stats/plugin.py', 'ckanext/stats/stats.py', 'ckanext/stats/tests/__init__.py', + 'ckanext/stats/tests/test_stats_lib.py', + 'ckanext/stats/tests/test_stats_plugin.py', + 'ckanext/test_tag_vocab_plugin.py', 'ckanext/tests/plugin.py', 'doc/conf.py', 'fabfile.py', From 8329733c471f48214617b47112c5069e2e8b4247 Mon Sep 17 00:00:00 2001 From: Vitor Baptista Date: Thu, 1 May 2014 20:28:16 -0300 Subject: [PATCH 40/77] [#1697] Unblacklist test files that are passing PEP8 --- ckan/tests/test_coding_standards.py | 5 ----- 1 file changed, 5 deletions(-) diff --git a/ckan/tests/test_coding_standards.py b/ckan/tests/test_coding_standards.py index a1cf2bea1e6..849f50c7df8 100644 --- a/ckan/tests/test_coding_standards.py +++ b/ckan/tests/test_coding_standards.py @@ -767,9 +767,7 @@ class TestPep8(object): 'ckan/tests/lib/test_accept.py', 'ckan/tests/lib/test_alphabet_pagination.py', 'ckan/tests/lib/test_cli.py', - 'ckan/tests/lib/test_datapreview.py', 'ckan/tests/lib/test_dictization.py', - 'ckan/tests/lib/test_dictization_schema.py', 'ckan/tests/lib/test_email_notifications.py', 'ckan/tests/lib/test_field_types.py', 'ckan/tests/lib/test_hash.py', @@ -788,7 +786,6 @@ class TestPep8(object): 'ckan/tests/logic/test_action.py', 'ckan/tests/logic/test_auth.py', 'ckan/tests/logic/test_tag.py', - 'ckan/tests/logic/test_tag_vocab.py', 'ckan/tests/logic/test_validators.py', 'ckan/tests/misc/test_format_text.py', 'ckan/tests/misc/test_mock_mail_server.py', @@ -817,9 +814,7 @@ class TestPep8(object): 'ckanext/datastore/bin/datastore_setup.py', 'ckanext/datastore/logic/action.py', 'ckanext/datastore/plugin.py', - 'ckanext/datastore/tests/test_configure.py', 'ckanext/datastore/tests/test_create.py', - 'ckanext/datastore/tests/test_delete.py', 'ckanext/datastore/tests/test_search.py', 'ckanext/datastore/tests/test_upsert.py', 'ckanext/example_idatasetform/plugin.py', From bcc8ea5836ca2ef8e57f964747645d70bed5a046 Mon Sep 17 00:00:00 2001 From: Vitor Baptista Date: Thu, 1 May 2014 21:03:57 -0300 Subject: [PATCH 41/77] [#1697] Fix minor PEP8 issues --- ckan/new_tests/logic/action/test_update.py | 2 +- ckan/new_tests/logic/test_validators.py | 4 ++-- ckan/tests/functional/test_tracking.py | 16 ++++++++-------- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/ckan/new_tests/logic/action/test_update.py b/ckan/new_tests/logic/action/test_update.py index 268ca339c36..035e52f894b 100644 --- a/ckan/new_tests/logic/action/test_update.py +++ b/ckan/new_tests/logic/action/test_update.py @@ -98,7 +98,7 @@ def test_user_update_with_invalid_name(self): user = factories.User() invalid_names = ('', 'a', False, 0, -1, 23, 'new', 'edit', 'search', - 'a'*200, 'Hi!', 'i++%') + 'a' * 200, 'Hi!', 'i++%') for name in invalid_names: user['name'] = name nose.tools.assert_raises(logic.ValidationError, diff --git a/ckan/new_tests/logic/test_validators.py b/ckan/new_tests/logic/test_validators.py index 42d8013112e..fdf3eab4c27 100644 --- a/ckan/new_tests/logic/test_validators.py +++ b/ckan/new_tests/logic/test_validators.py @@ -159,7 +159,7 @@ def test_name_validator_with_invalid_value(self): ('a', 2, False), [13, None, True], {'foo': 'bar'}, - lambda x: x**2, + lambda x: x ** 2, # Certain reserved strings aren't allowed as names. 'new', @@ -242,7 +242,7 @@ def test_user_name_validator_with_non_string_value(self): ('a', 2, False), [13, None, True], {'foo': 'bar'}, - lambda x: x**2, + lambda x: x ** 2, ] # Mock ckan.model. diff --git a/ckan/tests/functional/test_tracking.py b/ckan/tests/functional/test_tracking.py index 44393036f5f..ec95547822d 100644 --- a/ckan/tests/functional/test_tracking.py +++ b/ckan/tests/functional/test_tracking.py @@ -61,14 +61,14 @@ def _post_to_tracking(self, app, url, type_='page', ip='199.204.138.90', ''' params = {'url': url, 'type': type_} - app.post('/_tracking', params=params, - extra_environ={ - # The tracking middleware crashes if these aren't present. - 'HTTP_USER_AGENT': browser, - 'REMOTE_ADDR': ip, - 'HTTP_ACCEPT_LANGUAGE': 'en', - 'HTTP_ACCEPT_ENCODING': 'gzip, deflate', - }) + extra_environ = { + # The tracking middleware crashes if these aren't present. + 'HTTP_USER_AGENT': browser, + 'REMOTE_ADDR': ip, + 'HTTP_ACCEPT_LANGUAGE': 'en', + 'HTTP_ACCEPT_ENCODING': 'gzip, deflate', + } + app.post('/_tracking', params=params, extra_environ=extra_environ) def _update_tracking_summary(self): '''Update CKAN's tracking summary data. From 2a3312529ec70aa77cb9088f36d6f830ef9cb841 Mon Sep 17 00:00:00 2001 From: nigelb Date: Tue, 6 May 2014 10:27:12 +0530 Subject: [PATCH 42/77] Catch NotFound, ValidationError, and NotAuthorized --- ckan/lib/helpers.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ckan/lib/helpers.py b/ckan/lib/helpers.py index 0bd074186fe..5d03d5d51da 100644 --- a/ckan/lib/helpers.py +++ b/ckan/lib/helpers.py @@ -1876,7 +1876,7 @@ def get_organization(org=None): return {} try: return logic.get_action('organization_show')({}, {'id': org}) - except Exception: + except (NotFound, ValidationError, NotAuthorized): return {} # these are the functions that will end up in `h` template helpers From c68ae4fa9a75c8042ee4130d4bfc0e7c42492001 Mon Sep 17 00:00:00 2001 From: Dominik Moritz Date: Wed, 7 May 2014 07:25:28 +0200 Subject: [PATCH 43/77] Update year in readme --- README.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.rst b/README.rst index e5024520786..bce027b8506 100644 --- a/README.rst +++ b/README.rst @@ -60,7 +60,7 @@ others, make a new page on the `CKAN wiki`_, and tell us about it on Copying and License ------------------- -This material is copyright (c) 2006-2013 Open Knowledge Foundation. +This material is copyright (c) 2006-2014 Open Knowledge Foundation. It is open and licensed under the GNU Affero General Public License (AGPL) v3.0 whose full text may be found at: From 30426d7441828d9bdc308a2eb3f833b4d74decdb Mon Sep 17 00:00:00 2001 From: nigelb Date: Wed, 7 May 2014 11:36:15 +0530 Subject: [PATCH 44/77] [#1512] Upgrade select2 This fixes the issues we had with tag autocomplete. --- ckan/public/base/vendor/select2/.gitignore | 2 + ckan/public/base/vendor/select2/LICENSE | 18 + ckan/public/base/vendor/select2/README.md | 11 +- ckan/public/base/vendor/select2/bower.json | 8 + .../public/base/vendor/select2/component.json | 66 +++ ckan/public/base/vendor/select2/composer.json | 29 + ckan/public/base/vendor/select2/package.json | 20 + ckan/public/base/vendor/select2/release.sh | 79 +++ .../base/vendor/select2/select2-bootstrap.css | 87 +++ .../base/vendor/select2/select2-spinner.gif | Bin ckan/public/base/vendor/select2/select2.css | 105 ++-- .../base/vendor/select2/select2.jquery.json | 36 ++ ckan/public/base/vendor/select2/select2.js | 513 ++++++++++++------ .../public/base/vendor/select2/select2.min.js | 8 +- ckan/public/base/vendor/select2/select2.png | Bin .../base/vendor/select2/select2_locale_ar.js | 17 + .../base/vendor/select2/select2_locale_bg.js | 18 + .../base/vendor/select2/select2_locale_ca.js | 17 + .../base/vendor/select2/select2_locale_cs.js | 49 ++ .../base/vendor/select2/select2_locale_da.js | 17 + .../base/vendor/select2/select2_locale_de.js | 15 + .../base/vendor/select2/select2_locale_el.js | 17 + .../select2/select2_locale_en.js.template | 18 + .../base/vendor/select2/select2_locale_es.js | 15 + .../base/vendor/select2/select2_locale_et.js | 17 + .../base/vendor/select2/select2_locale_eu.js | 43 ++ .../base/vendor/select2/select2_locale_fa.js | 19 + .../base/vendor/select2/select2_locale_fi.js | 28 + .../base/vendor/select2/select2_locale_fr.js | 16 + .../base/vendor/select2/select2_locale_gl.js | 43 ++ .../base/vendor/select2/select2_locale_he.js | 17 + .../base/vendor/select2/select2_locale_hr.js | 22 + .../base/vendor/select2/select2_locale_hu.js | 15 + .../base/vendor/select2/select2_locale_id.js | 17 + .../base/vendor/select2/select2_locale_is.js | 15 + .../base/vendor/select2/select2_locale_it.js | 15 + .../base/vendor/select2/select2_locale_ja.js | 15 + .../base/vendor/select2/select2_locale_ka.js | 17 + .../base/vendor/select2/select2_locale_ko.js | 17 + .../base/vendor/select2/select2_locale_lt.js | 24 + .../base/vendor/select2/select2_locale_lv.js | 17 + .../base/vendor/select2/select2_locale_mk.js | 17 + .../base/vendor/select2/select2_locale_ms.js | 17 + .../base/vendor/select2/select2_locale_nl.js | 15 + .../base/vendor/select2/select2_locale_no.js | 18 + .../base/vendor/select2/select2_locale_pl.js | 22 + .../vendor/select2/select2_locale_pt-BR.js | 15 + .../vendor/select2/select2_locale_pt-PT.js | 15 + .../base/vendor/select2/select2_locale_ro.js | 15 + .../base/vendor/select2/select2_locale_rs.js | 17 + .../base/vendor/select2/select2_locale_ru.js | 21 + .../base/vendor/select2/select2_locale_sk.js | 48 ++ .../base/vendor/select2/select2_locale_sv.js | 17 + .../base/vendor/select2/select2_locale_th.js | 17 + .../base/vendor/select2/select2_locale_tr.js | 17 + .../base/vendor/select2/select2_locale_uk.js | 23 + .../base/vendor/select2/select2_locale_vi.js | 18 + .../vendor/select2/select2_locale_zh-CN.js | 14 + .../vendor/select2/select2_locale_zh-TW.js | 14 + ckan/public/base/vendor/select2/select2x2.png | Bin 60 files changed, 1659 insertions(+), 203 deletions(-) create mode 100644 ckan/public/base/vendor/select2/.gitignore create mode 100644 ckan/public/base/vendor/select2/LICENSE mode change 100755 => 100644 ckan/public/base/vendor/select2/README.md create mode 100644 ckan/public/base/vendor/select2/bower.json create mode 100644 ckan/public/base/vendor/select2/component.json create mode 100644 ckan/public/base/vendor/select2/composer.json create mode 100644 ckan/public/base/vendor/select2/package.json create mode 100755 ckan/public/base/vendor/select2/release.sh create mode 100644 ckan/public/base/vendor/select2/select2-bootstrap.css mode change 100755 => 100644 ckan/public/base/vendor/select2/select2-spinner.gif mode change 100755 => 100644 ckan/public/base/vendor/select2/select2.css create mode 100644 ckan/public/base/vendor/select2/select2.jquery.json mode change 100755 => 100644 ckan/public/base/vendor/select2/select2.js mode change 100755 => 100644 ckan/public/base/vendor/select2/select2.min.js mode change 100755 => 100644 ckan/public/base/vendor/select2/select2.png create mode 100644 ckan/public/base/vendor/select2/select2_locale_ar.js create mode 100644 ckan/public/base/vendor/select2/select2_locale_bg.js create mode 100644 ckan/public/base/vendor/select2/select2_locale_ca.js create mode 100644 ckan/public/base/vendor/select2/select2_locale_cs.js create mode 100644 ckan/public/base/vendor/select2/select2_locale_da.js create mode 100644 ckan/public/base/vendor/select2/select2_locale_de.js create mode 100644 ckan/public/base/vendor/select2/select2_locale_el.js create mode 100644 ckan/public/base/vendor/select2/select2_locale_en.js.template create mode 100644 ckan/public/base/vendor/select2/select2_locale_es.js create mode 100644 ckan/public/base/vendor/select2/select2_locale_et.js create mode 100644 ckan/public/base/vendor/select2/select2_locale_eu.js create mode 100644 ckan/public/base/vendor/select2/select2_locale_fa.js create mode 100644 ckan/public/base/vendor/select2/select2_locale_fi.js create mode 100644 ckan/public/base/vendor/select2/select2_locale_fr.js create mode 100644 ckan/public/base/vendor/select2/select2_locale_gl.js create mode 100644 ckan/public/base/vendor/select2/select2_locale_he.js create mode 100644 ckan/public/base/vendor/select2/select2_locale_hr.js create mode 100644 ckan/public/base/vendor/select2/select2_locale_hu.js create mode 100644 ckan/public/base/vendor/select2/select2_locale_id.js create mode 100644 ckan/public/base/vendor/select2/select2_locale_is.js create mode 100644 ckan/public/base/vendor/select2/select2_locale_it.js create mode 100644 ckan/public/base/vendor/select2/select2_locale_ja.js create mode 100644 ckan/public/base/vendor/select2/select2_locale_ka.js create mode 100644 ckan/public/base/vendor/select2/select2_locale_ko.js create mode 100644 ckan/public/base/vendor/select2/select2_locale_lt.js create mode 100644 ckan/public/base/vendor/select2/select2_locale_lv.js create mode 100644 ckan/public/base/vendor/select2/select2_locale_mk.js create mode 100644 ckan/public/base/vendor/select2/select2_locale_ms.js create mode 100644 ckan/public/base/vendor/select2/select2_locale_nl.js create mode 100644 ckan/public/base/vendor/select2/select2_locale_no.js create mode 100644 ckan/public/base/vendor/select2/select2_locale_pl.js create mode 100644 ckan/public/base/vendor/select2/select2_locale_pt-BR.js create mode 100644 ckan/public/base/vendor/select2/select2_locale_pt-PT.js create mode 100644 ckan/public/base/vendor/select2/select2_locale_ro.js create mode 100644 ckan/public/base/vendor/select2/select2_locale_rs.js create mode 100644 ckan/public/base/vendor/select2/select2_locale_ru.js create mode 100644 ckan/public/base/vendor/select2/select2_locale_sk.js create mode 100644 ckan/public/base/vendor/select2/select2_locale_sv.js create mode 100644 ckan/public/base/vendor/select2/select2_locale_th.js create mode 100644 ckan/public/base/vendor/select2/select2_locale_tr.js create mode 100644 ckan/public/base/vendor/select2/select2_locale_uk.js create mode 100644 ckan/public/base/vendor/select2/select2_locale_vi.js create mode 100644 ckan/public/base/vendor/select2/select2_locale_zh-CN.js create mode 100755 ckan/public/base/vendor/select2/select2_locale_zh-TW.js mode change 100755 => 100644 ckan/public/base/vendor/select2/select2x2.png diff --git a/ckan/public/base/vendor/select2/.gitignore b/ckan/public/base/vendor/select2/.gitignore new file mode 100644 index 00000000000..c6ef2182bdc --- /dev/null +++ b/ckan/public/base/vendor/select2/.gitignore @@ -0,0 +1,2 @@ +.idea + diff --git a/ckan/public/base/vendor/select2/LICENSE b/ckan/public/base/vendor/select2/LICENSE new file mode 100644 index 00000000000..0247cc76273 --- /dev/null +++ b/ckan/public/base/vendor/select2/LICENSE @@ -0,0 +1,18 @@ +Copyright 2014 Igor Vaynberg + +Version: @@ver@@ Timestamp: @@timestamp@@ + +This software is licensed under the Apache License, Version 2.0 (the "Apache License") or the GNU +General Public License version 2 (the "GPL License"). You may choose either license to govern your +use of this software only upon the condition that you accept all of the terms of either the Apache +License or the GPL License. + +You may obtain a copy of the Apache License and the GPL License at: + +http://www.apache.org/licenses/LICENSE-2.0 +http://www.gnu.org/licenses/gpl-2.0.html + +Unless required by applicable law or agreed to in writing, software distributed under the Apache License +or the GPL Licesnse is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, +either express or implied. See the Apache License and the GPL License for the specific language governing +permissions and limitations under the Apache License and the GPL License. diff --git a/ckan/public/base/vendor/select2/README.md b/ckan/public/base/vendor/select2/README.md old mode 100755 new mode 100644 index cb0be3c6eaa..406fe79dc95 --- a/ckan/public/base/vendor/select2/README.md +++ b/ckan/public/base/vendor/select2/README.md @@ -24,6 +24,10 @@ Browser compatibility * Firefox 10+ * Safari 3+ * Opera 10.6+ + +Usage +----- +You can source Select2 directly from a [CDN like JSDliver](http://www.jsdelivr.com/#!select2), [download it from this GitHub repo](https://github.com/ivaynberg/select2/tags), or use one of the integrations below. Integrations ------------ @@ -33,8 +37,11 @@ Integrations * [AngularUI](http://angular-ui.github.com/#directives-select2) ([AngularJS](angularjs.org)) * [Django](https://github.com/applegrew/django-select2) * [Symfony](https://github.com/19Gerhard85/sfSelect2WidgetsPlugin) -* [Bootstrap](https://github.com/t0m/select2-bootstrap-css) (CSS skin) -* [Yii](https://github.com/tonybolzan/yii-select2) +* [Symfony2](https://github.com/avocode/FormExtensions) +* [Bootstrap 2](https://github.com/t0m/select2-bootstrap-css) and [Bootstrap 3](https://github.com/t0m/select2-bootstrap-css/tree/bootstrap3) (CSS skins) +* [Meteor](https://github.com/nate-strauser/meteor-select2) (modern reactive JavaScript framework; + [Bootstrap 3 skin](https://github.com/esperadomedia/meteor-select2-bootstrap3-css/)) +* [Yii 2.x](http://demos.krajee.com/widgets#select2) +* [Yii 1.x](https://github.com/tonybolzan/yii-select2) Internationalization (i18n) --------------------------- diff --git a/ckan/public/base/vendor/select2/bower.json b/ckan/public/base/vendor/select2/bower.json new file mode 100644 index 00000000000..80e8596e806 --- /dev/null +++ b/ckan/public/base/vendor/select2/bower.json @@ -0,0 +1,8 @@ +{ + "name": "select2", + "version": "3.4.8", + "main": ["select2.js", "select2.css", "select2.png", "select2x2.png", "select2-spinner.gif"], + "dependencies": { + "jquery": ">= 1.7.1" + } +} diff --git a/ckan/public/base/vendor/select2/component.json b/ckan/public/base/vendor/select2/component.json new file mode 100644 index 00000000000..ad7abf9d9fa --- /dev/null +++ b/ckan/public/base/vendor/select2/component.json @@ -0,0 +1,66 @@ +{ + "name": "select2", + "repo": "ivaynberg/select2", + "description": "Select2 is a jQuery based replacement for select boxes. It supports searching, remote data sets, and infinite scrolling of results.", + "version": "3.4.8", + "demo": "http://ivaynberg.github.io/select2/", + "keywords": [ + "jquery" + ], + "main": "select2.js", + "styles": [ + "select2.css", + "select2-bootstrap.css" + ], + "scripts": [ + "select2.js", + "select2_locale_ar.js", + "select2_locale_bg.js", + "select2_locale_ca.js", + "select2_locale_cs.js", + "select2_locale_da.js", + "select2_locale_de.js", + "select2_locale_el.js", + "select2_locale_es.js", + "select2_locale_et.js", + "select2_locale_eu.js", + "select2_locale_fa.js", + "select2_locale_fi.js", + "select2_locale_fr.js", + "select2_locale_gl.js", + "select2_locale_he.js", + "select2_locale_hr.js", + "select2_locale_hu.js", + "select2_locale_id.js", + "select2_locale_is.js", + "select2_locale_it.js", + "select2_locale_ja.js", + "select2_locale_ka.js", + "select2_locale_ko.js", + "select2_locale_lt.js", + "select2_locale_lv.js", + "select2_locale_mk.js", + "select2_locale_ms.js", + "select2_locale_nl.js", + "select2_locale_no.js", + "select2_locale_pl.js", + "select2_locale_pt-BR.js", + "select2_locale_pt-PT.js", + "select2_locale_ro.js", + "select2_locale_ru.js", + "select2_locale_sk.js", + "select2_locale_sv.js", + "select2_locale_th.js", + "select2_locale_tr.js", + "select2_locale_uk.js", + "select2_locale_vi.js", + "select2_locale_zh-CN.js", + "select2_locale_zh-TW.js" + ], + "images": [ + "select2-spinner.gif", + "select2.png", + "select2x2.png" + ], + "license": "MIT" +} diff --git a/ckan/public/base/vendor/select2/composer.json b/ckan/public/base/vendor/select2/composer.json new file mode 100644 index 00000000000..c50fadba855 --- /dev/null +++ b/ckan/public/base/vendor/select2/composer.json @@ -0,0 +1,29 @@ +{ + "name": + "ivaynberg/select2", + "description": "Select2 is a jQuery based replacement for select boxes.", + "version": "3.4.8", + "type": "component", + "homepage": "http://ivaynberg.github.io/select2/", + "license": "Apache-2.0", + "require": { + "robloach/component-installer": "*", + "components/jquery": ">=1.7.1" + }, + "extra": { + "component": { + "scripts": [ + "select2.js" + ], + "files": [ + "select2.js", + "select2_locale_*.js", + "select2.css", + "select2-bootstrap.css", + "select2-spinner.gif", + "select2.png", + "select2x2.png" + ] + } + } +} diff --git a/ckan/public/base/vendor/select2/package.json b/ckan/public/base/vendor/select2/package.json new file mode 100644 index 00000000000..75ad84acaf8 --- /dev/null +++ b/ckan/public/base/vendor/select2/package.json @@ -0,0 +1,20 @@ +{ + "name" : "Select2", + "description": "Select2 is a jQuery based replacement for select boxes. It supports searching, remote data sets, and infinite scrolling of results.", + "homepage": "http://ivaynberg.github.io/select2", + "author": "Igor Vaynberg", + "repository": {"type": "git", "url": "git://github.com/ivaynberg/select2.git"}, + "main": "select2.js", + "version": "3.4.8", + "jspm": { + "main": "select2", + "files": ["select2.js", "select2.png", "select2.css", "select2-spinner.gif"], + "shim": { + "select2": { + "imports": ["jquery", "./select2.css!"], + "exports": "$" + } + }, + "buildConfig": { "uglify": true } + } +} diff --git a/ckan/public/base/vendor/select2/release.sh b/ckan/public/base/vendor/select2/release.sh new file mode 100755 index 00000000000..0d2e279ead4 --- /dev/null +++ b/ckan/public/base/vendor/select2/release.sh @@ -0,0 +1,79 @@ +#!/bin/bash +set -e + +echo -n "Enter the version for this release: " + +read ver + +if [ ! $ver ]; then + echo "Invalid version." + exit +fi + +name="select2" +js="$name.js" +mini="$name.min.js" +css="$name.css" +release="$name-$ver" +tag="$ver" +branch="build-$ver" +curbranch=`git branch | grep "*" | sed "s/* //"` +timestamp=$(date) +tokens="s/@@ver@@/$ver/g;s/\@@timestamp@@/$timestamp/g" +remote="github" + +echo "Pulling from origin" + +git pull + +echo "Updating Version Identifiers" + +sed -E -e "s/\"version\": \"([0-9\.]+)\",/\"version\": \"$ver\",/g" -i -- bower.json select2.jquery.json component.json composer.json package.json + +git add bower.json +git add select2.jquery.json +git add component.json +git add composer.json +git add package.json + +git commit -m "modified version identifiers in descriptors for release $ver" +git push + +git branch "$branch" +git checkout "$branch" + +echo "Tokenizing..." + +find . -name "$js" | xargs -I{} sed -e "$tokens" -i -- {} +find . -name "$css" | xargs -I{} sed -e "$tokens" -i -- {} + +sed -e "s/latest/$ver/g" -i -- bower.json + +git add "$js" +git add "$css" + +echo "Minifying..." + +echo "/*" > "$mini" +cat LICENSE | sed "$tokens" >> "$mini" +echo "*/" >> "$mini" + +curl -s \ + --data-urlencode "js_code@$js" \ + http://marijnhaverbeke.nl/uglifyjs \ + >> "$mini" + +git add "$mini" + +git commit -m "release $ver" + +echo "Tagging..." +git tag -a "$tag" -m "tagged version $ver" +git push "$remote" --tags + +echo "Cleaning Up..." + +git checkout "$curbranch" +git branch -D "$branch" + +echo "Done" diff --git a/ckan/public/base/vendor/select2/select2-bootstrap.css b/ckan/public/base/vendor/select2/select2-bootstrap.css new file mode 100644 index 00000000000..3b83f0a2297 --- /dev/null +++ b/ckan/public/base/vendor/select2/select2-bootstrap.css @@ -0,0 +1,87 @@ +.form-control .select2-choice { + border: 0; + border-radius: 2px; +} + +.form-control .select2-choice .select2-arrow { + border-radius: 0 2px 2px 0; +} + +.form-control.select2-container { + height: auto !important; + padding: 0; +} + +.form-control.select2-container.select2-dropdown-open { + border-color: #5897FB; + border-radius: 3px 3px 0 0; +} + +.form-control .select2-container.select2-dropdown-open .select2-choices { + border-radius: 3px 3px 0 0; +} + +.form-control.select2-container .select2-choices { + border: 0 !important; + border-radius: 3px; +} + +.control-group.warning .select2-container .select2-choice, +.control-group.warning .select2-container .select2-choices, +.control-group.warning .select2-container-active .select2-choice, +.control-group.warning .select2-container-active .select2-choices, +.control-group.warning .select2-dropdown-open.select2-drop-above .select2-choice, +.control-group.warning .select2-dropdown-open.select2-drop-above .select2-choices, +.control-group.warning .select2-container-multi.select2-container-active .select2-choices { + border: 1px solid #C09853 !important; +} + +.control-group.warning .select2-container .select2-choice div { + border-left: 1px solid #C09853 !important; + background: #FCF8E3 !important; +} + +.control-group.error .select2-container .select2-choice, +.control-group.error .select2-container .select2-choices, +.control-group.error .select2-container-active .select2-choice, +.control-group.error .select2-container-active .select2-choices, +.control-group.error .select2-dropdown-open.select2-drop-above .select2-choice, +.control-group.error .select2-dropdown-open.select2-drop-above .select2-choices, +.control-group.error .select2-container-multi.select2-container-active .select2-choices { + border: 1px solid #B94A48 !important; +} + +.control-group.error .select2-container .select2-choice div { + border-left: 1px solid #B94A48 !important; + background: #F2DEDE !important; +} + +.control-group.info .select2-container .select2-choice, +.control-group.info .select2-container .select2-choices, +.control-group.info .select2-container-active .select2-choice, +.control-group.info .select2-container-active .select2-choices, +.control-group.info .select2-dropdown-open.select2-drop-above .select2-choice, +.control-group.info .select2-dropdown-open.select2-drop-above .select2-choices, +.control-group.info .select2-container-multi.select2-container-active .select2-choices { + border: 1px solid #3A87AD !important; +} + +.control-group.info .select2-container .select2-choice div { + border-left: 1px solid #3A87AD !important; + background: #D9EDF7 !important; +} + +.control-group.success .select2-container .select2-choice, +.control-group.success .select2-container .select2-choices, +.control-group.success .select2-container-active .select2-choice, +.control-group.success .select2-container-active .select2-choices, +.control-group.success .select2-dropdown-open.select2-drop-above .select2-choice, +.control-group.success .select2-dropdown-open.select2-drop-above .select2-choices, +.control-group.success .select2-container-multi.select2-container-active .select2-choices { + border: 1px solid #468847 !important; +} + +.control-group.success .select2-container .select2-choice div { + border-left: 1px solid #468847 !important; + background: #DFF0D8 !important; +} diff --git a/ckan/public/base/vendor/select2/select2-spinner.gif b/ckan/public/base/vendor/select2/select2-spinner.gif old mode 100755 new mode 100644 diff --git a/ckan/public/base/vendor/select2/select2.css b/ckan/public/base/vendor/select2/select2.css old mode 100755 new mode 100644 index 2b32ed6f280..1eb4d229f6d --- a/ckan/public/base/vendor/select2/select2.css +++ b/ckan/public/base/vendor/select2/select2.css @@ -1,5 +1,5 @@ /* -Version: 3.4.5 Timestamp: Mon Nov 4 08:22:42 PST 2013 +Version: 3.4.8 Timestamp: Thu May 1 09:50:32 EDT 2014 */ .select2-container { margin: 0; @@ -18,7 +18,6 @@ Version: 3.4.5 Timestamp: Mon Nov 4 08:22:42 PST 2013 /* Force border-box so that % widths fit the parent container without overlap because of margin/padding. - More Info : http://www.quirksmode.org/css/box.html */ -webkit-box-sizing: border-box; /* webkit */ @@ -54,7 +53,7 @@ Version: 3.4.5 Timestamp: Mon Nov 4 08:22:42 PST 2013 background-image: -webkit-linear-gradient(center bottom, #eee 0%, #fff 50%); background-image: -moz-linear-gradient(center bottom, #eee 0%, #fff 50%); filter: progid:DXImageTransform.Microsoft.gradient(startColorstr = '#ffffff', endColorstr = '#eeeeee', GradientType = 0); - background-image: linear-gradient(top, #fff 0%, #eee 50%); + background-image: linear-gradient(to top, #eee 0%, #fff 50%); } .select2-container.select2-drop-above .select2-choice { @@ -66,7 +65,7 @@ Version: 3.4.5 Timestamp: Mon Nov 4 08:22:42 PST 2013 background-image: -webkit-linear-gradient(center bottom, #eee 0%, #fff 90%); background-image: -moz-linear-gradient(center bottom, #eee 0%, #fff 90%); filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#eeeeee', GradientType=0); - background-image: linear-gradient(top, #eee 0%, #fff 90%); + background-image: linear-gradient(to bottom, #eee 0%, #fff 90%); } .select2-container.select2-allowclear .select2-choice .select2-chosen { @@ -81,6 +80,8 @@ Version: 3.4.5 Timestamp: Mon Nov 4 08:22:42 PST 2013 white-space: nowrap; text-overflow: ellipsis; + float: none; + width: auto; } .select2-container .select2-choice abbr { @@ -145,15 +146,6 @@ Version: 3.4.5 Timestamp: Mon Nov 4 08:22:42 PST 2013 box-shadow: 0 4px 5px rgba(0, 0, 0, .15); } -.select2-drop-auto-width { - border-top: 1px solid #aaa; - width: auto; -} - -.select2-drop-auto-width .select2-search { - padding-top: 4px; -} - .select2-drop.select2-drop-above { margin-top: 1px; border-top: 1px solid #aaa; @@ -174,6 +166,15 @@ Version: 3.4.5 Timestamp: Mon Nov 4 08:22:42 PST 2013 border-top: 1px solid #5897fb; } +.select2-drop-auto-width { + border-top: 1px solid #aaa; + width: auto; +} + +.select2-drop-auto-width .select2-search { + padding-top: 4px; +} + .select2-container .select2-choice .select2-arrow { display: inline-block; width: 18px; @@ -192,7 +193,7 @@ Version: 3.4.5 Timestamp: Mon Nov 4 08:22:42 PST 2013 background-image: -webkit-linear-gradient(center bottom, #ccc 0%, #eee 60%); background-image: -moz-linear-gradient(center bottom, #ccc 0%, #eee 60%); filter: progid:DXImageTransform.Microsoft.gradient(startColorstr = '#eeeeee', endColorstr = '#cccccc', GradientType = 0); - background-image: linear-gradient(top, #ccc 0%, #eee 60%); + background-image: linear-gradient(to top, #ccc 0%, #eee 60%); } .select2-container .select2-choice .select2-arrow b { @@ -237,7 +238,7 @@ Version: 3.4.5 Timestamp: Mon Nov 4 08:22:42 PST 2013 background: url('select2.png') no-repeat 100% -22px, -webkit-gradient(linear, left bottom, left top, color-stop(0.85, #fff), color-stop(0.99, #eee)); background: url('select2.png') no-repeat 100% -22px, -webkit-linear-gradient(center bottom, #fff 85%, #eee 99%); background: url('select2.png') no-repeat 100% -22px, -moz-linear-gradient(center bottom, #fff 85%, #eee 99%); - background: url('select2.png') no-repeat 100% -22px, linear-gradient(top, #fff 85%, #eee 99%); + background: url('select2.png') no-repeat 100% -22px, linear-gradient(to bottom, #fff 85%, #eee 99%) 0 0; } .select2-drop.select2-drop-above .select2-search input { @@ -249,7 +250,7 @@ Version: 3.4.5 Timestamp: Mon Nov 4 08:22:42 PST 2013 background: url('select2-spinner.gif') no-repeat 100%, -webkit-gradient(linear, left bottom, left top, color-stop(0.85, #fff), color-stop(0.99, #eee)); background: url('select2-spinner.gif') no-repeat 100%, -webkit-linear-gradient(center bottom, #fff 85%, #eee 99%); background: url('select2-spinner.gif') no-repeat 100%, -moz-linear-gradient(center bottom, #fff 85%, #eee 99%); - background: url('select2-spinner.gif') no-repeat 100%, linear-gradient(top, #fff 85%, #eee 99%); + background: url('select2-spinner.gif') no-repeat 100%, linear-gradient(to bottom, #fff 85%, #eee 99%) 0 0; } .select2-container-active .select2-choice, @@ -274,7 +275,7 @@ Version: 3.4.5 Timestamp: Mon Nov 4 08:22:42 PST 2013 background-image: -webkit-linear-gradient(center bottom, #fff 0%, #eee 50%); background-image: -moz-linear-gradient(center bottom, #fff 0%, #eee 50%); filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#eeeeee', endColorstr='#ffffff', GradientType=0); - background-image: linear-gradient(top, #fff 0%, #eee 50%); + background-image: linear-gradient(to top, #fff 0%, #eee 50%); } .select2-dropdown-open.select2-drop-above .select2-choice, @@ -286,7 +287,7 @@ Version: 3.4.5 Timestamp: Mon Nov 4 08:22:42 PST 2013 background-image: -webkit-linear-gradient(center top, #fff 0%, #eee 50%); background-image: -moz-linear-gradient(center top, #fff 0%, #eee 50%); filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#eeeeee', endColorstr='#ffffff', GradientType=0); - background-image: linear-gradient(bottom, #fff 0%, #eee 50%); + background-image: linear-gradient(to bottom, #fff 0%, #eee 50%); } .select2-dropdown-open .select2-choice .select2-arrow { @@ -298,6 +299,17 @@ Version: 3.4.5 Timestamp: Mon Nov 4 08:22:42 PST 2013 background-position: -18px 1px; } +.select2-hidden-accessible { + border: 0; + clip: rect(0 0 0 0); + height: 1px; + margin: -1px; + overflow: hidden; + padding: 0; + position: absolute; + width: 1px; +} + /* results */ .select2-results { max-height: 200px; @@ -314,14 +326,6 @@ Version: 3.4.5 Timestamp: Mon Nov 4 08:22:42 PST 2013 padding-left: 0; } -.select2-results ul.select2-result-sub > li .select2-result-label { padding-left: 20px } -.select2-results ul.select2-result-sub ul.select2-result-sub > li .select2-result-label { padding-left: 40px } -.select2-results ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub > li .select2-result-label { padding-left: 60px } -.select2-results ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub > li .select2-result-label { padding-left: 80px } -.select2-results ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub > li .select2-result-label { padding-left: 100px } -.select2-results ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub > li .select2-result-label { padding-left: 110px } -.select2-results ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub > li .select2-result-label { padding-left: 120px } - .select2-results li { list-style: none; display: list-item; @@ -346,6 +350,14 @@ Version: 3.4.5 Timestamp: Mon Nov 4 08:22:42 PST 2013 user-select: none; } +.select2-results-dept-1 .select2-result-label { padding-left: 20px } +.select2-results-dept-2 .select2-result-label { padding-left: 40px } +.select2-results-dept-3 .select2-result-label { padding-left: 60px } +.select2-results-dept-4 .select2-result-label { padding-left: 80px } +.select2-results-dept-5 .select2-result-label { padding-left: 100px } +.select2-results-dept-6 .select2-result-label { padding-left: 110px } +.select2-results-dept-7 .select2-result-label { padding-left: 120px } + .select2-results .select2-highlighted { background: #3875d7; color: #fff; @@ -371,6 +383,7 @@ Version: 3.4.5 Timestamp: Mon Nov 4 08:22:42 PST 2013 .select2-results .select2-selection-limit { background: #f4f4f4; display: list-item; + padding-left: 5px; } /* @@ -438,7 +451,7 @@ disabled look for disabled choices in the results dropdown background-image: -webkit-gradient(linear, 0% 0%, 0% 100%, color-stop(1%, #eee), color-stop(15%, #fff)); background-image: -webkit-linear-gradient(top, #eee 1%, #fff 15%); background-image: -moz-linear-gradient(top, #eee 1%, #fff 15%); - background-image: linear-gradient(top, #eee 1%, #fff 15%); + background-image: linear-gradient(to bottom, #eee 1%, #fff 15%); } .select2-locked { @@ -460,6 +473,10 @@ disabled look for disabled choices in the results dropdown float: left; list-style: none; } +html[dir="rtl"] .select2-container-multi .select2-choices li +{ + float: right; +} .select2-container-multi .select2-choices .select2-search-field { margin: 0; padding: 0; @@ -516,7 +533,12 @@ disabled look for disabled choices in the results dropdown background-image: -webkit-gradient(linear, 0% 0%, 0% 100%, color-stop(20%, #f4f4f4), color-stop(50%, #f0f0f0), color-stop(52%, #e8e8e8), color-stop(100%, #eee)); background-image: -webkit-linear-gradient(top, #f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eee 100%); background-image: -moz-linear-gradient(top, #f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eee 100%); - background-image: linear-gradient(top, #f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eee 100%); + background-image: linear-gradient(to top, #f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eee 100%); +} +html[dir="rtl"] .select2-container-multi .select2-choices .select2-search-choice +{ + margin-left: 0; + margin-right: 5px; } .select2-container-multi .select2-choices .select2-search-choice .select2-chosen { cursor: default; @@ -537,6 +559,10 @@ disabled look for disabled choices in the results dropdown outline: none; background: url('select2.png') right top no-repeat; } +html[dir="rtl"] .select2-search-choice-close { + right: auto; + left: 3px; +} .select2-container-multi .select2-search-choice-close { left: 3px; @@ -601,15 +627,20 @@ disabled look for disabled choices in the results dropdown height: 100px; overflow: scroll; } + /* Retina-ize icons */ -@media only screen and (-webkit-min-device-pixel-ratio: 1.5), only screen and (min-resolution: 144dpi) { - .select2-search input, .select2-search-choice-close, .select2-container .select2-choice abbr, .select2-container .select2-choice .select2-arrow b { - background-image: url('select2x2.png') !important; - background-repeat: no-repeat !important; - background-size: 60px 40px !important; - } - .select2-search input { - background-position: 100% -21px !important; - } +@media only screen and (-webkit-min-device-pixel-ratio: 1.5), only screen and (min-resolution: 2dppx) { + .select2-search input, + .select2-search-choice-close, + .select2-container .select2-choice abbr, + .select2-container .select2-choice .select2-arrow b { + background-image: url('select2x2.png') !important; + background-repeat: no-repeat !important; + background-size: 60px 40px !important; + } + + .select2-search input { + background-position: 100% -21px !important; + } } diff --git a/ckan/public/base/vendor/select2/select2.jquery.json b/ckan/public/base/vendor/select2/select2.jquery.json new file mode 100644 index 00000000000..e9119279f11 --- /dev/null +++ b/ckan/public/base/vendor/select2/select2.jquery.json @@ -0,0 +1,36 @@ +{ + "name": "select2", + "title": "Select2", + "description": "Select2 is a jQuery based replacement for select boxes. It supports searching, remote data sets, and infinite scrolling of results.", + "keywords": [ + "select", + "autocomplete", + "typeahead", + "dropdown", + "multiselect", + "tag", + "tagging" + ], + "version": "3.4.8", + "author": { + "name": "Igor Vaynberg", + "url": "https://github.com/ivaynberg" + }, + "licenses": [ + { + "type": "Apache", + "url": "http://www.apache.org/licenses/LICENSE-2.0" + }, + { + "type": "GPL v2", + "url": "http://www.gnu.org/licenses/gpl-2.0.html" + } + ], + "bugs": "https://github.com/ivaynberg/select2/issues", + "homepage": "http://ivaynberg.github.com/select2", + "docs": "http://ivaynberg.github.com/select2/", + "download": "https://github.com/ivaynberg/select2/tags", + "dependencies": { + "jquery": ">=1.7.1" + } +} diff --git a/ckan/public/base/vendor/select2/select2.js b/ckan/public/base/vendor/select2/select2.js old mode 100755 new mode 100644 index 3b5e8e280cc..2969da5d1f7 --- a/ckan/public/base/vendor/select2/select2.js +++ b/ckan/public/base/vendor/select2/select2.js @@ -1,7 +1,7 @@ /* Copyright 2012 Igor Vaynberg -Version: 3.4.5 Timestamp: Mon Nov 4 08:22:42 PST 2013 +Version: 3.4.8 Timestamp: Thu May 1 09:50:32 EDT 2014 This software is licensed under the Apache License, Version 2.0 (the "Apache License") or the GNU General Public License version 2 (the "GPL License"). You may choose either license to govern your @@ -14,7 +14,7 @@ You may obtain a copy of the Apache License and the GPL License at: http://www.gnu.org/licenses/gpl-2.0.html Unless required by applicable law or agreed to in writing, software distributed under the -Apache License or the GPL Licesnse is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +Apache License or the GPL License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the Apache License and the GPL License for the specific language governing permissions and limitations under the Apache License and the GPL License. */ @@ -105,17 +105,21 @@ the specific language governing permissions and limitations under the Apache Lic nextUid=(function() { var counter=1; return function() { return counter++; }; }()); - function stripDiacritics(str) { - var ret, i, l, c; + function reinsertElement(element) { + var placeholder = $(document.createTextNode('')); - if (!str || str.length < 1) return str; + element.before(placeholder); + placeholder.before(element); + placeholder.remove(); + } - ret = ""; - for (i = 0, l = str.length; i < l; i++) { - c = str.charAt(i); - ret += DIACRITICS[c] || c; + function stripDiacritics(str) { + // Used 'uni range + named function' from http://jsperf.com/diacritics/18 + function match(a) { + return DIACRITICS[a] || a; } - return ret; + + return str.replace(/[^\u0000-\u007E]/g, match); } function indexOf(value, array) { @@ -230,20 +234,6 @@ the specific language governing permissions and limitations under the Apache Lic }; } - /** - * A simple implementation of a thunk - * @param formula function used to lazily initialize the thunk - * @return {Function} - */ - function thunk(formula) { - var evaluated = false, - value; - return function() { - if (evaluated === false) { value = formula(); evaluated = true; } - return value; - }; - }; - function installDebouncedScroll(threshold, element) { var notify = debounce(threshold, function (e) { element.trigger("scroll-debounced", e);}); element.on("scroll", function (e) { @@ -264,7 +254,8 @@ the specific language governing permissions and limitations under the Apache Lic /* make sure el received focus so we do not error out when trying to manipulate the caret. sometimes modals or others listeners may steal it after its set */ - if ($el.is(":visible") && el === document.activeElement) { + var isVisible = (el.offsetWidth > 0 || el.offsetHeight > 0); + if (isVisible && el === document.activeElement) { /* after the focus is set move the caret to the end, necessary when we val() just before setting focus */ @@ -393,12 +384,12 @@ the specific language governing permissions and limitations under the Apache Lic /** * Produces an ajax-based query function * - * @param options object containing configuration paramters + * @param options object containing configuration parameters * @param options.params parameter map for the transport ajax call, can contain such options as cache, jsonpCallback, etc. see $.ajax * @param options.transport function that will be used to execute the ajax request. must be compatible with parameters supported by $.ajax * @param options.url url for the data * @param options.data a function(searchTerm, pageNumber, context) that should return an object containing query string parameters for the above url. - * @param options.dataType request data type: ajax, jsonp, other datatatypes supported by jQuery's $.ajax function or the transport function if specified + * @param options.dataType request data type: ajax, jsonp, other datatypes supported by jQuery's $.ajax function or the transport function if specified * @param options.quietMillis (optional) milliseconds to wait before making the ajaxRequest, helps debounce the ajax function if invoked too often * @param options.results a function(remoteData, pageNumber) that converts data returned form the remote request to the format expected by Select2. * The expected format is an object containing the following keys: @@ -431,7 +422,7 @@ the specific language governing permissions and limitations under the Apache Lic data = data ? data.call(self, query.term, query.page, query.context) : null; url = (typeof url === 'function') ? url.call(self, query.term, query.page, query.context) : url; - if (handler) { handler.abort(); } + if (handler && typeof handler.abort === "function") { handler.abort(); } if (options.params) { if ($.isFunction(options.params)) { @@ -464,7 +455,7 @@ the specific language governing permissions and limitations under the Apache Lic * * If the array form is used it is assumed that it contains objects with 'id' and 'text' keys. * - * If the object form is used ti is assumed that it contains 'data' and 'text' keys. The 'data' key should contain + * If the object form is used it is assumed that it contains 'data' and 'text' keys. The 'data' key should contain * an array of objects that will be used as choices. These objects must contain at least an 'id' key. The 'text' * key can either be a String in which case it is expected that each element in the 'data' array has a key with the * value of 'text' which will be used to match choices. Alternatively, text can be a function(item) that can extract @@ -533,14 +524,17 @@ the specific language governing permissions and limitations under the Apache Lic var isFunc = $.isFunction(data); return function (query) { var t = query.term, filtered = {results: []}; - $(isFunc ? data() : data).each(function () { - var isObject = this.text !== undefined, - text = isObject ? this.text : this; - if (t === "" || query.matcher(t, text)) { - filtered.results.push(isObject ? this : {id: this, text: this}); - } - }); - query.callback(filtered); + var result = isFunc ? data(query) : data; + if ($.isArray(result)) { + $(result).each(function () { + var isObject = this.text !== undefined, + text = isObject ? this.text : this; + if (t === "" || query.matcher(t, text)) { + filtered.results.push(isObject ? this : {id: this, text: this}); + } + }); + query.callback(filtered); + } }; } @@ -555,11 +549,16 @@ the specific language governing permissions and limitations under the Apache Lic function checkFormatter(formatter, formatterName) { if ($.isFunction(formatter)) return true; if (!formatter) return false; - throw new Error(formatterName +" must be a function or a falsy value"); + if (typeof(formatter) === 'string') return true; + throw new Error(formatterName +" must be a string, function, or falsy value"); } function evaluate(val) { - return $.isFunction(val) ? val() : val; + if ($.isFunction(val)) { + var args = Array.prototype.slice.call(arguments, 1); + return val.apply(null, args); + } + return val; } function countResults(results) { @@ -627,6 +626,15 @@ the specific language governing permissions and limitations under the Apache Lic if (original!==input) return input; } + function cleanupJQueryElements() { + var self = this; + + Array.prototype.forEach.call(arguments, function (element) { + self[element].remove(); + self[element] = null; + }); + } + /** * Creates a new class * @@ -669,12 +677,22 @@ the specific language governing permissions and limitations under the Apache Lic this.container = this.createContainer(); + this.liveRegion = $("", { + role: "status", + "aria-live": "polite" + }) + .addClass("select2-hidden-accessible") + .appendTo(document.body); + this.containerId="s2id_"+(opts.element.attr("id") || "autogen"+nextUid()); - this.containerSelector="#"+this.containerId.replace(/([;&,\.\+\*\~':"\!\^#$%@\[\]\(\)=>\|])/g, '\\$1'); + this.containerEventName= this.containerId + .replace(/([.])/g, '_') + .replace(/([;&,\-\.\+\*\~':"\!\^#$%@\[\]\(\)=>\|])/g, '\\$1'); this.container.attr("id", this.containerId); - // cache the body so future lookups are cheap - this.body = thunk(function() { return opts.element.closest("body"); }); + this.container.attr("title", opts.element.attr("title")); + + this.body = $("body"); syncCssClasses(this.container, this.opts.element, this.opts.adaptContainerCssClass); @@ -714,7 +732,23 @@ the specific language governing permissions and limitations under the Apache Lic this.container.on("click", killEvent); installFilteredMouseMove(this.results); - this.dropdown.on("mousemove-filtered touchstart touchmove touchend", resultsSelector, this.bind(this.highlightUnderEvent)); + + this.dropdown.on("mousemove-filtered", resultsSelector, this.bind(this.highlightUnderEvent)); + this.dropdown.on("touchstart touchmove touchend", resultsSelector, this.bind(function (event) { + this._touchEvent = true; + this.highlightUnderEvent(event); + })); + this.dropdown.on("touchmove", resultsSelector, this.bind(this.touchMoved)); + this.dropdown.on("touchstart touchend", resultsSelector, this.bind(this.clearTouchMoved)); + + // Waiting for a click event on touch devices to select option and hide dropdown + // otherwise click will be triggered on an underlying element + this.dropdown.on('click', this.bind(function (event) { + if (this._touchEvent) { + this._touchEvent = false; + this.selectHighlighted(); + } + })); installDebouncedScroll(80, this.results); this.dropdown.on("scroll-debounced", resultsSelector, this.bind(this.loadMoreIfNeeded)); @@ -752,7 +786,10 @@ the specific language governing permissions and limitations under the Apache Lic // trap all mouse events from leaving the dropdown. sometimes there may be a modal that is listening // for mouse events outside of itself so it can close itself. since the dropdown is now outside the select2's // dom it will trigger the popup close, which is not what we want - this.dropdown.on("click mouseup mousedown", function (e) { e.stopPropagation(); }); + // focusin can cause focus wars between modals and select2 since the dropdown is outside the modal. + this.dropdown.on("click mouseup mousedown touchstart touchend focusin", function (e) { e.stopPropagation(); }); + + this.nextSearchTerm = undefined; if ($.isFunction(this.opts.initSelection)) { // initialize selection based on the current value of the source element @@ -782,7 +819,7 @@ the specific language governing permissions and limitations under the Apache Lic opts.element.prop("autofocus", false); if (this.autofocus) this.focus(); - this.nextSearchTerm = undefined; + this.search.attr("placeholder", opts.searchInputPlaceholder); }, // abstract @@ -791,10 +828,14 @@ the specific language governing permissions and limitations under the Apache Lic this.close(); - if (this.propertyObserver) { delete this.propertyObserver; this.propertyObserver = null; } + if (this.propertyObserver) { + this.propertyObserver.disconnect(); + this.propertyObserver = null; + } if (select2 !== undefined) { select2.container.remove(); + select2.liveRegion.remove(); select2.dropdown.remove(); element .removeClass("select2-offscreen") @@ -808,6 +849,14 @@ the specific language governing permissions and limitations under the Apache Lic } element.show(); } + + cleanupJQueryElements.call(this, + "container", + "liveRegion", + "dropdown", + "results", + "search" + ); }, // abstract @@ -852,7 +901,7 @@ the specific language governing permissions and limitations under the Apache Lic opts = $.extend({}, { populateResults: function(container, results, query) { - var populate, id=this.opts.id; + var populate, id=this.opts.id, liveRegion=this.liveRegion; populate=function(results, container, depth) { @@ -876,16 +925,19 @@ the specific language governing permissions and limitations under the Apache Lic if (disabled) { node.addClass("select2-disabled"); } if (compound) { node.addClass("select2-result-with-children"); } node.addClass(self.opts.formatResultCssClass(result)); + node.attr("role", "presentation"); label=$(document.createElement("div")); label.addClass("select2-result-label"); + label.attr("id", "select2-result-label-" + nextUid()); + label.attr("role", "option"); formatted=opts.formatResult(result, label, query, self.opts.escapeMarkup); if (formatted!==undefined) { label.html(formatted); + node.append(label); } - node.append(label); if (compound) { @@ -898,6 +950,8 @@ the specific language governing permissions and limitations under the Apache Lic node.data("select2-data", result); container.append(node); } + + liveRegion.text(opts.formatMatches(results.length)); }; populate(results, container, 0); @@ -953,7 +1007,6 @@ the specific language governing permissions and limitations under the Apache Lic }); // this is needed because inside val() we construct choices from options and there id is hardcoded opts.id=function(e) { return e.id; }; - opts.formatResultCssClass = function(data) { return data.css; }; } else { if (!("query" in opts)) { @@ -991,6 +1044,16 @@ the specific language governing permissions and limitations under the Apache Lic throw "query function not defined for Select2 " + opts.element.attr("id"); } + if (opts.createSearchChoicePosition === 'top') { + opts.createSearchChoicePosition = function(list, item) { list.unshift(item); }; + } + else if (opts.createSearchChoicePosition === 'bottom') { + opts.createSearchChoicePosition = function(list, item) { list.push(item); }; + } + else if (typeof(opts.createSearchChoicePosition) !== "function") { + throw "invalid createSearchChoicePosition option must be 'top', 'bottom' or a custom function"; + } + return opts; }, @@ -1026,21 +1089,20 @@ the specific language governing permissions and limitations under the Apache Lic }); - // IE8-10 - el.on("propertychange.select2", sync); - - // hold onto a reference of the callback to work around a chromium bug - if (this.mutationCallback === undefined) { - this.mutationCallback = function (mutations) { - mutations.forEach(sync); - } + // IE8-10 (IE9/10 won't fire propertyChange via attachEventListener) + if (el.length && el[0].attachEvent) { + el.each(function() { + this.attachEvent("onpropertychange", sync); + }); } - + // safari, chrome, firefox, IE11 observer = window.MutationObserver || window.WebKitMutationObserver|| window.MozMutationObserver; if (observer !== undefined) { if (this.propertyObserver) { delete this.propertyObserver; this.propertyObserver = null; } - this.propertyObserver = new observer(this.mutationCallback); + this.propertyObserver = new observer(function (mutations) { + mutations.forEach(sync); + }); this.propertyObserver.observe(el.get(0), { attributes:true, subtree:false }); } }, @@ -1069,7 +1131,7 @@ the specific language governing permissions and limitations under the Apache Lic // so here we trigger the click event manually this.opts.element.click(); - // ValidationEngine ignorea the change event and listens instead to blur + // ValidationEngine ignores the change event and listens instead to blur // so here we trigger the blur event manually if so desired if (this.opts.blurOnChange) this.opts.element.blur(); @@ -1113,12 +1175,11 @@ the specific language governing permissions and limitations under the Apache Lic // abstract readonly: function(enabled) { if (enabled === undefined) enabled = false; - if (this._readonly === enabled) return false; + if (this._readonly === enabled) return; this._readonly = enabled; this.opts.element.prop("readonly", enabled); this.enableInterface(); - return true; }, // abstract @@ -1141,7 +1202,7 @@ the specific language governing permissions and limitations under the Apache Lic dropTop = offset.top + height, dropLeft = offset.left, enoughRoomBelow = dropTop + dropHeight <= viewportBottom, - enoughRoomAbove = (offset.top - dropHeight) >= this.body().scrollTop(), + enoughRoomAbove = (offset.top - dropHeight) >= $window.scrollTop(), dropWidth = $dropdown.outerWidth(false), enoughRoomOnRight = dropLeft + dropWidth <= viewPortRight, aboveNow = $dropdown.hasClass("select2-drop-above"), @@ -1180,6 +1241,9 @@ the specific language governing permissions and limitations under the Apache Lic dropWidth = $dropdown.outerWidth(false); enoughRoomOnRight = dropLeft + dropWidth <= viewPortRight; $dropdown.show(); + + // fix so the cursor does not move to the left within the search-textbox in IE + this.focusSearch(); } if (this.opts.dropdownAutoWidth) { @@ -1189,6 +1253,7 @@ the specific language governing permissions and limitations under the Apache Lic // Add scrollbar width to dropdown if vertical scrollbar is present dropWidth = $dropdown.outerWidth(false) + (resultsListNode.scrollHeight === resultsListNode.clientHeight ? 0 : scrollBarDimensions.width); dropWidth > width ? width = dropWidth : dropWidth = width; + dropHeight = $dropdown.outerHeight(false); enoughRoomOnRight = dropLeft + dropWidth <= viewPortRight; } else { @@ -1196,17 +1261,17 @@ the specific language governing permissions and limitations under the Apache Lic } //console.log("below/ droptop:", dropTop, "dropHeight", dropHeight, "sum", (dropTop+dropHeight)+" viewport bottom", viewportBottom, "enough?", enoughRoomBelow); - //console.log("above/ offset.top", offset.top, "dropHeight", dropHeight, "top", (offset.top-dropHeight), "scrollTop", this.body().scrollTop(), "enough?", enoughRoomAbove); + //console.log("above/ offset.top", offset.top, "dropHeight", dropHeight, "top", (offset.top-dropHeight), "scrollTop", this.body.scrollTop(), "enough?", enoughRoomAbove); // fix positioning when body has an offset and is not position: static - if (this.body().css('position') !== 'static') { - bodyOffset = this.body().offset(); + if (this.body.css('position') !== 'static') { + bodyOffset = this.body.offset(); dropTop -= bodyOffset.top; dropLeft -= bodyOffset.left; } if (!enoughRoomOnRight) { - dropLeft = offset.left + width - dropWidth; + dropLeft = offset.left + this.container.outerWidth(false) - dropWidth; } css = { @@ -1215,8 +1280,8 @@ the specific language governing permissions and limitations under the Apache Lic }; if (above) { - css.bottom = windowHeight - offset.top; - css.top = 'auto'; + css.top = offset.top - dropHeight; + css.bottom = 'auto'; this.container.addClass("select2-drop-above"); $dropdown.addClass("select2-drop-above"); } @@ -1272,7 +1337,7 @@ the specific language governing permissions and limitations under the Apache Lic */ // abstract opening: function() { - var cid = this.containerId, + var cid = this.containerEventName, scroll = "scroll." + cid, resize = "resize."+cid, orient = "orientationchange."+cid, @@ -1282,25 +1347,28 @@ the specific language governing permissions and limitations under the Apache Lic this.clearDropdownAlignmentPreference(); - if(this.dropdown[0] !== this.body().children().last()[0]) { - this.dropdown.detach().appendTo(this.body()); + if(this.dropdown[0] !== this.body.children().last()[0]) { + this.dropdown.detach().appendTo(this.body); } - // create the dropdown mask if doesnt already exist + // create the dropdown mask if doesn't already exist mask = $("#select2-drop-mask"); if (mask.length == 0) { mask = $(document.createElement("div")); mask.attr("id","select2-drop-mask").attr("class","select2-drop-mask"); mask.hide(); - mask.appendTo(this.body()); + mask.appendTo(this.body); mask.on("mousedown touchstart click", function (e) { + // Prevent IE from generating a click event on the body + reinsertElement(mask); + var dropdown = $("#select2-drop"), self; if (dropdown.length > 0) { self=dropdown.data("select2"); if (self.opts.selectOnBlur) { self.selectHighlighted({noFocus: true}); } - self.close({focus:true}); + self.close(); e.preventDefault(); e.stopPropagation(); } @@ -1330,7 +1398,7 @@ the specific language governing permissions and limitations under the Apache Lic var that = this; this.container.parents().add(window).each(function () { $(this).on(resize+" "+scroll+" "+orient, function (e) { - that.positionDropdown(); + if (that.opened()) that.positionDropdown(); }); }); @@ -1341,7 +1409,7 @@ the specific language governing permissions and limitations under the Apache Lic close: function () { if (!this.opened()) return; - var cid = this.containerId, + var cid = this.containerEventName, scroll = "scroll." + cid, resize = "resize."+cid, orient = "orientationchange."+cid; @@ -1429,7 +1497,7 @@ the specific language governing permissions and limitations under the Apache Lic // abstract findHighlightableChoices: function() { - return this.results.find(".select2-result-selectable:not(.select2-disabled, .select2-selected)"); + return this.results.find(".select2-result-selectable:not(.select2-disabled):not(.select2-selected)"); }, // abstract @@ -1465,8 +1533,13 @@ the specific language governing permissions and limitations under the Apache Lic choice = $(choices[index]); choice.addClass("select2-highlighted"); + // ensure assistive technology can determine the active choice + this.search.attr("aria-activedescendant", choice.find(".select2-result-label").attr("id")); + this.ensureHighlightVisible(); + this.liveRegion.text(choice.text()); + data = choice.data("select2-data"); if (data) { this.opts.element.trigger({ type: "select2-highlight", val: this.id(data), choice: data }); @@ -1477,6 +1550,14 @@ the specific language governing permissions and limitations under the Apache Lic this.results.find(".select2-highlighted").removeClass("select2-highlighted"); }, + touchMoved: function() { + this._touchMoved = true; + }, + + clearTouchMoved: function() { + this._touchMoved = false; + }, + // abstract countSelectableResults: function() { return this.findHighlightableChoices().length; @@ -1525,7 +1606,7 @@ the specific language governing permissions and limitations under the Apache Lic self.postprocessResults(data, false, false); if (data.more===true) { - more.detach().appendTo(results).text(self.opts.formatLoadMore(page+1)); + more.detach().appendTo(results).text(evaluate(self.opts.formatLoadMore, page+1)); window.setTimeout(function() { self.loadMoreIfNeeded(); }, 10); } else { more.remove(); @@ -1574,6 +1655,12 @@ the specific language governing permissions and limitations under the Apache Lic function postRender() { search.removeClass("select2-active"); self.positionDropdown(); + if (results.find('.select2-no-results,.select2-selection-limit,.select2-searching').length) { + self.liveRegion.text(results.text()); + } + else { + self.liveRegion.text(self.opts.formatMatches(results.find('.select2-result-selectable').length)); + } } function render(html) { @@ -1587,14 +1674,14 @@ the specific language governing permissions and limitations under the Apache Lic if (maxSelSize >=1) { data = this.data(); if ($.isArray(data) && data.length >= maxSelSize && checkFormatter(opts.formatSelectionTooBig, "formatSelectionTooBig")) { - render("
  • " + opts.formatSelectionTooBig(maxSelSize) + "
  • "); + render("
  • " + evaluate(opts.formatSelectionTooBig, maxSelSize) + "
  • "); return; } } if (search.val().length < opts.minimumInputLength) { if (checkFormatter(opts.formatInputTooShort, "formatInputTooShort")) { - render("
  • " + opts.formatInputTooShort(search.val(), opts.minimumInputLength) + "
  • "); + render("
  • " + evaluate(opts.formatInputTooShort, search.val(), opts.minimumInputLength) + "
  • "); } else { render(""); } @@ -1604,7 +1691,7 @@ the specific language governing permissions and limitations under the Apache Lic if (opts.maximumInputLength && search.val().length > opts.maximumInputLength) { if (checkFormatter(opts.formatInputTooLong, "formatInputTooLong")) { - render("
  • " + opts.formatInputTooLong(search.val(), opts.maximumInputLength) + "
  • "); + render("
  • " + evaluate(opts.formatInputTooLong, search.val(), opts.maximumInputLength) + "
  • "); } else { render(""); } @@ -1612,7 +1699,7 @@ the specific language governing permissions and limitations under the Apache Lic } if (opts.formatSearching && this.findHighlightableChoices().length === 0) { - render("
  • " + opts.formatSearching() + "
  • "); + render("
  • " + evaluate(opts.formatSearching) + "
  • "); } search.addClass("select2-active"); @@ -1657,13 +1744,13 @@ the specific language governing permissions and limitations under the Apache Lic function () { return equal(self.id(this), self.id(def)); }).length === 0) { - data.results.unshift(def); + this.opts.createSearchChoicePosition(data.results, def); } } } if (data.results.length === 0 && checkFormatter(opts.formatNoMatches, "formatNoMatches")) { - render("
  • " + opts.formatNoMatches(search.val()) + "
  • "); + render("
  • " + evaluate(opts.formatNoMatches, search.val()) + "
  • "); return; } @@ -1671,7 +1758,7 @@ the specific language governing permissions and limitations under the Apache Lic self.opts.populateResults.call(this, results, data.results, {term: search.val(), page: this.resultsPage, context:null}); if (data.more === true && checkFormatter(opts.formatLoadMore, "formatLoadMore")) { - results.append("
  • " + self.opts.escapeMarkup(opts.formatLoadMore(this.resultsPage)) + "
  • "); + results.append("
  • " + self.opts.escapeMarkup(evaluate(opts.formatLoadMore, this.resultsPage)) + "
  • "); window.setTimeout(function() { self.loadMoreIfNeeded(); }, 10); } @@ -1709,6 +1796,10 @@ the specific language governing permissions and limitations under the Apache Lic // abstract selectHighlighted: function (options) { + if (this._touchMoved) { + this.clearTouchMoved(); + return; + } var index=this.highlight(), highlighted=this.results.find(".select2-highlighted"), data = highlighted.closest('.select2-result').data("select2-data"); @@ -1739,7 +1830,7 @@ the specific language governing permissions and limitations under the Apache Lic //Determine the placeholder option based on the specified placeholderOption setting return (this.opts.placeholderOption === "first" && firstOption) || (typeof this.opts.placeholderOption === "function" && this.opts.placeholderOption(this.select)); - } else if (firstOption.text() === "" && firstOption.val() === "") { + } else if ($.trim(firstOption.text()) === "" && firstOption.val() === "") { //No explicit placeholder option specified, use the first if it's blank return firstOption; } @@ -1807,16 +1898,19 @@ the specific language governing permissions and limitations under the Apache Lic var container = $(document.createElement("div")).attr({ "class": "select2-container" }).html([ - "", - "  ", - " ", + "", + "  ", + " ", "", - "", + "", + "", "
    ", " ", - "
      ", + "
        ", "
      ", "
    "].join("")); return container; @@ -1845,17 +1939,19 @@ the specific language governing permissions and limitations under the Apache Lic this.search.val(this.focusser.val()); } - this.search.focus(); - // move the cursor to the end after focussing, otherwise it will be at the beginning and - // new text will appear *before* focusser.val() - el = this.search.get(0); - if (el.createTextRange) { - range = el.createTextRange(); - range.collapse(false); - range.select(); - } else if (el.setSelectionRange) { - len = this.search.val().length; - el.setSelectionRange(len, len); + if (this.opts.shouldFocusInput(this)) { + this.search.focus(); + // move the cursor to the end after focussing, otherwise it will be at the beginning and + // new text will appear *before* focusser.val() + el = this.search.get(0); + if (el.createTextRange) { + range = el.createTextRange(); + range.collapse(false); + range.select(); + } else if (el.setSelectionRange) { + len = this.search.val().length; + el.setSelectionRange(len, len); + } } // initializes search's value with nextSearchTerm (if defined by user) @@ -1873,14 +1969,13 @@ the specific language governing permissions and limitations under the Apache Lic }, // single - close: function (params) { + close: function () { if (!this.opened()) return; this.parent.close.apply(this, arguments); - params = params || {focus: true}; - this.focusser.removeAttr("disabled"); + this.focusser.prop("disabled", false); - if (params.focus) { + if (this.opts.shouldFocusInput(this)) { this.focusser.focus(); } }, @@ -1890,8 +1985,10 @@ the specific language governing permissions and limitations under the Apache Lic if (this.opened()) { this.close(); } else { - this.focusser.removeAttr("disabled"); - this.focusser.focus(); + this.focusser.prop("disabled", false); + if (this.opts.shouldFocusInput(this)) { + this.focusser.focus(); + } } }, @@ -1903,8 +2000,11 @@ the specific language governing permissions and limitations under the Apache Lic // single cancel: function () { this.parent.cancel.apply(this, arguments); - this.focusser.removeAttr("disabled"); - this.focusser.focus(); + this.focusser.prop("disabled", false); + + if (this.opts.shouldFocusInput(this)) { + this.focusser.focus(); + } }, // single @@ -1912,6 +2012,11 @@ the specific language governing permissions and limitations under the Apache Lic $("label[for='" + this.focusser.attr('id') + "']") .attr('for', this.opts.element.attr("id")); this.parent.destroy.apply(this, arguments); + + cleanupJQueryElements.call(this, + "selection", + "focusser" + ); }, // single @@ -1919,7 +2024,9 @@ the specific language governing permissions and limitations under the Apache Lic var selection, container = this.container, - dropdown = this.dropdown; + dropdown = this.dropdown, + idSuffix = nextUid(), + elementLabel; if (this.opts.minimumResultsForSearch < 0) { this.showSearch(false); @@ -1931,14 +2038,34 @@ the specific language governing permissions and limitations under the Apache Lic this.focusser = container.find(".select2-focusser"); + // add aria associations + selection.find(".select2-chosen").attr("id", "select2-chosen-"+idSuffix); + this.focusser.attr("aria-labelledby", "select2-chosen-"+idSuffix); + this.results.attr("id", "select2-results-"+idSuffix); + this.search.attr("aria-owns", "select2-results-"+idSuffix); + // rewrite labels from original element to focusser - this.focusser.attr("id", "s2id_autogen"+nextUid()); + this.focusser.attr("id", "s2id_autogen"+idSuffix); + + elementLabel = $("label[for='" + this.opts.element.attr("id") + "']"); - $("label[for='" + this.opts.element.attr("id") + "']") + this.focusser.prev() + .text(elementLabel.text()) .attr('for', this.focusser.attr('id')); + // Ensure the original element retains an accessible name + var originalTitle = this.opts.element.attr("title"); + this.opts.element.attr("title", (originalTitle || elementLabel.text())); + this.focusser.attr("tabindex", this.elementTabIndex); + // write label for search field using the label from the focusser element + this.search.attr("id", this.focusser.attr('id') + '_search'); + + this.search.prev() + .text($("label[for='" + this.focusser.attr('id') + "']").text()) + .attr('for', this.search.attr('id')); + this.search.on("keydown", this.bind(function (e) { if (!this.isInterfaceEnabled()) return; @@ -1971,9 +2098,11 @@ the specific language governing permissions and limitations under the Apache Lic this.search.on("blur", this.bind(function(e) { // a workaround for chrome to keep the search field focussed when the scroll bar is used to scroll the dropdown. // without this the search field loses focus which is annoying - if (document.activeElement === this.body().get(0)) { + if (document.activeElement === this.body.get(0)) { window.setTimeout(this.bind(function() { - this.search.focus(); + if (this.opened()) { + this.search.focus(); + } }), 0); } })); @@ -2019,7 +2148,7 @@ the specific language governing permissions and limitations under the Apache Lic } })); - selection.on("mousedown", "abbr", this.bind(function (e) { + selection.on("mousedown touchstart", "abbr", this.bind(function (e) { if (!this.isInterfaceEnabled()) return; this.clear(); killEventImmediately(e); @@ -2027,7 +2156,9 @@ the specific language governing permissions and limitations under the Apache Lic this.selection.focus(); })); - selection.on("mousedown", this.bind(function (e) { + selection.on("mousedown touchstart", this.bind(function (e) { + // Prevent IE from generating a click event on the body + reinsertElement(selection); if (!this.container.hasClass("select2-container-active")) { this.opts.element.trigger($.Event("select2-focus")); @@ -2042,7 +2173,11 @@ the specific language governing permissions and limitations under the Apache Lic killEvent(e); })); - dropdown.on("mousedown", this.bind(function() { this.search.focus(); })); + dropdown.on("mousedown touchstart", this.bind(function() { + if (this.opts.shouldFocusInput(this)) { + this.search.focus(); + } + })); selection.on("focus", this.bind(function(e) { killEvent(e); @@ -2111,6 +2246,7 @@ the specific language governing permissions and limitations under the Apache Lic self.updateSelection(selected); self.close(); self.setPlaceholder(); + self.nextSearchTerm = self.opts.nextSearchTerm(selected, self.search.val()); } }); } @@ -2118,7 +2254,7 @@ the specific language governing permissions and limitations under the Apache Lic isPlaceholderOptionSelected: function() { var placeholderOption; - if (!this.getPlaceholder()) return false; // no placeholder specified so no option should be considered + if (this.getPlaceholder() === undefined) return false; // no placeholder specified so no option should be considered return ((placeholderOption = this.getPlaceholderOption()) !== undefined && placeholderOption.prop("selected")) || (this.opts.element.val() === "") || (this.opts.element.val() === undefined) @@ -2133,7 +2269,7 @@ the specific language governing permissions and limitations under the Apache Lic if (opts.element.get(0).tagName.toLowerCase() === "select") { // install the selection initializer opts.initSelection = function (element, callback) { - var selected = element.find("option").filter(function() { return this.selected }); + var selected = element.find("option").filter(function() { return this.selected && !this.disabled }); // a single select box always has a value, no need to null check 'selected' callback(self.optionToData(selected)); }; @@ -2250,10 +2386,13 @@ the specific language governing permissions and limitations under the Apache Lic this.nextSearchTerm = this.opts.nextSearchTerm(data, this.search.val()); this.close(); - if (!options || !options.noFocus) + if ((!options || !options.noFocus) && this.opts.shouldFocusInput(this)) { this.focusser.focus(); + } - if (!equal(old, this.id(data))) { this.triggerChange({added:data,removed:oldData}); } + if (!equal(old, this.id(data))) { + this.triggerChange({ added: data, removed: oldData }); + } }, // single @@ -2375,6 +2514,7 @@ the specific language governing permissions and limitations under the Apache Lic }).html([ "
      ", "
    • ", + " ", " ", "
    • ", "
    ", @@ -2393,12 +2533,12 @@ the specific language governing permissions and limitations under the Apache Lic // TODO validate placeholder is a string if specified if (opts.element.get(0).tagName.toLowerCase() === "select") { - // install sthe selection initializer + // install the selection initializer opts.initSelection = function (element, callback) { var data = []; - element.find("option").filter(function() { return this.selected }).each2(function (i, elm) { + element.find("option").filter(function() { return this.selected && !this.disabled }).each2(function (i, elm) { data.push(self.optionToData(elm)); }); callback(data); @@ -2467,6 +2607,11 @@ the specific language governing permissions and limitations under the Apache Lic $("label[for='" + this.search.attr('id') + "']") .attr('for', this.opts.element.attr("id")); this.parent.destroy.apply(this, arguments); + + cleanupJQueryElements.call(this, + "searchContainer", + "selection" + ); }, // multi @@ -2486,7 +2631,9 @@ the specific language governing permissions and limitations under the Apache Lic // rewrite labels from original element to focusser this.search.attr("id", "s2id_autogen"+nextUid()); - $("label[for='" + this.opts.element.attr("id") + "']") + + this.search.prev() + .text($("label[for='" + this.opts.element.attr("id") + "']").text()) .attr('for', this.search.attr('id')); this.search.on("input paste", this.bind(function() { @@ -2518,13 +2665,15 @@ the specific language governing permissions and limitations under the Apache Lic selectedChoice = next.length ? next : null; } else if (e.which === KEY.BACKSPACE) { - this.unselect(selected.first()); - this.search.width(10); - selectedChoice = prev.length ? prev : next; + if (this.unselect(selected.first())) { + this.search.width(10); + selectedChoice = prev.length ? prev : next; + } } else if (e.which == KEY.DELETE) { - this.unselect(selected.first()); - this.search.width(10); - selectedChoice = next.length ? next : null; + if (this.unselect(selected.first())) { + this.search.width(10); + selectedChoice = next.length ? next : null; + } } else if (e.which == KEY.ENTER) { selectedChoice = null; } @@ -2702,8 +2851,19 @@ the specific language governing permissions and limitations under the Apache Lic this.focusSearch(); + // initializes search's value with nextSearchTerm (if defined by user) + // ignore nextSearchTerm if the dropdown is opened by the user pressing a letter + if(this.search.val() === "") { + if(this.nextSearchTerm != undefined){ + this.search.val(this.nextSearchTerm); + this.search.select(); + } + } + this.updateResults(true); - this.search.focus(); + if (this.opts.shouldFocusInput(this)) { + this.search.focus(); + } this.opts.element.trigger($.Event("select2-open")); }, @@ -2766,6 +2926,12 @@ the specific language governing permissions and limitations under the Apache Lic this.opts.element.trigger({ type: "selected", val: this.id(data), choice: data }); + // keep track of the search's value before it gets cleared + this.nextSearchTerm = this.opts.nextSearchTerm(data, this.search.val()); + + this.clearSearch(); + this.updateResults(); + if (this.select || !this.opts.closeOnSelect) this.postprocessResults(data, false, this.opts.closeOnSelect===true); if (this.opts.closeOnSelect) { @@ -2779,6 +2945,13 @@ the specific language governing permissions and limitations under the Apache Lic // if we reached max selection size repaint the results so choices // are replaced with the max selection reached message this.updateResults(true); + } else { + // initializes search's value with nextSearchTerm and update search result + if(this.nextSearchTerm != undefined){ + this.search.val(this.nextSearchTerm); + this.updateResults(); + this.search.select(); + } } this.positionDropdown(); } else { @@ -2807,7 +2980,7 @@ the specific language governing permissions and limitations under the Apache Lic enabledItem = $( "
  • " + "
    " + - " " + + " " + "
  • "), disabledItem = $( "
  • " + @@ -2834,13 +3007,11 @@ the specific language governing permissions and limitations under the Apache Lic .on("click dblclick", this.bind(function (e) { if (!this.isInterfaceEnabled()) return; - $(e.target).closest(".select2-search-choice").fadeOut('fast', this.bind(function(){ - this.unselect($(e.target)); - this.selection.find(".select2-search-choice-focus").removeClass("select2-search-choice-focus"); - this.close(); - this.focusSearch(); - })).dequeue(); + this.unselect($(e.target)); + this.selection.find(".select2-search-choice-focus").removeClass("select2-search-choice-focus"); killEvent(e); + this.close(); + this.focusSearch(); })).on("focus", this.bind(function () { if (!this.isInterfaceEnabled()) return; this.container.addClass("select2-container-active"); @@ -2874,25 +3045,27 @@ the specific language governing permissions and limitations under the Apache Lic return; } - while((index = indexOf(this.id(data), val)) >= 0) { - val.splice(index, 1); - this.setVal(val); - if (this.select) this.postprocessResults(); - } - var evt = $.Event("select2-removing"); evt.val = this.id(data); evt.choice = data; this.opts.element.trigger(evt); if (evt.isDefaultPrevented()) { - return; + return false; + } + + while((index = indexOf(this.id(data), val)) >= 0) { + val.splice(index, 1); + this.setVal(val); + if (this.select) this.postprocessResults(); } selected.remove(); this.opts.element.trigger({ type: "select2-removed", val: this.id(data), choice: data }); this.triggerChange({ removed: data }); + + return true; }, // multi @@ -2912,7 +3085,7 @@ the specific language governing permissions and limitations under the Apache Lic }); compound.each2(function(i, choice) { - // hide an optgroup if it doesnt have any selectable children + // hide an optgroup if it doesn't have any selectable children if (!choice.is('.select2-result-selectable') && choice.find(".select2-result-selectable:not(.select2-selected)").length === 0) { choice.addClass("select2-selected"); @@ -2923,11 +3096,11 @@ the specific language governing permissions and limitations under the Apache Lic self.highlight(0); } - //If all results are chosen render formatNoMAtches + //If all results are chosen render formatNoMatches if(!this.opts.createSearchChoice && !choices.filter('.select2-result:not(.select2-selected)').length > 0){ if(!data || data && !data.more && this.results.find(".select2-no-results").length === 0) { if (checkFormatter(self.opts.formatNoMatches, "formatNoMatches")) { - this.results.append("
  • " + self.opts.formatNoMatches(self.search.val()) + "
  • "); + this.results.append("
  • " + evaluate(self.opts.formatNoMatches, self.search.val()) + "
  • "); } } } @@ -3103,7 +3276,7 @@ the specific language governing permissions and limitations under the Apache Lic var self=this, ids, old; if (arguments.length === 0) { return this.selection - .find(".select2-search-choice") + .children(".select2-search-choice") .map(function() { return $(this).data("select2-data"); }) .get(); } else { @@ -3143,7 +3316,7 @@ the specific language governing permissions and limitations under the Apache Lic if ("tags" in opts) {opts.multiple = multiple = true;} } - select2 = multiple ? new MultiSelect2() : new SingleSelect2(); + select2 = multiple ? new window.Select2["class"].multi() : new window.Select2["class"].single(); select2.init(opts); } else if (typeof(args[0]) === "string") { @@ -3167,7 +3340,7 @@ the specific language governing permissions and limitations under the Apache Lic value = select2[method].apply(select2, args.slice(1)); } if (indexOf(args[0], valueMethods) >= 0 - || (indexOf(args[0], propertyMethods) && args.length == 1)) { + || (indexOf(args[0], propertyMethods) >= 0 && args.length == 1)) { return false; // abort the iteration, ready to return first matched value } } else { @@ -3198,19 +3371,20 @@ the specific language governing permissions and limitations under the Apache Lic sortResults: function (results, container, query) { return results; }, - formatResultCssClass: function(data) {return undefined;}, + formatResultCssClass: function(data) {return data.css;}, formatSelectionCssClass: function(data, container) {return undefined;}, + formatMatches: function (matches) { return matches + " results are available, use up and down arrow keys to navigate."; }, formatNoMatches: function () { return "No matches found"; }, - formatInputTooShort: function (input, min) { var n = min - input.length; return "Please enter " + n + " more character" + (n == 1? "" : "s"); }, + formatInputTooShort: function (input, min) { var n = min - input.length; return "Please enter " + n + " or more character" + (n == 1? "" : "s"); }, formatInputTooLong: function (input, max) { var n = input.length - max; return "Please delete " + n + " character" + (n == 1? "" : "s"); }, formatSelectionTooBig: function (limit) { return "You can only select " + limit + " item" + (limit == 1 ? "" : "s"); }, - formatLoadMore: function (pageNumber) { return "Loading more results..."; }, - formatSearching: function () { return "Searching..."; }, + formatLoadMore: function (pageNumber) { return "Loading more results…"; }, + formatSearching: function () { return "Searching…"; }, minimumResultsForSearch: 0, minimumInputLength: 0, maximumInputLength: null, maximumSelectionSize: 0, - id: function (e) { return e.id; }, + id: function (e) { return e == undefined ? null : e.id; }, matcher: function(term, text) { return stripDiacritics(''+text).toUpperCase().indexOf(stripDiacritics(''+term).toUpperCase()) >= 0; }, @@ -3222,7 +3396,26 @@ the specific language governing permissions and limitations under the Apache Lic selectOnBlur: false, adaptContainerCssClass: function(c) { return c; }, adaptDropdownCssClass: function(c) { return null; }, - nextSearchTerm: function(selectedObject, currentSearchTerm) { return undefined; } + nextSearchTerm: function(selectedObject, currentSearchTerm) { return undefined; }, + searchInputPlaceholder: '', + createSearchChoicePosition: 'top', + shouldFocusInput: function (instance) { + // Attempt to detect touch devices + var supportsTouchEvents = (('ontouchstart' in window) || + (navigator.msMaxTouchPoints > 0)); + + // Only devices which support touch events should be special cased + if (!supportsTouchEvents) { + return true; + } + + // Never focus the input if search is disabled + if (instance.opts.minimumResultsForSearch < 0) { + return false; + } + + return true; + } }; $.fn.select2.ajaxDefaults = { diff --git a/ckan/public/base/vendor/select2/select2.min.js b/ckan/public/base/vendor/select2/select2.min.js old mode 100755 new mode 100644 index bffe4c241ad..f396992f24b --- a/ckan/public/base/vendor/select2/select2.min.js +++ b/ckan/public/base/vendor/select2/select2.min.js @@ -1,7 +1,7 @@ /* -Copyright 2012 Igor Vaynberg +Copyright 2014 Igor Vaynberg -Version: 3.4.5 Timestamp: Mon Nov 4 08:22:42 PST 2013 +Version: 3.4.8 Timestamp: Thu May 1 09:50:32 EDT 2014 This software is licensed under the Apache License, Version 2.0 (the "Apache License") or the GNU General Public License version 2 (the "GPL License"). You may choose either license to govern your @@ -18,5 +18,5 @@ or the GPL Licesnse is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CO either express or implied. See the Apache License and the GPL License for the specific language governing permissions and limitations under the Apache License and the GPL License. */ -!function(a){"undefined"==typeof a.fn.each2&&a.extend(a.fn,{each2:function(b){for(var c=a([0]),d=-1,e=this.length;++dc;c++)e=a.charAt(c),b+=m[e]||e;return b}function o(a,b){for(var c=0,d=b.length;d>c;c+=1)if(q(a,b[c]))return c;return-1}function p(){var b=a(l);b.appendTo("body");var c={width:b.width()-b[0].clientWidth,height:b.height()-b[0].clientHeight};return b.remove(),c}function q(a,c){return a===c?!0:a===b||c===b?!1:null===a||null===c?!1:a.constructor===String?a+""==c+"":c.constructor===String?c+""==a+"":!1}function r(b,c){var d,e,f;if(null===b||b.length<1)return[];for(d=b.split(c),e=0,f=d.length;f>e;e+=1)d[e]=a.trim(d[e]);return d}function s(a){return a.outerWidth(!1)-a.width()}function t(c){var d="keyup-change-value";c.on("keydown",function(){a.data(c,d)===b&&a.data(c,d,c.val())}),c.on("keyup",function(){var e=a.data(c,d);e!==b&&c.val()!==e&&(a.removeData(c,d),c.trigger("keyup-change"))})}function u(c){c.on("mousemove",function(c){var d=i;(d===b||d.x!==c.pageX||d.y!==c.pageY)&&a(c.target).trigger("mousemove-filtered",c)})}function v(a,c,d){d=d||b;var e;return function(){var b=arguments;window.clearTimeout(e),e=window.setTimeout(function(){c.apply(d,b)},a)}}function w(a){var c,b=!1;return function(){return b===!1&&(c=a(),b=!0),c}}function x(a,b){var c=v(a,function(a){b.trigger("scroll-debounced",a)});b.on("scroll",function(a){o(a.target,b.get())>=0&&c(a)})}function y(a){a[0]!==document.activeElement&&window.setTimeout(function(){var d,b=a[0],c=a.val().length;a.focus(),a.is(":visible")&&b===document.activeElement&&(b.setSelectionRange?b.setSelectionRange(c,c):b.createTextRange&&(d=b.createTextRange(),d.collapse(!1),d.select()))},0)}function z(b){b=a(b)[0];var c=0,d=0;if("selectionStart"in b)c=b.selectionStart,d=b.selectionEnd-c;else if("selection"in document){b.focus();var e=document.selection.createRange();d=document.selection.createRange().text.length,e.moveStart("character",-b.value.length),c=e.text.length-d}return{offset:c,length:d}}function A(a){a.preventDefault(),a.stopPropagation()}function B(a){a.preventDefault(),a.stopImmediatePropagation()}function C(b){if(!h){var c=b[0].currentStyle||window.getComputedStyle(b[0],null);h=a(document.createElement("div")).css({position:"absolute",left:"-10000px",top:"-10000px",display:"none",fontSize:c.fontSize,fontFamily:c.fontFamily,fontStyle:c.fontStyle,fontWeight:c.fontWeight,letterSpacing:c.letterSpacing,textTransform:c.textTransform,whiteSpace:"nowrap"}),h.attr("class","select2-sizer"),a("body").append(h)}return h.text(b.val()),h.width()}function D(b,c,d){var e,g,f=[];e=b.attr("class"),e&&(e=""+e,a(e.split(" ")).each2(function(){0===this.indexOf("select2-")&&f.push(this)})),e=c.attr("class"),e&&(e=""+e,a(e.split(" ")).each2(function(){0!==this.indexOf("select2-")&&(g=d(this),g&&f.push(g))})),b.attr("class",f.join(" "))}function E(a,b,c,d){var e=n(a.toUpperCase()).indexOf(n(b.toUpperCase())),f=b.length;return 0>e?(c.push(d(a)),void 0):(c.push(d(a.substring(0,e))),c.push(""),c.push(d(a.substring(e,e+f))),c.push(""),c.push(d(a.substring(e+f,a.length))),void 0)}function F(a){var b={"\\":"\","&":"&","<":"<",">":">",'"':""","'":"'","/":"/"};return String(a).replace(/[&<>"'\/\\]/g,function(a){return b[a]})}function G(c){var d,e=null,f=c.quietMillis||100,g=c.url,h=this;return function(i){window.clearTimeout(d),d=window.setTimeout(function(){var d=c.data,f=g,j=c.transport||a.fn.select2.ajaxDefaults.transport,k={type:c.type||"GET",cache:c.cache||!1,jsonpCallback:c.jsonpCallback||b,dataType:c.dataType||"json"},l=a.extend({},a.fn.select2.ajaxDefaults.params,k);d=d?d.call(h,i.term,i.page,i.context):null,f="function"==typeof f?f.call(h,i.term,i.page,i.context):f,e&&e.abort(),c.params&&(a.isFunction(c.params)?a.extend(l,c.params.call(h)):a.extend(l,c.params)),a.extend(l,{url:f,dataType:c.dataType,data:d,success:function(a){var b=c.results(a,i.page);i.callback(b)}}),e=j.call(h,l)},f)}}function H(b){var d,e,c=b,f=function(a){return""+a.text};a.isArray(c)&&(e=c,c={results:e}),a.isFunction(c)===!1&&(e=c,c=function(){return e});var g=c();return g.text&&(f=g.text,a.isFunction(f)||(d=g.text,f=function(a){return a[d]})),function(b){var g,d=b.term,e={results:[]};return""===d?(b.callback(c()),void 0):(g=function(c,e){var h,i;if(c=c[0],c.children){h={};for(i in c)c.hasOwnProperty(i)&&(h[i]=c[i]);h.children=[],a(c.children).each2(function(a,b){g(b,h.children)}),(h.children.length||b.matcher(d,f(h),c))&&e.push(h)}else b.matcher(d,f(c),c)&&e.push(c)},a(c().results).each2(function(a,b){g(b,e.results)}),b.callback(e),void 0)}}function I(c){var d=a.isFunction(c);return function(e){var f=e.term,g={results:[]};a(d?c():c).each(function(){var a=this.text!==b,c=a?this.text:this;(""===f||e.matcher(f,c))&&g.results.push(a?this:{id:this,text:this})}),e.callback(g)}}function J(b,c){if(a.isFunction(b))return!0;if(!b)return!1;throw new Error(c+" must be a function or a falsy value")}function K(b){return a.isFunction(b)?b():b}function L(b){var c=0;return a.each(b,function(a,b){b.children?c+=L(b.children):c++}),c}function M(a,c,d,e){var h,i,j,k,l,f=a,g=!1;if(!e.createSearchChoice||!e.tokenSeparators||e.tokenSeparators.length<1)return b;for(;;){for(i=-1,j=0,k=e.tokenSeparators.length;k>j&&(l=e.tokenSeparators[j],i=a.indexOf(l),!(i>=0));j++);if(0>i)break;if(h=a.substring(0,i),a=a.substring(i+l.length),h.length>0&&(h=e.createSearchChoice.call(this,h,c),h!==b&&null!==h&&e.id(h)!==b&&null!==e.id(h))){for(g=!1,j=0,k=c.length;k>j;j++)if(q(e.id(h),e.id(c[j]))){g=!0;break}g||d(h)}}return f!==a?a:void 0}function N(b,c){var d=function(){};return d.prototype=new b,d.prototype.constructor=d,d.prototype.parent=b.prototype,d.prototype=a.extend(d.prototype,c),d}if(window.Select2===b){var c,d,e,f,g,h,j,k,i={x:0,y:0},c={TAB:9,ENTER:13,ESC:27,SPACE:32,LEFT:37,UP:38,RIGHT:39,DOWN:40,SHIFT:16,CTRL:17,ALT:18,PAGE_UP:33,PAGE_DOWN:34,HOME:36,END:35,BACKSPACE:8,DELETE:46,isArrow:function(a){switch(a=a.which?a.which:a){case c.LEFT:case c.RIGHT:case c.UP:case c.DOWN:return!0}return!1},isControl:function(a){var b=a.which;switch(b){case c.SHIFT:case c.CTRL:case c.ALT:return!0}return a.metaKey?!0:!1},isFunctionKey:function(a){return a=a.which?a.which:a,a>=112&&123>=a}},l="
    ",m={"\u24b6":"A","\uff21":"A","\xc0":"A","\xc1":"A","\xc2":"A","\u1ea6":"A","\u1ea4":"A","\u1eaa":"A","\u1ea8":"A","\xc3":"A","\u0100":"A","\u0102":"A","\u1eb0":"A","\u1eae":"A","\u1eb4":"A","\u1eb2":"A","\u0226":"A","\u01e0":"A","\xc4":"A","\u01de":"A","\u1ea2":"A","\xc5":"A","\u01fa":"A","\u01cd":"A","\u0200":"A","\u0202":"A","\u1ea0":"A","\u1eac":"A","\u1eb6":"A","\u1e00":"A","\u0104":"A","\u023a":"A","\u2c6f":"A","\ua732":"AA","\xc6":"AE","\u01fc":"AE","\u01e2":"AE","\ua734":"AO","\ua736":"AU","\ua738":"AV","\ua73a":"AV","\ua73c":"AY","\u24b7":"B","\uff22":"B","\u1e02":"B","\u1e04":"B","\u1e06":"B","\u0243":"B","\u0182":"B","\u0181":"B","\u24b8":"C","\uff23":"C","\u0106":"C","\u0108":"C","\u010a":"C","\u010c":"C","\xc7":"C","\u1e08":"C","\u0187":"C","\u023b":"C","\ua73e":"C","\u24b9":"D","\uff24":"D","\u1e0a":"D","\u010e":"D","\u1e0c":"D","\u1e10":"D","\u1e12":"D","\u1e0e":"D","\u0110":"D","\u018b":"D","\u018a":"D","\u0189":"D","\ua779":"D","\u01f1":"DZ","\u01c4":"DZ","\u01f2":"Dz","\u01c5":"Dz","\u24ba":"E","\uff25":"E","\xc8":"E","\xc9":"E","\xca":"E","\u1ec0":"E","\u1ebe":"E","\u1ec4":"E","\u1ec2":"E","\u1ebc":"E","\u0112":"E","\u1e14":"E","\u1e16":"E","\u0114":"E","\u0116":"E","\xcb":"E","\u1eba":"E","\u011a":"E","\u0204":"E","\u0206":"E","\u1eb8":"E","\u1ec6":"E","\u0228":"E","\u1e1c":"E","\u0118":"E","\u1e18":"E","\u1e1a":"E","\u0190":"E","\u018e":"E","\u24bb":"F","\uff26":"F","\u1e1e":"F","\u0191":"F","\ua77b":"F","\u24bc":"G","\uff27":"G","\u01f4":"G","\u011c":"G","\u1e20":"G","\u011e":"G","\u0120":"G","\u01e6":"G","\u0122":"G","\u01e4":"G","\u0193":"G","\ua7a0":"G","\ua77d":"G","\ua77e":"G","\u24bd":"H","\uff28":"H","\u0124":"H","\u1e22":"H","\u1e26":"H","\u021e":"H","\u1e24":"H","\u1e28":"H","\u1e2a":"H","\u0126":"H","\u2c67":"H","\u2c75":"H","\ua78d":"H","\u24be":"I","\uff29":"I","\xcc":"I","\xcd":"I","\xce":"I","\u0128":"I","\u012a":"I","\u012c":"I","\u0130":"I","\xcf":"I","\u1e2e":"I","\u1ec8":"I","\u01cf":"I","\u0208":"I","\u020a":"I","\u1eca":"I","\u012e":"I","\u1e2c":"I","\u0197":"I","\u24bf":"J","\uff2a":"J","\u0134":"J","\u0248":"J","\u24c0":"K","\uff2b":"K","\u1e30":"K","\u01e8":"K","\u1e32":"K","\u0136":"K","\u1e34":"K","\u0198":"K","\u2c69":"K","\ua740":"K","\ua742":"K","\ua744":"K","\ua7a2":"K","\u24c1":"L","\uff2c":"L","\u013f":"L","\u0139":"L","\u013d":"L","\u1e36":"L","\u1e38":"L","\u013b":"L","\u1e3c":"L","\u1e3a":"L","\u0141":"L","\u023d":"L","\u2c62":"L","\u2c60":"L","\ua748":"L","\ua746":"L","\ua780":"L","\u01c7":"LJ","\u01c8":"Lj","\u24c2":"M","\uff2d":"M","\u1e3e":"M","\u1e40":"M","\u1e42":"M","\u2c6e":"M","\u019c":"M","\u24c3":"N","\uff2e":"N","\u01f8":"N","\u0143":"N","\xd1":"N","\u1e44":"N","\u0147":"N","\u1e46":"N","\u0145":"N","\u1e4a":"N","\u1e48":"N","\u0220":"N","\u019d":"N","\ua790":"N","\ua7a4":"N","\u01ca":"NJ","\u01cb":"Nj","\u24c4":"O","\uff2f":"O","\xd2":"O","\xd3":"O","\xd4":"O","\u1ed2":"O","\u1ed0":"O","\u1ed6":"O","\u1ed4":"O","\xd5":"O","\u1e4c":"O","\u022c":"O","\u1e4e":"O","\u014c":"O","\u1e50":"O","\u1e52":"O","\u014e":"O","\u022e":"O","\u0230":"O","\xd6":"O","\u022a":"O","\u1ece":"O","\u0150":"O","\u01d1":"O","\u020c":"O","\u020e":"O","\u01a0":"O","\u1edc":"O","\u1eda":"O","\u1ee0":"O","\u1ede":"O","\u1ee2":"O","\u1ecc":"O","\u1ed8":"O","\u01ea":"O","\u01ec":"O","\xd8":"O","\u01fe":"O","\u0186":"O","\u019f":"O","\ua74a":"O","\ua74c":"O","\u01a2":"OI","\ua74e":"OO","\u0222":"OU","\u24c5":"P","\uff30":"P","\u1e54":"P","\u1e56":"P","\u01a4":"P","\u2c63":"P","\ua750":"P","\ua752":"P","\ua754":"P","\u24c6":"Q","\uff31":"Q","\ua756":"Q","\ua758":"Q","\u024a":"Q","\u24c7":"R","\uff32":"R","\u0154":"R","\u1e58":"R","\u0158":"R","\u0210":"R","\u0212":"R","\u1e5a":"R","\u1e5c":"R","\u0156":"R","\u1e5e":"R","\u024c":"R","\u2c64":"R","\ua75a":"R","\ua7a6":"R","\ua782":"R","\u24c8":"S","\uff33":"S","\u1e9e":"S","\u015a":"S","\u1e64":"S","\u015c":"S","\u1e60":"S","\u0160":"S","\u1e66":"S","\u1e62":"S","\u1e68":"S","\u0218":"S","\u015e":"S","\u2c7e":"S","\ua7a8":"S","\ua784":"S","\u24c9":"T","\uff34":"T","\u1e6a":"T","\u0164":"T","\u1e6c":"T","\u021a":"T","\u0162":"T","\u1e70":"T","\u1e6e":"T","\u0166":"T","\u01ac":"T","\u01ae":"T","\u023e":"T","\ua786":"T","\ua728":"TZ","\u24ca":"U","\uff35":"U","\xd9":"U","\xda":"U","\xdb":"U","\u0168":"U","\u1e78":"U","\u016a":"U","\u1e7a":"U","\u016c":"U","\xdc":"U","\u01db":"U","\u01d7":"U","\u01d5":"U","\u01d9":"U","\u1ee6":"U","\u016e":"U","\u0170":"U","\u01d3":"U","\u0214":"U","\u0216":"U","\u01af":"U","\u1eea":"U","\u1ee8":"U","\u1eee":"U","\u1eec":"U","\u1ef0":"U","\u1ee4":"U","\u1e72":"U","\u0172":"U","\u1e76":"U","\u1e74":"U","\u0244":"U","\u24cb":"V","\uff36":"V","\u1e7c":"V","\u1e7e":"V","\u01b2":"V","\ua75e":"V","\u0245":"V","\ua760":"VY","\u24cc":"W","\uff37":"W","\u1e80":"W","\u1e82":"W","\u0174":"W","\u1e86":"W","\u1e84":"W","\u1e88":"W","\u2c72":"W","\u24cd":"X","\uff38":"X","\u1e8a":"X","\u1e8c":"X","\u24ce":"Y","\uff39":"Y","\u1ef2":"Y","\xdd":"Y","\u0176":"Y","\u1ef8":"Y","\u0232":"Y","\u1e8e":"Y","\u0178":"Y","\u1ef6":"Y","\u1ef4":"Y","\u01b3":"Y","\u024e":"Y","\u1efe":"Y","\u24cf":"Z","\uff3a":"Z","\u0179":"Z","\u1e90":"Z","\u017b":"Z","\u017d":"Z","\u1e92":"Z","\u1e94":"Z","\u01b5":"Z","\u0224":"Z","\u2c7f":"Z","\u2c6b":"Z","\ua762":"Z","\u24d0":"a","\uff41":"a","\u1e9a":"a","\xe0":"a","\xe1":"a","\xe2":"a","\u1ea7":"a","\u1ea5":"a","\u1eab":"a","\u1ea9":"a","\xe3":"a","\u0101":"a","\u0103":"a","\u1eb1":"a","\u1eaf":"a","\u1eb5":"a","\u1eb3":"a","\u0227":"a","\u01e1":"a","\xe4":"a","\u01df":"a","\u1ea3":"a","\xe5":"a","\u01fb":"a","\u01ce":"a","\u0201":"a","\u0203":"a","\u1ea1":"a","\u1ead":"a","\u1eb7":"a","\u1e01":"a","\u0105":"a","\u2c65":"a","\u0250":"a","\ua733":"aa","\xe6":"ae","\u01fd":"ae","\u01e3":"ae","\ua735":"ao","\ua737":"au","\ua739":"av","\ua73b":"av","\ua73d":"ay","\u24d1":"b","\uff42":"b","\u1e03":"b","\u1e05":"b","\u1e07":"b","\u0180":"b","\u0183":"b","\u0253":"b","\u24d2":"c","\uff43":"c","\u0107":"c","\u0109":"c","\u010b":"c","\u010d":"c","\xe7":"c","\u1e09":"c","\u0188":"c","\u023c":"c","\ua73f":"c","\u2184":"c","\u24d3":"d","\uff44":"d","\u1e0b":"d","\u010f":"d","\u1e0d":"d","\u1e11":"d","\u1e13":"d","\u1e0f":"d","\u0111":"d","\u018c":"d","\u0256":"d","\u0257":"d","\ua77a":"d","\u01f3":"dz","\u01c6":"dz","\u24d4":"e","\uff45":"e","\xe8":"e","\xe9":"e","\xea":"e","\u1ec1":"e","\u1ebf":"e","\u1ec5":"e","\u1ec3":"e","\u1ebd":"e","\u0113":"e","\u1e15":"e","\u1e17":"e","\u0115":"e","\u0117":"e","\xeb":"e","\u1ebb":"e","\u011b":"e","\u0205":"e","\u0207":"e","\u1eb9":"e","\u1ec7":"e","\u0229":"e","\u1e1d":"e","\u0119":"e","\u1e19":"e","\u1e1b":"e","\u0247":"e","\u025b":"e","\u01dd":"e","\u24d5":"f","\uff46":"f","\u1e1f":"f","\u0192":"f","\ua77c":"f","\u24d6":"g","\uff47":"g","\u01f5":"g","\u011d":"g","\u1e21":"g","\u011f":"g","\u0121":"g","\u01e7":"g","\u0123":"g","\u01e5":"g","\u0260":"g","\ua7a1":"g","\u1d79":"g","\ua77f":"g","\u24d7":"h","\uff48":"h","\u0125":"h","\u1e23":"h","\u1e27":"h","\u021f":"h","\u1e25":"h","\u1e29":"h","\u1e2b":"h","\u1e96":"h","\u0127":"h","\u2c68":"h","\u2c76":"h","\u0265":"h","\u0195":"hv","\u24d8":"i","\uff49":"i","\xec":"i","\xed":"i","\xee":"i","\u0129":"i","\u012b":"i","\u012d":"i","\xef":"i","\u1e2f":"i","\u1ec9":"i","\u01d0":"i","\u0209":"i","\u020b":"i","\u1ecb":"i","\u012f":"i","\u1e2d":"i","\u0268":"i","\u0131":"i","\u24d9":"j","\uff4a":"j","\u0135":"j","\u01f0":"j","\u0249":"j","\u24da":"k","\uff4b":"k","\u1e31":"k","\u01e9":"k","\u1e33":"k","\u0137":"k","\u1e35":"k","\u0199":"k","\u2c6a":"k","\ua741":"k","\ua743":"k","\ua745":"k","\ua7a3":"k","\u24db":"l","\uff4c":"l","\u0140":"l","\u013a":"l","\u013e":"l","\u1e37":"l","\u1e39":"l","\u013c":"l","\u1e3d":"l","\u1e3b":"l","\u017f":"l","\u0142":"l","\u019a":"l","\u026b":"l","\u2c61":"l","\ua749":"l","\ua781":"l","\ua747":"l","\u01c9":"lj","\u24dc":"m","\uff4d":"m","\u1e3f":"m","\u1e41":"m","\u1e43":"m","\u0271":"m","\u026f":"m","\u24dd":"n","\uff4e":"n","\u01f9":"n","\u0144":"n","\xf1":"n","\u1e45":"n","\u0148":"n","\u1e47":"n","\u0146":"n","\u1e4b":"n","\u1e49":"n","\u019e":"n","\u0272":"n","\u0149":"n","\ua791":"n","\ua7a5":"n","\u01cc":"nj","\u24de":"o","\uff4f":"o","\xf2":"o","\xf3":"o","\xf4":"o","\u1ed3":"o","\u1ed1":"o","\u1ed7":"o","\u1ed5":"o","\xf5":"o","\u1e4d":"o","\u022d":"o","\u1e4f":"o","\u014d":"o","\u1e51":"o","\u1e53":"o","\u014f":"o","\u022f":"o","\u0231":"o","\xf6":"o","\u022b":"o","\u1ecf":"o","\u0151":"o","\u01d2":"o","\u020d":"o","\u020f":"o","\u01a1":"o","\u1edd":"o","\u1edb":"o","\u1ee1":"o","\u1edf":"o","\u1ee3":"o","\u1ecd":"o","\u1ed9":"o","\u01eb":"o","\u01ed":"o","\xf8":"o","\u01ff":"o","\u0254":"o","\ua74b":"o","\ua74d":"o","\u0275":"o","\u01a3":"oi","\u0223":"ou","\ua74f":"oo","\u24df":"p","\uff50":"p","\u1e55":"p","\u1e57":"p","\u01a5":"p","\u1d7d":"p","\ua751":"p","\ua753":"p","\ua755":"p","\u24e0":"q","\uff51":"q","\u024b":"q","\ua757":"q","\ua759":"q","\u24e1":"r","\uff52":"r","\u0155":"r","\u1e59":"r","\u0159":"r","\u0211":"r","\u0213":"r","\u1e5b":"r","\u1e5d":"r","\u0157":"r","\u1e5f":"r","\u024d":"r","\u027d":"r","\ua75b":"r","\ua7a7":"r","\ua783":"r","\u24e2":"s","\uff53":"s","\xdf":"s","\u015b":"s","\u1e65":"s","\u015d":"s","\u1e61":"s","\u0161":"s","\u1e67":"s","\u1e63":"s","\u1e69":"s","\u0219":"s","\u015f":"s","\u023f":"s","\ua7a9":"s","\ua785":"s","\u1e9b":"s","\u24e3":"t","\uff54":"t","\u1e6b":"t","\u1e97":"t","\u0165":"t","\u1e6d":"t","\u021b":"t","\u0163":"t","\u1e71":"t","\u1e6f":"t","\u0167":"t","\u01ad":"t","\u0288":"t","\u2c66":"t","\ua787":"t","\ua729":"tz","\u24e4":"u","\uff55":"u","\xf9":"u","\xfa":"u","\xfb":"u","\u0169":"u","\u1e79":"u","\u016b":"u","\u1e7b":"u","\u016d":"u","\xfc":"u","\u01dc":"u","\u01d8":"u","\u01d6":"u","\u01da":"u","\u1ee7":"u","\u016f":"u","\u0171":"u","\u01d4":"u","\u0215":"u","\u0217":"u","\u01b0":"u","\u1eeb":"u","\u1ee9":"u","\u1eef":"u","\u1eed":"u","\u1ef1":"u","\u1ee5":"u","\u1e73":"u","\u0173":"u","\u1e77":"u","\u1e75":"u","\u0289":"u","\u24e5":"v","\uff56":"v","\u1e7d":"v","\u1e7f":"v","\u028b":"v","\ua75f":"v","\u028c":"v","\ua761":"vy","\u24e6":"w","\uff57":"w","\u1e81":"w","\u1e83":"w","\u0175":"w","\u1e87":"w","\u1e85":"w","\u1e98":"w","\u1e89":"w","\u2c73":"w","\u24e7":"x","\uff58":"x","\u1e8b":"x","\u1e8d":"x","\u24e8":"y","\uff59":"y","\u1ef3":"y","\xfd":"y","\u0177":"y","\u1ef9":"y","\u0233":"y","\u1e8f":"y","\xff":"y","\u1ef7":"y","\u1e99":"y","\u1ef5":"y","\u01b4":"y","\u024f":"y","\u1eff":"y","\u24e9":"z","\uff5a":"z","\u017a":"z","\u1e91":"z","\u017c":"z","\u017e":"z","\u1e93":"z","\u1e95":"z","\u01b6":"z","\u0225":"z","\u0240":"z","\u2c6c":"z","\ua763":"z"};j=a(document),g=function(){var a=1;return function(){return a++}}(),j.on("mousemove",function(a){i.x=a.pageX,i.y=a.pageY}),d=N(Object,{bind:function(a){var b=this;return function(){a.apply(b,arguments)}},init:function(c){var d,e,f=".select2-results";this.opts=c=this.prepareOpts(c),this.id=c.id,c.element.data("select2")!==b&&null!==c.element.data("select2")&&c.element.data("select2").destroy(),this.container=this.createContainer(),this.containerId="s2id_"+(c.element.attr("id")||"autogen"+g()),this.containerSelector="#"+this.containerId.replace(/([;&,\.\+\*\~':"\!\^#$%@\[\]\(\)=>\|])/g,"\\$1"),this.container.attr("id",this.containerId),this.body=w(function(){return c.element.closest("body")}),D(this.container,this.opts.element,this.opts.adaptContainerCssClass),this.container.attr("style",c.element.attr("style")),this.container.css(K(c.containerCss)),this.container.addClass(K(c.containerCssClass)),this.elementTabIndex=this.opts.element.attr("tabindex"),this.opts.element.data("select2",this).attr("tabindex","-1").before(this.container).on("click.select2",A),this.container.data("select2",this),this.dropdown=this.container.find(".select2-drop"),D(this.dropdown,this.opts.element,this.opts.adaptDropdownCssClass),this.dropdown.addClass(K(c.dropdownCssClass)),this.dropdown.data("select2",this),this.dropdown.on("click",A),this.results=d=this.container.find(f),this.search=e=this.container.find("input.select2-input"),this.queryCount=0,this.resultsPage=0,this.context=null,this.initContainer(),this.container.on("click",A),u(this.results),this.dropdown.on("mousemove-filtered touchstart touchmove touchend",f,this.bind(this.highlightUnderEvent)),x(80,this.results),this.dropdown.on("scroll-debounced",f,this.bind(this.loadMoreIfNeeded)),a(this.container).on("change",".select2-input",function(a){a.stopPropagation()}),a(this.dropdown).on("change",".select2-input",function(a){a.stopPropagation()}),a.fn.mousewheel&&d.mousewheel(function(a,b,c,e){var f=d.scrollTop();e>0&&0>=f-e?(d.scrollTop(0),A(a)):0>e&&d.get(0).scrollHeight-d.scrollTop()+e<=d.height()&&(d.scrollTop(d.get(0).scrollHeight-d.height()),A(a))}),t(e),e.on("keyup-change input paste",this.bind(this.updateResults)),e.on("focus",function(){e.addClass("select2-focused")}),e.on("blur",function(){e.removeClass("select2-focused")}),this.dropdown.on("mouseup",f,this.bind(function(b){a(b.target).closest(".select2-result-selectable").length>0&&(this.highlightUnderEvent(b),this.selectHighlighted(b))})),this.dropdown.on("click mouseup mousedown",function(a){a.stopPropagation()}),a.isFunction(this.opts.initSelection)&&(this.initSelection(),this.monitorSource()),null!==c.maximumInputLength&&this.search.attr("maxlength",c.maximumInputLength);var h=c.element.prop("disabled");h===b&&(h=!1),this.enable(!h);var i=c.element.prop("readonly");i===b&&(i=!1),this.readonly(i),k=k||p(),this.autofocus=c.element.prop("autofocus"),c.element.prop("autofocus",!1),this.autofocus&&this.focus(),this.nextSearchTerm=b},destroy:function(){var a=this.opts.element,c=a.data("select2");this.close(),this.propertyObserver&&(delete this.propertyObserver,this.propertyObserver=null),c!==b&&(c.container.remove(),c.dropdown.remove(),a.removeClass("select2-offscreen").removeData("select2").off(".select2").prop("autofocus",this.autofocus||!1),this.elementTabIndex?a.attr({tabindex:this.elementTabIndex}):a.removeAttr("tabindex"),a.show())},optionToData:function(a){return a.is("option")?{id:a.prop("value"),text:a.text(),element:a.get(),css:a.attr("class"),disabled:a.prop("disabled"),locked:q(a.attr("locked"),"locked")||q(a.data("locked"),!0)}:a.is("optgroup")?{text:a.attr("label"),children:[],element:a.get(),css:a.attr("class")}:void 0},prepareOpts:function(c){var d,e,f,g,h=this;if(d=c.element,"select"===d.get(0).tagName.toLowerCase()&&(this.select=e=c.element),e&&a.each(["id","multiple","ajax","query","createSearchChoice","initSelection","data","tags"],function(){if(this in c)throw new Error("Option '"+this+"' is not allowed for Select2 when attached to a ","
    "," ","
      ","
    ","
    "].join(""));return b},enableInterface:function(){this.parent.enableInterface.apply(this,arguments)&&this.focusser.prop("disabled",!this.isInterfaceEnabled())},opening:function(){var c,d,e;this.opts.minimumResultsForSearch>=0&&this.showSearch(!0),this.parent.opening.apply(this,arguments),this.showSearchInput!==!1&&this.search.val(this.focusser.val()),this.search.focus(),c=this.search.get(0),c.createTextRange?(d=c.createTextRange(),d.collapse(!1),d.select()):c.setSelectionRange&&(e=this.search.val().length,c.setSelectionRange(e,e)),""===this.search.val()&&this.nextSearchTerm!=b&&(this.search.val(this.nextSearchTerm),this.search.select()),this.focusser.prop("disabled",!0).val(""),this.updateResults(!0),this.opts.element.trigger(a.Event("select2-open"))},close:function(a){this.opened()&&(this.parent.close.apply(this,arguments),a=a||{focus:!0},this.focusser.removeAttr("disabled"),a.focus&&this.focusser.focus())},focus:function(){this.opened()?this.close():(this.focusser.removeAttr("disabled"),this.focusser.focus())},isFocused:function(){return this.container.hasClass("select2-container-active")},cancel:function(){this.parent.cancel.apply(this,arguments),this.focusser.removeAttr("disabled"),this.focusser.focus()},destroy:function(){a("label[for='"+this.focusser.attr("id")+"']").attr("for",this.opts.element.attr("id")),this.parent.destroy.apply(this,arguments)},initContainer:function(){var b,d=this.container,e=this.dropdown;this.opts.minimumResultsForSearch<0?this.showSearch(!1):this.showSearch(!0),this.selection=b=d.find(".select2-choice"),this.focusser=d.find(".select2-focusser"),this.focusser.attr("id","s2id_autogen"+g()),a("label[for='"+this.opts.element.attr("id")+"']").attr("for",this.focusser.attr("id")),this.focusser.attr("tabindex",this.elementTabIndex),this.search.on("keydown",this.bind(function(a){if(this.isInterfaceEnabled()){if(a.which===c.PAGE_UP||a.which===c.PAGE_DOWN)return A(a),void 0;switch(a.which){case c.UP:case c.DOWN:return this.moveHighlight(a.which===c.UP?-1:1),A(a),void 0;case c.ENTER:return this.selectHighlighted(),A(a),void 0;case c.TAB:return this.selectHighlighted({noFocus:!0}),void 0;case c.ESC:return this.cancel(a),A(a),void 0}}})),this.search.on("blur",this.bind(function(){document.activeElement===this.body().get(0)&&window.setTimeout(this.bind(function(){this.search.focus()}),0)})),this.focusser.on("keydown",this.bind(function(a){if(this.isInterfaceEnabled()&&a.which!==c.TAB&&!c.isControl(a)&&!c.isFunctionKey(a)&&a.which!==c.ESC){if(this.opts.openOnEnter===!1&&a.which===c.ENTER)return A(a),void 0;if(a.which==c.DOWN||a.which==c.UP||a.which==c.ENTER&&this.opts.openOnEnter){if(a.altKey||a.ctrlKey||a.shiftKey||a.metaKey)return;return this.open(),A(a),void 0}return a.which==c.DELETE||a.which==c.BACKSPACE?(this.opts.allowClear&&this.clear(),A(a),void 0):void 0}})),t(this.focusser),this.focusser.on("keyup-change input",this.bind(function(a){if(this.opts.minimumResultsForSearch>=0){if(a.stopPropagation(),this.opened())return;this.open()}})),b.on("mousedown","abbr",this.bind(function(a){this.isInterfaceEnabled()&&(this.clear(),B(a),this.close(),this.selection.focus())})),b.on("mousedown",this.bind(function(b){this.container.hasClass("select2-container-active")||this.opts.element.trigger(a.Event("select2-focus")),this.opened()?this.close():this.isInterfaceEnabled()&&this.open(),A(b)})),e.on("mousedown",this.bind(function(){this.search.focus()})),b.on("focus",this.bind(function(a){A(a)})),this.focusser.on("focus",this.bind(function(){this.container.hasClass("select2-container-active")||this.opts.element.trigger(a.Event("select2-focus")),this.container.addClass("select2-container-active")})).on("blur",this.bind(function(){this.opened()||(this.container.removeClass("select2-container-active"),this.opts.element.trigger(a.Event("select2-blur")))})),this.search.on("focus",this.bind(function(){this.container.hasClass("select2-container-active")||this.opts.element.trigger(a.Event("select2-focus")),this.container.addClass("select2-container-active")})),this.initContainerWidth(),this.opts.element.addClass("select2-offscreen"),this.setPlaceholder()},clear:function(b){var c=this.selection.data("select2-data");if(c){var d=a.Event("select2-clearing");if(this.opts.element.trigger(d),d.isDefaultPrevented())return;var e=this.getPlaceholderOption();this.opts.element.val(e?e.val():""),this.selection.find(".select2-chosen").empty(),this.selection.removeData("select2-data"),this.setPlaceholder(),b!==!1&&(this.opts.element.trigger({type:"select2-removed",val:this.id(c),choice:c}),this.triggerChange({removed:c}))}},initSelection:function(){if(this.isPlaceholderOptionSelected())this.updateSelection(null),this.close(),this.setPlaceholder();else{var c=this;this.opts.initSelection.call(null,this.opts.element,function(a){a!==b&&null!==a&&(c.updateSelection(a),c.close(),c.setPlaceholder())})}},isPlaceholderOptionSelected:function(){var a;return this.getPlaceholder()?(a=this.getPlaceholderOption())!==b&&a.prop("selected")||""===this.opts.element.val()||this.opts.element.val()===b||null===this.opts.element.val():!1},prepareOpts:function(){var b=this.parent.prepareOpts.apply(this,arguments),c=this;return"select"===b.element.get(0).tagName.toLowerCase()?b.initSelection=function(a,b){var d=a.find("option").filter(function(){return this.selected});b(c.optionToData(d))}:"data"in b&&(b.initSelection=b.initSelection||function(c,d){var e=c.val(),f=null;b.query({matcher:function(a,c,d){var g=q(e,b.id(d));return g&&(f=d),g},callback:a.isFunction(d)?function(){d(f)}:a.noop})}),b},getPlaceholder:function(){return this.select&&this.getPlaceholderOption()===b?b:this.parent.getPlaceholder.apply(this,arguments)},setPlaceholder:function(){var a=this.getPlaceholder();if(this.isPlaceholderOptionSelected()&&a!==b){if(this.select&&this.getPlaceholderOption()===b)return;this.selection.find(".select2-chosen").html(this.opts.escapeMarkup(a)),this.selection.addClass("select2-default"),this.container.removeClass("select2-allowclear")}},postprocessResults:function(a,b,c){var d=0,e=this;if(this.findHighlightableChoices().each2(function(a,b){return q(e.id(b.data("select2-data")),e.opts.element.val())?(d=a,!1):void 0}),c!==!1&&(b===!0&&d>=0?this.highlight(d):this.highlight(0)),b===!0){var g=this.opts.minimumResultsForSearch;g>=0&&this.showSearch(L(a.results)>=g)}},showSearch:function(b){this.showSearchInput!==b&&(this.showSearchInput=b,this.dropdown.find(".select2-search").toggleClass("select2-search-hidden",!b),this.dropdown.find(".select2-search").toggleClass("select2-offscreen",!b),a(this.dropdown,this.container).toggleClass("select2-with-searchbox",b))},onSelect:function(a,b){if(this.triggerSelect(a)){var c=this.opts.element.val(),d=this.data();this.opts.element.val(this.id(a)),this.updateSelection(a),this.opts.element.trigger({type:"select2-selected",val:this.id(a),choice:a}),this.nextSearchTerm=this.opts.nextSearchTerm(a,this.search.val()),this.close(),b&&b.noFocus||this.focusser.focus(),q(c,this.id(a))||this.triggerChange({added:a,removed:d})}},updateSelection:function(a){var d,e,c=this.selection.find(".select2-chosen");this.selection.data("select2-data",a),c.empty(),null!==a&&(d=this.opts.formatSelection(a,c,this.opts.escapeMarkup)),d!==b&&c.append(d),e=this.opts.formatSelectionCssClass(a,c),e!==b&&c.addClass(e),this.selection.removeClass("select2-default"),this.opts.allowClear&&this.getPlaceholder()!==b&&this.container.addClass("select2-allowclear")},val:function(){var a,c=!1,d=null,e=this,f=this.data();if(0===arguments.length)return this.opts.element.val();if(a=arguments[0],arguments.length>1&&(c=arguments[1]),this.select)this.select.val(a).find("option").filter(function(){return this.selected}).each2(function(a,b){return d=e.optionToData(b),!1}),this.updateSelection(d),this.setPlaceholder(),c&&this.triggerChange({added:d,removed:f});else{if(!a&&0!==a)return this.clear(c),void 0;if(this.opts.initSelection===b)throw new Error("cannot call val() if initSelection() is not defined");this.opts.element.val(a),this.opts.initSelection(this.opts.element,function(a){e.opts.element.val(a?e.id(a):""),e.updateSelection(a),e.setPlaceholder(),c&&e.triggerChange({added:a,removed:f})})}},clearSearch:function(){this.search.val(""),this.focusser.val("")},data:function(a){var c,d=!1;return 0===arguments.length?(c=this.selection.data("select2-data"),c==b&&(c=null),c):(arguments.length>1&&(d=arguments[1]),a?(c=this.data(),this.opts.element.val(a?this.id(a):""),this.updateSelection(a),d&&this.triggerChange({added:a,removed:c})):this.clear(d),void 0)}}),f=N(d,{createContainer:function(){var b=a(document.createElement("div")).attr({"class":"select2-container select2-container-multi"}).html(["
      ","
    • "," ","
    • ","
    ","
    ","
      ","
    ","
    "].join(""));return b},prepareOpts:function(){var b=this.parent.prepareOpts.apply(this,arguments),c=this;return"select"===b.element.get(0).tagName.toLowerCase()?b.initSelection=function(a,b){var d=[];a.find("option").filter(function(){return this.selected}).each2(function(a,b){d.push(c.optionToData(b))}),b(d)}:"data"in b&&(b.initSelection=b.initSelection||function(c,d){var e=r(c.val(),b.separator),f=[];b.query({matcher:function(c,d,g){var h=a.grep(e,function(a){return q(a,b.id(g))}).length;return h&&f.push(g),h},callback:a.isFunction(d)?function(){for(var a=[],c=0;c0||(this.selectChoice(null),this.clearPlaceholder(),this.container.hasClass("select2-container-active")||this.opts.element.trigger(a.Event("select2-focus")),this.open(),this.focusSearch(),b.preventDefault()))})),this.container.on("focus",b,this.bind(function(){this.isInterfaceEnabled()&&(this.container.hasClass("select2-container-active")||this.opts.element.trigger(a.Event("select2-focus")),this.container.addClass("select2-container-active"),this.dropdown.addClass("select2-drop-active"),this.clearPlaceholder())})),this.initContainerWidth(),this.opts.element.addClass("select2-offscreen"),this.clearSearch()},enableInterface:function(){this.parent.enableInterface.apply(this,arguments)&&this.search.prop("disabled",!this.isInterfaceEnabled())},initSelection:function(){if(""===this.opts.element.val()&&""===this.opts.element.text()&&(this.updateSelection([]),this.close(),this.clearSearch()),this.select||""!==this.opts.element.val()){var c=this;this.opts.initSelection.call(null,this.opts.element,function(a){a!==b&&null!==a&&(c.updateSelection(a),c.close(),c.clearSearch())})}},clearSearch:function(){var a=this.getPlaceholder(),c=this.getMaxSearchWidth();a!==b&&0===this.getVal().length&&this.search.hasClass("select2-focused")===!1?(this.search.val(a).addClass("select2-default"),this.search.width(c>0?c:this.container.css("width"))):this.search.val("").width(10)},clearPlaceholder:function(){this.search.hasClass("select2-default")&&this.search.val("").removeClass("select2-default")},opening:function(){this.clearPlaceholder(),this.resizeSearch(),this.parent.opening.apply(this,arguments),this.focusSearch(),this.updateResults(!0),this.search.focus(),this.opts.element.trigger(a.Event("select2-open"))},close:function(){this.opened()&&this.parent.close.apply(this,arguments)},focus:function(){this.close(),this.search.focus()},isFocused:function(){return this.search.hasClass("select2-focused")},updateSelection:function(b){var c=[],d=[],e=this;a(b).each(function(){o(e.id(this),c)<0&&(c.push(e.id(this)),d.push(this))}),b=d,this.selection.find(".select2-search-choice").remove(),a(b).each(function(){e.addSelectedChoice(this)}),e.postprocessResults()},tokenize:function(){var a=this.search.val();a=this.opts.tokenizer.call(this,a,this.data(),this.bind(this.onSelect),this.opts),null!=a&&a!=b&&(this.search.val(a),a.length>0&&this.open())},onSelect:function(a,b){this.triggerSelect(a)&&(this.addSelectedChoice(a),this.opts.element.trigger({type:"selected",val:this.id(a),choice:a}),(this.select||!this.opts.closeOnSelect)&&this.postprocessResults(a,!1,this.opts.closeOnSelect===!0),this.opts.closeOnSelect?(this.close(),this.search.width(10)):this.countSelectableResults()>0?(this.search.width(10),this.resizeSearch(),this.getMaximumSelectionSize()>0&&this.val().length>=this.getMaximumSelectionSize()&&this.updateResults(!0),this.positionDropdown()):(this.close(),this.search.width(10)),this.triggerChange({added:a}),b&&b.noFocus||this.focusSearch())},cancel:function(){this.close(),this.focusSearch()},addSelectedChoice:function(c){var j,k,d=!c.locked,e=a("
  • "),f=a("
  • "),g=d?e:f,h=this.id(c),i=this.getVal();j=this.opts.formatSelection(c,g.find("div"),this.opts.escapeMarkup),j!=b&&g.find("div").replaceWith("
    "+j+"
    "),k=this.opts.formatSelectionCssClass(c,g.find("div")),k!=b&&g.addClass(k),d&&g.find(".select2-search-choice-close").on("mousedown",A).on("click dblclick",this.bind(function(b){this.isInterfaceEnabled()&&(a(b.target).closest(".select2-search-choice").fadeOut("fast",this.bind(function(){this.unselect(a(b.target)),this.selection.find(".select2-search-choice-focus").removeClass("select2-search-choice-focus"),this.close(),this.focusSearch()})).dequeue(),A(b))})).on("focus",this.bind(function(){this.isInterfaceEnabled()&&(this.container.addClass("select2-container-active"),this.dropdown.addClass("select2-drop-active"))})),g.data("select2-data",c),g.insertBefore(this.searchContainer),i.push(h),this.setVal(i)},unselect:function(b){var d,e,c=this.getVal();if(b=b.closest(".select2-search-choice"),0===b.length)throw"Invalid argument: "+b+". Must be .select2-search-choice";if(d=b.data("select2-data")){for(;(e=o(this.id(d),c))>=0;)c.splice(e,1),this.setVal(c),this.select&&this.postprocessResults();var f=a.Event("select2-removing");f.val=this.id(d),f.choice=d,this.opts.element.trigger(f),f.isDefaultPrevented()||(b.remove(),this.opts.element.trigger({type:"select2-removed",val:this.id(d),choice:d}),this.triggerChange({removed:d}))}},postprocessResults:function(a,b,c){var d=this.getVal(),e=this.results.find(".select2-result"),f=this.results.find(".select2-result-with-children"),g=this;e.each2(function(a,b){var c=g.id(b.data("select2-data"));o(c,d)>=0&&(b.addClass("select2-selected"),b.find(".select2-result-selectable").addClass("select2-selected"))}),f.each2(function(a,b){b.is(".select2-result-selectable")||0!==b.find(".select2-result-selectable:not(.select2-selected)").length||b.addClass("select2-selected")}),-1==this.highlight()&&c!==!1&&g.highlight(0),!this.opts.createSearchChoice&&!e.filter(".select2-result:not(.select2-selected)").length>0&&(!a||a&&!a.more&&0===this.results.find(".select2-no-results").length)&&J(g.opts.formatNoMatches,"formatNoMatches")&&this.results.append("
  • "+g.opts.formatNoMatches(g.search.val())+"
  • ")},getMaxSearchWidth:function(){return this.selection.width()-s(this.search)},resizeSearch:function(){var a,b,c,d,e,f=s(this.search);a=C(this.search)+10,b=this.search.offset().left,c=this.selection.width(),d=this.selection.offset().left,e=c-(b-d)-f,a>e&&(e=c-f),40>e&&(e=c-f),0>=e&&(e=a),this.search.width(Math.floor(e))},getVal:function(){var a;return this.select?(a=this.select.val(),null===a?[]:a):(a=this.opts.element.val(),r(a,this.opts.separator))},setVal:function(b){var c;this.select?this.select.val(b):(c=[],a(b).each(function(){o(this,c)<0&&c.push(this)}),this.opts.element.val(0===c.length?"":c.join(this.opts.separator)))},buildChangeDetails:function(a,b){for(var b=b.slice(0),a=a.slice(0),c=0;c0&&c--,a.splice(d,1),d--);return{added:b,removed:a}},val:function(c,d){var e,f=this;if(0===arguments.length)return this.getVal();if(e=this.data(),e.length||(e=[]),!c&&0!==c)return this.opts.element.val(""),this.updateSelection([]),this.clearSearch(),d&&this.triggerChange({added:this.data(),removed:e}),void 0;if(this.setVal(c),this.select)this.opts.initSelection(this.select,this.bind(this.updateSelection)),d&&this.triggerChange(this.buildChangeDetails(e,this.data()));else{if(this.opts.initSelection===b)throw new Error("val() cannot be called if initSelection() is not defined");this.opts.initSelection(this.opts.element,function(b){var c=a.map(b,f.id);f.setVal(c),f.updateSelection(b),f.clearSearch(),d&&f.triggerChange(f.buildChangeDetails(e,f.data()))})}this.clearSearch()},onSortStart:function(){if(this.select)throw new Error("Sorting of elements is not supported when attached to instead.");this.search.width(0),this.searchContainer.hide()},onSortEnd:function(){var b=[],c=this;this.searchContainer.show(),this.searchContainer.appendTo(this.searchContainer.parent()),this.resizeSearch(),this.selection.find(".select2-search-choice").each(function(){b.push(c.opts.id(a(this).data("select2-data")))}),this.setVal(b),this.triggerChange()},data:function(b,c){var e,f,d=this;return 0===arguments.length?this.selection.find(".select2-search-choice").map(function(){return a(this).data("select2-data")}).get():(f=this.data(),b||(b=[]),e=a.map(b,function(a){return d.opts.id(a)}),this.setVal(e),this.updateSelection(b),this.clearSearch(),c&&this.triggerChange(this.buildChangeDetails(f,this.data())),void 0)}}),a.fn.select2=function(){var d,g,h,i,j,c=Array.prototype.slice.call(arguments,0),k=["val","destroy","opened","open","close","focus","isFocused","container","dropdown","onSortStart","onSortEnd","enable","disable","readonly","positionDropdown","data","search"],l=["opened","isFocused","container","dropdown"],m=["val","data"],n={search:"externalSearch"};return this.each(function(){if(0===c.length||"object"==typeof c[0])d=0===c.length?{}:a.extend({},c[0]),d.element=a(this),"select"===d.element.get(0).tagName.toLowerCase()?j=d.element.prop("multiple"):(j=d.multiple||!1,"tags"in d&&(d.multiple=j=!0)),g=j?new f:new e,g.init(d);else{if("string"!=typeof c[0])throw"Invalid arguments to select2 plugin: "+c;if(o(c[0],k)<0)throw"Unknown method: "+c[0];if(i=b,g=a(this).data("select2"),g===b)return;if(h=c[0],"container"===h?i=g.container:"dropdown"===h?i=g.dropdown:(n[h]&&(h=n[h]),i=g[h].apply(g,c.slice(1))),o(c[0],l)>=0||o(c[0],m)&&1==c.length)return!1}}),i===b?this:i},a.fn.select2.defaults={width:"copy",loadMorePadding:0,closeOnSelect:!0,openOnEnter:!0,containerCss:{},dropdownCss:{},containerCssClass:"",dropdownCssClass:"",formatResult:function(a,b,c,d){var e=[];return E(a.text,c.term,e,d),e.join("")},formatSelection:function(a,c,d){return a?d(a.text):b},sortResults:function(a){return a},formatResultCssClass:function(){return b},formatSelectionCssClass:function(){return b},formatNoMatches:function(){return"No matches found"},formatInputTooShort:function(a,b){var c=b-a.length;return"Please enter "+c+" more character"+(1==c?"":"s")},formatInputTooLong:function(a,b){var c=a.length-b;return"Please delete "+c+" character"+(1==c?"":"s")},formatSelectionTooBig:function(a){return"You can only select "+a+" item"+(1==a?"":"s")},formatLoadMore:function(){return"Loading more results..."},formatSearching:function(){return"Searching..."},minimumResultsForSearch:0,minimumInputLength:0,maximumInputLength:null,maximumSelectionSize:0,id:function(a){return a.id},matcher:function(a,b){return n(""+b).toUpperCase().indexOf(n(""+a).toUpperCase())>=0},separator:",",tokenSeparators:[],tokenizer:M,escapeMarkup:F,blurOnChange:!1,selectOnBlur:!1,adaptContainerCssClass:function(a){return a},adaptDropdownCssClass:function(){return null},nextSearchTerm:function(){return b}},a.fn.select2.ajaxDefaults={transport:a.ajax,params:{type:"GET",cache:!1,dataType:"json"}},window.Select2={query:{ajax:G,local:H,tags:I},util:{debounce:v,markMatch:E,escapeMarkup:F,stripDiacritics:n},"class":{"abstract":d,single:e,multi:f}}}}(jQuery); \ No newline at end of file +!function(a){"undefined"==typeof a.fn.each2&&a.extend(a.fn,{each2:function(b){for(var c=a([0]),d=-1,e=this.length;++dc;c+=1)if(r(a,b[c]))return c;return-1}function q(){var b=a(l);b.appendTo("body");var c={width:b.width()-b[0].clientWidth,height:b.height()-b[0].clientHeight};return b.remove(),c}function r(a,c){return a===c?!0:a===b||c===b?!1:null===a||null===c?!1:a.constructor===String?a+""==c+"":c.constructor===String?c+""==a+"":!1}function s(b,c){var d,e,f;if(null===b||b.length<1)return[];for(d=b.split(c),e=0,f=d.length;f>e;e+=1)d[e]=a.trim(d[e]);return d}function t(a){return a.outerWidth(!1)-a.width()}function u(c){var d="keyup-change-value";c.on("keydown",function(){a.data(c,d)===b&&a.data(c,d,c.val())}),c.on("keyup",function(){var e=a.data(c,d);e!==b&&c.val()!==e&&(a.removeData(c,d),c.trigger("keyup-change"))})}function v(c){c.on("mousemove",function(c){var d=i;(d===b||d.x!==c.pageX||d.y!==c.pageY)&&a(c.target).trigger("mousemove-filtered",c)})}function w(a,c,d){d=d||b;var e;return function(){var b=arguments;window.clearTimeout(e),e=window.setTimeout(function(){c.apply(d,b)},a)}}function x(a,b){var c=w(a,function(a){b.trigger("scroll-debounced",a)});b.on("scroll",function(a){p(a.target,b.get())>=0&&c(a)})}function y(a){a[0]!==document.activeElement&&window.setTimeout(function(){var d,b=a[0],c=a.val().length;a.focus();var e=b.offsetWidth>0||b.offsetHeight>0;e&&b===document.activeElement&&(b.setSelectionRange?b.setSelectionRange(c,c):b.createTextRange&&(d=b.createTextRange(),d.collapse(!1),d.select()))},0)}function z(b){b=a(b)[0];var c=0,d=0;if("selectionStart"in b)c=b.selectionStart,d=b.selectionEnd-c;else if("selection"in document){b.focus();var e=document.selection.createRange();d=document.selection.createRange().text.length,e.moveStart("character",-b.value.length),c=e.text.length-d}return{offset:c,length:d}}function A(a){a.preventDefault(),a.stopPropagation()}function B(a){a.preventDefault(),a.stopImmediatePropagation()}function C(b){if(!h){var c=b[0].currentStyle||window.getComputedStyle(b[0],null);h=a(document.createElement("div")).css({position:"absolute",left:"-10000px",top:"-10000px",display:"none",fontSize:c.fontSize,fontFamily:c.fontFamily,fontStyle:c.fontStyle,fontWeight:c.fontWeight,letterSpacing:c.letterSpacing,textTransform:c.textTransform,whiteSpace:"nowrap"}),h.attr("class","select2-sizer"),a("body").append(h)}return h.text(b.val()),h.width()}function D(b,c,d){var e,g,f=[];e=b.attr("class"),e&&(e=""+e,a(e.split(" ")).each2(function(){0===this.indexOf("select2-")&&f.push(this)})),e=c.attr("class"),e&&(e=""+e,a(e.split(" ")).each2(function(){0!==this.indexOf("select2-")&&(g=d(this),g&&f.push(g))})),b.attr("class",f.join(" "))}function E(a,b,c,d){var e=o(a.toUpperCase()).indexOf(o(b.toUpperCase())),f=b.length;return 0>e?(c.push(d(a)),void 0):(c.push(d(a.substring(0,e))),c.push(""),c.push(d(a.substring(e,e+f))),c.push(""),c.push(d(a.substring(e+f,a.length))),void 0)}function F(a){var b={"\\":"\","&":"&","<":"<",">":">",'"':""","'":"'","/":"/"};return String(a).replace(/[&<>"'\/\\]/g,function(a){return b[a]})}function G(c){var d,e=null,f=c.quietMillis||100,g=c.url,h=this;return function(i){window.clearTimeout(d),d=window.setTimeout(function(){var d=c.data,f=g,j=c.transport||a.fn.select2.ajaxDefaults.transport,k={type:c.type||"GET",cache:c.cache||!1,jsonpCallback:c.jsonpCallback||b,dataType:c.dataType||"json"},l=a.extend({},a.fn.select2.ajaxDefaults.params,k);d=d?d.call(h,i.term,i.page,i.context):null,f="function"==typeof f?f.call(h,i.term,i.page,i.context):f,e&&"function"==typeof e.abort&&e.abort(),c.params&&(a.isFunction(c.params)?a.extend(l,c.params.call(h)):a.extend(l,c.params)),a.extend(l,{url:f,dataType:c.dataType,data:d,success:function(a){var b=c.results(a,i.page);i.callback(b)}}),e=j.call(h,l)},f)}}function H(b){var d,e,c=b,f=function(a){return""+a.text};a.isArray(c)&&(e=c,c={results:e}),a.isFunction(c)===!1&&(e=c,c=function(){return e});var g=c();return g.text&&(f=g.text,a.isFunction(f)||(d=g.text,f=function(a){return a[d]})),function(b){var g,d=b.term,e={results:[]};return""===d?(b.callback(c()),void 0):(g=function(c,e){var h,i;if(c=c[0],c.children){h={};for(i in c)c.hasOwnProperty(i)&&(h[i]=c[i]);h.children=[],a(c.children).each2(function(a,b){g(b,h.children)}),(h.children.length||b.matcher(d,f(h),c))&&e.push(h)}else b.matcher(d,f(c),c)&&e.push(c)},a(c().results).each2(function(a,b){g(b,e.results)}),b.callback(e),void 0)}}function I(c){var d=a.isFunction(c);return function(e){var f=e.term,g={results:[]},h=d?c(e):c;a.isArray(h)&&(a(h).each(function(){var a=this.text!==b,c=a?this.text:this;(""===f||e.matcher(f,c))&&g.results.push(a?this:{id:this,text:this})}),e.callback(g))}}function J(b,c){if(a.isFunction(b))return!0;if(!b)return!1;if("string"==typeof b)return!0;throw new Error(c+" must be a string, function, or falsy value")}function K(b){if(a.isFunction(b)){var c=Array.prototype.slice.call(arguments,1);return b.apply(null,c)}return b}function L(b){var c=0;return a.each(b,function(a,b){b.children?c+=L(b.children):c++}),c}function M(a,c,d,e){var h,i,j,k,l,f=a,g=!1;if(!e.createSearchChoice||!e.tokenSeparators||e.tokenSeparators.length<1)return b;for(;;){for(i=-1,j=0,k=e.tokenSeparators.length;k>j&&(l=e.tokenSeparators[j],i=a.indexOf(l),!(i>=0));j++);if(0>i)break;if(h=a.substring(0,i),a=a.substring(i+l.length),h.length>0&&(h=e.createSearchChoice.call(this,h,c),h!==b&&null!==h&&e.id(h)!==b&&null!==e.id(h))){for(g=!1,j=0,k=c.length;k>j;j++)if(r(e.id(h),e.id(c[j]))){g=!0;break}g||d(h)}}return f!==a?a:void 0}function N(){var a=this;Array.prototype.forEach.call(arguments,function(b){a[b].remove(),a[b]=null})}function O(b,c){var d=function(){};return d.prototype=new b,d.prototype.constructor=d,d.prototype.parent=b.prototype,d.prototype=a.extend(d.prototype,c),d}if(window.Select2===b){var c,d,e,f,g,h,j,k,i={x:0,y:0},c={TAB:9,ENTER:13,ESC:27,SPACE:32,LEFT:37,UP:38,RIGHT:39,DOWN:40,SHIFT:16,CTRL:17,ALT:18,PAGE_UP:33,PAGE_DOWN:34,HOME:36,END:35,BACKSPACE:8,DELETE:46,isArrow:function(a){switch(a=a.which?a.which:a){case c.LEFT:case c.RIGHT:case c.UP:case c.DOWN:return!0}return!1},isControl:function(a){var b=a.which;switch(b){case c.SHIFT:case c.CTRL:case c.ALT:return!0}return a.metaKey?!0:!1},isFunctionKey:function(a){return a=a.which?a.which:a,a>=112&&123>=a}},l="
    ",m={"\u24b6":"A","\uff21":"A","\xc0":"A","\xc1":"A","\xc2":"A","\u1ea6":"A","\u1ea4":"A","\u1eaa":"A","\u1ea8":"A","\xc3":"A","\u0100":"A","\u0102":"A","\u1eb0":"A","\u1eae":"A","\u1eb4":"A","\u1eb2":"A","\u0226":"A","\u01e0":"A","\xc4":"A","\u01de":"A","\u1ea2":"A","\xc5":"A","\u01fa":"A","\u01cd":"A","\u0200":"A","\u0202":"A","\u1ea0":"A","\u1eac":"A","\u1eb6":"A","\u1e00":"A","\u0104":"A","\u023a":"A","\u2c6f":"A","\ua732":"AA","\xc6":"AE","\u01fc":"AE","\u01e2":"AE","\ua734":"AO","\ua736":"AU","\ua738":"AV","\ua73a":"AV","\ua73c":"AY","\u24b7":"B","\uff22":"B","\u1e02":"B","\u1e04":"B","\u1e06":"B","\u0243":"B","\u0182":"B","\u0181":"B","\u24b8":"C","\uff23":"C","\u0106":"C","\u0108":"C","\u010a":"C","\u010c":"C","\xc7":"C","\u1e08":"C","\u0187":"C","\u023b":"C","\ua73e":"C","\u24b9":"D","\uff24":"D","\u1e0a":"D","\u010e":"D","\u1e0c":"D","\u1e10":"D","\u1e12":"D","\u1e0e":"D","\u0110":"D","\u018b":"D","\u018a":"D","\u0189":"D","\ua779":"D","\u01f1":"DZ","\u01c4":"DZ","\u01f2":"Dz","\u01c5":"Dz","\u24ba":"E","\uff25":"E","\xc8":"E","\xc9":"E","\xca":"E","\u1ec0":"E","\u1ebe":"E","\u1ec4":"E","\u1ec2":"E","\u1ebc":"E","\u0112":"E","\u1e14":"E","\u1e16":"E","\u0114":"E","\u0116":"E","\xcb":"E","\u1eba":"E","\u011a":"E","\u0204":"E","\u0206":"E","\u1eb8":"E","\u1ec6":"E","\u0228":"E","\u1e1c":"E","\u0118":"E","\u1e18":"E","\u1e1a":"E","\u0190":"E","\u018e":"E","\u24bb":"F","\uff26":"F","\u1e1e":"F","\u0191":"F","\ua77b":"F","\u24bc":"G","\uff27":"G","\u01f4":"G","\u011c":"G","\u1e20":"G","\u011e":"G","\u0120":"G","\u01e6":"G","\u0122":"G","\u01e4":"G","\u0193":"G","\ua7a0":"G","\ua77d":"G","\ua77e":"G","\u24bd":"H","\uff28":"H","\u0124":"H","\u1e22":"H","\u1e26":"H","\u021e":"H","\u1e24":"H","\u1e28":"H","\u1e2a":"H","\u0126":"H","\u2c67":"H","\u2c75":"H","\ua78d":"H","\u24be":"I","\uff29":"I","\xcc":"I","\xcd":"I","\xce":"I","\u0128":"I","\u012a":"I","\u012c":"I","\u0130":"I","\xcf":"I","\u1e2e":"I","\u1ec8":"I","\u01cf":"I","\u0208":"I","\u020a":"I","\u1eca":"I","\u012e":"I","\u1e2c":"I","\u0197":"I","\u24bf":"J","\uff2a":"J","\u0134":"J","\u0248":"J","\u24c0":"K","\uff2b":"K","\u1e30":"K","\u01e8":"K","\u1e32":"K","\u0136":"K","\u1e34":"K","\u0198":"K","\u2c69":"K","\ua740":"K","\ua742":"K","\ua744":"K","\ua7a2":"K","\u24c1":"L","\uff2c":"L","\u013f":"L","\u0139":"L","\u013d":"L","\u1e36":"L","\u1e38":"L","\u013b":"L","\u1e3c":"L","\u1e3a":"L","\u0141":"L","\u023d":"L","\u2c62":"L","\u2c60":"L","\ua748":"L","\ua746":"L","\ua780":"L","\u01c7":"LJ","\u01c8":"Lj","\u24c2":"M","\uff2d":"M","\u1e3e":"M","\u1e40":"M","\u1e42":"M","\u2c6e":"M","\u019c":"M","\u24c3":"N","\uff2e":"N","\u01f8":"N","\u0143":"N","\xd1":"N","\u1e44":"N","\u0147":"N","\u1e46":"N","\u0145":"N","\u1e4a":"N","\u1e48":"N","\u0220":"N","\u019d":"N","\ua790":"N","\ua7a4":"N","\u01ca":"NJ","\u01cb":"Nj","\u24c4":"O","\uff2f":"O","\xd2":"O","\xd3":"O","\xd4":"O","\u1ed2":"O","\u1ed0":"O","\u1ed6":"O","\u1ed4":"O","\xd5":"O","\u1e4c":"O","\u022c":"O","\u1e4e":"O","\u014c":"O","\u1e50":"O","\u1e52":"O","\u014e":"O","\u022e":"O","\u0230":"O","\xd6":"O","\u022a":"O","\u1ece":"O","\u0150":"O","\u01d1":"O","\u020c":"O","\u020e":"O","\u01a0":"O","\u1edc":"O","\u1eda":"O","\u1ee0":"O","\u1ede":"O","\u1ee2":"O","\u1ecc":"O","\u1ed8":"O","\u01ea":"O","\u01ec":"O","\xd8":"O","\u01fe":"O","\u0186":"O","\u019f":"O","\ua74a":"O","\ua74c":"O","\u01a2":"OI","\ua74e":"OO","\u0222":"OU","\u24c5":"P","\uff30":"P","\u1e54":"P","\u1e56":"P","\u01a4":"P","\u2c63":"P","\ua750":"P","\ua752":"P","\ua754":"P","\u24c6":"Q","\uff31":"Q","\ua756":"Q","\ua758":"Q","\u024a":"Q","\u24c7":"R","\uff32":"R","\u0154":"R","\u1e58":"R","\u0158":"R","\u0210":"R","\u0212":"R","\u1e5a":"R","\u1e5c":"R","\u0156":"R","\u1e5e":"R","\u024c":"R","\u2c64":"R","\ua75a":"R","\ua7a6":"R","\ua782":"R","\u24c8":"S","\uff33":"S","\u1e9e":"S","\u015a":"S","\u1e64":"S","\u015c":"S","\u1e60":"S","\u0160":"S","\u1e66":"S","\u1e62":"S","\u1e68":"S","\u0218":"S","\u015e":"S","\u2c7e":"S","\ua7a8":"S","\ua784":"S","\u24c9":"T","\uff34":"T","\u1e6a":"T","\u0164":"T","\u1e6c":"T","\u021a":"T","\u0162":"T","\u1e70":"T","\u1e6e":"T","\u0166":"T","\u01ac":"T","\u01ae":"T","\u023e":"T","\ua786":"T","\ua728":"TZ","\u24ca":"U","\uff35":"U","\xd9":"U","\xda":"U","\xdb":"U","\u0168":"U","\u1e78":"U","\u016a":"U","\u1e7a":"U","\u016c":"U","\xdc":"U","\u01db":"U","\u01d7":"U","\u01d5":"U","\u01d9":"U","\u1ee6":"U","\u016e":"U","\u0170":"U","\u01d3":"U","\u0214":"U","\u0216":"U","\u01af":"U","\u1eea":"U","\u1ee8":"U","\u1eee":"U","\u1eec":"U","\u1ef0":"U","\u1ee4":"U","\u1e72":"U","\u0172":"U","\u1e76":"U","\u1e74":"U","\u0244":"U","\u24cb":"V","\uff36":"V","\u1e7c":"V","\u1e7e":"V","\u01b2":"V","\ua75e":"V","\u0245":"V","\ua760":"VY","\u24cc":"W","\uff37":"W","\u1e80":"W","\u1e82":"W","\u0174":"W","\u1e86":"W","\u1e84":"W","\u1e88":"W","\u2c72":"W","\u24cd":"X","\uff38":"X","\u1e8a":"X","\u1e8c":"X","\u24ce":"Y","\uff39":"Y","\u1ef2":"Y","\xdd":"Y","\u0176":"Y","\u1ef8":"Y","\u0232":"Y","\u1e8e":"Y","\u0178":"Y","\u1ef6":"Y","\u1ef4":"Y","\u01b3":"Y","\u024e":"Y","\u1efe":"Y","\u24cf":"Z","\uff3a":"Z","\u0179":"Z","\u1e90":"Z","\u017b":"Z","\u017d":"Z","\u1e92":"Z","\u1e94":"Z","\u01b5":"Z","\u0224":"Z","\u2c7f":"Z","\u2c6b":"Z","\ua762":"Z","\u24d0":"a","\uff41":"a","\u1e9a":"a","\xe0":"a","\xe1":"a","\xe2":"a","\u1ea7":"a","\u1ea5":"a","\u1eab":"a","\u1ea9":"a","\xe3":"a","\u0101":"a","\u0103":"a","\u1eb1":"a","\u1eaf":"a","\u1eb5":"a","\u1eb3":"a","\u0227":"a","\u01e1":"a","\xe4":"a","\u01df":"a","\u1ea3":"a","\xe5":"a","\u01fb":"a","\u01ce":"a","\u0201":"a","\u0203":"a","\u1ea1":"a","\u1ead":"a","\u1eb7":"a","\u1e01":"a","\u0105":"a","\u2c65":"a","\u0250":"a","\ua733":"aa","\xe6":"ae","\u01fd":"ae","\u01e3":"ae","\ua735":"ao","\ua737":"au","\ua739":"av","\ua73b":"av","\ua73d":"ay","\u24d1":"b","\uff42":"b","\u1e03":"b","\u1e05":"b","\u1e07":"b","\u0180":"b","\u0183":"b","\u0253":"b","\u24d2":"c","\uff43":"c","\u0107":"c","\u0109":"c","\u010b":"c","\u010d":"c","\xe7":"c","\u1e09":"c","\u0188":"c","\u023c":"c","\ua73f":"c","\u2184":"c","\u24d3":"d","\uff44":"d","\u1e0b":"d","\u010f":"d","\u1e0d":"d","\u1e11":"d","\u1e13":"d","\u1e0f":"d","\u0111":"d","\u018c":"d","\u0256":"d","\u0257":"d","\ua77a":"d","\u01f3":"dz","\u01c6":"dz","\u24d4":"e","\uff45":"e","\xe8":"e","\xe9":"e","\xea":"e","\u1ec1":"e","\u1ebf":"e","\u1ec5":"e","\u1ec3":"e","\u1ebd":"e","\u0113":"e","\u1e15":"e","\u1e17":"e","\u0115":"e","\u0117":"e","\xeb":"e","\u1ebb":"e","\u011b":"e","\u0205":"e","\u0207":"e","\u1eb9":"e","\u1ec7":"e","\u0229":"e","\u1e1d":"e","\u0119":"e","\u1e19":"e","\u1e1b":"e","\u0247":"e","\u025b":"e","\u01dd":"e","\u24d5":"f","\uff46":"f","\u1e1f":"f","\u0192":"f","\ua77c":"f","\u24d6":"g","\uff47":"g","\u01f5":"g","\u011d":"g","\u1e21":"g","\u011f":"g","\u0121":"g","\u01e7":"g","\u0123":"g","\u01e5":"g","\u0260":"g","\ua7a1":"g","\u1d79":"g","\ua77f":"g","\u24d7":"h","\uff48":"h","\u0125":"h","\u1e23":"h","\u1e27":"h","\u021f":"h","\u1e25":"h","\u1e29":"h","\u1e2b":"h","\u1e96":"h","\u0127":"h","\u2c68":"h","\u2c76":"h","\u0265":"h","\u0195":"hv","\u24d8":"i","\uff49":"i","\xec":"i","\xed":"i","\xee":"i","\u0129":"i","\u012b":"i","\u012d":"i","\xef":"i","\u1e2f":"i","\u1ec9":"i","\u01d0":"i","\u0209":"i","\u020b":"i","\u1ecb":"i","\u012f":"i","\u1e2d":"i","\u0268":"i","\u0131":"i","\u24d9":"j","\uff4a":"j","\u0135":"j","\u01f0":"j","\u0249":"j","\u24da":"k","\uff4b":"k","\u1e31":"k","\u01e9":"k","\u1e33":"k","\u0137":"k","\u1e35":"k","\u0199":"k","\u2c6a":"k","\ua741":"k","\ua743":"k","\ua745":"k","\ua7a3":"k","\u24db":"l","\uff4c":"l","\u0140":"l","\u013a":"l","\u013e":"l","\u1e37":"l","\u1e39":"l","\u013c":"l","\u1e3d":"l","\u1e3b":"l","\u017f":"l","\u0142":"l","\u019a":"l","\u026b":"l","\u2c61":"l","\ua749":"l","\ua781":"l","\ua747":"l","\u01c9":"lj","\u24dc":"m","\uff4d":"m","\u1e3f":"m","\u1e41":"m","\u1e43":"m","\u0271":"m","\u026f":"m","\u24dd":"n","\uff4e":"n","\u01f9":"n","\u0144":"n","\xf1":"n","\u1e45":"n","\u0148":"n","\u1e47":"n","\u0146":"n","\u1e4b":"n","\u1e49":"n","\u019e":"n","\u0272":"n","\u0149":"n","\ua791":"n","\ua7a5":"n","\u01cc":"nj","\u24de":"o","\uff4f":"o","\xf2":"o","\xf3":"o","\xf4":"o","\u1ed3":"o","\u1ed1":"o","\u1ed7":"o","\u1ed5":"o","\xf5":"o","\u1e4d":"o","\u022d":"o","\u1e4f":"o","\u014d":"o","\u1e51":"o","\u1e53":"o","\u014f":"o","\u022f":"o","\u0231":"o","\xf6":"o","\u022b":"o","\u1ecf":"o","\u0151":"o","\u01d2":"o","\u020d":"o","\u020f":"o","\u01a1":"o","\u1edd":"o","\u1edb":"o","\u1ee1":"o","\u1edf":"o","\u1ee3":"o","\u1ecd":"o","\u1ed9":"o","\u01eb":"o","\u01ed":"o","\xf8":"o","\u01ff":"o","\u0254":"o","\ua74b":"o","\ua74d":"o","\u0275":"o","\u01a3":"oi","\u0223":"ou","\ua74f":"oo","\u24df":"p","\uff50":"p","\u1e55":"p","\u1e57":"p","\u01a5":"p","\u1d7d":"p","\ua751":"p","\ua753":"p","\ua755":"p","\u24e0":"q","\uff51":"q","\u024b":"q","\ua757":"q","\ua759":"q","\u24e1":"r","\uff52":"r","\u0155":"r","\u1e59":"r","\u0159":"r","\u0211":"r","\u0213":"r","\u1e5b":"r","\u1e5d":"r","\u0157":"r","\u1e5f":"r","\u024d":"r","\u027d":"r","\ua75b":"r","\ua7a7":"r","\ua783":"r","\u24e2":"s","\uff53":"s","\xdf":"s","\u015b":"s","\u1e65":"s","\u015d":"s","\u1e61":"s","\u0161":"s","\u1e67":"s","\u1e63":"s","\u1e69":"s","\u0219":"s","\u015f":"s","\u023f":"s","\ua7a9":"s","\ua785":"s","\u1e9b":"s","\u24e3":"t","\uff54":"t","\u1e6b":"t","\u1e97":"t","\u0165":"t","\u1e6d":"t","\u021b":"t","\u0163":"t","\u1e71":"t","\u1e6f":"t","\u0167":"t","\u01ad":"t","\u0288":"t","\u2c66":"t","\ua787":"t","\ua729":"tz","\u24e4":"u","\uff55":"u","\xf9":"u","\xfa":"u","\xfb":"u","\u0169":"u","\u1e79":"u","\u016b":"u","\u1e7b":"u","\u016d":"u","\xfc":"u","\u01dc":"u","\u01d8":"u","\u01d6":"u","\u01da":"u","\u1ee7":"u","\u016f":"u","\u0171":"u","\u01d4":"u","\u0215":"u","\u0217":"u","\u01b0":"u","\u1eeb":"u","\u1ee9":"u","\u1eef":"u","\u1eed":"u","\u1ef1":"u","\u1ee5":"u","\u1e73":"u","\u0173":"u","\u1e77":"u","\u1e75":"u","\u0289":"u","\u24e5":"v","\uff56":"v","\u1e7d":"v","\u1e7f":"v","\u028b":"v","\ua75f":"v","\u028c":"v","\ua761":"vy","\u24e6":"w","\uff57":"w","\u1e81":"w","\u1e83":"w","\u0175":"w","\u1e87":"w","\u1e85":"w","\u1e98":"w","\u1e89":"w","\u2c73":"w","\u24e7":"x","\uff58":"x","\u1e8b":"x","\u1e8d":"x","\u24e8":"y","\uff59":"y","\u1ef3":"y","\xfd":"y","\u0177":"y","\u1ef9":"y","\u0233":"y","\u1e8f":"y","\xff":"y","\u1ef7":"y","\u1e99":"y","\u1ef5":"y","\u01b4":"y","\u024f":"y","\u1eff":"y","\u24e9":"z","\uff5a":"z","\u017a":"z","\u1e91":"z","\u017c":"z","\u017e":"z","\u1e93":"z","\u1e95":"z","\u01b6":"z","\u0225":"z","\u0240":"z","\u2c6c":"z","\ua763":"z"};j=a(document),g=function(){var a=1;return function(){return a++}}(),j.on("mousemove",function(a){i.x=a.pageX,i.y=a.pageY}),d=O(Object,{bind:function(a){var b=this;return function(){a.apply(b,arguments)}},init:function(c){var d,e,f=".select2-results";this.opts=c=this.prepareOpts(c),this.id=c.id,c.element.data("select2")!==b&&null!==c.element.data("select2")&&c.element.data("select2").destroy(),this.container=this.createContainer(),this.liveRegion=a("",{role:"status","aria-live":"polite"}).addClass("select2-hidden-accessible").appendTo(document.body),this.containerId="s2id_"+(c.element.attr("id")||"autogen"+g()),this.containerEventName=this.containerId.replace(/([.])/g,"_").replace(/([;&,\-\.\+\*\~':"\!\^#$%@\[\]\(\)=>\|])/g,"\\$1"),this.container.attr("id",this.containerId),this.container.attr("title",c.element.attr("title")),this.body=a("body"),D(this.container,this.opts.element,this.opts.adaptContainerCssClass),this.container.attr("style",c.element.attr("style")),this.container.css(K(c.containerCss)),this.container.addClass(K(c.containerCssClass)),this.elementTabIndex=this.opts.element.attr("tabindex"),this.opts.element.data("select2",this).attr("tabindex","-1").before(this.container).on("click.select2",A),this.container.data("select2",this),this.dropdown=this.container.find(".select2-drop"),D(this.dropdown,this.opts.element,this.opts.adaptDropdownCssClass),this.dropdown.addClass(K(c.dropdownCssClass)),this.dropdown.data("select2",this),this.dropdown.on("click",A),this.results=d=this.container.find(f),this.search=e=this.container.find("input.select2-input"),this.queryCount=0,this.resultsPage=0,this.context=null,this.initContainer(),this.container.on("click",A),v(this.results),this.dropdown.on("mousemove-filtered",f,this.bind(this.highlightUnderEvent)),this.dropdown.on("touchstart touchmove touchend",f,this.bind(function(a){this._touchEvent=!0,this.highlightUnderEvent(a)})),this.dropdown.on("touchmove",f,this.bind(this.touchMoved)),this.dropdown.on("touchstart touchend",f,this.bind(this.clearTouchMoved)),this.dropdown.on("click",this.bind(function(){this._touchEvent&&(this._touchEvent=!1,this.selectHighlighted())})),x(80,this.results),this.dropdown.on("scroll-debounced",f,this.bind(this.loadMoreIfNeeded)),a(this.container).on("change",".select2-input",function(a){a.stopPropagation()}),a(this.dropdown).on("change",".select2-input",function(a){a.stopPropagation()}),a.fn.mousewheel&&d.mousewheel(function(a,b,c,e){var f=d.scrollTop();e>0&&0>=f-e?(d.scrollTop(0),A(a)):0>e&&d.get(0).scrollHeight-d.scrollTop()+e<=d.height()&&(d.scrollTop(d.get(0).scrollHeight-d.height()),A(a))}),u(e),e.on("keyup-change input paste",this.bind(this.updateResults)),e.on("focus",function(){e.addClass("select2-focused")}),e.on("blur",function(){e.removeClass("select2-focused")}),this.dropdown.on("mouseup",f,this.bind(function(b){a(b.target).closest(".select2-result-selectable").length>0&&(this.highlightUnderEvent(b),this.selectHighlighted(b))})),this.dropdown.on("click mouseup mousedown touchstart touchend focusin",function(a){a.stopPropagation()}),this.nextSearchTerm=b,a.isFunction(this.opts.initSelection)&&(this.initSelection(),this.monitorSource()),null!==c.maximumInputLength&&this.search.attr("maxlength",c.maximumInputLength);var h=c.element.prop("disabled");h===b&&(h=!1),this.enable(!h);var i=c.element.prop("readonly");i===b&&(i=!1),this.readonly(i),k=k||q(),this.autofocus=c.element.prop("autofocus"),c.element.prop("autofocus",!1),this.autofocus&&this.focus(),this.search.attr("placeholder",c.searchInputPlaceholder)},destroy:function(){var a=this.opts.element,c=a.data("select2");this.close(),this.propertyObserver&&(this.propertyObserver.disconnect(),this.propertyObserver=null),c!==b&&(c.container.remove(),c.liveRegion.remove(),c.dropdown.remove(),a.removeClass("select2-offscreen").removeData("select2").off(".select2").prop("autofocus",this.autofocus||!1),this.elementTabIndex?a.attr({tabindex:this.elementTabIndex}):a.removeAttr("tabindex"),a.show()),N.call(this,"container","liveRegion","dropdown","results","search")},optionToData:function(a){return a.is("option")?{id:a.prop("value"),text:a.text(),element:a.get(),css:a.attr("class"),disabled:a.prop("disabled"),locked:r(a.attr("locked"),"locked")||r(a.data("locked"),!0)}:a.is("optgroup")?{text:a.attr("label"),children:[],element:a.get(),css:a.attr("class")}:void 0},prepareOpts:function(c){var d,e,f,h,i=this;if(d=c.element,"select"===d.get(0).tagName.toLowerCase()&&(this.select=e=c.element),e&&a.each(["id","multiple","ajax","query","createSearchChoice","initSelection","data","tags"],function(){if(this in c)throw new Error("Option '"+this+"' is not allowed for Select2 when attached to a ","
    "," ","
      ","
    ","
    "].join(""));return b},enableInterface:function(){this.parent.enableInterface.apply(this,arguments)&&this.focusser.prop("disabled",!this.isInterfaceEnabled())},opening:function(){var c,d,e;this.opts.minimumResultsForSearch>=0&&this.showSearch(!0),this.parent.opening.apply(this,arguments),this.showSearchInput!==!1&&this.search.val(this.focusser.val()),this.opts.shouldFocusInput(this)&&(this.search.focus(),c=this.search.get(0),c.createTextRange?(d=c.createTextRange(),d.collapse(!1),d.select()):c.setSelectionRange&&(e=this.search.val().length,c.setSelectionRange(e,e))),""===this.search.val()&&this.nextSearchTerm!=b&&(this.search.val(this.nextSearchTerm),this.search.select()),this.focusser.prop("disabled",!0).val(""),this.updateResults(!0),this.opts.element.trigger(a.Event("select2-open"))},close:function(){this.opened()&&(this.parent.close.apply(this,arguments),this.focusser.prop("disabled",!1),this.opts.shouldFocusInput(this)&&this.focusser.focus())},focus:function(){this.opened()?this.close():(this.focusser.prop("disabled",!1),this.opts.shouldFocusInput(this)&&this.focusser.focus())},isFocused:function(){return this.container.hasClass("select2-container-active")},cancel:function(){this.parent.cancel.apply(this,arguments),this.focusser.prop("disabled",!1),this.opts.shouldFocusInput(this)&&this.focusser.focus()},destroy:function(){a("label[for='"+this.focusser.attr("id")+"']").attr("for",this.opts.element.attr("id")),this.parent.destroy.apply(this,arguments),N.call(this,"selection","focusser")},initContainer:function(){var b,h,d=this.container,e=this.dropdown,f=g();this.opts.minimumResultsForSearch<0?this.showSearch(!1):this.showSearch(!0),this.selection=b=d.find(".select2-choice"),this.focusser=d.find(".select2-focusser"),b.find(".select2-chosen").attr("id","select2-chosen-"+f),this.focusser.attr("aria-labelledby","select2-chosen-"+f),this.results.attr("id","select2-results-"+f),this.search.attr("aria-owns","select2-results-"+f),this.focusser.attr("id","s2id_autogen"+f),h=a("label[for='"+this.opts.element.attr("id")+"']"),this.focusser.prev().text(h.text()).attr("for",this.focusser.attr("id"));var i=this.opts.element.attr("title");this.opts.element.attr("title",i||h.text()),this.focusser.attr("tabindex",this.elementTabIndex),this.search.attr("id",this.focusser.attr("id")+"_search"),this.search.prev().text(a("label[for='"+this.focusser.attr("id")+"']").text()).attr("for",this.search.attr("id")),this.search.on("keydown",this.bind(function(a){if(this.isInterfaceEnabled()){if(a.which===c.PAGE_UP||a.which===c.PAGE_DOWN)return A(a),void 0;switch(a.which){case c.UP:case c.DOWN:return this.moveHighlight(a.which===c.UP?-1:1),A(a),void 0;case c.ENTER:return this.selectHighlighted(),A(a),void 0;case c.TAB:return this.selectHighlighted({noFocus:!0}),void 0;case c.ESC:return this.cancel(a),A(a),void 0}}})),this.search.on("blur",this.bind(function(){document.activeElement===this.body.get(0)&&window.setTimeout(this.bind(function(){this.opened()&&this.search.focus()}),0)})),this.focusser.on("keydown",this.bind(function(a){if(this.isInterfaceEnabled()&&a.which!==c.TAB&&!c.isControl(a)&&!c.isFunctionKey(a)&&a.which!==c.ESC){if(this.opts.openOnEnter===!1&&a.which===c.ENTER)return A(a),void 0;if(a.which==c.DOWN||a.which==c.UP||a.which==c.ENTER&&this.opts.openOnEnter){if(a.altKey||a.ctrlKey||a.shiftKey||a.metaKey)return;return this.open(),A(a),void 0}return a.which==c.DELETE||a.which==c.BACKSPACE?(this.opts.allowClear&&this.clear(),A(a),void 0):void 0}})),u(this.focusser),this.focusser.on("keyup-change input",this.bind(function(a){if(this.opts.minimumResultsForSearch>=0){if(a.stopPropagation(),this.opened())return;this.open()}})),b.on("mousedown touchstart","abbr",this.bind(function(a){this.isInterfaceEnabled()&&(this.clear(),B(a),this.close(),this.selection.focus())})),b.on("mousedown touchstart",this.bind(function(c){n(b),this.container.hasClass("select2-container-active")||this.opts.element.trigger(a.Event("select2-focus")),this.opened()?this.close():this.isInterfaceEnabled()&&this.open(),A(c)})),e.on("mousedown touchstart",this.bind(function(){this.opts.shouldFocusInput(this)&&this.search.focus()})),b.on("focus",this.bind(function(a){A(a)})),this.focusser.on("focus",this.bind(function(){this.container.hasClass("select2-container-active")||this.opts.element.trigger(a.Event("select2-focus")),this.container.addClass("select2-container-active")})).on("blur",this.bind(function(){this.opened()||(this.container.removeClass("select2-container-active"),this.opts.element.trigger(a.Event("select2-blur")))})),this.search.on("focus",this.bind(function(){this.container.hasClass("select2-container-active")||this.opts.element.trigger(a.Event("select2-focus")),this.container.addClass("select2-container-active")})),this.initContainerWidth(),this.opts.element.addClass("select2-offscreen"),this.setPlaceholder()},clear:function(b){var c=this.selection.data("select2-data");if(c){var d=a.Event("select2-clearing");if(this.opts.element.trigger(d),d.isDefaultPrevented())return;var e=this.getPlaceholderOption();this.opts.element.val(e?e.val():""),this.selection.find(".select2-chosen").empty(),this.selection.removeData("select2-data"),this.setPlaceholder(),b!==!1&&(this.opts.element.trigger({type:"select2-removed",val:this.id(c),choice:c}),this.triggerChange({removed:c}))}},initSelection:function(){if(this.isPlaceholderOptionSelected())this.updateSelection(null),this.close(),this.setPlaceholder();else{var c=this;this.opts.initSelection.call(null,this.opts.element,function(a){a!==b&&null!==a&&(c.updateSelection(a),c.close(),c.setPlaceholder(),c.nextSearchTerm=c.opts.nextSearchTerm(a,c.search.val()))})}},isPlaceholderOptionSelected:function(){var a;return this.getPlaceholder()===b?!1:(a=this.getPlaceholderOption())!==b&&a.prop("selected")||""===this.opts.element.val()||this.opts.element.val()===b||null===this.opts.element.val()},prepareOpts:function(){var b=this.parent.prepareOpts.apply(this,arguments),c=this;return"select"===b.element.get(0).tagName.toLowerCase()?b.initSelection=function(a,b){var d=a.find("option").filter(function(){return this.selected&&!this.disabled});b(c.optionToData(d))}:"data"in b&&(b.initSelection=b.initSelection||function(c,d){var e=c.val(),f=null;b.query({matcher:function(a,c,d){var g=r(e,b.id(d));return g&&(f=d),g},callback:a.isFunction(d)?function(){d(f)}:a.noop})}),b},getPlaceholder:function(){return this.select&&this.getPlaceholderOption()===b?b:this.parent.getPlaceholder.apply(this,arguments)},setPlaceholder:function(){var a=this.getPlaceholder();if(this.isPlaceholderOptionSelected()&&a!==b){if(this.select&&this.getPlaceholderOption()===b)return;this.selection.find(".select2-chosen").html(this.opts.escapeMarkup(a)),this.selection.addClass("select2-default"),this.container.removeClass("select2-allowclear")}},postprocessResults:function(a,b,c){var d=0,e=this;if(this.findHighlightableChoices().each2(function(a,b){return r(e.id(b.data("select2-data")),e.opts.element.val())?(d=a,!1):void 0}),c!==!1&&(b===!0&&d>=0?this.highlight(d):this.highlight(0)),b===!0){var g=this.opts.minimumResultsForSearch;g>=0&&this.showSearch(L(a.results)>=g)}},showSearch:function(b){this.showSearchInput!==b&&(this.showSearchInput=b,this.dropdown.find(".select2-search").toggleClass("select2-search-hidden",!b),this.dropdown.find(".select2-search").toggleClass("select2-offscreen",!b),a(this.dropdown,this.container).toggleClass("select2-with-searchbox",b))},onSelect:function(a,b){if(this.triggerSelect(a)){var c=this.opts.element.val(),d=this.data();this.opts.element.val(this.id(a)),this.updateSelection(a),this.opts.element.trigger({type:"select2-selected",val:this.id(a),choice:a}),this.nextSearchTerm=this.opts.nextSearchTerm(a,this.search.val()),this.close(),b&&b.noFocus||!this.opts.shouldFocusInput(this)||this.focusser.focus(),r(c,this.id(a))||this.triggerChange({added:a,removed:d})}},updateSelection:function(a){var d,e,c=this.selection.find(".select2-chosen");this.selection.data("select2-data",a),c.empty(),null!==a&&(d=this.opts.formatSelection(a,c,this.opts.escapeMarkup)),d!==b&&c.append(d),e=this.opts.formatSelectionCssClass(a,c),e!==b&&c.addClass(e),this.selection.removeClass("select2-default"),this.opts.allowClear&&this.getPlaceholder()!==b&&this.container.addClass("select2-allowclear")},val:function(){var a,c=!1,d=null,e=this,f=this.data();if(0===arguments.length)return this.opts.element.val();if(a=arguments[0],arguments.length>1&&(c=arguments[1]),this.select)this.select.val(a).find("option").filter(function(){return this.selected}).each2(function(a,b){return d=e.optionToData(b),!1}),this.updateSelection(d),this.setPlaceholder(),c&&this.triggerChange({added:d,removed:f});else{if(!a&&0!==a)return this.clear(c),void 0;if(this.opts.initSelection===b)throw new Error("cannot call val() if initSelection() is not defined");this.opts.element.val(a),this.opts.initSelection(this.opts.element,function(a){e.opts.element.val(a?e.id(a):""),e.updateSelection(a),e.setPlaceholder(),c&&e.triggerChange({added:a,removed:f})})}},clearSearch:function(){this.search.val(""),this.focusser.val("")},data:function(a){var c,d=!1;return 0===arguments.length?(c=this.selection.data("select2-data"),c==b&&(c=null),c):(arguments.length>1&&(d=arguments[1]),a?(c=this.data(),this.opts.element.val(a?this.id(a):""),this.updateSelection(a),d&&this.triggerChange({added:a,removed:c})):this.clear(d),void 0)}}),f=O(d,{createContainer:function(){var b=a(document.createElement("div")).attr({"class":"select2-container select2-container-multi"}).html(["
      ","
    • "," "," ","
    • ","
    ","
    ","
      ","
    ","
    "].join(""));return b},prepareOpts:function(){var b=this.parent.prepareOpts.apply(this,arguments),c=this;return"select"===b.element.get(0).tagName.toLowerCase()?b.initSelection=function(a,b){var d=[];a.find("option").filter(function(){return this.selected&&!this.disabled}).each2(function(a,b){d.push(c.optionToData(b))}),b(d)}:"data"in b&&(b.initSelection=b.initSelection||function(c,d){var e=s(c.val(),b.separator),f=[];b.query({matcher:function(c,d,g){var h=a.grep(e,function(a){return r(a,b.id(g))}).length;return h&&f.push(g),h},callback:a.isFunction(d)?function(){for(var a=[],c=0;c0||(this.selectChoice(null),this.clearPlaceholder(),this.container.hasClass("select2-container-active")||this.opts.element.trigger(a.Event("select2-focus")),this.open(),this.focusSearch(),b.preventDefault()))})),this.container.on("focus",b,this.bind(function(){this.isInterfaceEnabled()&&(this.container.hasClass("select2-container-active")||this.opts.element.trigger(a.Event("select2-focus")),this.container.addClass("select2-container-active"),this.dropdown.addClass("select2-drop-active"),this.clearPlaceholder())})),this.initContainerWidth(),this.opts.element.addClass("select2-offscreen"),this.clearSearch()},enableInterface:function(){this.parent.enableInterface.apply(this,arguments)&&this.search.prop("disabled",!this.isInterfaceEnabled())},initSelection:function(){if(""===this.opts.element.val()&&""===this.opts.element.text()&&(this.updateSelection([]),this.close(),this.clearSearch()),this.select||""!==this.opts.element.val()){var c=this;this.opts.initSelection.call(null,this.opts.element,function(a){a!==b&&null!==a&&(c.updateSelection(a),c.close(),c.clearSearch())})}},clearSearch:function(){var a=this.getPlaceholder(),c=this.getMaxSearchWidth();a!==b&&0===this.getVal().length&&this.search.hasClass("select2-focused")===!1?(this.search.val(a).addClass("select2-default"),this.search.width(c>0?c:this.container.css("width"))):this.search.val("").width(10)},clearPlaceholder:function(){this.search.hasClass("select2-default")&&this.search.val("").removeClass("select2-default")},opening:function(){this.clearPlaceholder(),this.resizeSearch(),this.parent.opening.apply(this,arguments),this.focusSearch(),""===this.search.val()&&this.nextSearchTerm!=b&&(this.search.val(this.nextSearchTerm),this.search.select()),this.updateResults(!0),this.opts.shouldFocusInput(this)&&this.search.focus(),this.opts.element.trigger(a.Event("select2-open"))},close:function(){this.opened()&&this.parent.close.apply(this,arguments)},focus:function(){this.close(),this.search.focus()},isFocused:function(){return this.search.hasClass("select2-focused")},updateSelection:function(b){var c=[],d=[],e=this;a(b).each(function(){p(e.id(this),c)<0&&(c.push(e.id(this)),d.push(this))}),b=d,this.selection.find(".select2-search-choice").remove(),a(b).each(function(){e.addSelectedChoice(this)}),e.postprocessResults()},tokenize:function(){var a=this.search.val();a=this.opts.tokenizer.call(this,a,this.data(),this.bind(this.onSelect),this.opts),null!=a&&a!=b&&(this.search.val(a),a.length>0&&this.open())},onSelect:function(a,c){this.triggerSelect(a)&&(this.addSelectedChoice(a),this.opts.element.trigger({type:"selected",val:this.id(a),choice:a}),this.nextSearchTerm=this.opts.nextSearchTerm(a,this.search.val()),this.clearSearch(),this.updateResults(),(this.select||!this.opts.closeOnSelect)&&this.postprocessResults(a,!1,this.opts.closeOnSelect===!0),this.opts.closeOnSelect?(this.close(),this.search.width(10)):this.countSelectableResults()>0?(this.search.width(10),this.resizeSearch(),this.getMaximumSelectionSize()>0&&this.val().length>=this.getMaximumSelectionSize()?this.updateResults(!0):this.nextSearchTerm!=b&&(this.search.val(this.nextSearchTerm),this.updateResults(),this.search.select()),this.positionDropdown()):(this.close(),this.search.width(10)),this.triggerChange({added:a}),c&&c.noFocus||this.focusSearch())},cancel:function(){this.close(),this.focusSearch()},addSelectedChoice:function(c){var j,k,d=!c.locked,e=a("
  • "),f=a("
  • "),g=d?e:f,h=this.id(c),i=this.getVal();j=this.opts.formatSelection(c,g.find("div"),this.opts.escapeMarkup),j!=b&&g.find("div").replaceWith("
    "+j+"
    "),k=this.opts.formatSelectionCssClass(c,g.find("div")),k!=b&&g.addClass(k),d&&g.find(".select2-search-choice-close").on("mousedown",A).on("click dblclick",this.bind(function(b){this.isInterfaceEnabled()&&(this.unselect(a(b.target)),this.selection.find(".select2-search-choice-focus").removeClass("select2-search-choice-focus"),A(b),this.close(),this.focusSearch())})).on("focus",this.bind(function(){this.isInterfaceEnabled()&&(this.container.addClass("select2-container-active"),this.dropdown.addClass("select2-drop-active"))})),g.data("select2-data",c),g.insertBefore(this.searchContainer),i.push(h),this.setVal(i)},unselect:function(b){var d,e,c=this.getVal();if(b=b.closest(".select2-search-choice"),0===b.length)throw"Invalid argument: "+b+". Must be .select2-search-choice";if(d=b.data("select2-data")){var f=a.Event("select2-removing");if(f.val=this.id(d),f.choice=d,this.opts.element.trigger(f),f.isDefaultPrevented())return!1;for(;(e=p(this.id(d),c))>=0;)c.splice(e,1),this.setVal(c),this.select&&this.postprocessResults();return b.remove(),this.opts.element.trigger({type:"select2-removed",val:this.id(d),choice:d}),this.triggerChange({removed:d}),!0}},postprocessResults:function(a,b,c){var d=this.getVal(),e=this.results.find(".select2-result"),f=this.results.find(".select2-result-with-children"),g=this;e.each2(function(a,b){var c=g.id(b.data("select2-data"));p(c,d)>=0&&(b.addClass("select2-selected"),b.find(".select2-result-selectable").addClass("select2-selected"))}),f.each2(function(a,b){b.is(".select2-result-selectable")||0!==b.find(".select2-result-selectable:not(.select2-selected)").length||b.addClass("select2-selected")}),-1==this.highlight()&&c!==!1&&g.highlight(0),!this.opts.createSearchChoice&&!e.filter(".select2-result:not(.select2-selected)").length>0&&(!a||a&&!a.more&&0===this.results.find(".select2-no-results").length)&&J(g.opts.formatNoMatches,"formatNoMatches")&&this.results.append("
  • "+K(g.opts.formatNoMatches,g.search.val())+"
  • ")},getMaxSearchWidth:function(){return this.selection.width()-t(this.search)},resizeSearch:function(){var a,b,c,d,e,f=t(this.search);a=C(this.search)+10,b=this.search.offset().left,c=this.selection.width(),d=this.selection.offset().left,e=c-(b-d)-f,a>e&&(e=c-f),40>e&&(e=c-f),0>=e&&(e=a),this.search.width(Math.floor(e))},getVal:function(){var a;return this.select?(a=this.select.val(),null===a?[]:a):(a=this.opts.element.val(),s(a,this.opts.separator))},setVal:function(b){var c;this.select?this.select.val(b):(c=[],a(b).each(function(){p(this,c)<0&&c.push(this)}),this.opts.element.val(0===c.length?"":c.join(this.opts.separator)))},buildChangeDetails:function(a,b){for(var b=b.slice(0),a=a.slice(0),c=0;c0&&c--,a.splice(d,1),d--);return{added:b,removed:a}},val:function(c,d){var e,f=this;if(0===arguments.length)return this.getVal();if(e=this.data(),e.length||(e=[]),!c&&0!==c)return this.opts.element.val(""),this.updateSelection([]),this.clearSearch(),d&&this.triggerChange({added:this.data(),removed:e}),void 0;if(this.setVal(c),this.select)this.opts.initSelection(this.select,this.bind(this.updateSelection)),d&&this.triggerChange(this.buildChangeDetails(e,this.data()));else{if(this.opts.initSelection===b)throw new Error("val() cannot be called if initSelection() is not defined");this.opts.initSelection(this.opts.element,function(b){var c=a.map(b,f.id);f.setVal(c),f.updateSelection(b),f.clearSearch(),d&&f.triggerChange(f.buildChangeDetails(e,f.data()))})}this.clearSearch()},onSortStart:function(){if(this.select)throw new Error("Sorting of elements is not supported when attached to instead.");this.search.width(0),this.searchContainer.hide()},onSortEnd:function(){var b=[],c=this;this.searchContainer.show(),this.searchContainer.appendTo(this.searchContainer.parent()),this.resizeSearch(),this.selection.find(".select2-search-choice").each(function(){b.push(c.opts.id(a(this).data("select2-data")))}),this.setVal(b),this.triggerChange()},data:function(b,c){var e,f,d=this;return 0===arguments.length?this.selection.children(".select2-search-choice").map(function(){return a(this).data("select2-data")}).get():(f=this.data(),b||(b=[]),e=a.map(b,function(a){return d.opts.id(a)}),this.setVal(e),this.updateSelection(b),this.clearSearch(),c&&this.triggerChange(this.buildChangeDetails(f,this.data())),void 0)}}),a.fn.select2=function(){var d,e,f,g,h,c=Array.prototype.slice.call(arguments,0),i=["val","destroy","opened","open","close","focus","isFocused","container","dropdown","onSortStart","onSortEnd","enable","disable","readonly","positionDropdown","data","search"],j=["opened","isFocused","container","dropdown"],k=["val","data"],l={search:"externalSearch"};return this.each(function(){if(0===c.length||"object"==typeof c[0])d=0===c.length?{}:a.extend({},c[0]),d.element=a(this),"select"===d.element.get(0).tagName.toLowerCase()?h=d.element.prop("multiple"):(h=d.multiple||!1,"tags"in d&&(d.multiple=h=!0)),e=h?new window.Select2["class"].multi:new window.Select2["class"].single,e.init(d);else{if("string"!=typeof c[0])throw"Invalid arguments to select2 plugin: "+c;if(p(c[0],i)<0)throw"Unknown method: "+c[0];if(g=b,e=a(this).data("select2"),e===b)return;if(f=c[0],"container"===f?g=e.container:"dropdown"===f?g=e.dropdown:(l[f]&&(f=l[f]),g=e[f].apply(e,c.slice(1))),p(c[0],j)>=0||p(c[0],k)>=0&&1==c.length)return!1}}),g===b?this:g},a.fn.select2.defaults={width:"copy",loadMorePadding:0,closeOnSelect:!0,openOnEnter:!0,containerCss:{},dropdownCss:{},containerCssClass:"",dropdownCssClass:"",formatResult:function(a,b,c,d){var e=[];return E(a.text,c.term,e,d),e.join("")},formatSelection:function(a,c,d){return a?d(a.text):b},sortResults:function(a){return a},formatResultCssClass:function(a){return a.css},formatSelectionCssClass:function(){return b},formatMatches:function(a){return a+" results are available, use up and down arrow keys to navigate."},formatNoMatches:function(){return"No matches found"},formatInputTooShort:function(a,b){var c=b-a.length;return"Please enter "+c+" or more character"+(1==c?"":"s")},formatInputTooLong:function(a,b){var c=a.length-b;return"Please delete "+c+" character"+(1==c?"":"s")},formatSelectionTooBig:function(a){return"You can only select "+a+" item"+(1==a?"":"s")},formatLoadMore:function(){return"Loading more results\u2026"},formatSearching:function(){return"Searching\u2026"},minimumResultsForSearch:0,minimumInputLength:0,maximumInputLength:null,maximumSelectionSize:0,id:function(a){return a==b?null:a.id},matcher:function(a,b){return o(""+b).toUpperCase().indexOf(o(""+a).toUpperCase())>=0},separator:",",tokenSeparators:[],tokenizer:M,escapeMarkup:F,blurOnChange:!1,selectOnBlur:!1,adaptContainerCssClass:function(a){return a},adaptDropdownCssClass:function(){return null},nextSearchTerm:function(){return b},searchInputPlaceholder:"",createSearchChoicePosition:"top",shouldFocusInput:function(a){var b="ontouchstart"in window||navigator.msMaxTouchPoints>0;return b?a.opts.minimumResultsForSearch<0?!1:!0:!0}},a.fn.select2.ajaxDefaults={transport:a.ajax,params:{type:"GET",cache:!1,dataType:"json"}},window.Select2={query:{ajax:G,local:H,tags:I},util:{debounce:w,markMatch:E,escapeMarkup:F,stripDiacritics:o},"class":{"abstract":d,single:e,multi:f}}}}(jQuery); \ No newline at end of file diff --git a/ckan/public/base/vendor/select2/select2.png b/ckan/public/base/vendor/select2/select2.png old mode 100755 new mode 100644 diff --git a/ckan/public/base/vendor/select2/select2_locale_ar.js b/ckan/public/base/vendor/select2/select2_locale_ar.js new file mode 100644 index 00000000000..acb33a2f6ad --- /dev/null +++ b/ckan/public/base/vendor/select2/select2_locale_ar.js @@ -0,0 +1,17 @@ +/** + * Select2 Arabic translation. + * + * Author: Adel KEDJOUR + */ +(function ($) { + "use strict"; + + $.extend($.fn.select2.defaults, { + formatNoMatches: function () { return "لم يتم العثور على مطابقات"; }, + formatInputTooShort: function (input, min) { var n = min - input.length; if (n == 1){ return "الرجاء إدخال حرف واحد على الأكثر"; } return n == 2 ? "الرجاء إدخال حرفين على الأكثر" : "الرجاء إدخال " + n + " على الأكثر"; }, + formatInputTooLong: function (input, max) { var n = input.length - max; if (n == 1){ return "الرجاء إدخال حرف واحد على الأقل"; } return n == 2 ? "الرجاء إدخال حرفين على الأقل" : "الرجاء إدخال " + n + " على الأقل "; }, + formatSelectionTooBig: function (limit) { if (n == 1){ return "يمكنك أن تختار إختيار واحد فقط"; } return n == 2 ? "يمكنك أن تختار إختيارين فقط" : "يمكنك أن تختار " + n + " إختيارات فقط"; }, + formatLoadMore: function (pageNumber) { return "تحميل المزيد من النتائج…"; }, + formatSearching: function () { return "البحث…"; } + }); +})(jQuery); diff --git a/ckan/public/base/vendor/select2/select2_locale_bg.js b/ckan/public/base/vendor/select2/select2_locale_bg.js new file mode 100644 index 00000000000..585d28a2b0b --- /dev/null +++ b/ckan/public/base/vendor/select2/select2_locale_bg.js @@ -0,0 +1,18 @@ +/** + * Select2 Bulgarian translation. + * + * @author Lubomir Vikev + * @author Uriy Efremochkin + */ +(function ($) { + "use strict"; + + $.extend($.fn.select2.defaults, { + formatNoMatches: function () { return "Няма намерени съвпадения"; }, + formatInputTooShort: function (input, min) { var n = min - input.length; return "Моля въведете още " + n + " символ" + (n > 1 ? "а" : ""); }, + formatInputTooLong: function (input, max) { var n = input.length - max; return "Моля въведете с " + n + " по-малко символ" + (n > 1 ? "а" : ""); }, + formatSelectionTooBig: function (limit) { return "Можете да направите до " + limit + (limit > 1 ? " избора" : " избор"); }, + formatLoadMore: function (pageNumber) { return "Зареждат се още…"; }, + formatSearching: function () { return "Търсене…"; } + }); +})(jQuery); diff --git a/ckan/public/base/vendor/select2/select2_locale_ca.js b/ckan/public/base/vendor/select2/select2_locale_ca.js new file mode 100644 index 00000000000..7e19d3ce966 --- /dev/null +++ b/ckan/public/base/vendor/select2/select2_locale_ca.js @@ -0,0 +1,17 @@ +/** + * Select2 Catalan translation. + * + * Author: David Planella + */ +(function ($) { + "use strict"; + + $.extend($.fn.select2.defaults, { + formatNoMatches: function () { return "No s'ha trobat cap coincidència"; }, + formatInputTooShort: function (input, min) { var n = min - input.length; return "Introduïu " + n + " caràcter" + (n == 1 ? "" : "s") + " més"; }, + formatInputTooLong: function (input, max) { var n = input.length - max; return "Introduïu " + n + " caràcter" + (n == 1? "" : "s") + "menys"; }, + formatSelectionTooBig: function (limit) { return "Només podeu seleccionar " + limit + " element" + (limit == 1 ? "" : "s"); }, + formatLoadMore: function (pageNumber) { return "S'estan carregant més resultats…"; }, + formatSearching: function () { return "S'està cercant…"; } + }); +})(jQuery); diff --git a/ckan/public/base/vendor/select2/select2_locale_cs.js b/ckan/public/base/vendor/select2/select2_locale_cs.js new file mode 100644 index 00000000000..376b54a1352 --- /dev/null +++ b/ckan/public/base/vendor/select2/select2_locale_cs.js @@ -0,0 +1,49 @@ +/** + * Select2 Czech translation. + * + * Author: Michal Marek + * Author - sklonovani: David Vallner + */ +(function ($) { + "use strict"; + // use text for the numbers 2 through 4 + var smallNumbers = { + 2: function(masc) { return (masc ? "dva" : "dvě"); }, + 3: function() { return "tři"; }, + 4: function() { return "čtyři"; } + } + $.extend($.fn.select2.defaults, { + formatNoMatches: function () { return "Nenalezeny žádné položky"; }, + formatInputTooShort: function (input, min) { + var n = min - input.length; + if (n == 1) { + return "Prosím zadejte ještě jeden znak"; + } else if (n <= 4) { + return "Prosím zadejte ještě další "+smallNumbers[n](true)+" znaky"; + } else { + return "Prosím zadejte ještě dalších "+n+" znaků"; + } + }, + formatInputTooLong: function (input, max) { + var n = input.length - max; + if (n == 1) { + return "Prosím zadejte o jeden znak méně"; + } else if (n <= 4) { + return "Prosím zadejte o "+smallNumbers[n](true)+" znaky méně"; + } else { + return "Prosím zadejte o "+n+" znaků méně"; + } + }, + formatSelectionTooBig: function (limit) { + if (limit == 1) { + return "Můžete zvolit jen jednu položku"; + } else if (limit <= 4) { + return "Můžete zvolit maximálně "+smallNumbers[limit](false)+" položky"; + } else { + return "Můžete zvolit maximálně "+limit+" položek"; + } + }, + formatLoadMore: function (pageNumber) { return "Načítají se další výsledky…"; }, + formatSearching: function () { return "Vyhledávání…"; } + }); +})(jQuery); diff --git a/ckan/public/base/vendor/select2/select2_locale_da.js b/ckan/public/base/vendor/select2/select2_locale_da.js new file mode 100644 index 00000000000..dbce3e1748d --- /dev/null +++ b/ckan/public/base/vendor/select2/select2_locale_da.js @@ -0,0 +1,17 @@ +/** + * Select2 Danish translation. + * + * Author: Anders Jenbo + */ +(function ($) { + "use strict"; + + $.extend($.fn.select2.defaults, { + formatNoMatches: function () { return "Ingen resultater fundet"; }, + formatInputTooShort: function (input, min) { var n = min - input.length; return "Angiv venligst " + n + " tegn mere"; }, + formatInputTooLong: function (input, max) { var n = input.length - max; return "Angiv venligst " + n + " tegn mindre"; }, + formatSelectionTooBig: function (limit) { return "Du kan kun vælge " + limit + " emne" + (limit === 1 ? "" : "r"); }, + formatLoadMore: function (pageNumber) { return "Indlæser flere resultater…"; }, + formatSearching: function () { return "Søger…"; } + }); +})(jQuery); diff --git a/ckan/public/base/vendor/select2/select2_locale_de.js b/ckan/public/base/vendor/select2/select2_locale_de.js new file mode 100644 index 00000000000..93b18e81f85 --- /dev/null +++ b/ckan/public/base/vendor/select2/select2_locale_de.js @@ -0,0 +1,15 @@ +/** + * Select2 German translation + */ +(function ($) { + "use strict"; + + $.extend($.fn.select2.defaults, { + formatNoMatches: function () { return "Keine Übereinstimmungen gefunden"; }, + formatInputTooShort: function (input, min) { var n = min - input.length; return "Bitte " + n + " Zeichen mehr eingeben"; }, + formatInputTooLong: function (input, max) { var n = input.length - max; return "Bitte " + n + " Zeichen weniger eingeben"; }, + formatSelectionTooBig: function (limit) { return "Sie können nur " + limit + " Eintr" + (limit === 1 ? "ag" : "äge") + " auswählen"; }, + formatLoadMore: function (pageNumber) { return "Lade mehr Ergebnisse…"; }, + formatSearching: function () { return "Suche…"; } + }); +})(jQuery); \ No newline at end of file diff --git a/ckan/public/base/vendor/select2/select2_locale_el.js b/ckan/public/base/vendor/select2/select2_locale_el.js new file mode 100644 index 00000000000..e94b02cbc5f --- /dev/null +++ b/ckan/public/base/vendor/select2/select2_locale_el.js @@ -0,0 +1,17 @@ +/** + * Select2 Greek translation. + * + * @author Uriy Efremochkin + */ +(function ($) { + "use strict"; + + $.extend($.fn.select2.defaults, { + formatNoMatches: function () { return "Δεν βρέθηκαν αποτελέσματα"; }, + formatInputTooShort: function (input, min) { var n = min - input.length; return "Παρακαλούμε εισάγετε " + n + " περισσότερο" + (n > 1 ? "υς" : "") + " χαρακτήρ" + (n > 1 ? "ες" : "α"); }, + formatInputTooLong: function (input, max) { var n = input.length - max; return "Παρακαλούμε διαγράψτε " + n + " χαρακτήρ" + (n > 1 ? "ες" : "α"); }, + formatSelectionTooBig: function (limit) { return "Μπορείτε να επιλέξετε μόνο " + limit + " αντικείμεν" + (limit > 1 ? "α" : "ο"); }, + formatLoadMore: function (pageNumber) { return "Φόρτωση περισσότερων…"; }, + formatSearching: function () { return "Αναζήτηση…"; } + }); +})(jQuery); \ No newline at end of file diff --git a/ckan/public/base/vendor/select2/select2_locale_en.js.template b/ckan/public/base/vendor/select2/select2_locale_en.js.template new file mode 100644 index 00000000000..f66bcc844db --- /dev/null +++ b/ckan/public/base/vendor/select2/select2_locale_en.js.template @@ -0,0 +1,18 @@ +/** + * Select2 translation. + * + * Author: Your Name + */ +(function ($) { + "use strict"; + + $.extend($.fn.select2.defaults, { + formatMatches: function (matches) { return matches + " results are available, use up and down arrow keys to navigate."; }, + formatNoMatches: function () { return "No matches found"; }, + formatInputTooShort: function (input, min) { var n = min - input.length; return "Please enter " + n + " more character" + (n == 1 ? "" : "s"); }, + formatInputTooLong: function (input, max) { var n = input.length - max; return "Please delete " + n + " character" + (n == 1 ? "" : "s"); }, + formatSelectionTooBig: function (limit) { return "You can only select " + limit + " item" + (limit == 1 ? "" : "s"); }, + formatLoadMore: function (pageNumber) { return "Loading more results…"; }, + formatSearching: function () { return "Searching…"; } + }); +})(jQuery); diff --git a/ckan/public/base/vendor/select2/select2_locale_es.js b/ckan/public/base/vendor/select2/select2_locale_es.js new file mode 100644 index 00000000000..f2b581791eb --- /dev/null +++ b/ckan/public/base/vendor/select2/select2_locale_es.js @@ -0,0 +1,15 @@ +/** + * Select2 Spanish translation + */ +(function ($) { + "use strict"; + + $.extend($.fn.select2.defaults, { + formatNoMatches: function () { return "No se encontraron resultados"; }, + formatInputTooShort: function (input, min) { var n = min - input.length; return "Por favor, introduzca " + n + " car" + (n == 1? "ácter" : "acteres"); }, + formatInputTooLong: function (input, max) { var n = input.length - max; return "Por favor, elimine " + n + " car" + (n == 1? "ácter" : "acteres"); }, + formatSelectionTooBig: function (limit) { return "Sólo puede seleccionar " + limit + " elemento" + (limit == 1 ? "" : "s"); }, + formatLoadMore: function (pageNumber) { return "Cargando más resultados…"; }, + formatSearching: function () { return "Buscando…"; } + }); +})(jQuery); diff --git a/ckan/public/base/vendor/select2/select2_locale_et.js b/ckan/public/base/vendor/select2/select2_locale_et.js new file mode 100644 index 00000000000..a4045d22df7 --- /dev/null +++ b/ckan/public/base/vendor/select2/select2_locale_et.js @@ -0,0 +1,17 @@ +/** + * Select2 Estonian translation. + * + * Author: Kuldar Kalvik + */ +(function ($) { + "use strict"; + + $.extend($.fn.select2.defaults, { + formatNoMatches: function () { return "Tulemused puuduvad"; }, + formatInputTooShort: function (input, min) { var n = min - input.length; return "Sisesta " + n + " täht" + (n == 1 ? "" : "e") + " rohkem"; }, + formatInputTooLong: function (input, max) { var n = input.length - max; return "Sisesta " + n + " täht" + (n == 1? "" : "e") + " vähem"; }, + formatSelectionTooBig: function (limit) { return "Saad vaid " + limit + " tulemus" + (limit == 1 ? "e" : "t") + " valida"; }, + formatLoadMore: function (pageNumber) { return "Laen tulemusi.."; }, + formatSearching: function () { return "Otsin.."; } + }); +})(jQuery); diff --git a/ckan/public/base/vendor/select2/select2_locale_eu.js b/ckan/public/base/vendor/select2/select2_locale_eu.js new file mode 100644 index 00000000000..1da1a709481 --- /dev/null +++ b/ckan/public/base/vendor/select2/select2_locale_eu.js @@ -0,0 +1,43 @@ +/** + * Select2 Basque translation. + * + * Author: Julen Ruiz Aizpuru + */ +(function ($) { + "use strict"; + + $.extend($.fn.select2.defaults, { + formatNoMatches: function () { + return "Ez da bat datorrenik aurkitu"; + }, + formatInputTooShort: function (input, min) { + var n = min - input.length; + if (n === 1) { + return "Idatzi karaktere bat gehiago"; + } else { + return "Idatzi " + n + " karaktere gehiago"; + } + }, + formatInputTooLong: function (input, max) { + var n = input.length - max; + if (n === 1) { + return "Idatzi karaktere bat gutxiago"; + } else { + return "Idatzi " + n + " karaktere gutxiago"; + } + }, + formatSelectionTooBig: function (limit) { + if (limit === 1 ) { + return "Elementu bakarra hauta dezakezu"; + } else { + return limit + " elementu hauta ditzakezu soilik"; + } + }, + formatLoadMore: function (pageNumber) { + return "Emaitza gehiago kargatzen…"; + }, + formatSearching: function () { + return "Bilatzen…"; + } + }); +})(jQuery); diff --git a/ckan/public/base/vendor/select2/select2_locale_fa.js b/ckan/public/base/vendor/select2/select2_locale_fa.js new file mode 100644 index 00000000000..a9e95af4dba --- /dev/null +++ b/ckan/public/base/vendor/select2/select2_locale_fa.js @@ -0,0 +1,19 @@ +/** + * Select2 Persian translation. + * + * Author: Ali Choopan + * Author: Ebrahim Byagowi + */ +(function ($) { + "use strict"; + + $.extend($.fn.select2.defaults, { + formatMatches: function (matches) { return matches + " نتیجه موجود است، کلیدهای جهت بالا و پایین را برای گشتن استفاده کنید."; }, + formatNoMatches: function () { return "نتیجه‌ای یافت نشد."; }, + formatInputTooShort: function (input, min) { var n = min - input.length; return "لطفاً " + n + " نویسه بیشتر وارد نمایید"; }, + formatInputTooLong: function (input, max) { var n = input.length - max; return "لطفاً " + n + " نویسه را حذف کنید."; }, + formatSelectionTooBig: function (limit) { return "شما فقط می‌توانید " + limit + " مورد را انتخاب کنید"; }, + formatLoadMore: function (pageNumber) { return "در حال بارگیری موارد بیشتر…"; }, + formatSearching: function () { return "در حال جستجو…"; } + }); +})(jQuery); diff --git a/ckan/public/base/vendor/select2/select2_locale_fi.js b/ckan/public/base/vendor/select2/select2_locale_fi.js new file mode 100644 index 00000000000..9bed310f717 --- /dev/null +++ b/ckan/public/base/vendor/select2/select2_locale_fi.js @@ -0,0 +1,28 @@ +/** + * Select2 Finnish translation + */ +(function ($) { + "use strict"; + $.extend($.fn.select2.defaults, { + formatNoMatches: function () { + return "Ei tuloksia"; + }, + formatInputTooShort: function (input, min) { + var n = min - input.length; + return "Ole hyvä ja anna " + n + " merkkiä lisää"; + }, + formatInputTooLong: function (input, max) { + var n = input.length - max; + return "Ole hyvä ja anna " + n + " merkkiä vähemmän"; + }, + formatSelectionTooBig: function (limit) { + return "Voit valita ainoastaan " + limit + " kpl"; + }, + formatLoadMore: function (pageNumber) { + return "Ladataan lisää tuloksia…"; + }, + formatSearching: function () { + return "Etsitään…"; + } + }); +})(jQuery); diff --git a/ckan/public/base/vendor/select2/select2_locale_fr.js b/ckan/public/base/vendor/select2/select2_locale_fr.js new file mode 100644 index 00000000000..9afda2abdcd --- /dev/null +++ b/ckan/public/base/vendor/select2/select2_locale_fr.js @@ -0,0 +1,16 @@ +/** + * Select2 French translation + */ +(function ($) { + "use strict"; + + $.extend($.fn.select2.defaults, { + formatMatches: function (matches) { return matches + " résultats sont disponibles, utilisez les flèches haut et bas pour naviguer."; }, + formatNoMatches: function () { return "Aucun résultat trouvé"; }, + formatInputTooShort: function (input, min) { var n = min - input.length; return "Merci de saisir " + n + " caractère" + (n == 1 ? "" : "s") + " de plus"; }, + formatInputTooLong: function (input, max) { var n = input.length - max; return "Merci de supprimer " + n + " caractère" + (n == 1 ? "" : "s"); }, + formatSelectionTooBig: function (limit) { return "Vous pouvez seulement sélectionner " + limit + " élément" + (limit == 1 ? "" : "s"); }, + formatLoadMore: function (pageNumber) { return "Chargement de résultats supplémentaires…"; }, + formatSearching: function () { return "Recherche en cours…"; } + }); +})(jQuery); diff --git a/ckan/public/base/vendor/select2/select2_locale_gl.js b/ckan/public/base/vendor/select2/select2_locale_gl.js new file mode 100644 index 00000000000..80326320bf0 --- /dev/null +++ b/ckan/public/base/vendor/select2/select2_locale_gl.js @@ -0,0 +1,43 @@ +/** + * Select2 Galician translation + * + * Author: Leandro Regueiro + */ +(function ($) { + "use strict"; + + $.extend($.fn.select2.defaults, { + formatNoMatches: function () { + return "Non se atoparon resultados"; + }, + formatInputTooShort: function (input, min) { + var n = min - input.length; + if (n === 1) { + return "Engada un carácter"; + } else { + return "Engada " + n + " caracteres"; + } + }, + formatInputTooLong: function (input, max) { + var n = input.length - max; + if (n === 1) { + return "Elimine un carácter"; + } else { + return "Elimine " + n + " caracteres"; + } + }, + formatSelectionTooBig: function (limit) { + if (limit === 1 ) { + return "Só pode seleccionar un elemento"; + } else { + return "Só pode seleccionar " + limit + " elementos"; + } + }, + formatLoadMore: function (pageNumber) { + return "Cargando máis resultados…"; + }, + formatSearching: function () { + return "Buscando…"; + } + }); +})(jQuery); diff --git a/ckan/public/base/vendor/select2/select2_locale_he.js b/ckan/public/base/vendor/select2/select2_locale_he.js new file mode 100644 index 00000000000..00385410804 --- /dev/null +++ b/ckan/public/base/vendor/select2/select2_locale_he.js @@ -0,0 +1,17 @@ +/** +* Select2 Hebrew translation. +* +* Author: Yakir Sitbon +*/ +(function ($) { + "use strict"; + + $.extend($.fn.select2.defaults, { + formatNoMatches: function () { return "לא נמצאו התאמות"; }, + formatInputTooShort: function (input, min) { var n = min - input.length; return "נא להזין עוד " + n + " תווים נוספים"; }, + formatInputTooLong: function (input, max) { var n = input.length - max; return "נא להזין פחות " + n + " תווים"; }, + formatSelectionTooBig: function (limit) { return "ניתן לבחור " + limit + " פריטים"; }, + formatLoadMore: function (pageNumber) { return "טוען תוצאות נוספות…"; }, + formatSearching: function () { return "מחפש…"; } + }); +})(jQuery); diff --git a/ckan/public/base/vendor/select2/select2_locale_hr.js b/ckan/public/base/vendor/select2/select2_locale_hr.js new file mode 100644 index 00000000000..c29372524b6 --- /dev/null +++ b/ckan/public/base/vendor/select2/select2_locale_hr.js @@ -0,0 +1,22 @@ +/** + * Select2 Croatian translation. + * + * @author Edi Modrić + * @author Uriy Efremochkin + */ +(function ($) { + "use strict"; + + $.extend($.fn.select2.defaults, { + formatNoMatches: function () { return "Nema rezultata"; }, + formatInputTooShort: function (input, min) { return "Unesite još" + character(min - input.length); }, + formatInputTooLong: function (input, max) { return "Unesite" + character(input.length - max) + " manje"; }, + formatSelectionTooBig: function (limit) { return "Maksimalan broj odabranih stavki je " + limit; }, + formatLoadMore: function (pageNumber) { return "Učitavanje rezultata…"; }, + formatSearching: function () { return "Pretraga…"; } + }); + + function character (n) { + return " " + n + " znak" + (n%10 < 5 && n%10 > 0 && (n%100 < 5 || n%100 > 19) ? n%10 > 1 ? "a" : "" : "ova"); + } +})(jQuery); diff --git a/ckan/public/base/vendor/select2/select2_locale_hu.js b/ckan/public/base/vendor/select2/select2_locale_hu.js new file mode 100644 index 00000000000..a8c30881928 --- /dev/null +++ b/ckan/public/base/vendor/select2/select2_locale_hu.js @@ -0,0 +1,15 @@ +/** + * Select2 Hungarian translation + */ +(function ($) { + "use strict"; + + $.extend($.fn.select2.defaults, { + formatNoMatches: function () { return "Nincs találat."; }, + formatInputTooShort: function (input, min) { var n = min - input.length; return "Túl rövid. Még " + n + " karakter hiányzik."; }, + formatInputTooLong: function (input, max) { var n = input.length - max; return "Túl hosszú. " + n + " karakterrel több, mint kellene."; }, + formatSelectionTooBig: function (limit) { return "Csak " + limit + " elemet lehet kiválasztani."; }, + formatLoadMore: function (pageNumber) { return "Töltés…"; }, + formatSearching: function () { return "Keresés…"; } + }); +})(jQuery); diff --git a/ckan/public/base/vendor/select2/select2_locale_id.js b/ckan/public/base/vendor/select2/select2_locale_id.js new file mode 100644 index 00000000000..547454079ba --- /dev/null +++ b/ckan/public/base/vendor/select2/select2_locale_id.js @@ -0,0 +1,17 @@ +/** + * Select2 Indonesian translation. + * + * Author: Ibrahim Yusuf + */ +(function ($) { + "use strict"; + + $.extend($.fn.select2.defaults, { + formatNoMatches: function () { return "Tidak ada data yang sesuai"; }, + formatInputTooShort: function (input, min) { var n = min - input.length; return "Masukkan " + n + " huruf lagi" + (n == 1 ? "" : "s"); }, + formatInputTooLong: function (input, max) { var n = input.length - max; return "Hapus " + n + " huruf" + (n == 1 ? "" : "s"); }, + formatSelectionTooBig: function (limit) { return "Anda hanya dapat memilih " + limit + " pilihan" + (limit == 1 ? "" : "s"); }, + formatLoadMore: function (pageNumber) { return "Mengambil data…"; }, + formatSearching: function () { return "Mencari…"; } + }); +})(jQuery); diff --git a/ckan/public/base/vendor/select2/select2_locale_is.js b/ckan/public/base/vendor/select2/select2_locale_is.js new file mode 100644 index 00000000000..aecc6cd7194 --- /dev/null +++ b/ckan/public/base/vendor/select2/select2_locale_is.js @@ -0,0 +1,15 @@ +/** + * Select2 Icelandic translation. + */ +(function ($) { + "use strict"; + + $.extend($.fn.select2.defaults, { + formatNoMatches: function () { return "Ekkert fannst"; }, + formatInputTooShort: function (input, min) { var n = min - input.length; return "Vinsamlegast skrifið " + n + " staf" + (n > 1 ? "i" : "") + " í viðbót"; }, + formatInputTooLong: function (input, max) { var n = input.length - max; return "Vinsamlegast styttið texta um " + n + " staf" + (n > 1 ? "i" : ""); }, + formatSelectionTooBig: function (limit) { return "Þú getur aðeins valið " + limit + " atriði"; }, + formatLoadMore: function (pageNumber) { return "Sæki fleiri niðurstöður…"; }, + formatSearching: function () { return "Leita…"; } + }); +})(jQuery); diff --git a/ckan/public/base/vendor/select2/select2_locale_it.js b/ckan/public/base/vendor/select2/select2_locale_it.js new file mode 100644 index 00000000000..d4e24de7000 --- /dev/null +++ b/ckan/public/base/vendor/select2/select2_locale_it.js @@ -0,0 +1,15 @@ +/** + * Select2 Italian translation + */ +(function ($) { + "use strict"; + + $.extend($.fn.select2.defaults, { + formatNoMatches: function () { return "Nessuna corrispondenza trovata"; }, + formatInputTooShort: function (input, min) { var n = min - input.length; return "Inserisci ancora " + n + " caratter" + (n == 1? "e" : "i"); }, + formatInputTooLong: function (input, max) { var n = input.length - max; return "Inserisci " + n + " caratter" + (n == 1? "e" : "i") + " in meno"; }, + formatSelectionTooBig: function (limit) { return "Puoi selezionare solo " + limit + " element" + (limit == 1 ? "o" : "i"); }, + formatLoadMore: function (pageNumber) { return "Caricamento in corso…"; }, + formatSearching: function () { return "Ricerca…"; } + }); +})(jQuery); \ No newline at end of file diff --git a/ckan/public/base/vendor/select2/select2_locale_ja.js b/ckan/public/base/vendor/select2/select2_locale_ja.js new file mode 100644 index 00000000000..81106e78a80 --- /dev/null +++ b/ckan/public/base/vendor/select2/select2_locale_ja.js @@ -0,0 +1,15 @@ +/** + * Select2 Japanese translation. + */ +(function ($) { + "use strict"; + + $.extend($.fn.select2.defaults, { + formatNoMatches: function () { return "該当なし"; }, + formatInputTooShort: function (input, min) { var n = min - input.length; return "後" + n + "文字入れてください"; }, + formatInputTooLong: function (input, max) { var n = input.length - max; return "検索文字列が" + n + "文字長すぎます"; }, + formatSelectionTooBig: function (limit) { return "最多で" + limit + "項目までしか選択できません"; }, + formatLoadMore: function (pageNumber) { return "読込中・・・"; }, + formatSearching: function () { return "検索中・・・"; } + }); +})(jQuery); diff --git a/ckan/public/base/vendor/select2/select2_locale_ka.js b/ckan/public/base/vendor/select2/select2_locale_ka.js new file mode 100644 index 00000000000..366cc2d9c4d --- /dev/null +++ b/ckan/public/base/vendor/select2/select2_locale_ka.js @@ -0,0 +1,17 @@ +/** + * Select2 Georgian (Kartuli) translation. + * + * Author: Dimitri Kurashvili dimakura@gmail.com + */ +(function ($) { + "use strict"; + + $.extend($.fn.select2.defaults, { + formatNoMatches: function () { return "ვერ მოიძებნა"; }, + formatInputTooShort: function (input, min) { var n = min - input.length; return "გთხოვთ შეიყვანოთ კიდევ " + n + " სიმბოლო"; }, + formatInputTooLong: function (input, max) { var n = input.length - max; return "გთხოვთ წაშალოთ " + n + " სიმბოლო"; }, + formatSelectionTooBig: function (limit) { return "თქვენ შეგიძლიათ მხოლოდ " + limit + " ჩანაწერის მონიშვნა"; }, + formatLoadMore: function (pageNumber) { return "შედეგის ჩატვირთვა…"; }, + formatSearching: function () { return "ძებნა…"; } + }); +})(jQuery); diff --git a/ckan/public/base/vendor/select2/select2_locale_ko.js b/ckan/public/base/vendor/select2/select2_locale_ko.js new file mode 100644 index 00000000000..1a84d21eae6 --- /dev/null +++ b/ckan/public/base/vendor/select2/select2_locale_ko.js @@ -0,0 +1,17 @@ +/** + * Select2 Korean translation. + * + * @author Swen Mun + */ +(function ($) { + "use strict"; + + $.extend($.fn.select2.defaults, { + formatNoMatches: function () { return "결과 없음"; }, + formatInputTooShort: function (input, min) { var n = min - input.length; return "너무 짧습니다. "+n+"글자 더 입력해주세요."; }, + formatInputTooLong: function (input, max) { var n = input.length - max; return "너무 깁니다. "+n+"글자 지워주세요."; }, + formatSelectionTooBig: function (limit) { return "최대 "+limit+"개까지만 선택하실 수 있습니다."; }, + formatLoadMore: function (pageNumber) { return "불러오는 중…"; }, + formatSearching: function () { return "검색 중…"; } + }); +})(jQuery); diff --git a/ckan/public/base/vendor/select2/select2_locale_lt.js b/ckan/public/base/vendor/select2/select2_locale_lt.js new file mode 100644 index 00000000000..2e2f950b00d --- /dev/null +++ b/ckan/public/base/vendor/select2/select2_locale_lt.js @@ -0,0 +1,24 @@ +/** + * Select2 Lithuanian translation. + * + * @author CRONUS Karmalakas + * @author Uriy Efremochkin + */ +(function ($) { + "use strict"; + + $.extend($.fn.select2.defaults, { + formatNoMatches: function () { return "Atitikmenų nerasta"; }, + formatInputTooShort: function (input, min) { return "Įrašykite dar" + character(min - input.length); }, + formatInputTooLong: function (input, max) { return "Pašalinkite" + character(input.length - max); }, + formatSelectionTooBig: function (limit) { + return "Jūs galite pasirinkti tik " + limit + " element" + ((limit%100 > 9 && limit%100 < 21) || limit%10 == 0 ? "ų" : limit%10 > 1 ? "us" : "ą"); + }, + formatLoadMore: function (pageNumber) { return "Kraunama daugiau rezultatų…"; }, + formatSearching: function () { return "Ieškoma…"; } + }); + + function character (n) { + return " " + n + " simbol" + ((n%100 > 9 && n%100 < 21) || n%10 == 0 ? "ių" : n%10 > 1 ? "ius" : "į"); + } +})(jQuery); diff --git a/ckan/public/base/vendor/select2/select2_locale_lv.js b/ckan/public/base/vendor/select2/select2_locale_lv.js new file mode 100644 index 00000000000..b300ec770f4 --- /dev/null +++ b/ckan/public/base/vendor/select2/select2_locale_lv.js @@ -0,0 +1,17 @@ +/** + * Select2 Latvian translation. + * + * @author Uriy Efremochkin + */ +(function ($) { + "use strict"; + + $.extend($.fn.select2.defaults, { + formatNoMatches: function () { return "Sakritību nav"; }, + formatInputTooShort: function (input, min) { var n = min - input.length; return "Lūdzu ievadiet vēl " + n + " simbol" + (n == 11 ? "us" : n%10 == 1 ? "u" : "us"); }, + formatInputTooLong: function (input, max) { var n = input.length - max; return "Lūdzu ievadiet par " + n + " simbol" + (n == 11 ? "iem" : n%10 == 1 ? "u" : "iem") + " mazāk"; }, + formatSelectionTooBig: function (limit) { return "Jūs varat izvēlēties ne vairāk kā " + limit + " element" + (limit == 11 ? "us" : limit%10 == 1 ? "u" : "us"); }, + formatLoadMore: function (pageNumber) { return "Datu ielāde…"; }, + formatSearching: function () { return "Meklēšana…"; } + }); +})(jQuery); diff --git a/ckan/public/base/vendor/select2/select2_locale_mk.js b/ckan/public/base/vendor/select2/select2_locale_mk.js new file mode 100644 index 00000000000..513562c51bf --- /dev/null +++ b/ckan/public/base/vendor/select2/select2_locale_mk.js @@ -0,0 +1,17 @@ +/** + * Select2 Macedonian translation. + * + * Author: Marko Aleksic + */ +(function ($) { + "use strict"; + + $.extend($.fn.select2.defaults, { + formatNoMatches: function () { return "Нема пронајдено совпаѓања"; }, + formatInputTooShort: function (input, min) { var n = min - input.length; return "Ве молиме внесете уште " + n + " карактер" + (n == 1 ? "" : "и"); }, + formatInputTooLong: function (input, max) { var n = input.length - max; return "Ве молиме внесете " + n + " помалку карактер" + (n == 1? "" : "и"); }, + formatSelectionTooBig: function (limit) { return "Можете да изберете само " + limit + " ставк" + (limit == 1 ? "а" : "и"); }, + formatLoadMore: function (pageNumber) { return "Вчитување резултати…"; }, + formatSearching: function () { return "Пребарување…"; } + }); +})(jQuery); \ No newline at end of file diff --git a/ckan/public/base/vendor/select2/select2_locale_ms.js b/ckan/public/base/vendor/select2/select2_locale_ms.js new file mode 100644 index 00000000000..262042aab15 --- /dev/null +++ b/ckan/public/base/vendor/select2/select2_locale_ms.js @@ -0,0 +1,17 @@ +/** + * Select2 Malay translation. + * + * Author: Kepoweran + */ +(function ($) { + "use strict"; + + $.extend($.fn.select2.defaults, { + formatNoMatches: function () { return "Tiada padanan yang ditemui"; }, + formatInputTooShort: function (input, min) { var n = min - input.length; return "Sila masukkan " + n + " aksara lagi"; }, + formatInputTooLong: function (input, max) { var n = input.length - max; return "Sila hapuskan " + n + " aksara"; }, + formatSelectionTooBig: function (limit) { return "Anda hanya boleh memilih " + limit + " pilihan"; }, + formatLoadMore: function (pageNumber) { return "Sedang memuatkan keputusan…"; }, + formatSearching: function () { return "Mencari…"; } + }); +})(jQuery); diff --git a/ckan/public/base/vendor/select2/select2_locale_nl.js b/ckan/public/base/vendor/select2/select2_locale_nl.js new file mode 100644 index 00000000000..5b5c4156ce1 --- /dev/null +++ b/ckan/public/base/vendor/select2/select2_locale_nl.js @@ -0,0 +1,15 @@ +/** + * Select2 Dutch translation + */ +(function ($) { + "use strict"; + + $.extend($.fn.select2.defaults, { + formatNoMatches: function () { return "Geen resultaten gevonden"; }, + formatInputTooShort: function (input, min) { var n = min - input.length; return "Vul " + n + " karakter" + (n == 1? "" : "s") + " meer in"; }, + formatInputTooLong: function (input, max) { var n = input.length - max; return "Vul " + n + " karakter" + (n == 1? "" : "s") + " minder in"; }, + formatSelectionTooBig: function (limit) { return "Maximaal " + limit + " item" + (limit == 1 ? "" : "s") + " toegestaan"; }, + formatLoadMore: function (pageNumber) { return "Meer resultaten laden…"; }, + formatSearching: function () { return "Zoeken…"; } + }); +})(jQuery); \ No newline at end of file diff --git a/ckan/public/base/vendor/select2/select2_locale_no.js b/ckan/public/base/vendor/select2/select2_locale_no.js new file mode 100644 index 00000000000..ab61c082a02 --- /dev/null +++ b/ckan/public/base/vendor/select2/select2_locale_no.js @@ -0,0 +1,18 @@ +/** + * Select2 Norwegian translation. + * + * Author: Torgeir Veimo + */ +(function ($) { + "use strict"; + + $.extend($.fn.select2.defaults, { + formatNoMatches: function () { return "Ingen treff"; }, + formatInputTooShort: function (input, min) { var n = min - input.length; return "Vennligst skriv inn " + n + (n>1 ? " flere tegn" : " tegn til"); }, + formatInputTooLong: function (input, max) { var n = input.length - max; return "Vennligst fjern " + n + " tegn"; }, + formatSelectionTooBig: function (limit) { return "Du kan velge maks " + limit + " elementer"; }, + formatLoadMore: function (pageNumber) { return "Laster flere resultater…"; }, + formatSearching: function () { return "Søker…"; } + }); +})(jQuery); + diff --git a/ckan/public/base/vendor/select2/select2_locale_pl.js b/ckan/public/base/vendor/select2/select2_locale_pl.js new file mode 100644 index 00000000000..75054e76578 --- /dev/null +++ b/ckan/public/base/vendor/select2/select2_locale_pl.js @@ -0,0 +1,22 @@ +/** + * Select2 Polish translation. + * + * @author Jan Kondratowicz + * @author Uriy Efremochkin + */ +(function ($) { + "use strict"; + + $.extend($.fn.select2.defaults, { + formatNoMatches: function () { return "Brak wyników"; }, + formatInputTooShort: function (input, min) { return "Wpisz jeszcze" + character(min - input.length, "znak", "i"); }, + formatInputTooLong: function (input, max) { return "Wpisana fraza jest za długa o" + character(input.length - max, "znak", "i"); }, + formatSelectionTooBig: function (limit) { return "Możesz zaznaczyć najwyżej" + character(limit, "element", "y"); }, + formatLoadMore: function (pageNumber) { return "Ładowanie wyników…"; }, + formatSearching: function () { return "Szukanie…"; } + }); + + function character (n, word, pluralSuffix) { + return " " + n + " " + word + (n == 1 ? "" : n%10 < 5 && n%10 > 1 && (n%100 < 5 || n%100 > 20) ? pluralSuffix : "ów"); + } +})(jQuery); diff --git a/ckan/public/base/vendor/select2/select2_locale_pt-BR.js b/ckan/public/base/vendor/select2/select2_locale_pt-BR.js new file mode 100644 index 00000000000..ac4969acfbb --- /dev/null +++ b/ckan/public/base/vendor/select2/select2_locale_pt-BR.js @@ -0,0 +1,15 @@ +/** + * Select2 Brazilian Portuguese translation + */ +(function ($) { + "use strict"; + + $.extend($.fn.select2.defaults, { + formatNoMatches: function () { return "Nenhum resultado encontrado"; }, + formatInputTooShort: function (input, min) { var n = min - input.length; return "Digite mais " + n + " caracter" + (n == 1? "" : "es"); }, + formatInputTooLong: function (input, max) { var n = input.length - max; return "Apague " + n + " caracter" + (n == 1? "" : "es"); }, + formatSelectionTooBig: function (limit) { return "Só é possível selecionar " + limit + " elemento" + (limit == 1 ? "" : "s"); }, + formatLoadMore: function (pageNumber) { return "Carregando mais resultados…"; }, + formatSearching: function () { return "Buscando…"; } + }); +})(jQuery); diff --git a/ckan/public/base/vendor/select2/select2_locale_pt-PT.js b/ckan/public/base/vendor/select2/select2_locale_pt-PT.js new file mode 100644 index 00000000000..cced7cf3ec1 --- /dev/null +++ b/ckan/public/base/vendor/select2/select2_locale_pt-PT.js @@ -0,0 +1,15 @@ +/** + * Select2 Portuguese (Portugal) translation + */ +(function ($) { + "use strict"; + + $.extend($.fn.select2.defaults, { + formatNoMatches: function () { return "Nenhum resultado encontrado"; }, + formatInputTooShort: function (input, min) { var n = min - input.length; return "Introduza " + n + " car" + (n == 1 ? "ácter" : "acteres"); }, + formatInputTooLong: function (input, max) { var n = input.length - max; return "Apague " + n + " car" + (n == 1 ? "ácter" : "acteres"); }, + formatSelectionTooBig: function (limit) { return "Só é possível selecionar " + limit + " elemento" + (limit == 1 ? "" : "s"); }, + formatLoadMore: function (pageNumber) { return "A carregar mais resultados…"; }, + formatSearching: function () { return "A pesquisar…"; } + }); +})(jQuery); diff --git a/ckan/public/base/vendor/select2/select2_locale_ro.js b/ckan/public/base/vendor/select2/select2_locale_ro.js new file mode 100644 index 00000000000..87eca4cf740 --- /dev/null +++ b/ckan/public/base/vendor/select2/select2_locale_ro.js @@ -0,0 +1,15 @@ +/** + * Select2 Romanian translation. + */ +(function ($) { + "use strict"; + + $.extend($.fn.select2.defaults, { + formatNoMatches: function () { return "Nu a fost găsit nimic"; }, + formatInputTooShort: function (input, min) { var n = min - input.length; return "Vă rugăm să introduceți incă " + n + " caracter" + (n == 1 ? "" : "e"); }, + formatInputTooLong: function (input, max) { var n = input.length - max; return "Vă rugăm să introduceți mai puțin de " + n + " caracter" + (n == 1? "" : "e"); }, + formatSelectionTooBig: function (limit) { return "Aveți voie să selectați cel mult " + limit + " element" + (limit == 1 ? "" : "e"); }, + formatLoadMore: function (pageNumber) { return "Se încarcă…"; }, + formatSearching: function () { return "Căutare…"; } + }); +})(jQuery); diff --git a/ckan/public/base/vendor/select2/select2_locale_rs.js b/ckan/public/base/vendor/select2/select2_locale_rs.js new file mode 100644 index 00000000000..300c01bc5e5 --- /dev/null +++ b/ckan/public/base/vendor/select2/select2_locale_rs.js @@ -0,0 +1,17 @@ +/** + * Select2 Serbian translation. + * + * @author Limon Monte + */ +(function ($) { + "use strict"; + + $.extend($.fn.select2.defaults, { + formatNoMatches: function () { return "Ništa nije pronađeno"; }, + formatInputTooShort: function (input, min) { var n = min - input.length; return "Ukucajte bar još " + n + " simbol" + (n % 10 == 1 && n % 100 != 11 ? "" : "a"); }, + formatInputTooLong: function (input, max) { var n = input.length - max; return "Obrišite " + n + " simbol" + (n % 10 == 1 && n % 100 != 11 ? "" : "a"); }, + formatSelectionTooBig: function (limit) { return "Možete izabrati samo " + limit + " stavk" + (limit % 10 == 1 && limit % 100 != 11 ? "u" : (limit % 10 >= 2 && limit % 10 <= 4 && (limit % 100 < 12 || limit % 100 > 14)? "e" : "i")); }, + formatLoadMore: function (pageNumber) { return "Preuzimanje još rezultata…"; }, + formatSearching: function () { return "Pretraga…"; } + }); +})(jQuery); diff --git a/ckan/public/base/vendor/select2/select2_locale_ru.js b/ckan/public/base/vendor/select2/select2_locale_ru.js new file mode 100644 index 00000000000..0f45ce0dddf --- /dev/null +++ b/ckan/public/base/vendor/select2/select2_locale_ru.js @@ -0,0 +1,21 @@ +/** + * Select2 Russian translation. + * + * @author Uriy Efremochkin + */ +(function ($) { + "use strict"; + + $.extend($.fn.select2.defaults, { + formatNoMatches: function () { return "Совпадений не найдено"; }, + formatInputTooShort: function (input, min) { return "Пожалуйста, введите еще" + character(min - input.length); }, + formatInputTooLong: function (input, max) { return "Пожалуйста, введите на" + character(input.length - max) + " меньше"; }, + formatSelectionTooBig: function (limit) { return "Вы можете выбрать не более " + limit + " элемент" + (limit%10 == 1 && limit%100 != 11 ? "а" : "ов"); }, + formatLoadMore: function (pageNumber) { return "Загрузка данных…"; }, + formatSearching: function () { return "Поиск…"; } + }); + + function character (n) { + return " " + n + " символ" + (n%10 < 5 && n%10 > 0 && (n%100 < 5 || n%100 > 20) ? n%10 > 1 ? "a" : "" : "ов"); + } +})(jQuery); diff --git a/ckan/public/base/vendor/select2/select2_locale_sk.js b/ckan/public/base/vendor/select2/select2_locale_sk.js new file mode 100644 index 00000000000..772f304aca9 --- /dev/null +++ b/ckan/public/base/vendor/select2/select2_locale_sk.js @@ -0,0 +1,48 @@ +/** + * Select2 Slovak translation. + * + * Author: David Vallner + */ +(function ($) { + "use strict"; + // use text for the numbers 2 through 4 + var smallNumbers = { + 2: function(masc) { return (masc ? "dva" : "dve"); }, + 3: function() { return "tri"; }, + 4: function() { return "štyri"; } + } + $.extend($.fn.select2.defaults, { + formatNoMatches: function () { return "Nenašli sa žiadne položky"; }, + formatInputTooShort: function (input, min) { + var n = min - input.length; + if (n == 1) { + return "Prosím zadajte ešte jeden znak"; + } else if (n <= 4) { + return "Prosím zadajte ešte ďalšie "+smallNumbers[n](true)+" znaky"; + } else { + return "Prosím zadajte ešte ďalších "+n+" znakov"; + } + }, + formatInputTooLong: function (input, max) { + var n = input.length - max; + if (n == 1) { + return "Prosím zadajte o jeden znak menej"; + } else if (n <= 4) { + return "Prosím zadajte o "+smallNumbers[n](true)+" znaky menej"; + } else { + return "Prosím zadajte o "+n+" znakov menej"; + } + }, + formatSelectionTooBig: function (limit) { + if (limit == 1) { + return "Môžete zvoliť len jednu položku"; + } else if (limit <= 4) { + return "Môžete zvoliť najviac "+smallNumbers[limit](false)+" položky"; + } else { + return "Môžete zvoliť najviac "+limit+" položiek"; + } + }, + formatLoadMore: function (pageNumber) { return "Načítavajú sa ďalšie výsledky…"; }, + formatSearching: function () { return "Vyhľadávanie…"; } + }); +})(jQuery); diff --git a/ckan/public/base/vendor/select2/select2_locale_sv.js b/ckan/public/base/vendor/select2/select2_locale_sv.js new file mode 100644 index 00000000000..d611189a593 --- /dev/null +++ b/ckan/public/base/vendor/select2/select2_locale_sv.js @@ -0,0 +1,17 @@ +/** + * Select2 Swedish translation. + * + * Author: Jens Rantil + */ +(function ($) { + "use strict"; + + $.extend($.fn.select2.defaults, { + formatNoMatches: function () { return "Inga träffar"; }, + formatInputTooShort: function (input, min) { var n = min - input.length; return "Var god skriv in " + n + (n>1 ? " till tecken" : " tecken till"); }, + formatInputTooLong: function (input, max) { var n = input.length - max; return "Var god sudda ut " + n + " tecken"; }, + formatSelectionTooBig: function (limit) { return "Du kan max välja " + limit + " element"; }, + formatLoadMore: function (pageNumber) { return "Laddar fler resultat…"; }, + formatSearching: function () { return "Söker…"; } + }); +})(jQuery); diff --git a/ckan/public/base/vendor/select2/select2_locale_th.js b/ckan/public/base/vendor/select2/select2_locale_th.js new file mode 100644 index 00000000000..df59bdac36d --- /dev/null +++ b/ckan/public/base/vendor/select2/select2_locale_th.js @@ -0,0 +1,17 @@ +/** + * Select2 Thai translation. + * + * Author: Atsawin Chaowanakritsanakul + */ +(function ($) { + "use strict"; + + $.extend($.fn.select2.defaults, { + formatNoMatches: function () { return "ไม่พบข้อมูล"; }, + formatInputTooShort: function (input, min) { var n = min - input.length; return "โปรดพิมพ์เพิ่มอีก " + n + " ตัวอักษร"; }, + formatInputTooLong: function (input, max) { var n = input.length - max; return "โปรดลบออก " + n + " ตัวอักษร"; }, + formatSelectionTooBig: function (limit) { return "คุณสามารถเลือกได้ไม่เกิน " + limit + " รายการ"; }, + formatLoadMore: function (pageNumber) { return "กำลังค้นข้อมูลเพิ่ม…"; }, + formatSearching: function () { return "กำลังค้นข้อมูล…"; } + }); +})(jQuery); diff --git a/ckan/public/base/vendor/select2/select2_locale_tr.js b/ckan/public/base/vendor/select2/select2_locale_tr.js new file mode 100644 index 00000000000..f834dad2b89 --- /dev/null +++ b/ckan/public/base/vendor/select2/select2_locale_tr.js @@ -0,0 +1,17 @@ +/** + * Select2 Turkish translation. + * + * Author: Salim KAYABAŞI + */ +(function ($) { + "use strict"; + + $.extend($.fn.select2.defaults, { + formatNoMatches: function () { return "Sonuç bulunamadı"; }, + formatInputTooShort: function (input, min) { var n = min - input.length; return "En az " + n + " karakter daha girmelisiniz"; }, + formatInputTooLong: function (input, max) { var n = input.length - max; return n + " karakter azaltmalısınız"; }, + formatSelectionTooBig: function (limit) { return "Sadece " + limit + " seçim yapabilirsiniz"; }, + formatLoadMore: function (pageNumber) { return "Daha fazla…"; }, + formatSearching: function () { return "Aranıyor…"; } + }); +})(jQuery); diff --git a/ckan/public/base/vendor/select2/select2_locale_uk.js b/ckan/public/base/vendor/select2/select2_locale_uk.js new file mode 100644 index 00000000000..8d31a056080 --- /dev/null +++ b/ckan/public/base/vendor/select2/select2_locale_uk.js @@ -0,0 +1,23 @@ +/** + * Select2 Ukrainian translation. + * + * @author bigmihail + * @author Uriy Efremochkin + */ +(function ($) { + "use strict"; + + $.extend($.fn.select2.defaults, { + formatMatches: function (matches) { return character(matches, "результат") + " знайдено, використовуйте клавіші зі стрілками вверх та вниз для навігації."; }, + formatNoMatches: function () { return "Нічого не знайдено"; }, + formatInputTooShort: function (input, min) { return "Введіть буль ласка ще " + character(min - input.length, "символ"); }, + formatInputTooLong: function (input, max) { return "Введіть буль ласка на " + character(input.length - max, "символ") + " менше"; }, + formatSelectionTooBig: function (limit) { return "Ви можете вибрати лише " + character(limit, "елемент"); }, + formatLoadMore: function (pageNumber) { return "Завантаження даних…"; }, + formatSearching: function () { return "Пошук…"; } + }); + + function character (n, word) { + return n + " " + word + (n%10 < 5 && n%10 > 0 && (n%100 < 5 || n%100 > 19) ? n%10 > 1 ? "и" : "" : "ів"); + } +})(jQuery); diff --git a/ckan/public/base/vendor/select2/select2_locale_vi.js b/ckan/public/base/vendor/select2/select2_locale_vi.js new file mode 100644 index 00000000000..5dbc275361f --- /dev/null +++ b/ckan/public/base/vendor/select2/select2_locale_vi.js @@ -0,0 +1,18 @@ +/** + * Select2 Vietnamese translation. + * + * Author: Long Nguyen + */ +(function ($) { + "use strict"; + + $.extend($.fn.select2.defaults, { + formatNoMatches: function () { return "Không tìm thấy kết quả"; }, + formatInputTooShort: function (input, min) { var n = min - input.length; return "Vui lòng nhập nhiều hơn " + n + " ký tự" + (n == 1 ? "" : "s"); }, + formatInputTooLong: function (input, max) { var n = input.length - max; return "Vui lòng nhập ít hơn " + n + " ký tự" + (n == 1? "" : "s"); }, + formatSelectionTooBig: function (limit) { return "Chỉ có thể chọn được " + limit + " tùy chọn" + (limit == 1 ? "" : "s"); }, + formatLoadMore: function (pageNumber) { return "Đang lấy thêm kết quả…"; }, + formatSearching: function () { return "Đang tìm…"; } + }); +})(jQuery); + diff --git a/ckan/public/base/vendor/select2/select2_locale_zh-CN.js b/ckan/public/base/vendor/select2/select2_locale_zh-CN.js new file mode 100644 index 00000000000..6add3c52518 --- /dev/null +++ b/ckan/public/base/vendor/select2/select2_locale_zh-CN.js @@ -0,0 +1,14 @@ +/** + * Select2 Chinese translation + */ +(function ($) { + "use strict"; + $.extend($.fn.select2.defaults, { + formatNoMatches: function () { return "没有找到匹配项"; }, + formatInputTooShort: function (input, min) { var n = min - input.length; return "请再输入" + n + "个字符";}, + formatInputTooLong: function (input, max) { var n = input.length - max; return "请删掉" + n + "个字符";}, + formatSelectionTooBig: function (limit) { return "你只能选择最多" + limit + "项"; }, + formatLoadMore: function (pageNumber) { return "加载结果中…"; }, + formatSearching: function () { return "搜索中…"; } + }); +})(jQuery); diff --git a/ckan/public/base/vendor/select2/select2_locale_zh-TW.js b/ckan/public/base/vendor/select2/select2_locale_zh-TW.js new file mode 100755 index 00000000000..f072381faae --- /dev/null +++ b/ckan/public/base/vendor/select2/select2_locale_zh-TW.js @@ -0,0 +1,14 @@ +/** + * Select2 Traditional Chinese translation + */ +(function ($) { + "use strict"; + $.extend($.fn.select2.defaults, { + formatNoMatches: function () { return "沒有找到相符的項目"; }, + formatInputTooShort: function (input, min) { var n = min - input.length; return "請再輸入" + n + "個字元";}, + formatInputTooLong: function (input, max) { var n = input.length - max; return "請刪掉" + n + "個字元";}, + formatSelectionTooBig: function (limit) { return "你只能選擇最多" + limit + "項"; }, + formatLoadMore: function (pageNumber) { return "載入中…"; }, + formatSearching: function () { return "搜尋中…"; } + }); +})(jQuery); diff --git a/ckan/public/base/vendor/select2/select2x2.png b/ckan/public/base/vendor/select2/select2x2.png old mode 100755 new mode 100644 From fd00b4beca1d8dc88150b84f94b6f1443d44f148 Mon Sep 17 00:00:00 2001 From: Vitor Baptista Date: Wed, 7 May 2014 17:01:14 -0300 Subject: [PATCH 45/77] [#1703] Fix bug when uploading resources The problem was that we used to set the URL input as "disabled", which caused the browser not to send its value when submitting the FORM. The solution is simple: use "readonly" instead. --- ckan/public/base/javascript/modules/image-upload.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ckan/public/base/javascript/modules/image-upload.js b/ckan/public/base/javascript/modules/image-upload.js index 9b3a15ab68f..e6cb99cd31a 100644 --- a/ckan/public/base/javascript/modules/image-upload.js +++ b/ckan/public/base/javascript/modules/image-upload.js @@ -89,7 +89,7 @@ this.ckan.module('image-upload', function($, _) { this._showOnlyFieldUrl(); } else if (options.is_upload) { this._showOnlyFieldUrl(); - this.field_url_input.prop('disabled', true); + this.field_url_input.prop('readonly', true); } else { this._showOnlyButtons(); } @@ -114,7 +114,7 @@ this.ckan.module('image-upload', function($, _) { _onRemove: function() { this._showOnlyButtons(); this.field_url_input.val(''); - this.field_url_input.prop('disabled', false); + this.field_url_input.prop('readonly', false); this.field_clear.val('true'); }, @@ -125,7 +125,7 @@ this.ckan.module('image-upload', function($, _) { _onInputChange: function() { var file_name = this.input.val().split(/^C:\\fakepath\\/).pop(); this.field_url_input.val(file_name); - this.field_url_input.prop('disabled', true); + this.field_url_input.prop('readonly', true); this.field_clear.val(''); this._showOnlyFieldUrl(); }, From 5e731d59ed0a83fb76f72c4f7e25cd8d38db32c3 Mon Sep 17 00:00:00 2001 From: Vitor Baptista Date: Wed, 7 May 2014 17:16:14 -0300 Subject: [PATCH 46/77] [#1697] Add comment explaining why we're ignoring E501 on tests --- ckan/tests/test_coding_standards.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ckan/tests/test_coding_standards.py b/ckan/tests/test_coding_standards.py index 849f50c7df8..d0a433e2705 100644 --- a/ckan/tests/test_coding_standards.py +++ b/ckan/tests/test_coding_standards.py @@ -871,8 +871,12 @@ def find_pep8_errors(cls, filename=None, lines=None): try: sys.stdout = cStringIO.StringIO() config = {} + + # Ignore long lines on test files, as the test names can get long + # when following our test naming standards. if cls._is_test(filename): config['ignore'] = ['E501'] + checker = pep8.Checker(filename=filename, lines=lines, **config) checker.check_all() From f94ba37a8abfe4b7423a118400daf34a9a51dac0 Mon Sep 17 00:00:00 2001 From: Vitor Baptista Date: Wed, 7 May 2014 17:53:19 -0300 Subject: [PATCH 47/77] [#1691] Update "Add group" explanation in "Adding a new dataset" docs --- doc/images/add_dataset_3.jpg | Bin 97734 -> 90906 bytes doc/user-guide.rst | 8 +++++--- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/doc/images/add_dataset_3.jpg b/doc/images/add_dataset_3.jpg index 4f46594a1b640120335fc7c9d9c9542730401618..eee2f6b3f29ba9193890644cdbd68cd4db6fa7ff 100644 GIT binary patch literal 90906 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

    BlaB z^l!w42exM$#yrv0puAx-mSJkdhgue)CB2K0kt-Yhzvh{}+u~V}$8~`@c>uxxsb9nUi$gfTC5wVby7F)`kVE&ImFBo^%Nj~nOvg)Wx3sHi!a zBrs(41IDtKr!*M@G2$dwF6h^q%TfJmBm%Z`+bHEmP;44Op@YLPPI&-w2rxOdm&C|4@zE51A&(`9iG(&v<;OL&6~+bx zo^g1r3_P6R{HBW*TqI75A~HjE@a|DiSaxnAkol8X1mSR`Ti-F*Fm7mwO@&{HBX3hngx$W3}}- zD}28FN)m<@q5< zzO})|-Q6X)2X}XO4-N^|xJz&+K;y2ByF(zjySrO(f+xs3o%eU|w`SISv(`8Fzdn8H z>{DC1t7=#6=h>Kp)ma%Du&R&>xU3fr5UWM3En#f%fCUS|nZ~FkUr@$~lXI$rN;XYi zS=-LrbXqZG)D=Bd4}g3P9rxeJWBc$FufWV6EQu1rzTV&RFlENvgY-Tt%5RCsPqp5< z{OrQg_O4Lu_aM0v=WT;>IfYDDB^JYA!<~9?fDOlOBoeqkp=@oZDD@M8Y<@`OrYu+z zzmlw>p$ImC=qoKhB)q8;TWE|wi89`Pi*LVdX}fI3(x9OPQ?6p*N$cO|k*Ujg#3MnE zi^K09@4o82M^W$j-Pk)a{!;W`fpvm4^q^QZ4e2@Ff{@UKRx&t`GRs!E)4g1P;93_h zT36AxelT=vgS+JcY2&KJ4MHdmLMjPkusZTIxZ$`|)Z@g}YPPVyF58r`%H`Vb~7;{&I&qG~Ul3kJ|417kr;-pLpT;h4_w?O z4P_SGHhMN15py2-+UeOFh*Rx1$ArZXHehwoEyMl+Jo`oC@@{nHJ$IVLoOuzSIgoY_ zetwpg?}R#-gH`=KJfxuM`hd0Ba@dVTWzcmS(j z_G={J{p2}qSDX ztt6UKfDQk0#RucvU%bAY&fklIoN73n-qlN#Z!r?!yoS=|%@Ew1M&AABt6%riK|gob zdH6ZPNT1v5uds8ukv^>zOf;rzKoNU``CU&D{d9&&y}v*1?*pXegq;q>JFFVT1?m=F znJ4SF89j{FmqDKev}KH)4&nbiE!l(x8;%4U>%s9hQv#`=H>nSN8#{@kHxv~`-foWv z>QEBcUrs7}Z~TJa@HaL;F=p3?+<{-~_b7h4QqLK3phUlMW(ZN+HYJAaU>-Q}{o8}) z|L#FTNWQV|igO1ZRnIQCBG%t*o!q_uq4;1o&l@7)V7GV$4~`}igS5(z^SQ?ft+N$^ zj#o=iO+f*BH;hw5K>^1&Y4fnAsfa}LNh0$4*Ea|R06`5!kE_oKM7@NN@=0v~R2c|< z3@-gblr1B(~uzsiXP9x+eK zUVL4DcaaOo^f#L4iz3lOSw@GD`l#h`6s6Jr~p&kD*iMnXt}@Sfn@%M-)HfJ3;61g)Hf_QcC? z-o2yXb%k!95Y);ky35n~?l4E8GTTygcMuJWQ zKQ~~N{#RkOoSQAPx0mD@e%0o`QY`6Cq(g#RTHM?SNWJzJM&@9eZ?^vG{cqqTg!t}r zI-r6UkveG8AH}i*I*TCsjr@Xy8~We(AM6$y#DEB1g3$UJtY0WN@FR1byUm`T8H6nV z4Lfv8%9Lsa29_PYZHkS+Sj2yI+v!l)AXNPu8oqliW;m3XV)q!^+eR)sO<`)e|K+&< z*uLzeI%}oufaQ1gKdknq38f$YJ1+mV9I{5n6q@vct`Lmc6>D#{$=tt=fl%}cn+q<# z`s2n8;Uiv)P`@NDj>M0+vK~g=mHv$=IE25hd3j>`v(Ix7Oj&4dwUyo;2z(>yy;Nq` z7lPD5i~96?)I2{kJ`79BQ%mkcmi9jWiF|u)WP5+Z9uhO;e}nevN=G1S8%(3X&=&CH z7J{mb3%>|){nM3!&)?r%LdZ|%j=gZ_{*rIh7jC&GW-f_C~QehT@~? zI?1maHI-Jeb%Skx2nlU-Kq4}^}BtT8aSK%5)ERi`vt3jzml|Fv&PS9 za!ezlTWU(3hA57o?+50m(!>V&4t5J}S1c2LK>$dQ5g4oM2*|5$hC0QSx7zOmeoFiP zcdzaL(`&GCX=C##d6jd2G-Yy;gX0nqNS@}<(+m-lm*tSq!qxT6%$#zpM@Gxvgk}tL z5w=6(vi4&XUDu)RKW#3)HaB%WGYCV(gy_UMAH?v%+Gg(^u|h^^5tg;DUz|qzM0i&3 z-oTJfCUFaD8punZW*UBSKJJ#nv;o{c*{)d`t^);y7mYg#elLV*daL zlujMm`AI7|j0>rKaL3_qS7+ zw>jfC3QqWYt$%8E(xErS5PI@kVN(C&5r)6M{f~0?OvxVXM0+XCP#T(HOUbQ=Z|C8i z7!DZBo)9oXOh~AtyKY#LHhv_ODcDHkQP`}Y4eZM(qVfD^9R2x z?gv{@-VG?15vLeLaHH%WWLyQI+*(23skVCwJWV83kdgxQpvlO%oaqd#rfgynwqlKo z8Cox?=ibr!jm+SF3id9tVwc81KSUVjX=u{HgmSQ^dXE$crKwiEn92Pd%UO#qYKZH7^0K6r6=-?h& zerdlEiAdct6t%1!;%Fb-`YQXb^5RDsQ_(KzGZ==6guDwNLny8*f9%6c{Yu8z!|$)v zK;rRj04OR?-QV!A63$e?q}W{MsyZ^L{$}Ju8M`?Ch4l!`TBxKI24&ts(`#2a3|rSH z>-T+4{)vgnQx!E~DBjBb*mlzDqSm~!Twuk13V*|RB;@;sT4={p_Gi-ouc_4Or#8MW z(|YHnkH_(Xj#Li=7o-l&?#;2a<7}Z&kE7Y1Q}kvsmfF_h^JlFEX0Vj8~_A2e(K7gMghYcKLbSKz-r%F^@U6A)6ehT*==8a z>ABV_j34Y1>%-w_Z1)J6QGx+(HU*P5FsuEXI|~S5o{2R>p)ze^Y#Ep}}j_D_n42ucD7c}P>W-%E?TC5AlcFb8GR7H>sBUm)xL4_YXVu9sE zpm=DhB6N_mN1>FM@K0DS@i4MgIz^FumFiqoYz-NuVQH1|roE?|gvV!m2#~3<@d<|^ zj|iPWhjY%xyn!mlRrIa)$eP&4TzxUz{j5h)Sq4yFRH@=#^oqTkM`knkMM)KIGq0(K zS_8-8IBufWWGbr+=|(VLcbz@qi^30a0Je2OdI)TvnJpVhP!cDeMU8+r8-N2^IVuu! z8Eg0nbNQNWoYrT!V=M7+E%KH#GwUvcp3ihx2emX~s?r9_BBn)1BiT;F%^qY|pq^>T zndzD1qt~b&#*efdPR-KCl|R^oJo9NdBRKOk%aTfj*=JeVUO<^}eQ*vp=VcSd@T65$ zs&HDili&{6OnN90B7IqHu%&Vs5PaN3ogQ;;kg7DuZ|Iw@TCso^Qi+`9ae9((Ui%~u zoTg$|m}&%rQo@_8&Q6Hgtp32OPaoZ3c)$U|+;u@J&H6(@#2}9+?)zu(ENb!BgSeoc$Sn{q*?ja!eqt zCn#YG)1ZuVz(0|q@(M3@T zgV*Zn<};iqpbk)427iCj8EC}Np)J#|k#FQt28`J*Yt47_scXuq#P@D5cf`5~eZ1fB zQx2*dzW6+E>!;FdpZ2wKnbwg8OsfKiRlnhVjI-W;D0w)~q9Bid5d~WmizXxJMX@X1hc~bACuS<+ zR9U$%EKQM{?HPG65<||qZ)Aa_B3;-6hIm+ts-uY1EEO#-E)6=&EEN-y0T8#3N7?vd z#HZFoF>gMEEX#vdoFVq7B>cHf+diPZV-s<+Z#Q56(9Ff?nKkFn;YK3KD}Qx1<`Jz) zJl*}9s1IHVH|U@`(_*3z##KF65v3k>efPrA&yct3BE6xFd&VZ*$)c46!p~g#^CI-u z5(FIY`FksLcXa)>0A($fraQ`ZfBy*(8a9v@|8>{txz5O9`=r)vo%ytIO?@R!`xw}K`vo!CUO2E17L%2Ks6Mi|qD z&v!&wYe7m}8yVidN!Hbnl4>R7TDhqH!_ivdQ=K(7S`kcBcw8!FJ}LCk+{N%adwM0^ zAY8!eLlvbyYu9|hHEG#it|N2dJ~zsh(0*q9(SJl;#aQtEw>H~72GX>@x@9%GMT z_eTQUF>J?3Eg#N^+P&w^)DFrIx8;6TNh%pb!*Bs^owjHf-|qk zy8Fxj0QwB-Ng-Rq3lwD>J^i0=+ujNTyZXN(<&Wz-v0m(=t@IHNzeD#ZkvUfMW^1hxMscS@Ro)@bh zfOB+u;#d1qs3FyiJXg8JBp3r~l#5eL54e6KBiJLTOo0n2-scChiHkCx(K!80W>yW; zB>ceB2YCK?F?l2SZ5G4g5LQAr_=4?$5;|wU=_!Gy<9K^<;ub9QE%zE$KTu3v7q^lD4POPs%lER8r>3T}8@q7TKISs}$$pLb z>7crokQ2+BHt%@mLo3&oa3S$T+g!{-99~9wNzBAMlq?&|oopAQVMnm~+&=)u3!b+- zIe~*gGlhYM=2I&|Qer+1F}{d|VwV-I-XK`(X7USpH+v$C*6X{Cv#nu1HHXQ}`{OTG z-_$=#Pa99$5N4xSIu3;@Rd|&Q76uUG=SnvSaI7h|(1eHDgK4CQiQip1 z*B`&`Kd$dx6R8%fOXzA2E}F3-P#elm=<X{&4Q3$4A#BFEFr`{QYORFip>$L6`Zhr)5(W(r6J+dFO_MgJ@yX zpq`tmCPF2o=F-6Wk@LWKETvLS=}yq6KC&7cSyRR$6pmo_3%+PR_uf#FyrF6t6L&-- z45vUQxLL|2xrmmd4VTYsHmqwOZ4Bb#_}s!K)zYy&3K&9q^nBpZsW~%*PLB`B`PK5^zD`5e#mJ z#9J(VGycS32ta4}8Yz2lHz$?bv=`@ZY}JMg&a?5Xu&j^rjJ1_oM0&JK!l}y2%I(>0 zg50ztWo5=L4D+Pg6GP^PlX|+@rd0b9w1cvmPQ*@_PbdNE)bJ99Oh3*K(*dx_ba2_z zUj7?`hS}1&6ZB3U*Q48ppK&L(ZUd9$RZJ|B`8X!y?TT3jn}}chG1Z_rh6>a%V0=%&$jqS_(Rs`OkCK$m`c+Q@V)0IQVTzOi$^QTtc1{qfd);IPnE@8gsfE%Ih*$~w z>zdcO;uf*SrFYGa7tG=Ab(Tb5C|Y3lwriLBLj6e^JEB#9Ovh?wLw|KIwHvmM6haojx5B&a*Cp^7!4&aBwtL!%Q?_=@1qVLph1AtILny z!;82=bCi=^s+2x{A-~+B2>ir2sXUxSA>|Rrt-gREKfyn*n=UCdMg^H`84HC0zyQs{zjk+=2G8P1@=rL{M$a6p>F$^~h{ZoX5<&?3ZBXH$}0LD3^zGej$qHZiTFdK?RljS)KNg%2&ehbfHKt%*lJo?3plAvS8V6*@vHS2=5l2vFN) z4;&uP$RG$%bv&mML43f+Z=^yZ3pD=o3mMi840JT$JO(HxI<+Cj#Sq0S5V%GG1@OG? zdk!0M|(-r2`fpDEU$gm)YObg5j@anQ^rw6|;r6hO*?Fwb1pK+iE{4CGTXBq--zME@~mY#6q2T^rXy*Rn!^s z0kW+AYis+AfQlH);0oTv!SOuRESt$@W8~xc?5l?m1d+F~9lvaWV`#)^z}10g4z-~g z;RRQN9F8*nC=td zRKRa98{W9eH_rFEDa^HAc8Ws@%fwJ07$(PIrTI0(2mBfQoK6TJ$&4zY#H5xGK%6TW z{uJrFD30(kf*Usl%p{lq?fYUWZJTu*+~+!2@vj3Dr9+sis!E}#zW84cullCT_#sYd z9lGGTe&K!c?NZ~TPV}HX!3E)_COJcx%rO;s)f#s%Cp~xG(_ZhM7St5VSCU}29X9Tu-xe>>=#6OfcWY26y9C~gbt6ti+UzK zL?dir-H5HU1b7`*VW~1}igtxwVo|_|yj3myMoROpg4&83Pm^NM$R`jUz#d;8P)(Y{9eL?SN66^TS zsoR6}#?|lC-Dri;g95>E{$FfVX867!rnMWRW|z(r!oI5?821fe8@y$EzlXD20y7?L z%rxidTGxQqE$tg_s&18zi?B7VrHSa-)hc+<$p;u27Omk>-v)JBkGq$zVpVl`60HD$ zxPcrX5CYwGDN?BLU9*)bE|JtRl#CJD1{Lu;KbPR=4`i<0>DcYSmWWdptsJw8e0Tw| z@Yta;!<2x$-{sJ1fp%Jh;HIkV6R7&RQtmGn49y>FL+yhf_@LwkrSJ20*Sm!a+I>3= zWRy)X)hiT3#bHsbK~h0ga3`nS1e`?k0BEYY`75Ti_|UT@QsvAJ#<4CjAx)sQ<~I8A zPG;KmNLp)X+v4o8vHYwq)S@_FNBo88{D2#Eu7L=C+`5|Lmob58z{h!-Pl?2%r;Y&~ zku@`J;z3WzSY$-il=ilfZL3f?g8SceZ;($gtnEGR27=s zGtKBwWE5264e^Vuszayn>JNDmzQom16)BKTro|PI*d>nHtIUd{Lv_tC_hFuA&_tqU z03PgC4Mn5Txl7{4AfqmKjh-|2;1X450A&nirGlz9nC37HWNKYTkG(6di(^)6v(*Uc~#F~)q0p*U@SFp}PkjTqXVO3Q+>@Ds0Hc1)cqJbfsS$|3( zKWVS3MLz{`Kc?tId80eq!>%GI1a~ycs?fd11!w$B^d)I=$&hRQxGU}`4zPl9sWgH{ z#r&iyA7YjrC-si%6Xonltzze!M9;G2Y17`Bn4v<(31m&zU~;p zBia;O&Pn-;mbJ(PKo)aw-Bi$=J-m|{+dJy2n9fsnzO);Z_@XO;H305@JnRFHQQf&+Y;+-1^=8G^~f zHby;00tD<-RXc9L8pjC6Y*4;XgPC6P+ekblaP45L2Ay}JdScXMh9L)WiGw~}z_byI z3uC0cdWFy>@6%F=j;_(15s*3pKQtn?=OIW%F~La)-JdlEhp-AJ1|EGf%ieJ@`}Ag7{{Oc!=&d^;(NN!mE1dE1x$)s1Vrb$kRKpErA<~KWYv@=$L{i>l)-$on@;n|2?9__yI z{ur^kwDc#R(p6%Qte0N6)4WjU$eyV$0UuIpq%wj^!U6R-?jR6icPr(Cnm~m`+T~n3jqt)jEa#GPXk5gG_Vtgpsr0OR z^Ui4)8-G>@f*y$A>;3^u5K;dwyLp5!RaBmtnRU*|31ww`%J)tF@>-Z8roGQo#cQ771p6-wOs^VITBeKf2 z_?iUYuH#8OYuQ^`-EHd3I%FyVk-})gzKDS4`F`^{cehaaJG6zlwRj(Sm?Fb?inx%6 za=#ZHwpf!4Cdd#MS;z53P6Er3RO&Rd)Z8?3Xt4-b`ZGVFB_MUuG^&Bbu|dC5~_nP`{Q5XQ}lCMpsnCW>uRa*G4Y0&aq2TNm~A9xl1?fk;@nE5!~Kdq#+?t118 z=1z)cj0YXO^D^W=JI1LJ5c~S?2d%mWulHZ3+?>kErZTC(8sy)FAgf|ii;@3&BCk!1 z=ij>q=Wcg8{|fm(`|2OSDaIS#-*Z|;4hfmi<8O3qn$IA~tzN4z|hq{16h!U|ZCpnKud z0A!)6a|4N8tCWlXXcs-|{ywGn>1C!*V9}%Fuky5P5D{g0YK9P3vmb|ncOWwI|7TYOuoLB+cNAgt z*{1O6uQ+RX%OWrrVskp5wh$nrm1&cYA+ED1afeCp2j;o{+v>|6IjqC8goRb}JLPu> zOnfu@%Cp#R({H2q*`_&n*i`KA<>6luFGn7R&dntV7E7;Grmon)Fbh2t+*tAr>+7EL zf=<6S+A0ylwuaI|f) zuqKsyLZ=jA`ovfAJ43s0KiD9tNW}zhtcwIps7)te?87}Io4I*9n;qdD#1GSkzV(JF zZRjrpZK$vcfNR}!cN{6Yk=6u;r_^bs)1bJ!KmUmDq>Os z!+s0>v_M8l_dMD>V5R#~`HX~{vDu%+HTX3Y%z?KV zbW?rLvhb?L=M}gzLh81Nk7PF8teHG%$CW(D#;I(1MSpbI3uZ_gWiA||VDq^-)T!Ush_NaB3 zZ8npju?O%&Zm@^0W|?X=CXp>B=ff2?z=em6fas?_3T1n61Xm8}uYSQ5ZI9jz-i#na zL{@w|VhPwky}@~2V`53{ET}<6HXcxTIaE}%Tq)SA>=;TtnRsKr4VWguBAEtUOcCqp zoSf#4lbvk{Lfj!YtRe@jj23K!^z)^3g{+)j$5Kr>MY%N&P#LF6;`C0KkED)F&4VAq z7k)_aA;D(S4rb5X-KP^do=9P*NA6+WY1=uFpdJuqSQ98cUadDd$rjlv& z18w7O?c+gTrxLy4rA?HvTaSHjS&o7eIG;eR_yd_)Z+^Ju{ur7A?Ph6>^hynd6+pibjD_o@Ag-d)qlqCQyQ!vW+0fQJi;As|m4QO#&OPd&p zi~g2mb_}*X=smQINgnVNF&XV(I$m`XbK(qB99jDB@GNcR@evQ=^|i)NuMNL;)}o(~;H=KM_5sX^v8m`%$9xN3+>aTi$uE#!{H(kA;z9Iu6f&5Nz2ITjX&hi);q&9kTBvnC!Lu2;ws(=2ayU{avY?FuSON`63XEvSFSBh(=RwAXl+(V-IC*ZA(@nzw zQRU>TuTPT6TpxI=Z*hGX{kwGul1oRASq)kV%^{R#Zgs4YrficX&0uXKedDT#i;|*G zrAtdiXOdU$rnKSf_Z!@`X46JcsQ`D7&wyyd2ian>sffKl=x~q8xg{}a?eS#U*{nf= z(1_tJ4WHd!M9zG$K>BXT#YlTBg9F|>JMf|L! z2mS{MRCZdHCO_D!IwnQr@!*7{))l_^`ShODWAR2p;b7A{(^*=m!4r*Xs=}-8Uce_T7vc;ePt{U30Z_xhEUVjeJe}cAC8f2{ zAI-g9!MS7!lN3`7ZnM^9q?oS=^6xxJ@9I(1)1X8-X)M*?HCPpxM#L-xD=cpGQR**b ziPEz|l+gvA5;)=)A#{-28ekFI5W19yQp7B+UVC*HK!VK<{I(tYUQWGW`#yk50O8R>`UjxR z#NZjMzheMY=cXMpP#~Zr0fP8pfbi@(6^OJ7A0!YWs>pr}dPrbF(MnSxvxbFu#7{*+ zP{{DaKY@;-1zTH}?*m#x7~#wTrGFePg!q1*y?>#urzGPuoJD+l=snvs*>aXPl&SWa zEnMb1J$*BRl#LQ)h|?qL7-<;l72Is-ZLf6CV0lwN2~99KDncoKC_tP3rDK=I(S;Pu z!6Opd7HOAAQ#Z);*~5*~Zn*x4i~9Dl^Dvu>r=!zD3}3lhvt;z6TJ3bVa&8*-SKnG* zjvH&&bVkV&s6{Dpp_$tiV!a8QjSz>guJVFICI4JOd>DZ4(EvQ(mA=T zK2{sVf*YCn@&ZjTJWI-6W@m)Hp&$2h&_Js_Sf{qQ(K)Q~}~6BK<5i^Vd|!d*r*DjeX&qmB224!qJlRJ!%pUL zC&KF`9@W&Q?5;BK0(=#5jP7t~P0zt`Y-p|Xm2k!eoxG28dd@|A@R7_1Pe8z6sdGuH z8~dPctjN*znuC}ELIcCoRvvMCL`UlI)KcTI+u7v0v^ilXXdBFjoU>I864XN@W}EBZ z|D-cZg1rvJcJCS#qJsO;Ky;6yDl;qW82QrFkrZ2gYY?{m$$A;Kf3I>fi>9(g?vvx` zl8~e{h@Qf_rHAIC=p4O)bA4SA{}@DS3#it2X15_)GNGNFrJPXU0nnC^_Q3{!%*Z*a z5pj?qcBs=#bdPZp_?&Dk|G}#gT`LJj-SVoxdo5=ocZeS;bF+M6{fLWj`R1Iv(kk9d zdWki<@)PBxJVA~kNnn6mD$$Wr_!nfLta&5!thT4M4oB}222Igba!pPsG@W`HBx>>^ahYP2osNyA6e+svu4abBruO^$`% z0gMWzAES4$wGo(Gc*aCyE|t1HCZ-hb;+brWIek(&oAJ=Bie+PSOeK@t0zLNH0sv@i zuE#mG4u|Mkd6p6#Em@O7vDq{{b+io&KbQQtfX?y`K`1Q<{-g@;=fff;O1s3#zZD|w zPX||9^Ci->cn=5%TLRsA^_?wCp?4#HTU|@>Q&A*qrQI+H^dv!j=(Yny- zt6OpUvA7tmrjxJ*Z#U;y>>vMBK`Nzv#nDo_y=Y;Kny16#sKDL_k(hgFDkk~!`pFmx zj3BbuPlTo22T^jIT>*bq&Hc=PR){!h>AC#<{C<%%KY92RAR!!Fo!=Gzs%fwP) zC*|Ih!_Bdz0F%Q83zCvanUaD>qMftkY?)?_v=LvkAtZi|F`KY$sl_@c$ssEHZS$l6 z%Pqtf#Wqy`55PTv--a{$V^e8&L}L%qoSpt1hPeaBG+lYOVyRh$K^H5%uFKhxREFka z8%2f|YGN2Iu!mvo_yOB_NRI_N%Jzh=wn#*FlZedx!P2Lb4n~=SE7!i;27f+r^DaP7 z%k63sSzPKW8h1B|X1H`OeudngI75J>k{q=lgHAQd$^88q5FN z)Wk$hiU`L9vxonNxgwy(lU`9yp`LC_{6X57TV>(P6u-i3tsS4Y} z>gM8J251MB1oHCS72u8LapJjZRWM;h#C_b5LgfS%&gBies5-RfShQ{`TSe z#=z4K`G+nR2?YlUsjRGPM#Cv48>e3?lZ8sVY7OwO*Z~NYbPG5{fvQplnC}W`-*p&hE4YjbxHHn!OCn+@)_j z=eIywaCT0{lz&KiifO%vx2_9=?&F$lg=LpKyyer&6ueLPnm0v?EiX|l2r@Y0ob+7s z5APOfKNF;U?WB``#mIv!i}$t5f_>y(imVcPe_y|-BIdyzQCvlX#9;omruP27H{Ffi zHPLwgnfc*H)bD*Eg#Q2kbAo@LW5FP|AXk6Jt7bTV9-*@f#Hkxq@0G>LbIQa)(e&BK zO8SxQN1oRJYpixa`UjL67;vGI;ug<2o^QlBpcS7ksj00=um@*Lx4Z<_?Y?ldkomcZ z7fmwEFNM6nY@GwLs8C6(ph_)gR0bb|b`?HE6JG|7Qjh=lmL+7ziw5g|dr|%)f#J6_ zmbVcs-ZK)CN`J?b>Wk@Ik4)E%OnP{EPyu)|cB8I2;b#alvuti?mOQMZa~|a{m}-x8 z#Bxmabj6U~?ZE^K+5X2pSj`k{U?Ohb2MCVlbElj(mZZB~qh`^nJWZA55$_(P;115a z7Krvp-M{0s1gm41lBNLo34n%bUD=qr>%-3#r*H{GUQPI~Lq`!3hCD_&aE4FxgMhGD z4;M0%JS^V|ab!a^IEJ9)w>f&Cu-cgUF?IZODquUfJDTKrc*A7F306{(+H#iZgm;gj0q`cO*V72ib8*kf_% z&(tsl>@o-2+Qt#+ghQ)R#5Q?)q#RR7oC})O6}~o%5BO{LnIJ91??a2zBPI-z;$RiD-_kEvt~Zx$X-7j&#)Q%i(?(LRZvAVhPY zluFkJxh;Y=#5WZ>>iI^aY2eaFT~iL*bRmd?#BAnf$PcoS@@{0))DmR3(nZ$U0c*#& z>&P~wN?e-b239qLbk^|_RL2i`8b>L1dPFgrsD6hSwy@So?jcr~P5tIOQG;6jO)FJj z07sdzHtvF$=q?$U4Wy+fN z!%JXtYi*;bTstQ6ldLte;$kz;QsE1URQ_gaf7udWKcnWD@MbEkz6&Y=bb48xm zt=@hS)FEH_6U?0&icj# zdE9C5eTuSqwe(1UVvi8zh8qqVmAx&K{;wWf_e~JC96Iz_hMOwFGMc9`DNJM=gXkV? zueQb@&y~lwY|>*jd(vYH_fWE|U>epYs>t&D7T!v0rc6~$=){o8Mv{3DP<$RPSZJLY zFbI>Dw^#7QGV$4T6T<8HRJ%V&ANUb8X7*fm)XA@~rPGxh?-x7O*5ABOu-8MKCl=$7XrN8DV|0K}SK#L>LHbvm(P$>44@2zpplTS%}%Qg~FmQN~wO&Hjk zx-v9COK?X0A#O2d%R-=1x7#t+2L9O8Z0j$z?cNDVq1d%BvyFesIx$hPy>G?e$GwqrI$ZPRe5z1Eh=Eb?7&r?e?fbxYiGt`B>F*{OWCJKhyXXwZ|!`Ns?k0|=1#-({P z5y6!2H*Dz`3$Sbu6lP!QEMbc$`IU|9%Ye6@(Ct3}G;QZA!U7B9o+^#fY@)C-hKH4{ z{;35pn7k-ja>7j^-_FFc-&#hcu|Erm(Y@g8mL2<*$AS4VvpZ!+VVb--?K`4UmNNd@ zlr9bGnenWABGFIJQM^i#d(QUnVz)R^Y3KLhiY{EXw&PacF|w{KZfnLBQ@sQ$AJ+VF zSR<`}wODA@h5l0hU8%8^nN%yp$URw-Otm(I6nQ#T`-#fl$f+|7Y{rQ4AY`9P=n`6a zhUQXfIJ+E=77CC;#76Y1f3Tgzo|P(rNl#xT%^8fdAF_*gq!$WHi}W!v-jyF8UbgJb z=;%O#{`y4#)ofZr`wSm;5?#HKaM#jUB}7ESf=XjVD_QfN=}5JXN6Rx}3hj8np;V$` z*cyu$7uPUdiF6%%wI_FQ?{sfR4|U|zXWm&?KK+$QL8}cmfx#VCnpoKTo4N{h&FZ)P zLcwN<oxJ!W|Ipl<|#>ruPi(9mCuCBo$K< zwfSHIqxLVE(5oUU6!WW(6X~N7bj}{(+43mJWV;Po5^O(a2JI@lj0IX9rBmiyA9e)Y z$j~Qm^V)98nDjenxGZ+Hm}ExKF!IP|l+c+3YQz}FHE{`#TUB19r-X8!1Tu5y>TvGvcwX~UN@w3Gue?rz`D!{RYGop|qg49TDE^m~R0lz@RG~4H2>$s)09Fph=I+{UzFJUR~YtdbfFtnw)_j%H{&S zQ*5tfv_XD%`BnS&>wx`T5#HEYp4zixpgWd`76jG;Qt(s`~RM4Cd$a%`^b$`#tslN)ad)vuTk8ji<5d_ z%T4_ZVQI%8k=Ia!Vxr8AZ_gL$G>bx3-$z!^`V7{^=l%KOQxJm*hGtB1p(gzCrvLA&o*Tn=O8D8MZ6D#_*J-@!o zQ&)BEgBn4pd}Yppa6^#!ZK=jv_%ri65CL+?UFjZq_|Jq}35^|}%Dh89@uM(=PvCj~ z$S|k|ddTJlq{-KEIa2iU$B!~fj_-R=1tX07K8x%!LgYQ9A{7@p$#TBXrBS7BZlQf| z00NJvs9IkD9WlJp{pXR?n;cVG9Z7?65xPyDZjk=L$1DbnDA;A;z(e-zj?KFfb+7`f z4>Zd*`_r)q-HcrYL_A(;!=Sgq@++M4Tox3|`{*(z!90O-2u^1je3;a)T;{+-jxaCd z%#{n^nxZac2uUOsKdzFm zd132>fRm9kXPjSd?woIC&AM~fowe?N z)xE2$s`uKvs-CBQqLPM(ko0H#^1|laCSs0s-|B3rPd^wCvX(&Xijf>wJvT4RYEQ0a zZVnACk}hdELl!MG^d(*UHHr-Q5DYk!YSE%u1Cg&8?EqF*y7U%cEovyvbP4S4}6Lh~(7`&dB%c$Uboxjp^DE z4_STDU{vg6>}K_|A`M>*!Q?w9>G+Arwa+L4bP!v?`Kd}iN2`kLs^imD2gfofUjlEN zE@sS{>xLP69bjP~kZLy%F)Xrtmh4!0h&qzmqY%pKtjQz-bwk^5Xm|yG$U?Z)bE~1d z=GkrZ0sw+2(0M$=^wD+6`5V z0?o<}E8J^|Gb|17P4a3^0!of0ofJk{vimp>GJaolR~5mvAY45ejQR=cvYohki;fFI z60~E5Bd3DcD#9M|Y1*#kNgoaC;pF?o;_(x*Jp4fkl?yq(TnAjv&CrYr@%6@b&P_tFaT|2xxp^X#*X#I& zJ~_9@MUd3~N{=|LWJH_SqPc3`jFLdob8Tpzj$vEL^l z)6Iuo?Fn)HY)Q?>vChoS&d+m%!+w9O+ERLIs#4_dj*VTzo8rjhph5eCcTBwWmz;00 z^F{Z_w~7;X0HGbe!Tc!fL&$99?zNC%n8AilTKzlZ#SCM^8&;J8)8V48IrTo5brq%8)&@OmWX`TC%?-p%-!Zjs3XVTjm{}c* zchCB6tIby2=f2y5@{8dy9}Vv&QKp{hylVL+}IAhKV}TvV_-R=o>%+0017RDcueJoy7ZBDVTq| z;$43w{pJY4N4VQui&z7%YQB3(zsx{(y7LKW8Wj%!Wo1!DPh5GpE!8A5K}1lZkP$fP zpX`S1hCiW&NMWz>TG}n@!U5~QaMikYTtjSHm(U<#T;x zo{mOvzPDhp!IpLaz!XFe}Qx| z(HIv>Ii>HuBI$kejCQeo+Q!$*j<#wAhB(hl@_%^P@=vZJn)x8{E4W}eY={)2&Ve8Z}yWVUg(t@k5K51Ih?sUZ;EY^$Ua4dlXM@v=46D=GC7{jbA^T*1& zd!Kk`S@B{I@dGlat~B}<3buKsitJ*&pW5nshi$$FbNS~>`$8HUXJgKUv_#^LMy6_O ze5N~&h{V^oZTR|1)fDc%ruSk%`jt$CmTBzvn^=RP3FA|I{+G6JjE;^m?4+fAZxel} ztJ?GoAOp+fK=CG++3Ewe#3hIZ^9yRyLZ&cYP(LRmSOC?*RP?dCJlVIC97S#!;G;s% zF84#5L35roN}cB&XM%l>ISJIX^JtT8CH&`p`I~?(UzfE*`PqF6a0Zb9>L(rv>K2Fr z^<`2h_=7X~TGe}`3qij+H)S4BIMwe59#$ye_4QW{JDl}CaRwmQpF;BltQz z^3~y|q|=tH{9gH60obhObO$0`v|Zf4gE9fVuhlA<0Y@ zJI6KIVwKbiBIc>Ht?{5ssa)_1WZX3a=FdYVi@y3=sQQXn`Puw2U1QE&s&~z&8!r;f z6Ri;utsQCSW6Y_{E6`H!uhr~>IHmc zQJ*pJ+5NDVAQtQDzZn?UQfp0Vuq39J_QB_pt54-6nYPYk#{_9(aF&>kkG!0kiTfnm z$deI#Z!2yF75ZQNl?)t(p_=LQFGUO+z$&%J1s-%WFF;sY>tP!k@ov(wQ)4NQ#IOVe zS$2=GjJh%iy?8>$Z+Zw72YPc)B$!{hbh)oTHJo!^eO)xe{@e?-yyvHXhW=B-(%JvpvK1$W1NGRvd*R zm!zq4+2;Eo$41|h7B~ut`?D#fEn4Fx4ZX98<>Ha*L*_cKRaqJz(on>sDXxrI&o__y zxK)ph-{{RaS3gkqRZ4;jOXT>0G!~46ng~#u;M3a?6NT*a;yG!uJWBt4H7iX`wIIPN zo)28^eh+I-kW6)GW6nV}3T0NRS(O}X;jKklE>zLYQ=C#tB=RuzIc@9OQ`Ag_Frs=M zK&s0A#j$t^IfcX|lw}v3%Ef#{i`@v!5R8OBem0L|fMh?%;ELaFAS_^0fBikUED1RJ zEDBACqaQ;v(iF*@683;b|6y{MlB1caDwOZ_XThyb110S6{1GXgB~|>K^OAn{IG#0d z@>z=0%?O#)QR#=)hkd-_ud@fHzpl|rXHM7ke}WJkVXfbnUrNhS^qc;2eOB^6Z{SV8 z$-#`k%g-ZZI$_QKYd`(J_YKjwtY0H^S7|mzK!g5fJN@_Tmfi~{y|3}CUq0YcmvuJ3 ze|q^!k0bTI)0(83b&}K#3E|>|W$*x+Ag6nW=o`VBZ9||Pfzdv`NOJciC8kFTy)ejc zXG6q(E;n$Y!Hl3p0$CdM#zvrD%$2$VIgHn+ON^}bm0Vl0Sf;cSp1X`U*#!p%0ScUpVY2CgIufq z6V*F0-M*AA5*geh1f(Y}#otuLpW=Y21^b@aBc2rk=7pHT4EvUbPTxQ7xf4Th)j$~c zbbu)=W@um1-ZVu+gnXnr&ON<*)5XI*0)hc@k@tvfGA7ws7QX-`5l*qW4v7@2=y8gz zFJpA#I<0T%DqRIGGr(O~6p4T7svXSX9FJ2O1-TN=>`Ci%dCJ7ot3|vAUgHMDh7wmc zBv_7}@dgrVS7x9XDi^NB!(ZnxiF~v+G+fT}CfDzsCWa`pM zs-Z3{bxn8-qDL)wMZGB%G2zWQWHM6)ywj&h^vp6SS1@x6o=RYA4=zvh=7qP9NIni! z7V08yYCKmgxM84jXf;)cIu)r6=Ltz$uglNYu57DS!1sD5d2=Ob;^7|liAarQMWI$> z%=?Z8`jyNPQvf5?BUa-L5)&oT%+&fyoQS9a*tB>O70zB=xfaC^08*#z&mZGPo#Cvb zGA@~kz1#;H3p9G(Tj#uic{{R*@t$7AjJgJVo7;qHrDMv)VY zs2NM@=Gzeafy$q>O0f>VNo~fyU6Eg2@G4oz{ew`ZGxdKEu2H!^{C*dngVeS70G>S3&}^iHD+ts z^*x)lCijPm5Ztc6o1Oa?>Sa9gcbmfi-zB!X`4^{#B!(*js{9cLdjP~H<;8d@Q%|596 zM19daN_zthWiw~-xqMizjvI}-IidP=fm`vD{G@vLev_XMaXoMxaGZctfq+Po#yOBh za+~b|j=Wuox2FS%_836sD|3B8aLCL8>!);bd=vYf0Q!9Hc%PXhzH}1fr9^MJv^0-b z$w(*E;mOwBNUc?IE<9@6-_lo2ukvXHSahR83!;XaRdC$fv7EAv%~%%C&q?(zYr-XZ zRnIp??Lh41OW5K4Noh&$&qbFb9=NIN*=wZ%^5N+`-f(3z=#v(wo=FK_wMoemj<7cnS7Irk0IHM)&%l%m6*X<-($urlOmKGrTa6B)$_XdQUmlT zh??KzjeB;Cir?({ zEwyMT{yNekZ!@K@_`sKoW}56{3&dG^3#C9hwVsw_?bkf7N%19=vmLo{SzgbcdmF`a zCyD`$Jr>09@=haSN)}d8P1{aj4fNKeG;yKhVPy4%^NywGShCs(`?XRq*ZeBD$+6C2 zS2^nUotU#6x_C|>RHBJECKGlD^DnC^l~uQ(@z|3E$dPFjY?z_)Nn9KUx_5+(!v}V#NdZMFgN4y za}$NC13Mh{XG$a0F9l4C%wC5ZHSkX;m5-c2L9UfbQ@D}UGh7!+G%(a#++&ZqR-^ZdZ1WaGxC+2$zM1Ultlb^U9Akl?A5(3Sv{8THa`=PK|xiwbB{7;&^KJdRAo z$tPiSaR1>6ZB$uGY}D6-guVHi_{QiXY(XeU*|cCm!>4xv+BF#yL2@Vs{VB&jsx5c` z$5w?YzgtDcS>UxJ$}eo;L4i$8XtV(*bdH?mv#Tr=gn2IVL*MPiKEu#HaGW9+otfn- z(cUa0imR{mw$c3L;gY>K?!?(Tp6~vEA=v%=2X!fx>Z7&;#i*9KvLM>gSXB4)l<1mN zkFj}4F}EdIHF>khDib7gUMTnLMxg(62|0~^Qf;ttOoi``aBHG9QSy^m%g<{QDcW*E zR*%vgv$?(wk?Xdn5ftgV1F|9Z0E33}I-|jI^sT^D14jTD#=!uwOv2~Ig7;?6bl_4E zi^Y?wa}O#$Di%oQ6(Q)x;jLBm%Gz+&kEb>^cQrzp3w)v*DZJ^(51S5Z!G%59S#6!< z3!4j7g()ST70Z}}$wv}NHgum!72D^r)VNKT*6Cds3qa#QJVCkHReM?xrYZosZuj&7 zq&nB~ncT4H19kblw-U~~csO)+@4?ioJH#wsbJCR?z_#ybKDTuBj%$15L;6U>+&+oh zqXlok#}2%4w^(viWVwH97dfM^RGcEJDa>}_ZAL$_FUB*Gbd#3mIBs#S;ymA_f&iSH zaD4(@$IZFLEnN%gIUr91ujpB!IyDlImC5iSoi@(4I2{hitmx{(kU>@nr7fm`V~nUj zIkO!iU%*BBz1#=iV+!#LxiO^`@-Gq_u6E!`KR!fi|gCp$oLsR0RmnIzPVw%OxZw^vpBrx%7Y z5!@tm+}gH3rjUfhtZ#(0ixrCw=hF_fgw<5FMBQ83&Qycj1yxO8%6$ZgHw=3D?IRJP zDpx9`M4HeJ2EdP3JaZ8XrMRTHkJTRUKR50?%@58Nfz#1vCse!|KAO-ZccO zFs($WC@Zvf=p(h1Uak*Hw{bn$UDFK2oI|5`s>#PE4`WPG*h*ymAo3n&fg&1kQ&4w}(yyM4n@S}sA>-auG|shWCXqg+pyC20Nr z^aOn}Oi`nzfRywDn{cM#I*r*RO*ZVC<&R0zMG>$mQ7oGe^(1#6E9`5wdjuAD6yvV? zS_H2AT&+04Y$HBjEUP`^(rvFN{!YS(@%rF|GfM3afvEx1RmpluYS{# z?}6X-0Z@yxnGFbDHP^*p{|)l=c*U24hjhkMpQz6W>}CYThZ%C3in5N7bxGrQn*6jb zOU!9O+*0zmc}Tj6A$X+tDfOaV_7Az`6Z&R<73TgaCoxYA;dUc)!FYuT6QM6FsOTYzPkT>|bz<8blA<2RaRq0j~R?`yr zLj+#gX^O7k;l2rzBP(ay4Yg!g%7QQ|DQJewlHmBHYm%Q9E0~R^47PT=nbv=}dNEnq zY1(k0ttx!mofLhk_po;M#6`SPuf(rg5XtaeD>lQ(;Qf2itV}NqfmFsM6X!H@C=c(# zS#Mi%@|1XrJyx~ZH&@?*_Yy3vPsI7n7)9=|$|rT36R)6GKKtwa#8YRL&OU~9LeUh^ zC4rmxQ}wh;39;z}F+#Z+IN!^58;vem7#0c6SWAN;ZembWLgnY8Afo(b;)j=oko4jf z;Vkb;6O=d}g`@}n?u%3qS@(#xJv4-w6MB62r0#%vbHo%&HITs0CgJpKsy;eOFt14q z4FGDn*<&#z34rfH|!WMz}Se*S|;K(kFT;{!21m@rDkIRVQe=L2iHoz;&5+0fKo z5Ow#aAP5mk{cD&iRWrY&Xn2x{!C-82fSi21{CWK|t$Ucbwy=*{`Ql%?Q>!;~#lUYj39?BkAf2G4E*rP4G z0QNb@n9$dL?XX^K8?dZm?DyB@Xn`2jgyn55*87SnW1kV+59B3 z%|XBNT5qk(S=-)`L}eZ0F2bLn)^8YtnCvOpZyLjMw#==&&FhJx4x#F|Z>f+6@>$CT z>zPPHP@~81@A}PozaR`Q$?zu84WBkrDXdm6MhuC(m5}lM(|1y@L+#WK7`i;H4gTml z7#f-c8%noL{z$A5g0;4_{H8Y@*2>FOPlsOgSI!C_sF}^jydK3+#|Kf610^rNsC30Y zSyfi_q+`r70mY+p2!rXHYEKs=>luU}gpZh99hO0p>iu+1#GhP7tfu517uF&HSD`E1i(dZ~N^hb|9HY<3O> z%jK>r@ObgctXq+lkG1Qh*?wI9I){dwnAfpsn2N!2UaM!l)}dXi(d`Nz#3qFKynfN8Cyi<4hbH|rHahXsL)Kh!ZAHiBD z?zP;+Gk-{JyS6oj_?+capNJlcwwxnG=o-1a+ECW-lU{1fhlL^G+T9IUT&8p(UhN}_ zneMmjcC7Ogy5?>-!o#02R@@m~A7;ET8d!k#hP4J~A|b)~4N?+Pvc=wfv4^_zy7|d$s%BWua;h5D-Rc*mN-d&G zn$&_hqDe~MQiha`>1P_%F1xSj4;Sbol(QbOi$A*>BTgMuoWlx`FLGsz^4j%u-DEt*6+Z%+txj==y$a^quNTXqRiT~I6KG@}5|;dp zlg@1#UMRh8UJJ>V;jfUM&)gxt?@`bObI8I536?0)25b@AYHX32Sx1i&#!ut35B0)BD4ZMRo1q&*p)ed*aW6-dqO~TbY>FK>A(v>~N%R0Yz3w3|T%JAaf&h zsl8z84|CPen5k?KJJ9r<6%IxUA2>8=r_yJ_KUK+w)VuebZI~>#-3ja4laYYw*pIdS z&eseKE9VH^cz5T=0iElNyUOlSX{4)TV5w5ZLN=GxyBdL_;3$~OJ2w5Q``71L9mtyc znR)9u=s9a+5=&CYGaGEk;7w*6;#ZyNgVRg*tXm_zrVBo78Akyt# zd^eA~K@;Vah@Vf;8>l^Tk0Wll3G-62@t`!&-d}kS2z_RB-;7{k(}t)RUg28Ko}F$? z0u2F44T_Z;F5MVLm;28u@fwgoDoRfFU9(-d*eRnsy2q5o3c;)LZkkPol)?5to1i4^ zip;Th*x(war=1Yd{*^D1oo(ndMl?$tWH?S})QF*2nl#2s!87bl)a%1pEfk&h^nBqcd}SA)G0m zwJ{5VWMgT!n!wrJsP>OMK_k@- z{0S*sIl1TRhF6om&PQ%`4Ty(gyu}(vh4Yy!m+$=k4*yym`e(nuM2-{l6pw9iAch<} zQf%$x^Wyl*b$?%sj-L&c!xvzEipyO9{%bw)Q)FRv4K!PP$xvm5!Q*fX^D=duT!L*Pln>LhJL{6>MNg8LUMtZi zcd;*)$$|jROjz5;Iw6ZQJP@fIw98^j*VSz96R&U4BiHWyOCSLVS2)h;TsA6V@m)G? zc%4+jxi4ec^#U!TlHHzY*pDkDolmnkyLw{rC}X2M(EQTKDY!G?=OD2u6f7PW>VGY_ zc|gySZSi$aBBytOtrO->`YFq{QK1w2u zmm8tJw_AB6Q5U(I0g8j%QO1rh2@Cz`ZQAUK5OB>yp^ogbFWv$msw?WWiU|DfuV%u4 zm_@<@K^Qu$W1&HSs1fpVR5ZiWKofSzugA>amsK9*K}pg&c>n&gk-aEO=K%M`e zm9727i1yZ{hfr`zNfD^6+8lCHy<+(W`M=r6(9OIXVM&>kc)+WW`qhe@ZzV}4ce+y84aI^vAFf~Pd`Mk8W^aW zCC&^QOFf94tfC#nvJtzS0>5%F3Dfn{tV% zEiHADyLZyEN~W0x3?O86yRkeN#UDP0lPXoFd5#TZ7ry-NQ+g}^I?kEujbZnYADjI6 zb*2yTf>)3^N+6_$Jl#u&fy#vNa>0h=_Y;q5R*vV{wPS2gIb}N?hcBellng~-rF3jS z28N1N@6)|c*Mp=;HSISo0|X#1*1rIJ<3QtX^>J*jjzbdBz0l9giev-^%@r)j$fhQ# zfbeS8p&OF%ArXV1XkhKgwa)g+2s1kQ@J_bx^W8RHm1;AC9EIxl&p<8K5joNdGH2E_ z09GYl<$rU&_dnRSvT(FIVnM0C%w1zAc^gQjHpgx9^3g(# zzLpvpTKjt)MOou$&ArIv1`a>LU$DDS>%YU_uHbt!xR&2}dmkOR_uKv5`#<-X23V4u zU&0+$nT_*gcj9h4uKwt3g^m=p>vM%Y&JTTQohSPj;OwB(JRVyy`b&VLpItqBC=R_} zsmcpkx@k7)$NAwq{4WPTKJ6q#{3cKh&qAO~&#Dpl_iUOk+L;2BPByi$! z{lTAp&dIT@n-wtw-Wm7#$LA> zz{+tv27mXH@4JbKa_Z`d2HBV*?nmecA86Eg>i3vcl-Ctde1hiTE!~eW?g(-UvH1X&5}tpqfL~?aPhHJL>g4mO?LC~ zZ+;~%z>X@OR_a~ftYHst2U?m3s4HAE&{QXmefcqnHD@vFtOqmYO1^{o^gSH>%S*|; z!bLu-#PjvX)!WaXe$6SxIpXz`)>n{bMQ4-`eU$%IEVj`ZyMo{gs7mHRijB$KxNm-r}7F&o##B>v|$VJY!k zrV=e_V9R8JnW;a?sk?oNm1ObrE1#qYf6?yCbTMf{cn66}#rYW2h9%kxKk9w-3+nlo zQtaQ|h1Pn5HdBM>l$^gL zPQw!~VyJ6$FLhrqZ+^@=vDa~}aFm@d9RRXyHyNk;t#o>kI+t`_sEfMsfau86pPRSh zCTv$?>WjGiI}y`{%8Xkbl4tsrEdokZYD$kErr{oSLP|b;pvk%jTiRa=Rv%Ya@BYkc= zLqb<-;$t;vIoC59^2Yc`DpiP}G>)w$(Mr2CPN9v-u`V9v;y$W>K6G5rK?SkB}6O8(A)4yUJ|Dw|Q+%REkG zn`MMXke3~+yDKp$(ZI!^66-ws%8*qd^ z{BrAZe6KJ|5a6q?(P&h)p`=`+UQ~V-()MGG6JnmZ@7p&S4l&7AU|fe~bX)u$x2vWR(qRUf?8qRy`9*mw;SniRTlNCAHC!6c8 zV$2g)hP?Jt^^>TxS3l*E)bb-Mhzd74KEzm9m5Eyqq1+In2}VW#eSUX9adf(e^&CpG zA%PZ3KnW!eUG7cVPiabSRBl{~(kKU5(;$5N)#oj;iFkT z{Zn`BeABA>;=Wc}gSFSpt7GGe#ZPw32}bMP+0G){L)DjL)BbJM7j22LLhhdbFf~Qa zJ6$$F!Wwn+ipsBhYS9@BBE0ztbE*~#{_fQA-0Ahm8hneQ=92&$4L+>faLTsVWSRfi z-kUd&q+L8`=e33a=cV>@!%-ZR!lif)^5~)RUi|^JY^0q-Q6%D`UmGGpUDWdMkrq?P z&-5IQyL=kwAh*{@#khH8e=XXa5(uCT2~iX1F;U(fc?jNO4ylsK@d+xGs0}h);T8^| za`2ZVV9VC>)-O75?<|ye)TlIFV?SiHWkH_;)#CybS?nOv>1mW6Zi$ePwXR4jc3b-tt{e%H6yoY9;}(H>=YOn(s#!h8K1Xyg0X zn&7_x5~*i`S>qh+RMzG9wPBA%;@>UGKriPsE~FHX7pdpWim>NZbv>qYCKSljRx_|d zNW%5O1n#wh{1}*Zg&r_dObe_)CX)*R8`AH-PT?NiRc&o)LY}pZ_>;)3qvhxK>fS~~ z4JdYEy6L<&x|O;XUNJ!wqr%(8O>NffjJ!$^vcw~s=VW+v`#a0-fjXMmuW>XrR<CmF=u$Xr*ajfe7hmk0$)YqnCOLp$8!F$evQA|aG7*lZ*`{?U)ELK&}4#knD zpE=O(#|-!6;ql?-(eq}mgN((q+sA&#`Ls!-y}Dnk2rHG4BF{8~H5}sPJT+Wo6+-mJ zR;N(iiG~aSoVX0_*WjY5fga`P?(R4<nqj_ z&*7Ant_89wRccDw;T5O2ZL~gzo@fmXd~xC{x1poaCgNyK;ZoGz;WUwFx+FAl0^nN| zFomViL|Ml;?k)jN-Zu4Dji-*w^SJ9+?pcWw@wg<@>Wb4xrjdjZ->IS+>Ap4K?6V;6 zsgpE}&x00hFP>B3@4xf~>QMa5V+|_Z9HbcegTgD}xaU{Ae%6iPNccTPCarU2lki_E zp{YdMk0;)RTN{6cRI{$(-Lc{|{AYZrf2T+dedjAQVuo`Ym2Q!&ej^^89RnrtbrE)} z?d`9c{kC>5OGL_X5nxnYJ}0yD{%VDX6jj5QQ#VkGd@L0bg7!e9DvKxcs{yBgRtql| zLQ6SFnt^&YVq^;A_pMHZ>W&i!*>%WZB(JJnR-$vv)=kl`f%cZ`_DY8dmL#8X2G3WFM{5Wb^ zDXZrItDfX(?Y)198Y|H6 zWGmkF)Xisb=PaHQ6VjJ(3+-hYIT`jv3Edp-mN3>Y6?A))A=y)WexLu~qRXUv7DG~u zv!Z{%IS;#u@k8PdEqlriNCH@Ubs}REmyFYknPIfz!{IG&Uij(p_CGs$^xur^=RZcq z8j>^h%6Fnfh-F|ma01K)F;3M+%DR{S&<6Sn>J4FXu2nl8R~I3HnJ2q?+EjKK@R z{hzWT^jN|WpbGr$sB<$Y@+yP6!x2|=^J$kCmW4;<@ifT z4z=x(%pT8=XnSP&`HC+6`ieq^^kI)Aw;)fTtQ!WrPmM-wDZIGh+AZjpu9B;-trDJ5 z9kvILtaRY|pOoE1e2)6tHJEU_K5sbN}0_dDhAT z9rg`TQ9k=ycX?56Z4n`-r^FD&{HSsr1Y4B>^I@AbZyC6f7_;$ssqa8%hXcx0X& z0F9O@Jsr{l0ULH*O;4>}<={0<4XJtJFMGT^oaiE@xbJ*K(ii*3g!SIVy{~`cf9(xO z02;zF3M~dH%-o3Y&f~KTkM%;WgVZ71s{8KvN-S!u_X$ei3-?|!o29Uqan9rT zKYgSV{sFIQMW5&|fUDi3sD+(o1Sh&C^ZNJU-Ea37HVNl-vCrDC;|5PZuMSeI7!$p8 zJ@`j8j>bmXKP&%Pb0s}pc0a9Y!Rx*7$m~F90=)fx|WD?K68~8+FdC6Z3LnAX0aqjIfUH(PWk`k_ME9p(aTt z9-3VPB=)I0*2bvB9)5S_uZ|C|j0^XSneF#@&P0F+}$hyF%k#wKKfBz9^ ztf%3?1X0Ic#O~ZIMEk~}_?6`K??=H6kWE62yT_zTY-~0c>XBSh-^>$kuzJZb6S}Y= z{p%`(=5MQ#$!vqZS>qeQGD>Y;yLpC+_BTeIoSY)~f;g)FrWXAN`29aV7@(C3$!zle zGx>xdyB?YePksqDpFm$R!H;~^59P^y276}=l%}V-CLRv?>zRU|Yq;I0a7ib&yfH_p zz*x;G1V7bNh^**Kz@r>}gD9K!WF)LEz9<1Re{4X{fK2JLM;Tr*KGaqAJ{RK>9cDwM z+Jt`@CUc3uq(8#&h_RSj>*bED%?oMf6`9>zF;D-Z^}L+td_0WZdm>5s>xsFlTZ}6g zHapioBY)eJlFxbu(fUf;QgfUF)Im`5NCK-~FJ%-~wqor4PzE222a7kq1$h$rD@W0N z7RcH)_;Y1{6qDqG|@G%<55Dt0H<*oPY; zKbom}bsWH9S%7D<>tV@t3XB)xe`xEpGFdgO6TiY#oWsZj((}e*#@=+SUa*-RL*1SR zVXm_`l?=`K(kq9=wD<t6d4dApLzKmbR;R~UoSeXiCo=?jwmG_xeW^HypcHJu(?;TVw;|7Eb zzNOb}%bTH|Lf+f^WdDLAT0S(SOWelYaJf<#HqAVF-Oa}$ct`33tKrjBxPeYgNlsq$ z2}tqCBXjoLTh2BY&~mNjYE}3;MKxzP7Kh0PlKTr3I9^L^AIq?#^SnF5`=>|r-{_Fv zg>9(-7P8XJ)$YxRw~>wv&kw*DETK9XJ6v4HkY0v}8@fiFhw^N326Ec~0VQZC>0}ZvQ>U1u(k=NU7FG z_8$CQd@uNu1YSva)=|ZQ2h1dH`3B8t1`bnb8q|rHrHDRJ8TA>?Zzj7hl>F1?G0p=po;&W5 zPjA(G_JR`d;LUtiz{=_s_A65>hX_61Nf$P4^gwEJXvg(uf4$0`_HqT!_{LgTtijsGbA`2%cdeI62SGHPF-V?icd(!~mw@lu=**-fap9i&h@ zM|(W10JS(8@&4uIWt$}PgGiSvqpQHTbq|z_WNv={dZY9Y8qN%%t|3`O8muvRqmX#) znft69f~R&*wy-`1tMWMfopm%B{=&YAu$-9aW(h;;t78NUmZ@b1wbJPH*y*=#x8LL_ z)6jZ@Wk^ytS@2Hd{nzvp1Pkjf#D+LaX{ON6`WV3tQB_l#FI&YnnwQ&G#XN9NxIjQT z)Cri3Q(oTzFxD21PX2bMz6*3w&;kzg}Cb|0#mtCXjuhdj|idA@q z{w{McH%~M-$m);&OZI)dzTHC4zmIqR0b&0Sd|V}^FE?`3f2-Q6{8QC-mSX51F&Z^h zs?QCUqa_zCDo=?Vt$F;!6m~vA70bJNFw+{w@KE!J)*5HQ5C49{d(wb@kzy6 zRIkMf|3`egqJ`1MC-UW&ByhV{9Q3rcx4DaV31|SWuxKkMYuc)HhilMb^NPp|qLL4S zU|Ix7U*ZYT+0e9|?T0pfd(srqdA0(~b)dzN*}WlCYXbN)cnf^Zeyqb#Jc2ZeTR@c- zia!fGe@+h!bJin z3ERDefx6YE@1M{+3SVM%aeo$|sD2e-8Y;;2g<#q#nA69(dY|5rr`n!fPy0EX>)Rb? zR%t*aPu0=cjcvuW4x0lF1xZ5i3y+^@Q5WzQ{*z(@Yq4Wq9yDZbbfoh^E%XpRAGj>U z{wBdSVY(xI&CQ&VH6upBy| zT+WF`Bq%Q$T#j`exHC(|bsIS@K$TF}7LJP>n?R%Da7goFA0v<) zgS)Jjwe*Qhz8|AG;=Jn($%q7j?ybleORFd%aG9m zqnSOAqftyI45}f+kuH+pWLi-hJ)a)6OaM7FnS4d_#h#pZQO7jNMY^l2YxyifMYE^%>1#qVU!B&2vWLxv^ZDYNkdLrd1o=n}`HKbSe?L{a;JS9v8_Gs%xS8## zlXT(tEj1YTP1)??1FuZ^a}W$!XWb>Qj~H70end&|#@F1!g{KlA<6+>A?F_yr3W;zz zCa(C?PDQl2BUaR_db~@7+B0&U-fM2^2mo0c=;wzdExi_IZaA^c2SfQ82&#sPZHY2w zFCZ=9UMCbzpy6|hf|XonQ`;3Tlgi(^7~YW3Y|G9+1<&qFz{zqnxKlbv1jS!%7Tr#v z`pBZrf++Y-*<%nbb+ooFa>2ehRtiMYlMbV1XY*Ott0V&eY5?9yhAgg6RAEwTm0?Z@ zY9dr;>U|LNLs`OkA>>j)@b~UZ6oRACt*V`9@;>q}KmlG!cT35l5Z^W~TCDi*`nvxI z)L*#y$9T@zT`6cMNq3`FZ8r^dTuNaEzb4!1eKQ)6jd#KC*fj3cx%>g(fD%l+P6Bb0 ze;EUy)fsJ)hQ-0ra|L=Fx-WLIr|&xL$sEF`(B5Xp*t1C=Jw%^6vqo>J;cOlRcC-Fu z8b1Al2Bb$q7M0NMKpuE!T_@ks&I$M&=y_L7l?G@wbkCGp{GFB+926!o>hK4#_9r8!a z5GH5Vq3hcZk80DP>cn^5ScN`+T+PsPc}Z!f+CSw{|KskT>wmyo`sbvtlZe;vLyE@* zxk(4=2ZVgOmLtEoeY1~XTRT@71!}Y|ze>c*b!uRyB!kYHJ>_JzENKhVReUGo{JkvU ze^YhWzgs6K>(3~>^F&YYTck?-|6xV?=LZ98m8`JWc)cQ#o2uoYNE>E9hKPW!^K&%w zAP1cFy$*cYKWrl=)1-t=psvaSXI-H=?;qOMKnsq?gQz$oFatmvFFFqvuF;C)TFW9x zh@@Yd^6vVF-%sBDu!$!%kSCBgaPPPW6@CsMydIfD*j6^}n5gAN>VL{dZRnqGi;625Gz1hePhSWjo1MwMOc5>3-4cBPn<9 z3*)ec>*c7hBk5BQ;cQN}eVy$0d)H`>;wN%g>I0yX|BJo142x^~(tQgkpnyPdcXxM4 zaQDL92@+g_Taci^-KoMog%oZHP6%!Rf=jTV0g`=d@9w_m^uN2$?cII)+x@Vfrxvwl zP1c;XR;@Y4`~C*)!wVW~ptd&p#%x(7YJI49gaqPy@p81?I6bgyTB8| zlGNTAg}pk73GXyF?%FLAG{ibB^QLBzxnap;3fVZmjBwAOS{YSeOi@X#rIejJ35Mja zjaDmnw2v)dN-q^fLpo=TXj*d=V{;p2&amEt z{mTy`+|0Unxom^?nPJA4gt6+7PidJHSFfT!?j>=f4oRPAUCF5jSx>#ZDCq{JpI}gx z;7e7#_~`LX@@zcujYRy>vIH-05kqn5Hd`Hop@V@hmRYp3IYja)A+G1~8+PaF{4yLv z|KXH0+;Ps;q>OwY-hb($;_|+UI3-B74JyL7*ex@02{7FNMc-KkuS`si4`xt$MtHgs z;9IK}iU|dfjlGG9ixUEr++(&xaw1F=SZ0=quPpMbwZt+2A;Ze|VV{w!%eD1x1Sa46 z^C|_7_840CUhCaAfQguyL_&nqbwQc!k2RYclqJANk z*dAjI=oz+~-62d-(Q9mXV%$Wr89ds(I{<&LnPS$$?7(PldsG|rMaM}F8!XV)A@ zu8MM6mWNmL zl`@@3w3YcJ*jC}dxE`o*(GrN{M)_R+;@ifj}>`oH46gl&2g99tdLpOxg_4r0KI)C6C2BJ`(hn183VYr_ZvHH zzL5tqipLJZ2sqPa=n+F`|GZ;gXoRb@GM)1{Gu|QGX|7_bD%;O^F`x0w7pEiqmAsL! zYH5Z~u=@1#8ixwblwlVW)ALt+>RVhL_2LvJKc}!e8a#VgbubNJ%T%(*4m;St?jKWs z%wV;kI@qFFd+iR%k=YKOu+RJm(bF)`bX5nYR(D2{|_$>om$ zqFF*!ot;txiPfcc>{yz%U$_d|^|D9c2sY+#ifh*tmsC9|@~UY7S~~hA;Ax+0htI`P zBr7oxm1=ZWb$Y1W%RLn33s4v0`0Mz4ZQ(oNouMxXT6I*E=+~Q?{_|mqi@xGh7a8J0 zh2HHaBHOS#QJUju1)lYKw^|?OV*qYRiU@7O>X4TbUK5{JwSFsYLMA>>Q+uN8mxZ2@ zWf{Vf*D0%D%_aT%j^no5M;{qHM4p8m0F^Mhpbq`ehp@pZgTqbm^ApULkwS|mes|EL zibhvUlt67gf?bm8o?pGAFX>=}wz3k0oO;iB0*(Bvoo=WMz>ScSa3$0t*ANO{ce(7Sm{JGbX}TSa3E`cH}eNzZ4Zwm z1;_Y7l6t;Uea@vCUDs7@Lesh*e#XiFTz*3)#m-rP?zN=(x@o=PRZL;7&*WV{Y>doo z#a)=p$q3t~WJ-Ecn>q)h$l13wvy=B}2-O)?@~e!!M!hoAlzFw@HtPI#v1~1BiM)Qb z`R-*JM^=~Q_t!{FV9&bdLVyMNjLP)(xZV*g^|!9({x9xSV7^HwJoH-^evU<>M*8PY z4HlAl-mkh?dVEAuAa;vVDb3KgvK7tDSA*^*yE8XP-dNe}Epy`A_@>~11&^xlK~DV9 z`~4>cUr|QuHLISJjmF#O{|JLoIWK4RWKz5qn{$b&%QCd)5|irgcY z#kKeCitf~X0hT#hPf1sRi(^Z=++8o_L{uS)Oxn!e$CWjyoRM}4{x6II+87}#1UVC2 zfV6Euj)g>6hv&OX3q|`|#eIw5y?u7bH%T_bAsEI8??;f1r8fUn- zz&$yR$Fy-8{hW|aMK139?5Fl(qKy>~Uj~U&``{Ob!kQkpI=&2y;q3S_Btk1TO{mMS zW*|S7#I4t{Gfn2m)y%ae60X(`MEv0a243 zuHG=0ECvydJ$O3>70k|)-?8lCzW(WE&7M<8^}C)2Qno%3gp+u*7`_&h!aqj~OvVwu zevj{^6V%A#w5S_8Ah>|i(|F{VXez&C%xgUj~w2}4YZPx4g1I)>8Ml}%T5 z=0r=_T<(~lMz+A!Sw)viq8SNh7#U#Yi557~A3HDj9lLgkY31blGvQ43QUur7%H=HxZJZH8 znZ`7I)08Bt*|ogoM6z-vpMgHF<%VvbXnnyP|4JJqLse$WYpa7icH=EE`PA@(w@RO# zw8gnAfj4TtRbyo(TCFvfaLvYg(K!kBkpKMffa0Ru;YgWr0vW{KX+NE)bZRQ^l+1-u6Q@VwAv=viGe{P`eK?i)Zm8@+F{9Lbmx=;mUU$8 zfKy8KmW7P+b5z{4G(E*n)J-nYO3(GrXg$$DMg15qiV6+3<|Rmag5H49m7?Eqz!9f5 zmX`_d7G7m+s1c3p!Uq|fw{Z(h+E)VY$BZ-8ML17B_m&)fU7#hTc2P zA+K^lykW3|9N}Rzk*`!z^-RY49~ZCC6LU z+Ov?ynwMpWUegS#g61X`!*qiE2fGpn-%GkiFbzb2MO%H=kb_0@+}eJAzhZS>_MNs9 zykyXCnRZQ8S$eQg&B@!&&FT&&O7I6Db1*F9*^hVC>Ye4zn%R$MoD7|Fo2SLHk$|lb zy!alC5%)4sHdXICdNaQV+Bna(!$_w8)StNAla(*d48jsIe=7(9O{u7dW&S;V1U~3r z>ONSa6rY4Nf%Ve)PfzFiKF=AOJ|x+~c;e1R^@l7F7F@1cMg2pfhF-i2>XW<6{5Ve?g9d{_#6+Y z2KuLcCF$l!PUiY>j|GRa8%?Jg2<#++ZeeVGA1bz;YL|_IL(3%%C{zV5BLx9y6Si&| z28-W+?89KUG(w;f{0N^yx$c#~4+zLty#vvcANN1)yl~-d+-ZI@D4xBDc!)KQ4x>uw z#hdSKMsO1*IqtukUnE0s-q8mxT3e3ToJaZc)FGZ>KVbfrAPHuu4zWRS6LJhMm%F}E zsh!};-_#BEC4bxm9skwif6z(%3m1>dolEzB?$JD2iY6fxU+=FTzq8#xnO>y*Q;*-Y zMz%Nq>XGo_zuLXj!^od!95P>k6wBI*R^yepP+agDceaw-d)x73Q&^h)KPaBAL-+n=9Z5hYIJn54Onq(yqih$$|9DwM=;h(}yzg>!Sc zQEUtk5Oyd=8>^6~iD;pkz8^!#tEvqRAQfA9Hsx)Lv;+s=`pQ66&3ElYP~jDk*0Uhc z_jXGppotT)WWt3pNqhZZ*aBv}Wr;zO!4WtzdHlnG{DrXc;iK=zaVV;?FsdT}1>)2h zo09xe7pPY8&}|M_M@C|KucWmWOG;nU$_l`5O-LRJEe}O+1C<<8)C;d3Zw$K!VO=2X zaK5-`P-m4j+tyC$cBM2>9bwNBv`HB*DSj8pDZmR$WH92&bi&R*?qIxf^S!+epiTH% z{kLUR32|C<%)=3T@0f8*0$8HdOV~cs-=c@&B@GZ1YMi!LFw4g2pU1RcMzMIQru{%d z-o7M3WtXeczEtK*i!;e;&+&~jIkiYt7-}IxgP6I-7Ufs7o0`_x8=%Y(|D*!Mqy;V)7&0 zQ~T&7l5e@lU1<<>M&E)NhqNuJ!_Uz*+z3jG3uiby6AW#E^UzLEc~25MpLhrwPm zTqK3*MY2R+Nv#Uw-7EIh$PlvE=K+nZUNePVCVj3RASP0u3f9-p4z;mF(3kmHpzI#` z)Hr{X5#wP%<>lsHwBNUOhpZ$V-s;S(TP?drg(%X_{(tQR2>vrebW+nXMDgv2<-{l! zZHB1|d}}tB*7~vg%Jmpfjh$D?DAMjo%ejRn^u^QD(d^Nr$g{AmWOjG=44=y=LDH z=zJ|2CXZ*d3{?R~Dx+EmA55(Q_2==o7DALl4A&EUOdaWmJTH_7g}{3Fh3o($&;9kL zUluv^cY%SSUwQvds#4pZl>RAn?=r8T?7|>uE1sHcnhoZK-7=Cw~(KKnzcWhR9^*wt)braDQv5xB%0rxw6Q!+5A$WkQ8RsV{K{#>-aB zvl?=2NY-M-xGVD)oH!nDnZ*^Zx(m~HjyNRe0O=6gLFKN+iaW`eG1n$5WJMzIS@@lT zhu*FAVu&lpeUg4)p>S=i$BiXxZGu-(`$Zw9o9;7ME{W>il6IAbA;m@F#Cs9??{BBN z2@RquIk}M8uW;-?wpy$gEatr}sGt@5O6=`Z;B0n@1BfVp7i);a6>O?8zifuM05k1Y zn5H|+Nhf3uHz>WrL(nz$YQLh39p*8qvHjQ!kgppxNAFqb&)n5ZmAP@}iv@ox5>Un<5tS7_FOq||DfY66uNzmi8r$Xf*kJ1>Mdr!b= z-d8+1gnn>w!2?}PurS6I?q0oz)5dboO)IMG);4K2aF#O5(cS57lVCBDzG545MMP=| z1Vi`3{KN-qI((b5SjWnczn5g^*Wzgtp@S}41;LS!z#=97{IBxc`JO@Rw0m@|H6X^U z7_-IJdW1py1VX^^;k_dfjde_G$=>i6^fv2HR*E(+I$rQ}l6@r_ZV?sWbs-bep7^Ok zDPvKw==9?rxlxRTgEPxX=FVAg7pj{ciea{(@+K|Ey|3%5G*e4-ndGO>pA5MncOOc@ z=_-uWNefMb7yMjds`b2sW+KI zXxyFn)sU2cF2E}4V45kf%4V$lg+aZhs$R=Ot$dZsjjmp1w*TbIti4s+?&SJya5Us9*)gX9>F z!Vc+u`3T+uLqj^-VE zOrf6NEKDdr9ErvoqJ6eku&GupxBtG#(XhZbO`4lotvNL|0q4`lFpJF3u;UXP{>X2k z&&pMg8au~-2o~EYB=0cLsW#sGl+VRLOYJlv;M4y+NJHf?fl57ms4S0ET_N!MU~_p< z)qw!Rvpxtpxz*E}mavJ&$J5|!3>=!W0Nq^wd_k|l^0-TzBUoO&Y^qA5h_rLG81oI9 zX2`;%stBLpW4!#_apt*&hcMn`XDqk`kty2vxMe95k*PE-xOydKK|Xjv?oHfLFh)BH z$X5}EowU>o>sQb<0FzUE+78e<6^+CB?+#^uF-xQC_ix)4eK2e~#+Cm+Yzq1S!DXaw zyinU$)M6tm`k5zFby$kS9kYhmwt-M3JnKLO(dnt}c>ZI8w9gZ~tJ;+Ti`fD^!f6Zd z&+MH$eHo8z*u^qQzm>w9I}Zfo-6X!Xa^fU@_ilIKhRW;Nu3|UfZh3uyh;5;ya##A6 z(_4@t0UJMe%ZvwQXAw*a{~(z^^(Nakk>#BbGI^>%&Xt=JlD)yP34l$}!dV0u_~SDT zjMz9Q2n85hqBCJ9&4;%RG#L6f*h<$%W)!rMk34oA4l+LcRk0Y)ak>1A3|taSwgKL2 zo&@RcX)|A+@gfg-FygxTPV`#xgc=A{C&mYX5FQnqgg8%Z>NpVri71XV4Y+uxE8f^~ zNRg4Bq5Ar-0N6C~S2dd~ZHO3jiNPdETx;a&wSe>(ju;8XydC}GP+~ZZ2Qrt}-cqfZ zcEdi>v@QT(hxOabv^vFXF(E>D>?Y1psvd4@LK<0}t#7vk_2f4TghhQ8P|AVQT|~1r zJE=soEndeAVlYN$kPz5)qzE0ip{UEZRvPCz3akhS7pw`VDKq)Hz=Ug;fieun@A&Zf z`G)O$$#{&zIfe1S^%}9-kxc)Gjq6qZqkS(QanrfLAArdm`W5A)AH^B}nA}cC3PvO~ zn-D+#1UoY;s_>SStFMJGgpYpNfLgXR;3ddnzX851s)`$k+l z154h$?n==suh`#m3*G!O2Lx+orf@>m@j`A_7m2SB`9HKhl6lB?U(29#w}B;~p|(dA zD`Q%U##pDD7DejdqY0>kiV^nEuW;@zV)ZK|MWIp$0l8;2!#nXv|4ZL3@u$9f%0o3H z(!H6&J+$xOCl5(YW>V@7Yf7VC3DQfh#y%wkbY2oqj}`56yv%a?FkWcG6vFl&UQ+my zw;5AXap%24JSzyVNtVvFq4`t=W4vsN9f;Rjk4Hs&dPfxD|^Vww@YTu(A0FBdiSBKiK7j z-%Yz8U&x<#uRld+zx+A%%K}t*mtUOHa_lk|G_3AApEuP;7zMBi*2JhA;K)z;Kn5ju2ZTsV~j?V={$&S-Gf^0JK)ndCseYZp7|! zN6n>5J>@`jRj0FSV|!J}{E;?6@PFp?SpK6C?2JEU;BR(i55m!hG`--?7fzYD!k_!V z-8n9VtQRvs4u-lmu~Qq-uRBp{{TtE6zht1Ww?dpt+9+hRdIQd=45<)@kIzIm4qwW? zp}nN^TlQTJ?rBnx&rdQ*TR~oA-?{WN0o8#-blb($I7(s(|7&8LyX<4lnTI8#Iu>|o)I1er$RQDbq6${J8mm=$*N zT&{v(<9{j?OxL%#ygF24@!ZreckGx~v6t4)`xFx*ntUvFb$Y1IExB>ZapyV7*pcqB9gl_6^N zPcQ?gTXlj*E3rL)W}S+3`BXKXHN3hl&sgI-P9`hG>o*7)X8RHW&#xY<&EVw+Z3PD2 z3#1j%19a9K%yb$}P&wkgo}R5g-}8{a8J_q9;BF+cDf|+_HS**~l{?|=KRKVGYW z8qmx@xwV}-e6Nz!cOpX=xQ$SpwAWFb=hLWyiaK(`PEXJt_eW+C3NU8N$H0N!pUu|@ zWmsJH?~Nw+-q#_l^#9Ek@IB8(P*I+Zsv7Ax}?OS)Uqz3W5A08vJM=ueag z;^m@Ejc&wc06>2KPMJjGp5l2j2!c$qg95<@UaU>i#^a+wDlJ7_LsZs%^Pek~w}47H z*jU-x3gyGKv_7r?^*zG^!S6bn$deD=TONM{n)s4DCR`Y8zV0BoLzFR_j$ce%Jm}0w zA;u(d%cm&pAh2E-YHZ=wXH}igNWd?wx65}r-1#!pj&OaLB~Y=m{V4%lUqjrX>$-rr zZmB_)A<~zJn>$C5^aF6sOtkt>UzNNOtdLAmqADgfVUphAYqRq&K%JmtO!7rS)bu8X zDvE$m2^nIt97rOIA;+u%zH-NU64quAb&6HO*D;a4H3SXnUk{q{p9JZuUWBe|fKO`+ z5y|<~A~lW&G~V_{#H!zEv`6yb{fOR!vZMu+#(D)|>b1bxQmeo zxcD9WN0_nvZV}zfNIq`kTYy|oS`3bwVXE0_MI&cfzf!%aF-U1l;hUUS*b5dp!R5Fw zVkgvjFU5bX%-EzmVC>KRvb-y@$?amEQufw2P*ig=R*s#*&tDqebMN^G6wMm=*rGz;@ zKV@L<6Ca{8o`*l*x%g2mhJDuhXLSZ_9qx&`Kr6bUi#eiCSBBE)O`Ag7dRoctdDz+z z^wvZLX?oP5zGiD_c_UjP8J98T7Jjjqoc_+1@<5swiADAU2KCW7eO{JJE#sbmTjR+) zKGh4$pspwmSJk}ES6?fMJtWp*Bhbd~?2<_n1xAXI_W1k|Ql#U5q>HN&l;y%Z->=q=d@1jM3Mf z>(^BLW1eJ!K5CuvKJv%X5~3|mFGq7oXkLj-+w(EgHL*baRVeg-pO7%bvXfemQwufP zyk?OQ(oN5=Q~B~rYIVsTy1QwGK_tlHF#N+AY@-2A>}5`Po5z7SI=JJwP{W4qU_`mW zn3s`5hQfPaw=@(UgS>;xqDA!Hp1r=bHckNVi;J<&-hq^!x900}f0zU2##0X5&OVI2 zKtOt!lsNaj1RF(Ar~|QLCRD!5cQV*O)Z8h^?hWLbLo zrcP4MPmw`pn*@w%5>%?@3%Ho_Gvfe$8+cRF#fJv5i%i3kRKF z(fDvlLPLF38iDl&5D&3s3r*u?I7`n*R8IuwuH!sqLCSyZ?%rSds07>VSMOCY6{lxa z(We?f#lKH}AYkKBsjwfDmmCt%8h0wfw;z1;+Eepn1DSUUUSw)$TEXHYk%8OqG61Zjuz5euw-$>wEUdy$D}Z7JI?q za}E6?@bSLHjZa(_6LVJF-b7p$p{a0LdHehev0k|{l)(FwF?!_~ZjbW3Q!@J`qAHkjn(T%-SjzeZz9k4T6ro-N`NfhQ z-C02y>Fm`SQ|U1FZE7_Eqa4-^ZIkr;#@4{lkyy!aQ3@a6(_2Fy5?a!s9N7=Ll{; zZGDzrHj@D&TP0vP(mzFTU}lnv>wWcB9{>!6Ga`$cp-$mMA}Xr4nD1qdCB=F?a_{Sl zm4f-v%$>`pp>1UO=_&aR4)zXa%qE7pb+hpmRIE;|h_(NGbXsb(nUJEMpoO?}Olp6& z2~yJ88-+fjx75{1&N;{GINph9Z9Azq*29H@NDbT%CHPi63f9Io7L3Ck_$BdrSNPN1 zHJbupXczN?nj?0h*Lf)p%O}})?8@_LnaoFEmFh{ZxDBLvDrpIr*glTcC@rq+*C1C< zr>|K%mt-`Kqm2sBUdYjg!Ty?-a-#U+|20Q(|F`GgAq*85x`PTax8K@@Kv&z5kpSNd$TIQpP&}Natdmfaj z7`BhE2MEKF-?|a90r3U%uRVlmToB(fZdHP5l#+yV8zSl$ef5PrNC4d2`t_g`~;PvPSk z$@MZL9RVXNp_`K9#s@X`JmEIHgRY{w_?l+2Stk0V+PYgQmOoJsk+7#?f`eV@*cpo? zu>5@1f&yscOK=4nrkGx`0aE;fU&Xp>AqvMG)5#la8WkpuX*BjpQ}|hcO6g?!Q{2+6 zUWd z&j|8_rOyE^zH8k5P3QhIJpY3XOZsQYdm;%Q6~dFu0{HLas=aC;eIn7#u8QHEzo^`q z?%0In7_Sr&(O>QCXI)WACUw##gEd2QgqJAz>!YxNDM(W`-^WUNqir>HciIUR%#kJU zsyr6;UnQb|t>@?fq+9GQqJ!gXFQv4^lb_Sq%|mXo4T`yFmv6UiR~GUT#;6z{5c<&eK0#qzD}2Vw`2&W6?+>rA0|z>?EVz8R3O z3Sq0d0)}7!8Bc3Q>|uD4C&QwEPwOdq-{Z)tRw#wAwe4{eLDKy zdnbV*0(hLv{=K(N*^fnvEs77J!%E!AQ;?Cl8g!K;$c$#QLhI_-wk?6d&NW1X3lN!z49Y1XXw+2mi@e_64;mbxv<&Rb7hL6gAQCT+Uzcd47<)7 zXA=0CUju-~%F61!70PDbRXq=!X!JNXis`~0KRQ>>#HU^{v{o%Q?PI#v+`L$9Iy=)6 zlkjTV31<3*Paae+)7f6bnaSB?9Ok&SJpDQjo`j9|2EF-;TxEZC)>c?eIkNRcn~0+e zUj;`*9iLIG(IwA@sp5{5pIe}V2kaHLTOBSYtXq{K*)c2zyQQq0bzoE1brEgwg0i>V zXgWZy*ODa5C<{&J8c{Xa&)Axx@MY!Qng{Ck^Jd6Vg(IkIonWn{-Td^SFl28eb}+Yp z)wT*Mq8vz0cPzetijw>W>Pj%t9{TjKMqv1mC9`oQlLm--(Yecf`QU!=7-zT{?0M>*L5tW>*mg zd-G-ZK9h>#tCs^U@D{Qi7wUM=AIs^gOL2aAhK_qD!oed5_al`Xm3!SbVHI-JT8`Oa zJDEo~i7w4J#%MOUQ`8EwwVuxLHaWa$SQ*^@$f+-Bp5&dgeNRt*K#?de22}Qr zU1*=Xw|utOtG{>b;fDKZ0pq(AooxBc(X2pgso?qtd=)trQ;px32hm?cZ1$GWK6E5c zOHh37`3w^_(=?3&kYg||&&-gEy!z;9eYB!jC;)72QkTzVOhW^!@Y^brqkjLAAK;Ky zdVGcDDRplW>OX5xee-of%H7}e8uoM{|3C0r0bPWDa_!-1@DBjA@*t82f5(g_L+o3I z*xQVNeBJEafrVA5zJRORLN=Yi)V=XojJf^od^WlM%z3aHeb8b314Np^O#a9wfW zqt8iuoOSxf8KW)RwfU=}(m1Up%3F1RcG-8P=ZScxG1euT1((WGVhld*nHDyAS41nm zsV68*qn9#JVk@VZCqg&kqq&2xFso&#wktP!mUU(^nY#+LDUGQCFOXq$R{3o_B``8&$L+WzMhyQkvI~4%f+<1yS)vdYuWiin*yt` zW_!^}`VA5F?7+#AcEjBk9e%|H3}QfEx`-jJ+X@J%>-THt;Os2hsM4<)%g@pAaiKif zUjo#X0wV0_Fi2);?;XgW!-fdPQ)HN5q7zRvZ!@|hW465yn`v_ z9&Mv^4ENFr_~I{@-Z7D6Tv$-}d9xpi+COQ1oe1$XH@32> z4;KRCf+3OWvQ`F407n>961w;2Q+?+OlSXh%`XOcr1up0Xif13*aO&I~0?Cpb#WqDh zxED5natHZcMW0EV0x=oi(k$Lsd-r{9H@{qGm=%RoKbMJ#`p z=|Bg#1Pl-w`GV;GaU*;?Lz@s)!X}?zg?PXTKD&#Tu~yWUqpgx$XuWpERW0d zMfQy!%df2BCR^`ep|A18vigYMPerouFKvJM*(ASj@?;_<3@VtgOitRqx!>vLiKT8P8)-S06FhgCaKA~>|T3X=bBYt6sW zF_D@w`bTA|HW*$Az(|JhU-NT_NQPbK5LzjJTOh>@-VVjpS-$VN6>9e#0**4l4JAR# z=tx72Xcl?#g6dTio~hk(I3*P@sTC(OFc9Hzt0?5qeS@j9Z24Y^CS!mwt1hG7i5*DA zzUjGgd1C^C_Cx8|R4JLH8Bt~wPQR=;(nqsKwwM{*wuGaH)M-3Lg5V~!;>)Nez9mLQ zD27@J=bpd#5@M9QufkQtLSh@;AHUlE1SL6#Ho{%|ysqh(3}vHd2=(+sS$4K~ZdZjD z%W5>{YlZb%L}uMX%SwCy%&;J#$_}8~g(HW=t8_F!`rQr?9vQL9`k>Sd2zOwj4M#k5 zx+7RNdW6#83>dPj%VyAna3n3cGFYZV|9lp7O8Ii#D$WW+Hp>^uhG%c*hh@cuLhL^N zcvGgiJrg^2M#cW4x2Eqy;636Qx{F|L{_fGBY*B*4R2Y4!|8X{6#ihyl`=KBlFLd8Dp-Hi?SbkHK*$fB_)z zkW5V))%57~WB2mr$aAxBFux-+a@{SpR)7*lJ87faLRExc0IAV{pQ_ZkLw_oayYXN} zW+toK7SM6L5K_NBMNkY*lEEPqnJofsO#V zG%>OAwmP5?H*-3uIbWr? zN^K`oaz|M;jYKVrO~eypW9YH#XBpUF4gr<|)~porqK?v>ayBCjI~+MLkLIXOo^%2v!yR?O7q;IU@}3h3fwEPM?wPG{oZmKYysGDX-rj0H34x0Zdj2Iy09R zFKX1(;R4BN!-LMgWI#GXxb-x%h0|h0Gn}2xMW=1u9~3t&71XWduS=$ShU!9IjpQ`R zRE=sPLpWwi5M&xlak{q(n6{Ro)bHj=4(aVfJTBaE8^)HyUxg1I(2Q?Seg*SXrT1pxH56c`@y-#VTDuQT@{E$j|@Tcyvbxi4`s%a}r=R}Raf zknhI?l&UHv=10Dv_}#*_nm+9Jj{?{KrIa)=h{s}b2Fq4Z()WMomJq!iAT|P*VESZ= zqSm?gQw0A3;KY+*QD!$LS)t$kj#|I_4TfiGP+KaUffxWSg4@0|M|#Gus0?2Hmmmnm@b*st&FmnYJaPV(l zNm~-fgwHuxzj-{)?>k0*;E}^%cU&W97U2Lkc|xPrA@}6po_(No6UXv;hsD;xI^lMu z;whkfH0!b%fD6LBUVV^j7ZJ0 z{JqF_{Bsnb<@@d)IQ4!*;H!PK$v|$ET}yV#XB#+gFvn&*Z6|I-&bBOlxXdOxzv1nxEZ85`@eE0`jquZjKcPVy6H_t*pW=c!?yjUHwOR zKUs;=e=PnwJ8rfp z-e?u*v&IqG?Q2s z&yT#>KFH{T?W)n+K4KtZfvr1j3>kVoR2@TsAaN{lJNSnmq}=7_Pc*m~Ka*eYsqQWzo67KtoHCA=o*dz0KjPl6R~VPA#{A^1dDkA9l{Ui9 zySo$=r{-;aDrqpG#qjz2CmY8+uJQhHy8i2=MH@v1h=aE%c**5UfGec;HwW+i?0CV| zfbc@w#(QO{XO1*>&op-U^2yzZ*ODD*yxx-=)=4y3V?xKsEU=7 zgP!Y5GUBA5pLz0KJykKbQDQM3c4fKqO|c)i3>8t#`A zewOl#m1h}ff;mXz)?K+Gyv{-PyOU7iq;MC37)38PP5mV#4L(?d{ZV|O2HZKJ!P`y! zt>7a^u1_@GSsM@8iB0&=C1SBUz%rFDx7#}cw0yenz}3N#gjHz|S5jwJ@BG+?M>hP6 z;wu7tzNZWXAEtA-tcEVBXj+O z_1wJ7j7*bw#+6JzSMb>WY)1E*D}`|h+O1GVb(8gBhghBPTe6fzzU*vVN_Q^qSchjF zV*$*0`kMy%?DJ#O_@=~b+}`yOb?8XUT3>RUf3d5EFL=*}8tvB-wN@gKL~{r9Y^GuRRlVjrd4prp76YrZ9O9{=y2ZYVSZI8 zlBa^L=Y6H#UMiWrHz){c1La-wu-sefZIQQIlKP{jnUcx;xf#b=+rP7ldHyv+LIlG3EnDE68ay zA|PqDd7N%12;v!vnQx6+oe-tj4{^Ifv$OQE*}#Cf$#?t$&J*?l;&(E&-alXH4wJzR z2kA2n%ivO6bjeGS+PhHZx2$_Ad)2J+bKEa98#~}krDs0#vWs6#=G%N|-r;;A|5l>Q zEEihUX@-$_W{nLHCN)tree4`%I= zS7z%Su<4u7xgM`Z)t!2-4oyOx!E-gf3v6zYh_x4f0IZq|J0DNqP}$8J+i_OV5lGD_ zPvZQ8TP$hU z?jL}Cb-dRQpPymI|H$J+tS17L#t|hpMCpJttF)YzMgBgPUZUxQ$JOWlZ&9z3ymTcA{exK=SdPPg}FBhy^-=83= z1u!4eGOiQNeE^Q#nEP(1}Rlsg~+{d7&Z^Hq<@DgAO z2i?f-*&RVo=6^0DOiY5ZcJ6p&7*7_qqt!=Q z0hQpBgV8mnrpX=;2M8{cfTcSBNx{ zY?>-zZKt7^!T<%egaqI8;u287UR z`~Phg38527PkSWmY!SjMq@{nuWI+th|oLq6G{) zn^E{Ny@y=6N1c{8l2bqS3V@|*Z-=jpiAfO`lr&45KzBnCAF^cC&WZVF_i6Hs^kDI0z6W|I@$hUG-+IM$)bGN$3O5f6 zQ$G7>Y`-vzZyf21P2i0_l==@uQpYn2!v$4&Zh?xBMQfY=N+^8Vet3Kon|v0(EBUs$ z1K>Ug>iVqHQTf%D?Dt!ZhdR6$irdA$iLV~8MUI=~{~UltzT!i{%^C!~*NyGY=u=q9 zTxcy&>%Z9~crG9aT*C{;ytUdMKcyN34wt9RYLwXn-j=GmM%AHMf7g5d8t?T5*S}Si z5T5_FigyQM&5&yh%7kogtgq+epiJ~3E;|hr2t`0i z{2POeNFVmWAuEj$q?tE6j`Vv<-*8(Xwdd~`hF6yW?k<)eCP@3_E&ThLe+I<{hSh(P zN_n>kMc@h6+Igg-!n28XswmDlRRbHZKCR9hsDiZV$EW~nu~cL2SjjJV74(ku`-vT~ z2is3tM~@=eA*@Fx3iJ9_GJyArzdRIJj5O=}m+|_O8)#g&;uTV)wRPNf-s5~0zFP$) z02nJ}XQd^@HU9w6ymEhyXAO@DFQC&?%q%7{V2JF!?K$rm#tVWAZ~om-5hI>n9Vk*q zw@_u%MRu!9FBYj|bsHa2yDnemj4R*KjpzKNRY1yvsb5_B`Ju5!pInykQO`^WTzl70 zTFn*!2A`v4=;Fq^O`G z=1N`r^2YCvrmrwG?m_EE5nfl9tRd^GQbQ?AA4X zHO0|$vay4TXJlmx52<)s(^i!-RxuK|Aky0|(UvU;iQHe&nSbBp7k#1G2PoGV;OSIy zU;9(Jl?f;T>9=o2oJMj`A(6wX7$a;7`*%X6SR>hiM`{Tz@2UFHWe$5f0<7Y}Z|i7? z7+~jav#z1EZnW`ukmK2Kin$=xw_oPmrP4rEA~Rd!nL$_-Zh_L&VeyE#7YC+YxUB3K z&;E#7H!75yPdr~pig}+uSz4c8`o7<#7pi{f-D~@`*^4zJ%?csdF&1vEBN!Ux>Vqh* z&TFUC5<-#;<~nw~7v@F~C23wG6Z#NB%us#J&Up4CIU2$7(c=qNdRll3eOd@2cr`mX zZbcabuCj$L{in356bVSg_OXh6Y|Yp7!|4Ko^{b)@!D2Fr07iI8D5>LF8^`cO)jTMS zA%Z;a_d+-4OWyA95b>@Ng1;wBWam;~WAwG4EqjXGbNb3JSt#b_6|{T6rc$QYvh4{M za?sH689S=ZBdhJbE+pg=;0bWjC(G5Z9@a3{Y&(%DCe0an)vaHxC$-?ng~#t4?^f%W zLaLDHV)gRm1bjF!{iKh)E@3gb5vZsF06(|q|DLyVBH6p+g2KAMv|_)_-uT9yn1M&2 zocAbKC;dlayHdqxt1;vC0G6rQ#arUqrLP)(9;|c%r8TD5%vr12MRzVnM8OKReumMXCKZRI~*{*^M$Cx1+Su) zHk^{(^Rseww5hmCR{hPZ;|IE*z9RRt&|lomThs1KzY^v?Bo!j#6FY2^_eduD&wXU>N;scX&Tne{xmpXV+1N!t>sFoFG%=_k|~tTpflJIJWN5}V^oV-AKW2+y)FrO zsaB#d&%`$6)MiixE1zpZ#mh4dZJAp0IId))-J_eL1_xH}ncu}i6jTTm*7mUp%S-$n zaIQT2A@~=oqaL_l$? z6<1c?)3H2K9E#l7$hcDcGXZ6z*vUyi!lVP|GiP0tmtD5(jTN2VNV`;4dN%@WMJT{J zMY{*Ss#Cc9jO%r>a=HBV>;UlK>M*%*a(lEt^@3%AR`##l4^3dL|I!bXvMhgt2ATkZ zHM`BuBeyC0XNHc5SiRnRLo03a_k=ZG=|f+amem;>iS_%#T(gY85l{{c=?RTWw3UXJ zC!J?9Lf|>YYTy+~-J1Jyy_UV|n&l)sQ^Cewj8Wei&1&HZ}iI!VDLL_UiSQA4*W>MayaqOc>E)sni{O*VC|ROXzut z5k92iJBePC?2&)M+S;FB-*x*zC2@$ZlEB0Zmf;$g8Uh{&I^-2xGXBN$5vXPTw}Jf+ z4Znaqf@MmQOrElkmM`fF5>r80x)LWX=g1pjAic$xzSN6lik-vw50gTngdhnfyrEWx zP1p>f`sOINh0L|(+N+~qMlk;EoQRS&=Xc#d zoN`Mi9Fr$7m3#;f?=xt>!w2cDG_<)p(JX}~OfLqJhGwAjiMNTc@)YY&q$Y9qd`iJ0 ztN$v=_ET9jS(W63ySzkNhN$H_Xj^PFirZt(AdWSnRC_=}*KO(+PU9}eXK2Jgzxa3t z#(DcuJwpmQO%D!rHi7b6a$8D|YyF^~XVJc%%*Nnp2_b=>_MG#94Qc(-Q4@vi3lVx z&b|I5*2+jjN!e>s&(&BDk&ABoJaj+nD&6&2JZMpe9miZBP}uIDgT> z4?t0YfRh1}U(1nf({-}F1GJy0TPC=bE~FY8pN*6NJ_EBARjP&|Tz#l>83n^C0@!Gx zPLb=R{WPR1VM@MW0}{{mgNoKEf@8k}*3y)b5Y_vW>&Fz)Z&2)lJYn1YZ=*pKPM*Ch zzT<^K?W}(xfeff%Z@o@|VYgCypJm4_$y|G`RMKn?n$&YfV;WG)x!VfZfCI`4S2kck zxfJ*`S)m2dR6BGo6$_?8yS1k$Xn{s?9F-cB+|7s7oa{nI#M1_h(1nw7!XU@+IyvEn zpBHU1d9f5j;Lvc#ek7c249d(V-H;;>B0A_~Zu^q}{lDa*W#eMqX;hpN>cHy%`vchV z&C0q+?4qFuFCq>)>3c7k`@q`Fr%%{u<({krx;^?Yd|L&~a}>n|dNs}wGtF)duyp?U zqqKmk(zO||lJt89Hq+5lQ#?O^`@La={s73Q>$g@@jvBl|HIfW}5mm9SVcLSK!JrK% zY(PKIf@Mq*r-1PS-mvKL$!XK}9Hi(GuMAzsbyVKMs}7>+jX6jRF9H-Uh;B1))jai4 zV!i>>;iZ6+_tr53KCjh~7OdXGcp5smJ9*&?mia){AV2{-QrXM`?jz=z=kdR^>Mp_` zHz*h_G%me8=?tLPWe=Y2Aere_=1kPd%-#EX*0h;8nkNhl{E}kUReQ2cO?ci zmYr)0Udtc98_dp{3s})CbWU$SuB%L~P-@X>ubdA#I0_7+QQ4b3kiRwlAKyX3FJi~H zi^`&{dc@Dl`oU26Bwh8XN;ESwdpeEELa{bu2zfb+QG3bpsEYh%%&*$<_FaWWG{669 zhqHLibM4){=taMpc`CuhiF11{-yFf?ZnYEqs8h2eg_ z^;)Rp$^{^yce|gFKnw$|cBoO8$F+V(K0xnd`yzJ##Xs$D@bBZ-fBg^r8+Ov)y*T54 z#*5>9`t0e_BYdH7*|eESy-qmV0KN^P2P4l+QaKouML$?QNZ_>38=}b{RgLX}RD4V4 z-POMPj(R8%sM;9B9G7KukZ%C!a<)MX*&^--%Wu%?1t5SZz4ow}{K2~X=efBS|AnhJeukW( z1)RGQ(M^B3NQ0ld4U2?$YtKIVd8I+7BkI891tB~1ICLS9{%7L_TE6*d`g@s@odS8X zx$GxBekH$5W^UQD_jM}m%^yP6wmZZxi3l(3=%oMG$$AeE62QVu16=$>fiK6#^}b4z-_`J=KKm4>=pO7pC~3ug~Tyi9|9PpA#5Ic}0tcPI^;iw_#5NY+|CL z$P#?49K96LOzWCHG6vQuA`Pq2F=?%F3hgd{RJu^2_pODU=&dHnw}HwH^0*cA9T&3v z7XGIA8rKvh8ovH(w6;6v|uA9wGpz=9M(|@IV-fIP;UFloqj&0$P+amyC_WKUgbN%Qxi_irBoZcT)#!|4EOi zzf~6hZVLQ^nId#WoJiU|1H?+Nl5?rm%yp0}@<4B93A4`=H$TGGgtOXtm|$;T)TEVM z4ja}|m)Rj8wN(4kQcPXn>AmiS3gPipy}VHJ4>69-=nsjwV@dzNvRLy*0_M7OP|C|| zObvVIm7bArg-%J&4%GHqpZOT+2;%SPv%PY6erGw3TQ7-6BvwaqBGSsO9a@>#{k;M( z+2#6I&+B8{QEllO6%Kmo9*uKGkBbCUsYmp^nq{)ZJ_oxGZL-bYLS%@H?%5{ucz#b+ zan{t3y_)Il{g7)h3daio`Y?D1oAeNMTZqw?rHV> z5JDnC#mb*UN{7_(-&}qO=H>)v#tSe9m^I%CE08$5|7I5N6Dz8ihTgWsKoq35B^o)B zPV~z+LC<7dU14#D-IJSa&=42l;5DKll=VtpTEnE`9ea+Llut%>wW10>HbQs3hUOgo z^`k{KrM*pPwX;gCGiBp6bf1+qqkSF+o!sz-r)GFg;(n+nc|~IND=~)NybmOAHO{{* z?lW*`ncSX?lJ@kv5oO;h%)3)c_Skr3oGDG3Km zFvG?t##_``A~z&H@}3Es-uKy}3~ClBZ8)57>nW`pL)E9W=@9O}_CPE5{HMau(so0O z8viqEa=_H)H)zi2K)t_@%&P5hoj$!qJ-Q+}L;o6L+p|*J0GDam!80hP@9Bt?-dJ!( zL9L58t)O}dsWjl=q;)drsTrfQih@bJXZRN8g8id#s;d32nv{mFgsicswdD1?eah`b zN?&@@q{||=GrkFUb|pR>ER$2t6l};+5@?;Qh%ZM*oUBZ9IeiQYJRT16gH=$uz8a>}%A1baP zif<5B8w4{I>DV^j)qZ__4OIV%2Z@>zZs|7nsOzVApm`%v@}IPlpp%)& zUYocL9ecu7x!eSOT-zXgbM)x-+e+f@bOD!s;^RZ+RPDJLiK+5I0TcMfReVfkd(oS5 z67J;ixQ48@k^xmNvhE&ny|N&gmpHAex&v@rH2Ug#7FulNry5YI`9wzG#;t+W$yfPO zhgqRkwZxIPeU38D_6LA5X$RCnk&D!y)L-a-gK&3NPeis15eET#3I>6*K@EVlWw;+{ zy)ta`Gc(y|?ox|2)N-t_W54cf?aI8(hYQ%M)RTUfX0C$ADJlF|9og(q4sYx+V8Ia< zWTcmZ_3Oz^cVUHawMOeI>oL(5zvmB;__noT&s6}wec*j%KA3gMnjF{3uv^9(%=g9Y z$VKYdeg3CqY-(*bDxQ-cd2M6rpxHE%S^@HBd;5tPa!vA^MSBY73G#hq>SeJ`uC}FWB z8UuKS3gQMlu6Q%gEPgq5pt%qsR5W6h^#tR$$vB#0s-BTlYPAKQHA2jn`jf&;2T*p` z8t29sCcnBB^+uL|h zWw1t!va{U*XL zw@E1?iL=Rrl*JYrzw$nVMXhp_oJUwzN-M=pA` zbJ(}}39+RdRW$$IV#+UX?uFeA@4bVFyobP9syU~8JKFN%q&sxVu!Fhl?eZ35UdG^g zh4Vnf`l!h1(oOkKJn7i%%V+L#+781A2mE|`DQA0F$g(U`%lfNilZF8&j4E`YW^jiQ zk@TUV@@=(FX+2^6jkcz8zL?$Q1ZUuC7ty}*mDuqRGnJ8g==`i-@mSA9`A(P_wL4PQ z2C{uBGkN2ie6{^?T9RzB(Ln_FLd9O~nB!Kpj`YoERm1>vtA0#tA7~ray#19Sgal=sFi1IySSTILYdVz zQ{z{9qW&@*pMlmgyT`MB`w=t#toob>dP&mei9ckelGX|~T{pQU)+aEP&z z>q7zu2(pZ186B6`nF<9#KK}-l$TgphWM6Vf2JX3F%#Q<=mQxo^FD|BA*QU|uXGnkg#Gq#|RNG)udC}j=zn5yk9q8msQHyVOG2M|7u8+op zz+{RqqwGQUEMg>XAC)(4E@A$rF=5eefpB`AtOeU#BmbfE^uI(Fu6_v}xQB7&AKFS^ zzZJqh$fg-{7i*~I&Egnr@zlFa0$M-bw(~yCG#-ywyTeeJrH2nOpf81-sfzdvU-c0( z=)PeOa=3D&+ONuY*OcGRpHCEYp5-BSPtM~q_N2)C=94MzUXh}Zw!3InGBmn~N+83_ z%zc%k$gbcUOgVnihdWxq3Fr-(i+O*OD|#WUJ?h=b*R@%&t|gr_SrIXeYc6!ViKK%B zteDo{A~}=Y^uUFA>j#93Ul(u-UVt)<3wKae0me@10d$Nziky-l(^`v5pg-3f|HDPR zDAiF7Q&>FBZ8+STm|lO^CkoF*l5g|)uq#x&l3!tnO?0x0ziWP<@!q2K;B-wEcI{HSPRtQ`ev;c!=QQljA%qVqP!&He|~^^ws`~~E;vhATs${J8WCq5E}0FNPwk2ttI zZ(kD2(}cuafhe?VW9^j%Iq`WWTwS~jHH8BYbio$a-+#R}igaH5b-3y)>)J+Z7r5%* zYc4tQ+{<`oJ~$swYwmPgkDU|BZG%Jp291Dq=!-i+95b=#0Mbjq7g~*m$v@v~VSeoS z(gYyydfIzG{DAcDnMYLx{dDaxqlI$@#JGf7c}Qh&HDpR=cnLKoF;($R diff --git a/doc/user-guide.rst b/doc/user-guide.rst index a51180f15ec..997b28e6e62 100644 --- a/doc/user-guide.rst +++ b/doc/user-guide.rst @@ -239,9 +239,6 @@ select "Next: Additional Info". talk to your site administrator about changing the default schema and dataset forms. -* *Group* -- Moderated collection of datasets. You can add the dataset to - an existing group here. - .. image:: /images/add_dataset_3.jpg .. note:: @@ -250,6 +247,11 @@ select "Next: Additional Info". "Visibility" is set correctly. It is also good practice to ensure an Author is named. +.. versionchanged:: 2.2 + Previous versions of CKAN used to allow adding the dataset to existing + groups in this step. This was changed. To add a dataset to an existing group + now, go to the "Group" tab in the Dataset's page. + **Step 8**. Select the 'Finish' button. CKAN creates the dataset and shows you the result. You have finished! From d8dc948da2440247cd15b5a8eaaef873e449caf7 Mon Sep 17 00:00:00 2001 From: Vitor Baptista Date: Thu, 8 May 2014 07:39:35 -0300 Subject: [PATCH 48/77] Fix typo datesets -> datasets --- ckan/plugins/interfaces.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ckan/plugins/interfaces.py b/ckan/plugins/interfaces.py index 1f510891906..50380bdf471 100644 --- a/ckan/plugins/interfaces.py +++ b/ckan/plugins/interfaces.py @@ -179,7 +179,7 @@ def after_rollback(self, session): class IDomainObjectModification(Interface): """ - Receives notification of new, changed and deleted datesets. + Receives notification of new, changed and deleted datasets. """ def notify(self, entity, operation): From 9e8e5a4dde817d090822d1947bd0dfd52a2f187e Mon Sep 17 00:00:00 2001 From: Ian Ward Date: Mon, 12 May 2014 14:58:54 -0400 Subject: [PATCH 49/77] [#1711] prevent membership update when updating orgs --- ckan/logic/action/update.py | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/ckan/logic/action/update.py b/ckan/logic/action/update.py index 0cd0332efde..152c520c648 100644 --- a/ckan/logic/action/update.py +++ b/ckan/logic/action/update.py @@ -523,13 +523,7 @@ def _group_or_org_update(context, data_dict, is_org=False): else: rev.message = _(u'REST API: Update object %s') % data.get("name") - # when editing an org we do not want to update the packages if using the - # new templates. - if ((not is_org) - and not converters.asbool( - config.get('ckan.legacy_templates', False)) - and 'api_version' not in context): - context['prevent_packages_update'] = True + context['prevent_packages_update'] = is_org group = model_save.group_dict_save(data, context) if is_org: From 931c1b6d0e48dc08e046e93033f3628b27ec4a85 Mon Sep 17 00:00:00 2001 From: joetsoi Date: Tue, 13 May 2014 15:37:25 +0100 Subject: [PATCH 50/77] [#790] save pylons config prior to tests, restore config in teardown The plugin implements IConfigurer which adds a directory to the templates. This clashes with the tests for the multilingual extension that are running off the legacy templates. Having the package/search.html template here causes the clash. Saving and restoring the config means the multilingual tests will not pickup and templates from this plugin. --- .../{new_tests => tests}/__init__.py | 0 .../test_example_idatasetform.py | 33 +++++++++++++++++-- 2 files changed, 30 insertions(+), 3 deletions(-) rename ckanext/example_idatasetform/{new_tests => tests}/__init__.py (100%) rename ckanext/example_idatasetform/{new_tests => tests}/test_example_idatasetform.py (89%) diff --git a/ckanext/example_idatasetform/new_tests/__init__.py b/ckanext/example_idatasetform/tests/__init__.py similarity index 100% rename from ckanext/example_idatasetform/new_tests/__init__.py rename to ckanext/example_idatasetform/tests/__init__.py diff --git a/ckanext/example_idatasetform/new_tests/test_example_idatasetform.py b/ckanext/example_idatasetform/tests/test_example_idatasetform.py similarity index 89% rename from ckanext/example_idatasetform/new_tests/test_example_idatasetform.py rename to ckanext/example_idatasetform/tests/test_example_idatasetform.py index c917b53f8df..f0683ce2e59 100644 --- a/ckanext/example_idatasetform/new_tests/test_example_idatasetform.py +++ b/ckanext/example_idatasetform/tests/test_example_idatasetform.py @@ -1,20 +1,33 @@ import nose.tools as nt +import pylons.config as config + import ckan.model as model import ckan.plugins as plugins import ckan.new_tests.helpers as helpers import ckanext.example_idatasetform as idf +import ckan.lib.search class ExampleIDatasetFormPluginBase(object): '''Version 1, 2 and 3 of the plugin are basically the same, so this class provides the tests that all three versions of the plugins will run''' + @classmethod + def setup_class(cls): + cls.original_config = config.copy() + def teardown(self): model.repo.rebuild_db() + ckan.lib.search.clear() @classmethod def teardown_class(cls): helpers.reset_db() + model.repo.rebuild_db() + ckan.lib.search.clear() + + config.clear() + config.update(cls.original_config) def test_package_create(self): result = helpers.call_action('package_create', name='test_package', @@ -38,39 +51,43 @@ def test_package_show(self): class TestVersion1(ExampleIDatasetFormPluginBase): @classmethod def setup_class(cls): + super(TestVersion1, cls).setup_class() plugins.load('example_idatasetform_v1') @classmethod def teardown_class(cls): - super(TestVersion1, cls).teardown_class() plugins.unload('example_idatasetform_v1') + super(TestVersion1, cls).teardown_class() class TestVersion2(ExampleIDatasetFormPluginBase): @classmethod def setup_class(cls): + super(TestVersion2, cls).setup_class() plugins.load('example_idatasetform_v2') @classmethod def teardown_class(cls): - super(TestVersion2, cls).teardown_class() plugins.unload('example_idatasetform_v2') + super(TestVersion2, cls).teardown_class() class TestVersion3(ExampleIDatasetFormPluginBase): @classmethod def setup_class(cls): + super(TestVersion3, cls).setup_class() plugins.load('example_idatasetform_v3') @classmethod def teardown_class(cls): - super(TestVersion3, cls).teardown_class() plugins.unload('example_idatasetform_v3') + super(TestVersion3, cls).teardown_class() class TestIDatasetFormPluginVersion4(object): @classmethod def setup_class(cls): + cls.original_config = config.copy() plugins.load('example_idatasetform_v4') def teardown(self): @@ -80,6 +97,10 @@ def teardown(self): def teardown_class(cls): plugins.unload('example_idatasetform_v4') helpers.reset_db() + ckan.lib.search.clear() + + config.clear() + config.update(cls.original_config) def test_package_create(self): idf.plugin_v4.create_country_codes() @@ -113,15 +134,21 @@ def test_package_update(self): class TestIDatasetFormPlugin(object): @classmethod def setup_class(cls): + cls.original_config = config.copy() plugins.load('example_idatasetform') def teardown(self): model.repo.rebuild_db() + ckan.lib.search.clear() @classmethod def teardown_class(cls): plugins.unload('example_idatasetform') helpers.reset_db() + ckan.lib.search.clear() + + config.clear() + config.update(cls.original_config) def test_package_create(self): idf.plugin.create_country_codes() From 2341b712a62ae4896431aab66cd4a51ed13e3f4d Mon Sep 17 00:00:00 2001 From: joetsoi Date: Tue, 13 May 2014 17:11:30 +0100 Subject: [PATCH 51/77] [#790] add test for search ordering by custom fields --- ckan/new_tests/helpers.py | 17 +++++++ .../tests/test_example_idatasetform.py | 48 +++++++++++++++++++ 2 files changed, 65 insertions(+) diff --git a/ckan/new_tests/helpers.py b/ckan/new_tests/helpers.py index 4e1e1ffd0c7..cbfb5fd9361 100644 --- a/ckan/new_tests/helpers.py +++ b/ckan/new_tests/helpers.py @@ -17,6 +17,10 @@ This module is reserved for these very useful functions. ''' +import pylons.config as config +import webtest + +import ckan.config.middleware import ckan.model as model import ckan.logic as logic @@ -116,3 +120,16 @@ def call_auth(auth_name, context, **kwargs): # FIXME: Do we want to go through check_access() here? auth_function = ckan.logic.auth.update.__getattribute__(auth_name) return auth_function(context=context, data_dict=kwargs) + + +def _get_test_app(): + '''Return a webtest.TestApp for CKAN, with legacy templates disabled. + + For functional tests that need to request CKAN pages or post to the API. + Unit tests shouldn't need this. + + ''' + config['ckan.legacy_templates'] = False + app = ckan.config.middleware.make_app(config['global_conf'], **config) + app = webtest.TestApp(app) + return app diff --git a/ckanext/example_idatasetform/tests/test_example_idatasetform.py b/ckanext/example_idatasetform/tests/test_example_idatasetform.py index f0683ce2e59..e8f16f8129a 100644 --- a/ckanext/example_idatasetform/tests/test_example_idatasetform.py +++ b/ckanext/example_idatasetform/tests/test_example_idatasetform.py @@ -201,3 +201,51 @@ def test_package_show(self): result['resources'][0]['custom_resource_text']) nt.assert_equals('my custom resource', result['resources'][0]['custom_resource_text']) + + +class TestCustomSearch(object): + @classmethod + def setup_class(cls): + cls.original_config = config.copy() + cls.app = helpers._get_test_app() + plugins.load('example_idatasetform') + + def teardown(self): + model.repo.rebuild_db() + ckan.lib.search.clear() + + @classmethod + def teardown_class(cls): + plugins.unload('example_idatasetform') + helpers.reset_db() + ckan.lib.search.clear() + + config.clear() + config.update(cls.original_config) + + + def test_custom_search(self): + helpers.call_action('package_create', name='test_package_a', + custom_text='z') + helpers.call_action('package_create', name='test_package_b', + custom_text='y') + + response = self.app.get('/dataset') + + #change the sort by form to our custom_text ascending + response.forms[1].fields['sort'][0].value = 'custom_text asc' + response = response.forms[1].submit() + #check that package_b appears before package a (y < z) + nt.assert_less( + response.body.index('test_package_b'), + response.body.index('test_package_a'), + ) + + response.forms[1].fields['sort'][0].value = 'custom_text desc' + #check that package_a appears before package b (z is first in + #descending order) + response = response.forms[1].submit() + nt.assert_less( + response.body.index('test_package_a'), + response.body.index('test_package_b') + ) From 0840aefd4fce39c210e5a92709c577a337fa46cf Mon Sep 17 00:00:00 2001 From: joetsoi Date: Tue, 13 May 2014 17:45:54 +0100 Subject: [PATCH 52/77] [#790] pep8 --- .../tests/test_example_idatasetform.py | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/ckanext/example_idatasetform/tests/test_example_idatasetform.py b/ckanext/example_idatasetform/tests/test_example_idatasetform.py index e8f16f8129a..8479f8db40e 100644 --- a/ckanext/example_idatasetform/tests/test_example_idatasetform.py +++ b/ckanext/example_idatasetform/tests/test_example_idatasetform.py @@ -223,7 +223,6 @@ def teardown_class(cls): config.clear() config.update(cls.original_config) - def test_custom_search(self): helpers.call_action('package_create', name='test_package_a', custom_text='z') @@ -232,18 +231,18 @@ def test_custom_search(self): response = self.app.get('/dataset') - #change the sort by form to our custom_text ascending + # change the sort by form to our custom_text ascending response.forms[1].fields['sort'][0].value = 'custom_text asc' response = response.forms[1].submit() - #check that package_b appears before package a (y < z) + # check that package_b appears before package a (y < z) nt.assert_less( response.body.index('test_package_b'), response.body.index('test_package_a'), ) response.forms[1].fields['sort'][0].value = 'custom_text desc' - #check that package_a appears before package b (z is first in - #descending order) + # check that package_a appears before package b (z is first in + # descending order) response = response.forms[1].submit() nt.assert_less( response.body.index('test_package_a'), From 51f865abc3815f1eef5fd2cebdb10c53e15f3469 Mon Sep 17 00:00:00 2001 From: joetsoi Date: Tue, 13 May 2014 18:06:26 +0100 Subject: [PATCH 53/77] [#790] make tests python 2.6 compatible --- .../tests/test_example_idatasetform.py | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/ckanext/example_idatasetform/tests/test_example_idatasetform.py b/ckanext/example_idatasetform/tests/test_example_idatasetform.py index 8479f8db40e..cbe34059e92 100644 --- a/ckanext/example_idatasetform/tests/test_example_idatasetform.py +++ b/ckanext/example_idatasetform/tests/test_example_idatasetform.py @@ -235,16 +235,14 @@ def test_custom_search(self): response.forms[1].fields['sort'][0].value = 'custom_text asc' response = response.forms[1].submit() # check that package_b appears before package a (y < z) - nt.assert_less( - response.body.index('test_package_b'), - response.body.index('test_package_a'), - ) + a = response.body.index('test_package_a') + b = response.body.index('test_package_b') + nt.assert_true(b < a) response.forms[1].fields['sort'][0].value = 'custom_text desc' # check that package_a appears before package b (z is first in # descending order) response = response.forms[1].submit() - nt.assert_less( - response.body.index('test_package_a'), - response.body.index('test_package_b') - ) + a = response.body.index('test_package_a') + b = response.body.index('test_package_b') + nt.assert_true(a < b) From 225933e65e75cc433333f1e4837b0858392ced0b Mon Sep 17 00:00:00 2001 From: Rodrigo Parra Date: Tue, 13 May 2014 18:30:58 -0400 Subject: [PATCH 54/77] [#1708] Use data-module attribute in custom-fields JavaScript module --- ckan/public/base/javascript/modules/custom-fields.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ckan/public/base/javascript/modules/custom-fields.js b/ckan/public/base/javascript/modules/custom-fields.js index 3bd6daa0646..e26ea01c3c2 100644 --- a/ckan/public/base/javascript/modules/custom-fields.js +++ b/ckan/public/base/javascript/modules/custom-fields.js @@ -90,14 +90,14 @@ this.ckan.module('custom-fields', function (jQuery, _) { */ _onChange: function (event) { if (event.target.value !== '') { - var parent = jQuery(event.target).parents('.control-custom'); + var parent = jQuery(event.target).parents(this.options.fieldSelector); this.newField(parent); } }, /* Event handler called when the remove checkbox is checked */ _onRemove: function (event) { - var parent = jQuery(event.target).parents('.control-custom'); + var parent = jQuery(event.target).parents(this.options.fieldSelector); this.disableField(parent, event.target.checked); } }; From f9bcc77418a4417ea274794bce82dd9fe21d0b9e Mon Sep 17 00:00:00 2001 From: Ian Ward Date: Wed, 14 May 2014 14:50:19 -0400 Subject: [PATCH 55/77] [#1711] document packages ignored by organization_update --- ckan/logic/action/update.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/ckan/logic/action/update.py b/ckan/logic/action/update.py index 152c520c648..17a2687d1e7 100644 --- a/ckan/logic/action/update.py +++ b/ckan/logic/action/update.py @@ -611,6 +611,9 @@ def organization_update(context, data_dict): :param id: the name or id of the organization to update :type id: string + :param packages: ignored. use + :py:func:`~ckan.logic.action.update.package_owner_org_update` + to change package ownership :returns: the updated organization :rtype: dictionary From b8faad3618c8ab55984e730f745071d9fe9aca78 Mon Sep 17 00:00:00 2001 From: Tom Lukasiak Date: Thu, 15 May 2014 00:42:35 -0400 Subject: [PATCH 56/77] Changed external http:// links to // protocol-independent paths --- ckan/templates/footer.html | 2 +- ckan/templates/snippets/license.html | 2 +- ckan/templates/user/snippets/recaptcha.html | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/ckan/templates/footer.html b/ckan/templates/footer.html index 01248a5d4cd..6c8373f3ab2 100644 --- a/ckan/templates/footer.html +++ b/ckan/templates/footer.html @@ -13,7 +13,7 @@ {% set api_url = 'http://docs.ckan.org/en/{0}/api.html'.format(g.ckan_doc_version) %}

  • {{ _('CKAN API') }}
  • {{ _('Open Knowledge Foundation') }}
  • -
  • +
  • {% endblock %} {% endblock %} diff --git a/ckan/templates/snippets/license.html b/ckan/templates/snippets/license.html index 43c89aed48d..cae9943830c 100644 --- a/ckan/templates/snippets/license.html +++ b/ckan/templates/snippets/license.html @@ -26,7 +26,7 @@

    {{ _('License') {{ license_string(pkg_dict) }} {% if pkg_dict.isopen %} - [Open Data] + [Open Data] {% endif %} {% endblock %} diff --git a/ckan/templates/user/snippets/recaptcha.html b/ckan/templates/user/snippets/recaptcha.html index 994867dc97f..c4dba81442d 100644 --- a/ckan/templates/user/snippets/recaptcha.html +++ b/ckan/templates/user/snippets/recaptcha.html @@ -1,9 +1,9 @@
    - + From 303ab34354dafd214144ff49117df4403ce9174a Mon Sep 17 00:00:00 2001 From: Ian Ward Date: Thu, 15 May 2014 07:17:40 -0400 Subject: [PATCH 57/77] [#1711] reduce context unpleasantness --- ckan/lib/dictization/model_save.py | 3 +-- ckan/logic/action/update.py | 4 ++-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/ckan/lib/dictization/model_save.py b/ckan/lib/dictization/model_save.py index 540bf645c6e..b0d2bd89803 100644 --- a/ckan/lib/dictization/model_save.py +++ b/ckan/lib/dictization/model_save.py @@ -381,14 +381,13 @@ def group_member_save(context, group_dict, member_table_name): return processed -def group_dict_save(group_dict, context): +def group_dict_save(group_dict, context, prevent_packages_update=False): from ckan.lib.search import rebuild model = context["model"] session = context["session"] group = context.get("group") allow_partial_update = context.get("allow_partial_update", False) - prevent_packages_update = context.get("prevent_packages_update", False) Group = model.Group if group: diff --git a/ckan/logic/action/update.py b/ckan/logic/action/update.py index 17a2687d1e7..3cbd2abbe8d 100644 --- a/ckan/logic/action/update.py +++ b/ckan/logic/action/update.py @@ -523,8 +523,8 @@ def _group_or_org_update(context, data_dict, is_org=False): else: rev.message = _(u'REST API: Update object %s') % data.get("name") - context['prevent_packages_update'] = is_org - group = model_save.group_dict_save(data, context) + group = model_save.group_dict_save(data, context, + prevent_packages_update=is_org) if is_org: plugin_type = plugins.IOrganizationController From 8df3d434eb47f3c1182584028b44f9ead007ae96 Mon Sep 17 00:00:00 2001 From: Ian Ward Date: Thu, 15 May 2014 13:09:55 -0400 Subject: [PATCH 58/77] [#1711] group_dict_save: save extras before session.commit+rebuild --- ckan/lib/dictization/model_save.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/ckan/lib/dictization/model_save.py b/ckan/lib/dictization/model_save.py index b0d2bd89803..4a3ff1015d8 100644 --- a/ckan/lib/dictization/model_save.py +++ b/ckan/lib/dictization/model_save.py @@ -417,14 +417,6 @@ def group_dict_save(group_dict, context, prevent_packages_update=False): 'Groups: %r Tags: %r', pkgs_edited, group_users_changed, group_groups_changed, group_tags_changed) - # We will get a list of packages that we have either added or - # removed from the group, and trigger a re-index. - package_ids = pkgs_edited['removed'] - package_ids.extend( pkgs_edited['added'] ) - if package_ids: - session.commit() - map( rebuild, package_ids ) - extras = group_extras_save(group_dict.get("extras", {}), context) if extras or not allow_partial_update: old_extras = set(group.extras.keys()) @@ -434,6 +426,14 @@ def group_dict_save(group_dict, context, prevent_packages_update=False): for key in new_extras: group.extras[key] = extras[key] + # We will get a list of packages that we have either added or + # removed from the group, and trigger a re-index. + package_ids = pkgs_edited['removed'] + package_ids.extend( pkgs_edited['added'] ) + if package_ids: + session.commit() + map( rebuild, package_ids ) + return group From 31dcb2cbbd09eab1cf30a0d6632fd814f285431c Mon Sep 17 00:00:00 2001 From: amercader Date: Mon, 19 May 2014 18:00:10 +0100 Subject: [PATCH 59/77] [#1652] Fix dodgy test --- ckanext/datastore/tests/test_create.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ckanext/datastore/tests/test_create.py b/ckanext/datastore/tests/test_create.py index 3dcde2f694b..c1f464b48a9 100644 --- a/ckanext/datastore/tests/test_create.py +++ b/ckanext/datastore/tests/test_create.py @@ -572,7 +572,7 @@ def test_create_datastore_resource_on_dataset(self): res = self.app.post('/api/action/resource_show', params=postparams) res_dict = json.loads(res.body) - assert res_dict['datastore_active'] is True + assert res_dict['result']['datastore_active'] is True def test_guess_types(self): From e8c7443b65289b2eb06e554a961d8fd7b979f3f0 Mon Sep 17 00:00:00 2001 From: nigelb Date: Tue, 20 May 2014 08:40:56 +0530 Subject: [PATCH 60/77] [#1684] Wrap error message in _ --- ckanext/resourceproxy/controller.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ckanext/resourceproxy/controller.py b/ckanext/resourceproxy/controller.py index b22b0595092..0075298bfb0 100644 --- a/ckanext/resourceproxy/controller.py +++ b/ckanext/resourceproxy/controller.py @@ -24,7 +24,7 @@ def proxy_resource(context, data_dict): resource = logic.get_action('resource_show')(context, {'id': resource_id}) except logic.NotFound: - base.abort(404, 'Resource not found') + base.abort(404, _('Resource not found')) url = resource['url'] parts = urlparse.urlsplit(url) From e0f1ab407d5294731965605636d6b300c4e8bbc6 Mon Sep 17 00:00:00 2001 From: nigelb Date: Tue, 20 May 2014 09:04:25 +0530 Subject: [PATCH 61/77] import _ --- ckanext/resourceproxy/controller.py | 1 + 1 file changed, 1 insertion(+) diff --git a/ckanext/resourceproxy/controller.py b/ckanext/resourceproxy/controller.py index 0075298bfb0..c0bd4db47a0 100644 --- a/ckanext/resourceproxy/controller.py +++ b/ckanext/resourceproxy/controller.py @@ -5,6 +5,7 @@ import ckan.logic as logic import ckan.lib.base as base +from ckan.common import _ log = getLogger(__name__) From 3c61c253a036ebb7ae040b832e90ed37b446041c Mon Sep 17 00:00:00 2001 From: Sean Hammond Date: Wed, 21 May 2014 11:48:01 +0000 Subject: [PATCH 62/77] [#1193] Deprecate helpers.get_action() Fixes #1193 --- ckan/lib/helpers.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/ckan/lib/helpers.py b/ckan/lib/helpers.py index 5d03d5d51da..ea9d581740a 100644 --- a/ckan/lib/helpers.py +++ b/ckan/lib/helpers.py @@ -737,6 +737,17 @@ def check_access(action, data_dict=None): return authorized +@maintain.deprecated("helpers.get_action() is deprecated and will be removed " + "in a future version of CKAN. Since action functions " + "raise exceptions and templates cannot catch exceptions, " + "it's not a good idea to call action functions from " + "templates. Instead, either wrap individual action " + "functions in custom template helper functions that " + "handle any exceptions appropriately, or have controller " + "methods call the action functions and pass the results " + "to templates as extra_vars. Note that " + "logic.get_action() and toolkit.get_action() are *not* " + "deprecated.") def get_action(action_name, data_dict=None): '''Calls an action function from a template.''' if data_dict is None: From cff83a8c58a2c35725c3389a3ab4fa41c090b413 Mon Sep 17 00:00:00 2001 From: Sean Hammond Date: Wed, 21 May 2014 14:43:14 +0000 Subject: [PATCH 63/77] [#1694] Document using extra_vars over c --- doc/theming/best-practices.rst | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/doc/theming/best-practices.rst b/doc/theming/best-practices.rst index 6ff17d5c044..91b9bc5f44e 100644 --- a/doc/theming/best-practices.rst +++ b/doc/theming/best-practices.rst @@ -9,8 +9,23 @@ Don't use ``c`` --------------- As much as possible, avoid accessing the Pylons template context :py:data:`c` -(or :py:data:`tmpl_context`). Use +(or :py:data:`tmpl_context`). :py:data:`c` is a thread-global variable, which +encourages spaghetti code that's difficult to understand and to debug. + +Instead, have controller methods add variables to the :py:data:`extra_vars` +parameter of :py:func:`~ckan.lib.base.render`, or have the templates +call :doc:`template helper functions ` instead. + +:py:data:`extra_vars` has the advantage that it allows templates, which are +difficult to debug, to be simpler and shifts logic into the easier-to-test and +easier-to-debug Python code. On the other hand, template helper functions are +easier to reuse as they're available to all templates and they avoid +inconsistencies between the namespaces of templates that are rendered by +different controllers (e.g. one controller method passes the package dict as an +extra var named ``package``, another controller method passes the same thing +but calls it ``pkg``, a third calls it ``pkg_dict``). + You can use the :py:class:`~ckan.plugins.interfaces.ITemplateHelpers` plugin interface to add custom helper functions, see :ref:`custom template helper functions`. From 1f16dfa5783a95496b6703695badbc905fcda684 Mon Sep 17 00:00:00 2001 From: Sean Hammond Date: Wed, 21 May 2014 15:01:26 +0000 Subject: [PATCH 64/77] [#1503] Clarify data vs metadata licenses Fixes #1503 --- ckan/templates/package/snippets/package_form.html | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/ckan/templates/package/snippets/package_form.html b/ckan/templates/package/snippets/package_form.html index 6602abbe63c..43d098cf853 100644 --- a/ckan/templates/package/snippets/package_form.html +++ b/ckan/templates/package/snippets/package_form.html @@ -26,9 +26,11 @@ {% block disclaimer %}

    {%- trans -%} - Important: By submitting content, you - agree to release your contributions under the Open Database - License. + The data license you select above only applies to the contents + of any resource files that you add to this dataset. By submitting + this form, you agree to release the metadata values that you + enter into the form under the + Open Database License. {%- endtrans -%}

    {% endblock %} From c932bb1be3100a770690eba5ff5336ee956217a5 Mon Sep 17 00:00:00 2001 From: Sean Hammond Date: Wed, 28 May 2014 08:30:29 +0000 Subject: [PATCH 65/77] [#1193] Move long deprecation message to changelog Also add "deprecated" to docstring, needed to prevent warnings and test fails. --- CHANGELOG.rst | 23 +++++++++++++++++++++++ ckan/lib/helpers.py | 15 ++++----------- 2 files changed, 27 insertions(+), 11 deletions(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 7f37a4ec889..93be4288c29 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -7,6 +7,29 @@ Changelog --------- +v2.3 +==== + +API changes and deprecations +---------------------------- + +* ``helpers.get_action()`` (or ``h.get_action()`` in templates) is deprecated. + + Since action functions raise exceptions and templates cannot catch + exceptions, it's not a good idea to call action functions from templates. + + Instead, have your controller method call the action function and pass the + result to your template using the ``extra_vars`` param of ``render()``. + + Alternatively you can wrap individual action functions in custom template + helper functions that handle any exceptions appropriately, but this is likely + to make your the logic in your templates more complex and templates are + difficult to test and debug. + + Note that logic.get_action() and toolkit.get_action() are *not* deprecated, + core code and plugin code should still use ``get_action()``. + + v2.2 2014-02-04 =============== diff --git a/ckan/lib/helpers.py b/ckan/lib/helpers.py index ea9d581740a..81b9dc3e9a5 100644 --- a/ckan/lib/helpers.py +++ b/ckan/lib/helpers.py @@ -738,18 +738,11 @@ def check_access(action, data_dict=None): @maintain.deprecated("helpers.get_action() is deprecated and will be removed " - "in a future version of CKAN. Since action functions " - "raise exceptions and templates cannot catch exceptions, " - "it's not a good idea to call action functions from " - "templates. Instead, either wrap individual action " - "functions in custom template helper functions that " - "handle any exceptions appropriately, or have controller " - "methods call the action functions and pass the results " - "to templates as extra_vars. Note that " - "logic.get_action() and toolkit.get_action() are *not* " - "deprecated.") + "in a future version of CKAN. Instead, please use the " + "extra_vars param to render() in your controller to pass " + "results from action functions to your templates.") def get_action(action_name, data_dict=None): - '''Calls an action function from a template.''' + '''Calls an action function from a template. Deprecated in CKAN 2.3.''' if data_dict is None: data_dict = {} return logic.get_action(action_name)({}, data_dict) From f0c87283f42af0a39ab7570d31babdcab5c99388 Mon Sep 17 00:00:00 2001 From: Sean Hammond Date: Wed, 28 May 2014 08:42:55 +0000 Subject: [PATCH 66/77] [#1193] Improve doc on how to deprecate functions --- doc/contributing/architecture.rst | 39 ++++++++++++++++++++----------- 1 file changed, 25 insertions(+), 14 deletions(-) diff --git a/doc/contributing/architecture.rst b/doc/contributing/architecture.rst index 50114ff53d4..be571c13b3a 100644 --- a/doc/contributing/architecture.rst +++ b/doc/contributing/architecture.rst @@ -160,21 +160,32 @@ the helper functions found in ``ckan.lib.helpers.__allowed_functions__``. Deprecation ----------- -- Anything that may be used by extensions (see :doc:`/extensions/index`) needs - to maintain backward compatibility at call-site. ie - template helper - functions and functions defined in the plugins toolkit. +- Anything that may be used by :doc:`extensions `, + :doc:`themes ` or :doc:`API clients ` needs to + maintain backward compatibility at call-site. For example: action functions, + template helper functions and functions defined in the plugins toolkit. - The length of time of deprecation is evaluated on a function-by-function - basis. At minimum, a function should be marked as deprecated during a point + basis. At minimum, a function should be marked as deprecated during a point release. -- To mark a helper function, use the ``deprecated`` decorator found in - ``ckan.lib.maintain`` eg: :: - - @deprecated() - def facet_items(*args, **kwargs): - """ - DEPRECATED: Use the new facet data structure, and `unselected_facet_items()` - """ - # rest of function definition. - +- To deprecate a function use the :py:func:`ckan.lib.maintain.deprecated` + decorator and add "deprecated" to the function's docstring:: + + @maintain.deprecated("helpers.get_action() is deprecated and will be removed " + "in a future version of CKAN. Instead, please use the " + "extra_vars param to render() in your controller to pass " + "results from action functions to your templates.") + def get_action(action_name, data_dict=None): + '''Calls an action function from a template. Deprecated in CKAN 2.3.''' + if data_dict is None: + data_dict = {} + return logic.get_action(action_name)({}, data_dict) + +- Any deprecated functions should be added to an *API changes and deprecations* + section in the :doc:`/changelog` entry for the next release (do this before + merging the deprecation into master) + +- Keep the deprecation messages passed to the decorator short, they appear in + logs. Put longer explanations of why something was deprecated in the + changelog. From e5dfe3a25ac6941447879ab48165ad499ad7ba51 Mon Sep 17 00:00:00 2001 From: Vitor Baptista Date: Wed, 28 May 2014 19:05:58 -0300 Subject: [PATCH 67/77] [#1697] Simplify _is_test() a bit --- ckan/tests/test_coding_standards.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ckan/tests/test_coding_standards.py b/ckan/tests/test_coding_standards.py index d0a433e2705..14eb2690b45 100644 --- a/ckan/tests/test_coding_standards.py +++ b/ckan/tests/test_coding_standards.py @@ -895,7 +895,7 @@ def find_pep8_errors(cls, filename=None, lines=None): @classmethod def _is_test(cls, filename): - return not not re.search('(^|\W)test_.*\.py', filename, re.IGNORECASE) + return bool(re.search('(^|\W)test_.*\.py$', filename, re.IGNORECASE)) class TestActionAuth(object): From da757ddbbbf48a958a225ce800f80e3ab0fc25eb Mon Sep 17 00:00:00 2001 From: Vitor Baptista Date: Wed, 28 May 2014 20:05:08 -0300 Subject: [PATCH 68/77] [#1697] Remove ckanext/resourceproxy/tests/test_proxy.py from blacklist It's passing now. --- ckan/tests/test_coding_standards.py | 1 - 1 file changed, 1 deletion(-) diff --git a/ckan/tests/test_coding_standards.py b/ckan/tests/test_coding_standards.py index 14eb2690b45..bba9d3633dc 100644 --- a/ckan/tests/test_coding_standards.py +++ b/ckan/tests/test_coding_standards.py @@ -823,7 +823,6 @@ class TestPep8(object): 'ckanext/reclinepreview/plugin.py', 'ckanext/reclinepreview/tests/test_preview.py', 'ckanext/resourceproxy/plugin.py', - 'ckanext/resourceproxy/tests/test_proxy.py', 'ckanext/stats/controller.py', 'ckanext/stats/plugin.py', 'ckanext/stats/stats.py', From abe84fa4801eb938e5f349052022f37a96692bc8 Mon Sep 17 00:00:00 2001 From: Vitor Baptista Date: Wed, 28 May 2014 22:19:32 -0300 Subject: [PATCH 69/77] [#1697] Fix PEP8's E303 on ckanext/resourceproxy/tests/test_proxy.py --- ckanext/resourceproxy/tests/test_proxy.py | 1 - 1 file changed, 1 deletion(-) diff --git a/ckanext/resourceproxy/tests/test_proxy.py b/ckanext/resourceproxy/tests/test_proxy.py index 52b96f373ff..4c9798da510 100644 --- a/ckanext/resourceproxy/tests/test_proxy.py +++ b/ckanext/resourceproxy/tests/test_proxy.py @@ -138,7 +138,6 @@ def test_invalid_url(self): assert result.status == 409, result.status assert 'Invalid URL' in result.body, result.body - def test_non_existent_url(self): self.data_dict = set_resource_url('http://foo.bar') From 0ea13e88b3709555fb25422783a08c096dd3ff00 Mon Sep 17 00:00:00 2001 From: "Brenda J. Butler" Date: Mon, 2 Jun 2014 14:03:37 -0400 Subject: [PATCH 70/77] add argument for postgresql port in datastore_setup.py --- ckanext/datastore/bin/datastore_setup.py | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/ckanext/datastore/bin/datastore_setup.py b/ckanext/datastore/bin/datastore_setup.py index 3a5564fbb1a..ee29389825a 100644 --- a/ckanext/datastore/bin/datastore_setup.py +++ b/ckanext/datastore/bin/datastore_setup.py @@ -21,15 +21,16 @@ def _run_cmd(command_line, inputstring=''): sys.exit(1) -def _run_sql(sql, as_sql_user, database='postgres'): +def _run_sql(sql, as_sql_user, pgport, database='postgres'): logging.debug("Executing: \n#####\n", sql, "\n####\nOn database:", database) - _run_cmd("sudo -u '{username}' psql --dbname='{database}' --no-password --set ON_ERROR_STOP=1".format( + _run_cmd("sudo -u '{username}' psql -p {pgport} --dbname='{database}' --no-password --set ON_ERROR_STOP=1".format( + pgport=pgport, username=as_sql_user, database=database ), inputstring=sql) -def set_permissions(pguser, ckandb, datastoredb, ckanuser, writeuser, readonlyuser): +def set_permissions(pguser, pgport, ckandb, datastoredb, ckanuser, writeuser, readonlyuser): __dir__ = os.path.dirname(os.path.abspath(__file__)) filepath = os.path.join(__dir__, 'set_permissions.sql') with open(filepath) as f: @@ -44,6 +45,7 @@ def set_permissions(pguser, ckandb, datastoredb, ckanuser, writeuser, readonlyus _run_sql(sql, as_sql_user=pguser, + pgport=pgport, database=datastoredb) @@ -53,6 +55,8 @@ def set_permissions(pguser, ckandb, datastoredb, ckanuser, writeuser, readonlyus description='Set the permissions on the CKAN datastore. ', epilog='"The ships hung in the sky in much the same way that bricks don\'t."') + argparser.add_argument('-P', '--pg_port', dest='pgport', default='5432', type=str, + help="the postgres port") argparser.add_argument('-p', '--pg_super_user', dest='pguser', default='postgres', type=str, help="the postgres super user") @@ -71,6 +75,7 @@ def set_permissions(pguser, ckandb, datastoredb, ckanuser, writeuser, readonlyus set_permissions( pguser=args.pguser, + pgport=args.pgport, ckandb=args.ckandb, datastoredb=args.datastoredb, ckanuser=args.ckanuser, From 0f57bdc9830b2076681a367dd74aedfbb60f7582 Mon Sep 17 00:00:00 2001 From: Sean Hammond Date: Mon, 2 Jun 2014 18:48:21 +0000 Subject: [PATCH 71/77] [#1740] Support ignore_auth in group_ and organization_member_create So we can call them from new-style action function tests, which depend on ignore_auth. --- ckan/logic/action/create.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ckan/logic/action/create.py b/ckan/logic/action/create.py index 425853d0c16..8f4c20796f0 100644 --- a/ckan/logic/action/create.py +++ b/ckan/logic/action/create.py @@ -1256,7 +1256,8 @@ def _group_or_org_member_create(context, data_dict, is_org=False): member_create_context = { 'model': model, 'user': user, - 'session': session + 'session': session, + 'ignore_auth': context.get('ignore_auth'), } logic.get_action('member_create')(member_create_context, member_dict) From 3b1062632c89ddec13e87bcd7203e63156262ca3 Mon Sep 17 00:00:00 2001 From: David Read Date: Tue, 3 Jun 2014 15:23:10 +0000 Subject: [PATCH 72/77] [#1738] Cover the case when calling via paster. --- ckanext/datastore/bin/datastore_setup.py | 2 +- ckanext/datastore/commands.py | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/ckanext/datastore/bin/datastore_setup.py b/ckanext/datastore/bin/datastore_setup.py index ee29389825a..d27af1cba70 100644 --- a/ckanext/datastore/bin/datastore_setup.py +++ b/ckanext/datastore/bin/datastore_setup.py @@ -24,7 +24,7 @@ def _run_cmd(command_line, inputstring=''): def _run_sql(sql, as_sql_user, pgport, database='postgres'): logging.debug("Executing: \n#####\n", sql, "\n####\nOn database:", database) _run_cmd("sudo -u '{username}' psql -p {pgport} --dbname='{database}' --no-password --set ON_ERROR_STOP=1".format( - pgport=pgport, + pgport=pgport or '5432', username=as_sql_user, database=database ), inputstring=sql) diff --git a/ckanext/datastore/commands.py b/ckanext/datastore/commands.py index 37866cb7ed5..c1171058628 100644 --- a/ckanext/datastore/commands.py +++ b/ckanext/datastore/commands.py @@ -59,6 +59,7 @@ def command(self): if cmd == 'set-permissions': setup.set_permissions( pguser=self.args[1], + pgport=self.db_ckan_url_parts['db_port'], ckandb=self.db_ckan_url_parts['db_name'], datastoredb=self.db_write_url_parts['db_name'], ckanuser=self.db_ckan_url_parts['db_user'], From f3558a8f1c3659bf8c4f4c8b5062343a9e55d533 Mon Sep 17 00:00:00 2001 From: Alice Heaton Date: Wed, 4 Jun 2014 13:03:52 +0100 Subject: [PATCH 73/77] [#1743] Fetch list of flash messages from the loop itself to avoid issues with variables and block scopes. --- ckan/templates/page.html | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/ckan/templates/page.html b/ckan/templates/page.html index 18f14a82902..c92b5fbe5e9 100644 --- a/ckan/templates/page.html +++ b/ckan/templates/page.html @@ -21,10 +21,9 @@
    {% block main_content %} {% block flash %} - {% set flash_messages = h.flash.pop_messages() | list %}
    {% block flash_inner %} - {% for message in flash_messages %} + {% for message in h.flash.pop_messages() | list %}
    {{ h.literal(message) }}
    From 861e1e1b8922669f6c70d5a484537dc3fd842331 Mon Sep 17 00:00:00 2001 From: tlacoyodefrijol Date: Tue, 10 Jun 2014 08:40:28 -0500 Subject: [PATCH 74/77] Update the complete route for "promoted-image.jpg" --- doc/theming/static-files.rst | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/doc/theming/static-files.rst b/doc/theming/static-files.rst index 271ebd1d8ac..db280a3e77d 100644 --- a/doc/theming/static-files.rst +++ b/doc/theming/static-files.rst @@ -22,11 +22,13 @@ to use our file as the promoted image on the front page. use Fanstatic, see :doc:`javascript`. First, create a ``public`` directory in your extension with a -``promoted-image.jpg`` file in it:: +``promoted-image.jpg`` file in it: ckanext-example_theme/ - public/ - promoted-image.jpg + ckanext/ + example_theme/ + public/ + promoted-image.jpg ``promoted-image.jpg`` should be a 420x220px JPEG image file. You could use this image file for example: From 0f7676feefe36382b1349a7cee9fb4e5cabdedb4 Mon Sep 17 00:00:00 2001 From: amercader Date: Tue, 10 Jun 2014 15:27:23 +0100 Subject: [PATCH 75/77] Add missing colon --- doc/theming/static-files.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/theming/static-files.rst b/doc/theming/static-files.rst index db280a3e77d..9ce61a7ea38 100644 --- a/doc/theming/static-files.rst +++ b/doc/theming/static-files.rst @@ -22,7 +22,7 @@ to use our file as the promoted image on the front page. use Fanstatic, see :doc:`javascript`. First, create a ``public`` directory in your extension with a -``promoted-image.jpg`` file in it: +``promoted-image.jpg`` file in it:: ckanext-example_theme/ ckanext/ From 37aba0fd86a70e64474a1d39d437d959c16eb0ef Mon Sep 17 00:00:00 2001 From: Jari Voutilainen Date: Mon, 9 Jun 2014 09:53:59 +0300 Subject: [PATCH 76/77] Upgrade minified jquery to 1.10.2, for issue #1750 --- ckan/public/base/vendor/jquery.min.js | 618 +------------------------- 1 file changed, 6 insertions(+), 612 deletions(-) diff --git a/ckan/public/base/vendor/jquery.min.js b/ckan/public/base/vendor/jquery.min.js index 64373a7ac36..da4170647dd 100644 --- a/ckan/public/base/vendor/jquery.min.js +++ b/ckan/public/base/vendor/jquery.min.js @@ -1,612 +1,6 @@ -(function(window,undefined){var document=window.document,navigator=window.navigator,location=window.location;var jQuery=(function(){var jQuery=function(selector,context){return new jQuery.fn.init(selector,context,rootjQuery);},_jQuery=window.jQuery,_$=window.$,rootjQuery,quickExpr=/^(?:[^#<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/,rnotwhite=/\S/,trimLeft=/^\s+/,trimRight=/\s+$/,rsingleTag=/^<(\w+)\s*\/?>(?:<\/\1>)?$/,rvalidchars=/^[\],:{}\s]*$/,rvalidescape=/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,rvalidtokens=/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,rvalidbraces=/(?:^|:|,)(?:\s*\[)+/g,rwebkit=/(webkit)[ \/]([\w.]+)/,ropera=/(opera)(?:.*version)?[ \/]([\w.]+)/,rmsie=/(msie) ([\w.]+)/,rmozilla=/(mozilla)(?:.*? rv:([\w.]+))?/,rdashAlpha=/-([a-z]|[0-9])/ig,rmsPrefix=/^-ms-/,fcamelCase=function(all,letter){return(letter+"").toUpperCase();},userAgent=navigator.userAgent,browserMatch,readyList,DOMContentLoaded,toString=Object.prototype.toString,hasOwn=Object.prototype.hasOwnProperty,push=Array.prototype.push,slice=Array.prototype.slice,trim=String.prototype.trim,indexOf=Array.prototype.indexOf,class2type={};jQuery.fn=jQuery.prototype={constructor:jQuery,init:function(selector,context,rootjQuery){var match,elem,ret,doc;if(!selector){return this;} -if(selector.nodeType){this.context=this[0]=selector;this.length=1;return this;} -if(selector==="body"&&!context&&document.body){this.context=document;this[0]=document.body;this.selector=selector;this.length=1;return this;} -if(typeof selector==="string"){if(selector.charAt(0)==="<"&&selector.charAt(selector.length-1)===">"&&selector.length>=3){match=[null,selector,null];}else{match=quickExpr.exec(selector);} -if(match&&(match[1]||!context)){if(match[1]){context=context instanceof jQuery?context[0]:context;doc=(context?context.ownerDocument||context:document);ret=rsingleTag.exec(selector);if(ret){if(jQuery.isPlainObject(context)){selector=[document.createElement(ret[1])];jQuery.fn.attr.call(selector,context,true);}else{selector=[doc.createElement(ret[1])];}}else{ret=jQuery.buildFragment([match[1]],[doc]);selector=(ret.cacheable?jQuery.clone(ret.fragment):ret.fragment).childNodes;} -return jQuery.merge(this,selector);}else{elem=document.getElementById(match[2]);if(elem&&elem.parentNode){if(elem.id!==match[2]){return rootjQuery.find(selector);} -this.length=1;this[0]=elem;} -this.context=document;this.selector=selector;return this;}}else if(!context||context.jquery){return(context||rootjQuery).find(selector);}else{return this.constructor(context).find(selector);}}else if(jQuery.isFunction(selector)){return rootjQuery.ready(selector);} -if(selector.selector!==undefined){this.selector=selector.selector;this.context=selector.context;} -return jQuery.makeArray(selector,this);},selector:"",jquery:"1.7.2",length:0,size:function(){return this.length;},toArray:function(){return slice.call(this,0);},get:function(num){return num==null?this.toArray():(num<0?this[this.length+num]:this[num]);},pushStack:function(elems,name,selector){var ret=this.constructor();if(jQuery.isArray(elems)){push.apply(ret,elems);}else{jQuery.merge(ret,elems);} -ret.prevObject=this;ret.context=this.context;if(name==="find"){ret.selector=this.selector+(this.selector?" ":"")+selector;}else if(name){ret.selector=this.selector+"."+name+"("+selector+")";} -return ret;},each:function(callback,args){return jQuery.each(this,callback,args);},ready:function(fn){jQuery.bindReady();readyList.add(fn);return this;},eq:function(i){i=+i;return i===-1?this.slice(i):this.slice(i,i+1);},first:function(){return this.eq(0);},last:function(){return this.eq(-1);},slice:function(){return this.pushStack(slice.apply(this,arguments),"slice",slice.call(arguments).join(","));},map:function(callback){return this.pushStack(jQuery.map(this,function(elem,i){return callback.call(elem,i,elem);}));},end:function(){return this.prevObject||this.constructor(null);},push:push,sort:[].sort,splice:[].splice};jQuery.fn.init.prototype=jQuery.fn;jQuery.extend=jQuery.fn.extend=function(){var options,name,src,copy,copyIsArray,clone,target=arguments[0]||{},i=1,length=arguments.length,deep=false;if(typeof target==="boolean"){deep=target;target=arguments[1]||{};i=2;} -if(typeof target!=="object"&&!jQuery.isFunction(target)){target={};} -if(length===i){target=this;--i;} -for(;i0){return;} -readyList.fireWith(document,[jQuery]);if(jQuery.fn.trigger){jQuery(document).trigger("ready").off("ready");}}},bindReady:function(){if(readyList){return;} -readyList=jQuery.Callbacks("once memory");if(document.readyState==="complete"){return setTimeout(jQuery.ready,1);} -if(document.addEventListener){document.addEventListener("DOMContentLoaded",DOMContentLoaded,false);window.addEventListener("load",jQuery.ready,false);}else if(document.attachEvent){document.attachEvent("onreadystatechange",DOMContentLoaded);window.attachEvent("onload",jQuery.ready);var toplevel=false;try{toplevel=window.frameElement==null;}catch(e){} -if(document.documentElement.doScroll&&toplevel){doScrollCheck();}}},isFunction:function(obj){return jQuery.type(obj)==="function";},isArray:Array.isArray||function(obj){return jQuery.type(obj)==="array";},isWindow:function(obj){return obj!=null&&obj==obj.window;},isNumeric:function(obj){return!isNaN(parseFloat(obj))&&isFinite(obj);},type:function(obj){return obj==null?String(obj):class2type[toString.call(obj)]||"object";},isPlainObject:function(obj){if(!obj||jQuery.type(obj)!=="object"||obj.nodeType||jQuery.isWindow(obj)){return false;} -try{if(obj.constructor&&!hasOwn.call(obj,"constructor")&&!hasOwn.call(obj.constructor.prototype,"isPrototypeOf")){return false;}}catch(e){return false;} -var key;for(key in obj){} -return key===undefined||hasOwn.call(obj,key);},isEmptyObject:function(obj){for(var name in obj){return false;} -return true;},error:function(msg){throw new Error(msg);},parseJSON:function(data){if(typeof data!=="string"||!data){return null;} -data=jQuery.trim(data);if(window.JSON&&window.JSON.parse){return window.JSON.parse(data);} -if(rvalidchars.test(data.replace(rvalidescape,"@").replace(rvalidtokens,"]").replace(rvalidbraces,""))){return(new Function("return "+data))();} -jQuery.error("Invalid JSON: "+data);},parseXML:function(data){if(typeof data!=="string"||!data){return null;} -var xml,tmp;try{if(window.DOMParser){tmp=new DOMParser();xml=tmp.parseFromString(data,"text/xml");}else{xml=new ActiveXObject("Microsoft.XMLDOM");xml.async="false";xml.loadXML(data);}}catch(e){xml=undefined;} -if(!xml||!xml.documentElement||xml.getElementsByTagName("parsererror").length){jQuery.error("Invalid XML: "+data);} -return xml;},noop:function(){},globalEval:function(data){if(data&&rnotwhite.test(data)){(window.execScript||function(data){window["eval"].call(window,data);})(data);}},camelCase:function(string){return string.replace(rmsPrefix,"ms-").replace(rdashAlpha,fcamelCase);},nodeName:function(elem,name){return elem.nodeName&&elem.nodeName.toUpperCase()===name.toUpperCase();},each:function(object,callback,args){var name,i=0,length=object.length,isObj=length===undefined||jQuery.isFunction(object);if(args){if(isObj){for(name in object){if(callback.apply(object[name],args)===false){break;}}}else{for(;i0&&elems[0]&&elems[length-1])||length===0||jQuery.isArray(elems));if(isArray){for(;i1?sliceDeferred.call(arguments,0):value;if(!(--count)){deferred.resolveWith(deferred,args);}};} -function progressFunc(i){return function(value){pValues[i]=arguments.length>1?sliceDeferred.call(arguments,0):value;deferred.notifyWith(promise,pValues);};} -if(length>1){for(;i
    a";all=div.getElementsByTagName("*");a=div.getElementsByTagName("a")[0];if(!all||!all.length||!a){return{};} -select=document.createElement("select");opt=select.appendChild(document.createElement("option"));input=div.getElementsByTagName("input")[0];support={leadingWhitespace:(div.firstChild.nodeType===3),tbody:!div.getElementsByTagName("tbody").length,htmlSerialize:!!div.getElementsByTagName("link").length,style:/top/.test(a.getAttribute("style")),hrefNormalized:(a.getAttribute("href")==="/a"),opacity:/^0.55/.test(a.style.opacity),cssFloat:!!a.style.cssFloat,checkOn:(input.value==="on"),optSelected:opt.selected,getSetAttribute:div.className!=="t",enctype:!!document.createElement("form").enctype,html5Clone:document.createElement("nav").cloneNode(true).outerHTML!=="<:nav>",submitBubbles:true,changeBubbles:true,focusinBubbles:false,deleteExpando:true,noCloneEvent:true,inlineBlockNeedsLayout:false,shrinkWrapBlocks:false,reliableMarginRight:true,pixelMargin:true};jQuery.boxModel=support.boxModel=(document.compatMode==="CSS1Compat");input.checked=true;support.noCloneChecked=input.cloneNode(true).checked;select.disabled=true;support.optDisabled=!opt.disabled;try{delete div.test;}catch(e){support.deleteExpando=false;} -if(!div.addEventListener&&div.attachEvent&&div.fireEvent){div.attachEvent("onclick",function(){support.noCloneEvent=false;});div.cloneNode(true).fireEvent("onclick");} -input=document.createElement("input");input.value="t";input.setAttribute("type","radio");support.radioValue=input.value==="t";input.setAttribute("checked","checked");input.setAttribute("name","t");div.appendChild(input);fragment=document.createDocumentFragment();fragment.appendChild(div.lastChild);support.checkClone=fragment.cloneNode(true).cloneNode(true).lastChild.checked;support.appendChecked=input.checked;fragment.removeChild(input);fragment.appendChild(div);if(div.attachEvent){for(i in{submit:1,change:1,focusin:1}){eventName="on"+i;isSupported=(eventName in div);if(!isSupported){div.setAttribute(eventName,"return;");isSupported=(typeof div[eventName]==="function");} -support[i+"Bubbles"]=isSupported;}} -fragment.removeChild(div);fragment=select=opt=div=input=null;jQuery(function(){var container,outer,inner,table,td,offsetSupport,marginDiv,conMarginTop,style,html,positionTopLeftWidthHeight,paddingMarginBorderVisibility,paddingMarginBorder,body=document.getElementsByTagName("body")[0];if(!body){return;} -conMarginTop=1;paddingMarginBorder="padding:0;margin:0;border:";positionTopLeftWidthHeight="position:absolute;top:0;left:0;width:1px;height:1px;";paddingMarginBorderVisibility=paddingMarginBorder+"0;visibility:hidden;";style="style='"+positionTopLeftWidthHeight+paddingMarginBorder+"5px solid #000;";html="
    "+""+"
    ";container=document.createElement("div");container.style.cssText=paddingMarginBorderVisibility+"width:0;height:0;position:static;top:0;margin-top:"+conMarginTop+"px";body.insertBefore(container,body.firstChild);div=document.createElement("div");container.appendChild(div);div.innerHTML="
    t
    ";tds=div.getElementsByTagName("td");isSupported=(tds[0].offsetHeight===0);tds[0].style.display="";tds[1].style.display="none";support.reliableHiddenOffsets=isSupported&&(tds[0].offsetHeight===0);if(window.getComputedStyle){div.innerHTML="";marginDiv=document.createElement("div");marginDiv.style.width="0";marginDiv.style.marginRight="0";div.style.width="2px";div.appendChild(marginDiv);support.reliableMarginRight=(parseInt((window.getComputedStyle(marginDiv,null)||{marginRight:0}).marginRight,10)||0)===0;} -if(typeof div.style.zoom!=="undefined"){div.innerHTML="";div.style.width=div.style.padding="1px";div.style.border=0;div.style.overflow="hidden";div.style.display="inline";div.style.zoom=1;support.inlineBlockNeedsLayout=(div.offsetWidth===3);div.style.display="block";div.style.overflow="visible";div.innerHTML="
    ";support.shrinkWrapBlocks=(div.offsetWidth!==3);} -div.style.cssText=positionTopLeftWidthHeight+paddingMarginBorderVisibility;div.innerHTML=html;outer=div.firstChild;inner=outer.firstChild;td=outer.nextSibling.firstChild.firstChild;offsetSupport={doesNotAddBorder:(inner.offsetTop!==5),doesAddBorderForTableAndCells:(td.offsetTop===5)};inner.style.position="fixed";inner.style.top="20px";offsetSupport.fixedPosition=(inner.offsetTop===20||inner.offsetTop===15);inner.style.position=inner.style.top="";outer.style.overflow="hidden";outer.style.position="relative";offsetSupport.subtractsBorderForOverflowNotVisible=(inner.offsetTop===-5);offsetSupport.doesNotIncludeMarginInBodyOffset=(body.offsetTop!==conMarginTop);if(window.getComputedStyle){div.style.marginTop="1%";support.pixelMargin=(window.getComputedStyle(div,null)||{marginTop:0}).marginTop!=="1%";} -if(typeof container.style.zoom!=="undefined"){container.style.zoom=1;} -body.removeChild(container);marginDiv=div=container=null;jQuery.extend(support,offsetSupport);});return support;})();var rbrace=/^(?:\{.*\}|\[.*\])$/,rmultiDash=/([A-Z])/g;jQuery.extend({cache:{},uuid:0,expando:"jQuery"+(jQuery.fn.jquery+Math.random()).replace(/\D/g,""),noData:{"embed":true,"object":"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000","applet":true},hasData:function(elem){elem=elem.nodeType?jQuery.cache[elem[jQuery.expando]]:elem[jQuery.expando];return!!elem&&!isEmptyDataObject(elem);},data:function(elem,name,data,pvt){if(!jQuery.acceptData(elem)){return;} -var privateCache,thisCache,ret,internalKey=jQuery.expando,getByName=typeof name==="string",isNode=elem.nodeType,cache=isNode?jQuery.cache:elem,id=isNode?elem[internalKey]:elem[internalKey]&&internalKey,isEvents=name==="events";if((!id||!cache[id]||(!isEvents&&!pvt&&!cache[id].data))&&getByName&&data===undefined){return;} -if(!id){if(isNode){elem[internalKey]=id=++jQuery.uuid;}else{id=internalKey;}} -if(!cache[id]){cache[id]={};if(!isNode){cache[id].toJSON=jQuery.noop;}} -if(typeof name==="object"||typeof name==="function"){if(pvt){cache[id]=jQuery.extend(cache[id],name);}else{cache[id].data=jQuery.extend(cache[id].data,name);}} -privateCache=thisCache=cache[id];if(!pvt){if(!thisCache.data){thisCache.data={};} -thisCache=thisCache.data;} -if(data!==undefined){thisCache[jQuery.camelCase(name)]=data;} -if(isEvents&&!thisCache[name]){return privateCache.events;} -if(getByName){ret=thisCache[name];if(ret==null){ret=thisCache[jQuery.camelCase(name)];}}else{ret=thisCache;} -return ret;},removeData:function(elem,name,pvt){if(!jQuery.acceptData(elem)){return;} -var thisCache,i,l,internalKey=jQuery.expando,isNode=elem.nodeType,cache=isNode?jQuery.cache:elem,id=isNode?elem[internalKey]:internalKey;if(!cache[id]){return;} -if(name){thisCache=pvt?cache[id]:cache[id].data;if(thisCache){if(!jQuery.isArray(name)){if(name in thisCache){name=[name];}else{name=jQuery.camelCase(name);if(name in thisCache){name=[name];}else{name=name.split(" ");}}} -for(i=0,l=name.length;i1,null,false);},removeData:function(key){return this.each(function(){jQuery.removeData(this,key);});}});function dataAttr(elem,key,data){if(data===undefined&&elem.nodeType===1){var name="data-"+key.replace(rmultiDash,"-$1").toLowerCase();data=elem.getAttribute(name);if(typeof data==="string"){try{data=data==="true"?true:data==="false"?false:data==="null"?null:jQuery.isNumeric(data)?+data:rbrace.test(data)?jQuery.parseJSON(data):data;}catch(e){} -jQuery.data(elem,key,data);}else{data=undefined;}} -return data;} -function isEmptyDataObject(obj){for(var name in obj){if(name==="data"&&jQuery.isEmptyObject(obj[name])){continue;} -if(name!=="toJSON"){return false;}} -return true;} -function handleQueueMarkDefer(elem,type,src){var deferDataKey=type+"defer",queueDataKey=type+"queue",markDataKey=type+"mark",defer=jQuery._data(elem,deferDataKey);if(defer&&(src==="queue"||!jQuery._data(elem,queueDataKey))&&(src==="mark"||!jQuery._data(elem,markDataKey))){setTimeout(function(){if(!jQuery._data(elem,queueDataKey)&&!jQuery._data(elem,markDataKey)){jQuery.removeData(elem,deferDataKey,true);defer.fire();}},0);}} -jQuery.extend({_mark:function(elem,type){if(elem){type=(type||"fx")+"mark";jQuery._data(elem,type,(jQuery._data(elem,type)||0)+1);}},_unmark:function(force,elem,type){if(force!==true){type=elem;elem=force;force=false;} -if(elem){type=type||"fx";var key=type+"mark",count=force?0:((jQuery._data(elem,key)||1)-1);if(count){jQuery._data(elem,key,count);}else{jQuery.removeData(elem,key,true);handleQueueMarkDefer(elem,type,"mark");}}},queue:function(elem,type,data){var q;if(elem){type=(type||"fx")+"queue";q=jQuery._data(elem,type);if(data){if(!q||jQuery.isArray(data)){q=jQuery._data(elem,type,jQuery.makeArray(data));}else{q.push(data);}} -return q||[];}},dequeue:function(elem,type){type=type||"fx";var queue=jQuery.queue(elem,type),fn=queue.shift(),hooks={};if(fn==="inprogress"){fn=queue.shift();} -if(fn){if(type==="fx"){queue.unshift("inprogress");} -jQuery._data(elem,type+".run",hooks);fn.call(elem,function(){jQuery.dequeue(elem,type);},hooks);} -if(!queue.length){jQuery.removeData(elem,type+"queue "+type+".run",true);handleQueueMarkDefer(elem,type,"queue");}}});jQuery.fn.extend({queue:function(type,data){var setter=2;if(typeof type!=="string"){data=type;type="fx";setter--;} -if(arguments.length1);},removeAttr:function(name){return this.each(function(){jQuery.removeAttr(this,name);});},prop:function(name,value){return jQuery.access(this,jQuery.prop,name,value,arguments.length>1);},removeProp:function(name){name=jQuery.propFix[name]||name;return this.each(function(){try{this[name]=undefined;delete this[name];}catch(e){}});},addClass:function(value){var classNames,i,l,elem,setClass,c,cl;if(jQuery.isFunction(value)){return this.each(function(j){jQuery(this).addClass(value.call(this,j,this.className));});} -if(value&&typeof value==="string"){classNames=value.split(rspace);for(i=0,l=this.length;i-1){return true;}} -return false;},val:function(value){var hooks,ret,isFunction,elem=this[0];if(!arguments.length){if(elem){hooks=jQuery.valHooks[elem.type]||jQuery.valHooks[elem.nodeName.toLowerCase()];if(hooks&&"get"in hooks&&(ret=hooks.get(elem,"value"))!==undefined){return ret;} -ret=elem.value;return typeof ret==="string"?ret.replace(rreturn,""):ret==null?"":ret;} -return;} -isFunction=jQuery.isFunction(value);return this.each(function(i){var self=jQuery(this),val;if(this.nodeType!==1){return;} -if(isFunction){val=value.call(this,i,self.val());}else{val=value;} -if(val==null){val="";}else if(typeof val==="number"){val+="";}else if(jQuery.isArray(val)){val=jQuery.map(val,function(value){return value==null?"":value+"";});} -hooks=jQuery.valHooks[this.type]||jQuery.valHooks[this.nodeName.toLowerCase()];if(!hooks||!("set"in hooks)||hooks.set(this,val,"value")===undefined){this.value=val;}});}});jQuery.extend({valHooks:{option:{get:function(elem){var val=elem.attributes.value;return!val||val.specified?elem.value:elem.text;}},select:{get:function(elem){var value,i,max,option,index=elem.selectedIndex,values=[],options=elem.options,one=elem.type==="select-one";if(index<0){return null;} -i=one?index:0;max=one?index+1:options.length;for(;i=0;});if(!values.length){elem.selectedIndex=-1;} -return values;}}},attrFn:{val:true,css:true,html:true,text:true,data:true,width:true,height:true,offset:true},attr:function(elem,name,value,pass){var ret,hooks,notxml,nType=elem.nodeType;if(!elem||nType===3||nType===8||nType===2){return;} -if(pass&&name in jQuery.attrFn){return jQuery(elem)[name](value);} -if(typeof elem.getAttribute==="undefined"){return jQuery.prop(elem,name,value);} -notxml=nType!==1||!jQuery.isXMLDoc(elem);if(notxml){name=name.toLowerCase();hooks=jQuery.attrHooks[name]||(rboolean.test(name)?boolHook:nodeHook);} -if(value!==undefined){if(value===null){jQuery.removeAttr(elem,name);return;}else if(hooks&&"set"in hooks&¬xml&&(ret=hooks.set(elem,value,name))!==undefined){return ret;}else{elem.setAttribute(name,""+value);return value;}}else if(hooks&&"get"in hooks&¬xml&&(ret=hooks.get(elem,name))!==null){return ret;}else{ret=elem.getAttribute(name);return ret===null?undefined:ret;}},removeAttr:function(elem,value){var propName,attrNames,name,l,isBool,i=0;if(value&&elem.nodeType===1){attrNames=value.toLowerCase().split(rspace);l=attrNames.length;for(;i=0);}}});});var rformElems=/^(?:textarea|input|select)$/i,rtypenamespace=/^([^\.]*)?(?:\.(.+))?$/,rhoverHack=/(?:^|\s)hover(\.\S+)?\b/,rkeyEvent=/^key/,rmouseEvent=/^(?:mouse|contextmenu)|click/,rfocusMorph=/^(?:focusinfocus|focusoutblur)$/,rquickIs=/^(\w*)(?:#([\w\-]+))?(?:\.([\w\-]+))?$/,quickParse=function(selector){var quick=rquickIs.exec(selector);if(quick){quick[1]=(quick[1]||"").toLowerCase();quick[3]=quick[3]&&new RegExp("(?:^|\\s)"+quick[3]+"(?:\\s|$)");} -return quick;},quickIs=function(elem,m){var attrs=elem.attributes||{};return((!m[1]||elem.nodeName.toLowerCase()===m[1])&&(!m[2]||(attrs.id||{}).value===m[2])&&(!m[3]||m[3].test((attrs["class"]||{}).value)));},hoverHack=function(events){return jQuery.event.special.hover?events:events.replace(rhoverHack,"mouseenter$1 mouseleave$1");};jQuery.event={add:function(elem,types,handler,data,selector){var elemData,eventHandle,events,t,tns,type,namespaces,handleObj,handleObjIn,quick,handlers,special;if(elem.nodeType===3||elem.nodeType===8||!types||!handler||!(elemData=jQuery._data(elem))){return;} -if(handler.handler){handleObjIn=handler;handler=handleObjIn.handler;selector=handleObjIn.selector;} -if(!handler.guid){handler.guid=jQuery.guid++;} -events=elemData.events;if(!events){elemData.events=events={};} -eventHandle=elemData.handle;if(!eventHandle){elemData.handle=eventHandle=function(e){return typeof jQuery!=="undefined"&&(!e||jQuery.event.triggered!==e.type)?jQuery.event.dispatch.apply(eventHandle.elem,arguments):undefined;};eventHandle.elem=elem;} -types=jQuery.trim(hoverHack(types)).split(" ");for(t=0;t=0){type=type.slice(0,-1);exclusive=true;} -if(type.indexOf(".")>=0){namespaces=type.split(".");type=namespaces.shift();namespaces.sort();} -if((!elem||jQuery.event.customEvent[type])&&!jQuery.event.global[type]){return;} -event=typeof event==="object"?event[jQuery.expando]?event:new jQuery.Event(type,event):new jQuery.Event(type);event.type=type;event.isTrigger=true;event.exclusive=exclusive;event.namespace=namespaces.join(".");event.namespace_re=event.namespace?new RegExp("(^|\\.)"+namespaces.join("\\.(?:.*\\.)?")+"(\\.|$)"):null;ontype=type.indexOf(":")<0?"on"+type:"";if(!elem){cache=jQuery.cache;for(i in cache){if(cache[i].events&&cache[i].events[type]){jQuery.event.trigger(event,data,cache[i].handle.elem,true);}} -return;} -event.result=undefined;if(!event.target){event.target=elem;} -data=data!=null?jQuery.makeArray(data):[];data.unshift(event);special=jQuery.event.special[type]||{};if(special.trigger&&special.trigger.apply(elem,data)===false){return;} -eventPath=[[elem,special.bindType||type]];if(!onlyHandlers&&!special.noBubble&&!jQuery.isWindow(elem)){bubbleType=special.delegateType||type;cur=rfocusMorph.test(bubbleType+type)?elem:elem.parentNode;old=null;for(;cur;cur=cur.parentNode){eventPath.push([cur,bubbleType]);old=cur;} -if(old&&old===elem.ownerDocument){eventPath.push([old.defaultView||old.parentWindow||window,bubbleType]);}} -for(i=0;idelegateCount){handlerQueue.push({elem:this,matches:handlers.slice(delegateCount)});} -for(i=0;i0?this.on(name,null,data,fn):this.trigger(name);};if(jQuery.attrFn){jQuery.attrFn[name]=true;} -if(rkeyEvent.test(name)){jQuery.event.fixHooks[name]=jQuery.event.keyHooks;} -if(rmouseEvent.test(name)){jQuery.event.fixHooks[name]=jQuery.event.mouseHooks;}});(function(){var chunker=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^\[\]]*\]|['"][^'"]*['"]|[^\[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,expando="sizcache"+(Math.random()+'').replace('.',''),done=0,toString=Object.prototype.toString,hasDuplicate=false,baseHasDuplicate=true,rBackslash=/\\/g,rReturn=/\r\n/g,rNonWord=/\W/;[0,0].sort(function(){baseHasDuplicate=false;return 0;});var Sizzle=function(selector,context,results,seed){results=results||[];context=context||document;var origContext=context;if(context.nodeType!==1&&context.nodeType!==9){return[];} -if(!selector||typeof selector!=="string"){return results;} -var m,set,checkSet,extra,ret,cur,pop,i,prune=true,contextXML=Sizzle.isXML(context),parts=[],soFar=selector;do{chunker.exec("");m=chunker.exec(soFar);if(m){soFar=m[3];parts.push(m[1]);if(m[2]){extra=m[3];break;}}}while(m);if(parts.length>1&&origPOS.exec(selector)){if(parts.length===2&&Expr.relative[parts[0]]){set=posProcess(parts[0]+parts[1],context,seed);}else{set=Expr.relative[parts[0]]?[context]:Sizzle(parts.shift(),context);while(parts.length){selector=parts.shift();if(Expr.relative[selector]){selector+=parts.shift();} -set=posProcess(selector,set,seed);}}}else{if(!seed&&parts.length>1&&context.nodeType===9&&!contextXML&&Expr.match.ID.test(parts[0])&&!Expr.match.ID.test(parts[parts.length-1])){ret=Sizzle.find(parts.shift(),context,contextXML);context=ret.expr?Sizzle.filter(ret.expr,ret.set)[0]:ret.set[0];} -if(context){ret=seed?{expr:parts.pop(),set:makeArray(seed)}:Sizzle.find(parts.pop(),parts.length===1&&(parts[0]==="~"||parts[0]==="+")&&context.parentNode?context.parentNode:context,contextXML);set=ret.expr?Sizzle.filter(ret.expr,ret.set):ret.set;if(parts.length>0){checkSet=makeArray(set);}else{prune=false;} -while(parts.length){cur=parts.pop();pop=cur;if(!Expr.relative[cur]){cur="";}else{pop=parts.pop();} -if(pop==null){pop=context;} -Expr.relative[cur](checkSet,pop,contextXML);}}else{checkSet=parts=[];}} -if(!checkSet){checkSet=set;} -if(!checkSet){Sizzle.error(cur||selector);} -if(toString.call(checkSet)==="[object Array]"){if(!prune){results.push.apply(results,checkSet);}else if(context&&context.nodeType===1){for(i=0;checkSet[i]!=null;i++){if(checkSet[i]&&(checkSet[i]===true||checkSet[i].nodeType===1&&Sizzle.contains(context,checkSet[i]))){results.push(set[i]);}}}else{for(i=0;checkSet[i]!=null;i++){if(checkSet[i]&&checkSet[i].nodeType===1){results.push(set[i]);}}}}else{makeArray(checkSet,results);} -if(extra){Sizzle(extra,origContext,results,seed);Sizzle.uniqueSort(results);} -return results;};Sizzle.uniqueSort=function(results){if(sortOrder){hasDuplicate=baseHasDuplicate;results.sort(sortOrder);if(hasDuplicate){for(var i=1;i0;};Sizzle.find=function(expr,context,isXML){var set,i,len,match,type,left;if(!expr){return[];} -for(i=0,len=Expr.order.length;i":function(checkSet,part){var elem,isPartStr=typeof part==="string",i=0,l=checkSet.length;if(isPartStr&&!rNonWord.test(part)){part=part.toLowerCase();for(;i=0)){if(!inplace){result.push(elem);}}else if(inplace){curLoop[i]=false;}}} -return false;},ID:function(match){return match[1].replace(rBackslash,"");},TAG:function(match,curLoop){return match[1].replace(rBackslash,"").toLowerCase();},CHILD:function(match){if(match[1]==="nth"){if(!match[2]){Sizzle.error(match[0]);} -match[2]=match[2].replace(/^\+|\s*/g,'');var test=/(-?)(\d*)(?:n([+\-]?\d*))?/.exec(match[2]==="even"&&"2n"||match[2]==="odd"&&"2n+1"||!/\D/.test(match[2])&&"0n+"+match[2]||match[2]);match[2]=(test[1]+(test[2]||1))-0;match[3]=test[3]-0;} -else if(match[2]){Sizzle.error(match[0]);} -match[0]=done++;return match;},ATTR:function(match,curLoop,inplace,result,not,isXML){var name=match[1]=match[1].replace(rBackslash,"");if(!isXML&&Expr.attrMap[name]){match[1]=Expr.attrMap[name];} -match[4]=(match[4]||match[5]||"").replace(rBackslash,"");if(match[2]==="~="){match[4]=" "+match[4]+" ";} -return match;},PSEUDO:function(match,curLoop,inplace,result,not){if(match[1]==="not"){if((chunker.exec(match[3])||"").length>1||/^\w/.test(match[3])){match[3]=Sizzle(match[3],null,null,curLoop);}else{var ret=Sizzle.filter(match[3],curLoop,inplace,true^not);if(!inplace){result.push.apply(result,ret);} -return false;}}else if(Expr.match.POS.test(match[0])||Expr.match.CHILD.test(match[0])){return true;} -return match;},POS:function(match){match.unshift(true);return match;}},filters:{enabled:function(elem){return elem.disabled===false&&elem.type!=="hidden";},disabled:function(elem){return elem.disabled===true;},checked:function(elem){return elem.checked===true;},selected:function(elem){if(elem.parentNode){elem.parentNode.selectedIndex;} -return elem.selected===true;},parent:function(elem){return!!elem.firstChild;},empty:function(elem){return!elem.firstChild;},has:function(elem,i,match){return!!Sizzle(match[3],elem).length;},header:function(elem){return(/h\d/i).test(elem.nodeName);},text:function(elem){var attr=elem.getAttribute("type"),type=elem.type;return elem.nodeName.toLowerCase()==="input"&&"text"===type&&(attr===type||attr===null);},radio:function(elem){return elem.nodeName.toLowerCase()==="input"&&"radio"===elem.type;},checkbox:function(elem){return elem.nodeName.toLowerCase()==="input"&&"checkbox"===elem.type;},file:function(elem){return elem.nodeName.toLowerCase()==="input"&&"file"===elem.type;},password:function(elem){return elem.nodeName.toLowerCase()==="input"&&"password"===elem.type;},submit:function(elem){var name=elem.nodeName.toLowerCase();return(name==="input"||name==="button")&&"submit"===elem.type;},image:function(elem){return elem.nodeName.toLowerCase()==="input"&&"image"===elem.type;},reset:function(elem){var name=elem.nodeName.toLowerCase();return(name==="input"||name==="button")&&"reset"===elem.type;},button:function(elem){var name=elem.nodeName.toLowerCase();return name==="input"&&"button"===elem.type||name==="button";},input:function(elem){return(/input|select|textarea|button/i).test(elem.nodeName);},focus:function(elem){return elem===elem.ownerDocument.activeElement;}},setFilters:{first:function(elem,i){return i===0;},last:function(elem,i,match,array){return i===array.length-1;},even:function(elem,i){return i%2===0;},odd:function(elem,i){return i%2===1;},lt:function(elem,i,match){return imatch[3]-0;},nth:function(elem,i,match){return match[3]-0===i;},eq:function(elem,i,match){return match[3]-0===i;}},filter:{PSEUDO:function(elem,match,i,array){var name=match[1],filter=Expr.filters[name];if(filter){return filter(elem,i,match,array);}else if(name==="contains"){return(elem.textContent||elem.innerText||getText([elem])||"").indexOf(match[3])>=0;}else if(name==="not"){var not=match[3];for(var j=0,l=not.length;j=0);}}},ID:function(elem,match){return elem.nodeType===1&&elem.getAttribute("id")===match;},TAG:function(elem,match){return(match==="*"&&elem.nodeType===1)||!!elem.nodeName&&elem.nodeName.toLowerCase()===match;},CLASS:function(elem,match){return(" "+(elem.className||elem.getAttribute("class"))+" ").indexOf(match)>-1;},ATTR:function(elem,match){var name=match[1],result=Sizzle.attr?Sizzle.attr(elem,name):Expr.attrHandle[name]?Expr.attrHandle[name](elem):elem[name]!=null?elem[name]:elem.getAttribute(name),value=result+"",type=match[2],check=match[4];return result==null?type==="!=":!type&&Sizzle.attr?result!=null:type==="="?value===check:type==="*="?value.indexOf(check)>=0:type==="~="?(" "+value+" ").indexOf(check)>=0:!check?value&&result!==false:type==="!="?value!==check:type==="^="?value.indexOf(check)===0:type==="$="?value.substr(value.length-check.length)===check:type==="|="?value===check||value.substr(0,check.length+1)===check+"-":false;},POS:function(elem,match,i,array){var name=match[2],filter=Expr.setFilters[name];if(filter){return filter(elem,i,match,array);}}}};var origPOS=Expr.match.POS,fescape=function(all,num){return"\\"+(num-0+1);};for(var type in Expr.match){Expr.match[type]=new RegExp(Expr.match[type].source+(/(?![^\[]*\])(?![^\(]*\))/.source));Expr.leftMatch[type]=new RegExp(/(^(?:.|\r|\n)*?)/.source+Expr.match[type].source.replace(/\\(\d+)/g,fescape));} -Expr.match.globalPOS=origPOS;var makeArray=function(array,results){array=Array.prototype.slice.call(array,0);if(results){results.push.apply(results,array);return results;} -return array;};try{Array.prototype.slice.call(document.documentElement.childNodes,0)[0].nodeType;}catch(e){makeArray=function(array,results){var i=0,ret=results||[];if(toString.call(array)==="[object Array]"){Array.prototype.push.apply(ret,array);}else{if(typeof array.length==="number"){for(var l=array.length;i";root.insertBefore(form,root.firstChild);if(document.getElementById(id)){Expr.find.ID=function(match,context,isXML){if(typeof context.getElementById!=="undefined"&&!isXML){var m=context.getElementById(match[1]);return m?m.id===match[1]||typeof m.getAttributeNode!=="undefined"&&m.getAttributeNode("id").nodeValue===match[1]?[m]:undefined:[];}};Expr.filter.ID=function(elem,match){var node=typeof elem.getAttributeNode!=="undefined"&&elem.getAttributeNode("id");return elem.nodeType===1&&node&&node.nodeValue===match;};} -root.removeChild(form);root=form=null;})();(function(){var div=document.createElement("div");div.appendChild(document.createComment(""));if(div.getElementsByTagName("*").length>0){Expr.find.TAG=function(match,context){var results=context.getElementsByTagName(match[1]);if(match[1]==="*"){var tmp=[];for(var i=0;results[i];i++){if(results[i].nodeType===1){tmp.push(results[i]);}} -results=tmp;} -return results;};} -div.innerHTML="";if(div.firstChild&&typeof div.firstChild.getAttribute!=="undefined"&&div.firstChild.getAttribute("href")!=="#"){Expr.attrHandle.href=function(elem){return elem.getAttribute("href",2);};} -div=null;})();if(document.querySelectorAll){(function(){var oldSizzle=Sizzle,div=document.createElement("div"),id="__sizzle__";div.innerHTML="

    ";if(div.querySelectorAll&&div.querySelectorAll(".TEST").length===0){return;} -Sizzle=function(query,context,extra,seed){context=context||document;if(!seed&&!Sizzle.isXML(context)){var match=/^(\w+$)|^\.([\w\-]+$)|^#([\w\-]+$)/.exec(query);if(match&&(context.nodeType===1||context.nodeType===9)){if(match[1]){return makeArray(context.getElementsByTagName(query),extra);}else if(match[2]&&Expr.find.CLASS&&context.getElementsByClassName){return makeArray(context.getElementsByClassName(match[2]),extra);}} -if(context.nodeType===9){if(query==="body"&&context.body){return makeArray([context.body],extra);}else if(match&&match[3]){var elem=context.getElementById(match[3]);if(elem&&elem.parentNode){if(elem.id===match[3]){return makeArray([elem],extra);}}else{return makeArray([],extra);}} -try{return makeArray(context.querySelectorAll(query),extra);}catch(qsaError){}}else if(context.nodeType===1&&context.nodeName.toLowerCase()!=="object"){var oldContext=context,old=context.getAttribute("id"),nid=old||id,hasParent=context.parentNode,relativeHierarchySelector=/^\s*[+~]/.test(query);if(!old){context.setAttribute("id",nid);}else{nid=nid.replace(/'/g,"\\$&");} -if(relativeHierarchySelector&&hasParent){context=context.parentNode;} -try{if(!relativeHierarchySelector||hasParent){return makeArray(context.querySelectorAll("[id='"+nid+"'] "+query),extra);}}catch(pseudoError){}finally{if(!old){oldContext.removeAttribute("id");}}}} -return oldSizzle(query,context,extra,seed);};for(var prop in oldSizzle){Sizzle[prop]=oldSizzle[prop];} -div=null;})();} -(function(){var html=document.documentElement,matches=html.matchesSelector||html.mozMatchesSelector||html.webkitMatchesSelector||html.msMatchesSelector;if(matches){var disconnectedMatch=!matches.call(document.createElement("div"),"div"),pseudoWorks=false;try{matches.call(document.documentElement,"[test!='']:sizzle");}catch(pseudoError){pseudoWorks=true;} -Sizzle.matchesSelector=function(node,expr){expr=expr.replace(/\=\s*([^'"\]]*)\s*\]/g,"='$1']");if(!Sizzle.isXML(node)){try{if(pseudoWorks||!Expr.match.PSEUDO.test(expr)&&!/!=/.test(expr)){var ret=matches.call(node,expr);if(ret||!disconnectedMatch||node.document&&node.document.nodeType!==11){return ret;}}}catch(e){}} -return Sizzle(expr,null,null,[node]).length>0;};}})();(function(){var div=document.createElement("div");div.innerHTML="
    ";if(!div.getElementsByClassName||div.getElementsByClassName("e").length===0){return;} -div.lastChild.className="e";if(div.getElementsByClassName("e").length===1){return;} -Expr.order.splice(1,0,"CLASS");Expr.find.CLASS=function(match,context,isXML){if(typeof context.getElementsByClassName!=="undefined"&&!isXML){return context.getElementsByClassName(match[1]);}};div=null;})();function dirNodeCheck(dir,cur,doneName,checkSet,nodeCheck,isXML){for(var i=0,l=checkSet.length;i0){match=elem;break;}} -elem=elem[dir];} -checkSet[i]=match;}}} -if(document.documentElement.contains){Sizzle.contains=function(a,b){return a!==b&&(a.contains?a.contains(b):true);};}else if(document.documentElement.compareDocumentPosition){Sizzle.contains=function(a,b){return!!(a.compareDocumentPosition(b)&16);};}else{Sizzle.contains=function(){return false;};} -Sizzle.isXML=function(elem){var documentElement=(elem?elem.ownerDocument||elem:0).documentElement;return documentElement?documentElement.nodeName!=="HTML":false;};var posProcess=function(selector,context,seed){var match,tmpSet=[],later="",root=context.nodeType?[context]:context;while((match=Expr.match.PSEUDO.exec(selector))){later+=match[0];selector=selector.replace(Expr.match.PSEUDO,"");} -selector=Expr.relative[selector]?selector+"*":selector;for(var i=0,l=root.length;i0){for(n=length;n=0:jQuery.filter(selector,this).length>0:this.filter(selector).length>0);},closest:function(selectors,context){var ret=[],i,l,cur=this[0];if(jQuery.isArray(selectors)){var level=1;while(cur&&cur.ownerDocument&&cur!==context){for(i=0;i-1:jQuery.find.matchesSelector(cur,selectors)){ret.push(cur);break;}else{cur=cur.parentNode;if(!cur||!cur.ownerDocument||cur===context||cur.nodeType===11){break;}}}} -ret=ret.length>1?jQuery.unique(ret):ret;return this.pushStack(ret,"closest",selectors);},index:function(elem){if(!elem){return(this[0]&&this[0].parentNode)?this.prevAll().length:-1;} -if(typeof elem==="string"){return jQuery.inArray(this[0],jQuery(elem));} -return jQuery.inArray(elem.jquery?elem[0]:elem,this);},add:function(selector,context){var set=typeof selector==="string"?jQuery(selector,context):jQuery.makeArray(selector&&selector.nodeType?[selector]:selector),all=jQuery.merge(this.get(),set);return this.pushStack(isDisconnected(set[0])||isDisconnected(all[0])?all:jQuery.unique(all));},andSelf:function(){return this.add(this.prevObject);}});function isDisconnected(node){return!node||!node.parentNode||node.parentNode.nodeType===11;} -jQuery.each({parent:function(elem){var parent=elem.parentNode;return parent&&parent.nodeType!==11?parent:null;},parents:function(elem){return jQuery.dir(elem,"parentNode");},parentsUntil:function(elem,i,until){return jQuery.dir(elem,"parentNode",until);},next:function(elem){return jQuery.nth(elem,2,"nextSibling");},prev:function(elem){return jQuery.nth(elem,2,"previousSibling");},nextAll:function(elem){return jQuery.dir(elem,"nextSibling");},prevAll:function(elem){return jQuery.dir(elem,"previousSibling");},nextUntil:function(elem,i,until){return jQuery.dir(elem,"nextSibling",until);},prevUntil:function(elem,i,until){return jQuery.dir(elem,"previousSibling",until);},siblings:function(elem){return jQuery.sibling((elem.parentNode||{}).firstChild,elem);},children:function(elem){return jQuery.sibling(elem.firstChild);},contents:function(elem){return jQuery.nodeName(elem,"iframe")?elem.contentDocument||elem.contentWindow.document:jQuery.makeArray(elem.childNodes);}},function(name,fn){jQuery.fn[name]=function(until,selector){var ret=jQuery.map(this,fn,until);if(!runtil.test(name)){selector=until;} -if(selector&&typeof selector==="string"){ret=jQuery.filter(selector,ret);} -ret=this.length>1&&!guaranteedUnique[name]?jQuery.unique(ret):ret;if((this.length>1||rmultiselector.test(selector))&&rparentsprev.test(name)){ret=ret.reverse();} -return this.pushStack(ret,name,slice.call(arguments).join(","));};});jQuery.extend({filter:function(expr,elems,not){if(not){expr=":not("+expr+")";} -return elems.length===1?jQuery.find.matchesSelector(elems[0],expr)?[elems[0]]:[]:jQuery.find.matches(expr,elems);},dir:function(elem,dir,until){var matched=[],cur=elem[dir];while(cur&&cur.nodeType!==9&&(until===undefined||cur.nodeType!==1||!jQuery(cur).is(until))){if(cur.nodeType===1){matched.push(cur);} -cur=cur[dir];} -return matched;},nth:function(cur,result,dir,elem){result=result||1;var num=0;for(;cur;cur=cur[dir]){if(cur.nodeType===1&&++num===result){break;}} -return cur;},sibling:function(n,elem){var r=[];for(;n;n=n.nextSibling){if(n.nodeType===1&&n!==elem){r.push(n);}} -return r;}});function winnow(elements,qualifier,keep){qualifier=qualifier||0;if(jQuery.isFunction(qualifier)){return jQuery.grep(elements,function(elem,i){var retVal=!!qualifier.call(elem,i,elem);return retVal===keep;});}else if(qualifier.nodeType){return jQuery.grep(elements,function(elem,i){return(elem===qualifier)===keep;});}else if(typeof qualifier==="string"){var filtered=jQuery.grep(elements,function(elem){return elem.nodeType===1;});if(isSimple.test(qualifier)){return jQuery.filter(qualifier,filtered,!keep);}else{qualifier=jQuery.filter(qualifier,filtered);}} -return jQuery.grep(elements,function(elem,i){return(jQuery.inArray(elem,qualifier)>=0)===keep;});} -function createSafeFragment(document){var list=nodeNames.split("|"),safeFrag=document.createDocumentFragment();if(safeFrag.createElement){while(list.length){safeFrag.createElement(list.pop());}} -return safeFrag;} -var nodeNames="abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|"+"header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",rinlinejQuery=/ jQuery\d+="(?:\d+|null)"/g,rleadingWhitespace=/^\s+/,rxhtmlTag=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig,rtagName=/<([\w:]+)/,rtbody=/]","i"),rchecked=/checked\s*(?:[^=]|=\s*.checked.)/i,rscriptType=/\/(java|ecma)script/i,rcleanScript=/^\s*",""],legend:[1,"
    ","
    "],thead:[1,"","
    "],tr:[2,"","
    "],td:[3,"","
    "],col:[2,"","
    "],area:[1,"",""],_default:[0,"",""]},safeFragment=createSafeFragment(document);wrapMap.optgroup=wrapMap.option;wrapMap.tbody=wrapMap.tfoot=wrapMap.colgroup=wrapMap.caption=wrapMap.thead;wrapMap.th=wrapMap.td;if(!jQuery.support.htmlSerialize){wrapMap._default=[1,"div
    ","
    "];} -jQuery.fn.extend({text:function(value){return jQuery.access(this,function(value){return value===undefined?jQuery.text(this):this.empty().append((this[0]&&this[0].ownerDocument||document).createTextNode(value));},null,value,arguments.length);},wrapAll:function(html){if(jQuery.isFunction(html)){return this.each(function(i){jQuery(this).wrapAll(html.call(this,i));});} -if(this[0]){var wrap=jQuery(html,this[0].ownerDocument).eq(0).clone(true);if(this[0].parentNode){wrap.insertBefore(this[0]);} -wrap.map(function(){var elem=this;while(elem.firstChild&&elem.firstChild.nodeType===1){elem=elem.firstChild;} -return elem;}).append(this);} -return this;},wrapInner:function(html){if(jQuery.isFunction(html)){return this.each(function(i){jQuery(this).wrapInner(html.call(this,i));});} -return this.each(function(){var self=jQuery(this),contents=self.contents();if(contents.length){contents.wrapAll(html);}else{self.append(html);}});},wrap:function(html){var isFunction=jQuery.isFunction(html);return this.each(function(i){jQuery(this).wrapAll(isFunction?html.call(this,i):html);});},unwrap:function(){return this.parent().each(function(){if(!jQuery.nodeName(this,"body")){jQuery(this).replaceWith(this.childNodes);}}).end();},append:function(){return this.domManip(arguments,true,function(elem){if(this.nodeType===1){this.appendChild(elem);}});},prepend:function(){return this.domManip(arguments,true,function(elem){if(this.nodeType===1){this.insertBefore(elem,this.firstChild);}});},before:function(){if(this[0]&&this[0].parentNode){return this.domManip(arguments,false,function(elem){this.parentNode.insertBefore(elem,this);});}else if(arguments.length){var set=jQuery.clean(arguments);set.push.apply(set,this.toArray());return this.pushStack(set,"before",arguments);}},after:function(){if(this[0]&&this[0].parentNode){return this.domManip(arguments,false,function(elem){this.parentNode.insertBefore(elem,this.nextSibling);});}else if(arguments.length){var set=this.pushStack(this,"after",arguments);set.push.apply(set,jQuery.clean(arguments));return set;}},remove:function(selector,keepData){for(var i=0,elem;(elem=this[i])!=null;i++){if(!selector||jQuery.filter(selector,[elem]).length){if(!keepData&&elem.nodeType===1){jQuery.cleanData(elem.getElementsByTagName("*"));jQuery.cleanData([elem]);} -if(elem.parentNode){elem.parentNode.removeChild(elem);}}} -return this;},empty:function(){for(var i=0,elem;(elem=this[i])!=null;i++){if(elem.nodeType===1){jQuery.cleanData(elem.getElementsByTagName("*"));} -while(elem.firstChild){elem.removeChild(elem.firstChild);}} -return this;},clone:function(dataAndEvents,deepDataAndEvents){dataAndEvents=dataAndEvents==null?false:dataAndEvents;deepDataAndEvents=deepDataAndEvents==null?dataAndEvents:deepDataAndEvents;return this.map(function(){return jQuery.clone(this,dataAndEvents,deepDataAndEvents);});},html:function(value){return jQuery.access(this,function(value){var elem=this[0]||{},i=0,l=this.length;if(value===undefined){return elem.nodeType===1?elem.innerHTML.replace(rinlinejQuery,""):null;} -if(typeof value==="string"&&!rnoInnerhtml.test(value)&&(jQuery.support.leadingWhitespace||!rleadingWhitespace.test(value))&&!wrapMap[(rtagName.exec(value)||["",""])[1].toLowerCase()]){value=value.replace(rxhtmlTag,"<$1>");try{for(;i1&&i0?this.clone(true):this).get();jQuery(insert[i])[original](elems);ret=ret.concat(elems);} -return this.pushStack(ret,name,insert.selector);}};});function getAll(elem){if(typeof elem.getElementsByTagName!=="undefined"){return elem.getElementsByTagName("*");}else if(typeof elem.querySelectorAll!=="undefined"){return elem.querySelectorAll("*");}else{return[];}} -function fixDefaultChecked(elem){if(elem.type==="checkbox"||elem.type==="radio"){elem.defaultChecked=elem.checked;}} -function findInputs(elem){var nodeName=(elem.nodeName||"").toLowerCase();if(nodeName==="input"){fixDefaultChecked(elem);}else if(nodeName!=="script"&&typeof elem.getElementsByTagName!=="undefined"){jQuery.grep(elem.getElementsByTagName("input"),fixDefaultChecked);}} -function shimCloneNode(elem){var div=document.createElement("div");safeFragment.appendChild(div);div.innerHTML=elem.outerHTML;return div.firstChild;} -jQuery.extend({clone:function(elem,dataAndEvents,deepDataAndEvents){var srcElements,destElements,i,clone=jQuery.support.html5Clone||jQuery.isXMLDoc(elem)||!rnoshimcache.test("<"+elem.nodeName+">")?elem.cloneNode(true):shimCloneNode(elem);if((!jQuery.support.noCloneEvent||!jQuery.support.noCloneChecked)&&(elem.nodeType===1||elem.nodeType===11)&&!jQuery.isXMLDoc(elem)){cloneFixAttributes(elem,clone);srcElements=getAll(elem);destElements=getAll(clone);for(i=0;srcElements[i];++i){if(destElements[i]){cloneFixAttributes(srcElements[i],destElements[i]);}}} -if(dataAndEvents){cloneCopyEvent(elem,clone);if(deepDataAndEvents){srcElements=getAll(elem);destElements=getAll(clone);for(i=0;srcElements[i];++i){cloneCopyEvent(srcElements[i],destElements[i]);}}} -srcElements=destElements=null;return clone;},clean:function(elems,context,fragment,scripts){var checkScriptType,script,j,ret=[];context=context||document;if(typeof context.createElement==="undefined"){context=context.ownerDocument||context[0]&&context[0].ownerDocument||document;} -for(var i=0,elem;(elem=elems[i])!=null;i++){if(typeof elem==="number"){elem+="";} -if(!elem){continue;} -if(typeof elem==="string"){if(!rhtml.test(elem)){elem=context.createTextNode(elem);}else{elem=elem.replace(rxhtmlTag,"<$1>");var tag=(rtagName.exec(elem)||["",""])[1].toLowerCase(),wrap=wrapMap[tag]||wrapMap._default,depth=wrap[0],div=context.createElement("div"),safeChildNodes=safeFragment.childNodes,remove;if(context===document){safeFragment.appendChild(div);}else{createSafeFragment(context).appendChild(div);} -div.innerHTML=wrap[1]+elem+wrap[2];while(depth--){div=div.lastChild;} -if(!jQuery.support.tbody){var hasBody=rtbody.test(elem),tbody=tag==="table"&&!hasBody?div.firstChild&&div.firstChild.childNodes:wrap[1]===""&&!hasBody?div.childNodes:[];for(j=tbody.length-1;j>=0;--j){if(jQuery.nodeName(tbody[j],"tbody")&&!tbody[j].childNodes.length){tbody[j].parentNode.removeChild(tbody[j]);}}} -if(!jQuery.support.leadingWhitespace&&rleadingWhitespace.test(elem)){div.insertBefore(context.createTextNode(rleadingWhitespace.exec(elem)[0]),div.firstChild);} -elem=div.childNodes;if(div){div.parentNode.removeChild(div);if(safeChildNodes.length>0){remove=safeChildNodes[safeChildNodes.length-1];if(remove&&remove.parentNode){remove.parentNode.removeChild(remove);}}}}} -var len;if(!jQuery.support.appendChecked){if(elem[0]&&typeof(len=elem.length)==="number"){for(j=0;j1);};jQuery.extend({cssHooks:{opacity:{get:function(elem,computed){if(computed){var ret=curCSS(elem,"opacity");return ret===""?"1":ret;}else{return elem.style.opacity;}}}},cssNumber:{"fillOpacity":true,"fontWeight":true,"lineHeight":true,"opacity":true,"orphans":true,"widows":true,"zIndex":true,"zoom":true},cssProps:{"float":jQuery.support.cssFloat?"cssFloat":"styleFloat"},style:function(elem,name,value,extra){if(!elem||elem.nodeType===3||elem.nodeType===8||!elem.style){return;} -var ret,type,origName=jQuery.camelCase(name),style=elem.style,hooks=jQuery.cssHooks[origName];name=jQuery.cssProps[origName]||origName;if(value!==undefined){type=typeof value;if(type==="string"&&(ret=rrelNum.exec(value))){value=(+(ret[1]+1)*+ret[2])+parseFloat(jQuery.css(elem,name));type="number";} -if(value==null||type==="number"&&isNaN(value)){return;} -if(type==="number"&&!jQuery.cssNumber[origName]){value+="px";} -if(!hooks||!("set"in hooks)||(value=hooks.set(elem,value))!==undefined){try{style[name]=value;}catch(e){}}}else{if(hooks&&"get"in hooks&&(ret=hooks.get(elem,false,extra))!==undefined){return ret;} -return style[name];}},css:function(elem,name,extra){var ret,hooks;name=jQuery.camelCase(name);hooks=jQuery.cssHooks[name];name=jQuery.cssProps[name]||name;if(name==="cssFloat"){name="float";} -if(hooks&&"get"in hooks&&(ret=hooks.get(elem,true,extra))!==undefined){return ret;}else if(curCSS){return curCSS(elem,name);}},swap:function(elem,options,callback){var old={},ret,name;for(name in options){old[name]=elem.style[name];elem.style[name]=options[name];} -ret=callback.call(elem);for(name in options){elem.style[name]=old[name];} -return ret;}});jQuery.curCSS=jQuery.css;if(document.defaultView&&document.defaultView.getComputedStyle){getComputedStyle=function(elem,name){var ret,defaultView,computedStyle,width,style=elem.style;name=name.replace(rupper,"-$1").toLowerCase();if((defaultView=elem.ownerDocument.defaultView)&&(computedStyle=defaultView.getComputedStyle(elem,null))){ret=computedStyle.getPropertyValue(name);if(ret===""&&!jQuery.contains(elem.ownerDocument.documentElement,elem)){ret=jQuery.style(elem,name);}} -if(!jQuery.support.pixelMargin&&computedStyle&&rmargin.test(name)&&rnumnonpx.test(ret)){width=style.width;style.width=ret;ret=computedStyle.width;style.width=width;} -return ret;};} -if(document.documentElement.currentStyle){currentStyle=function(elem,name){var left,rsLeft,uncomputed,ret=elem.currentStyle&&elem.currentStyle[name],style=elem.style;if(ret==null&&style&&(uncomputed=style[name])){ret=uncomputed;} -if(rnumnonpx.test(ret)){left=style.left;rsLeft=elem.runtimeStyle&&elem.runtimeStyle.left;if(rsLeft){elem.runtimeStyle.left=elem.currentStyle.left;} -style.left=name==="fontSize"?"1em":ret;ret=style.pixelLeft+"px";style.left=left;if(rsLeft){elem.runtimeStyle.left=rsLeft;}} -return ret===""?"auto":ret;};} -curCSS=getComputedStyle||currentStyle;function getWidthOrHeight(elem,name,extra){var val=name==="width"?elem.offsetWidth:elem.offsetHeight,i=name==="width"?1:0,len=4;if(val>0){if(extra!=="border"){for(;i=1&&jQuery.trim(filter.replace(ralpha,""))===""){style.removeAttribute("filter");if(currentStyle&&!currentStyle.filter){return;}} -style.filter=ralpha.test(filter)?filter.replace(ralpha,opacity):filter+" "+opacity;}};} -jQuery(function(){if(!jQuery.support.reliableMarginRight){jQuery.cssHooks.marginRight={get:function(elem,computed){return jQuery.swap(elem,{"display":"inline-block"},function(){if(computed){return curCSS(elem,"margin-right");}else{return elem.style.marginRight;}});}};}});if(jQuery.expr&&jQuery.expr.filters){jQuery.expr.filters.hidden=function(elem){var width=elem.offsetWidth,height=elem.offsetHeight;return(width===0&&height===0)||(!jQuery.support.reliableHiddenOffsets&&((elem.style&&elem.style.display)||jQuery.css(elem,"display"))==="none");};jQuery.expr.filters.visible=function(elem){return!jQuery.expr.filters.hidden(elem);};} -jQuery.each({margin:"",padding:"",border:"Width"},function(prefix,suffix){jQuery.cssHooks[prefix+suffix]={expand:function(value){var i,parts=typeof value==="string"?value.split(" "):[value],expanded={};for(i=0;i<4;i++){expanded[prefix+cssExpand[i]+suffix]=parts[i]||parts[i-2]||parts[0];} -return expanded;}};});var r20=/%20/g,rbracket=/\[\]$/,rCRLF=/\r?\n/g,rhash=/#.*$/,rheaders=/^(.*?):[ \t]*([^\r\n]*)\r?$/mg,rinput=/^(?:color|date|datetime|datetime-local|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,rlocalProtocol=/^(?:about|app|app\-storage|.+\-extension|file|res|widget):$/,rnoContent=/^(?:GET|HEAD)$/,rprotocol=/^\/\//,rquery=/\?/,rscript=/)<[^<]*)*<\/script>/gi,rselectTextarea=/^(?:select|textarea)/i,rspacesAjax=/\s+/,rts=/([?&])_=[^&]*/,rurl=/^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+))?)?/,_load=jQuery.fn.load,prefilters={},transports={},ajaxLocation,ajaxLocParts,allTypes=["*/"]+["*"];try{ajaxLocation=location.href;}catch(e){ajaxLocation=document.createElement("a");ajaxLocation.href="";ajaxLocation=ajaxLocation.href;} -ajaxLocParts=rurl.exec(ajaxLocation.toLowerCase())||[];function addToPrefiltersOrTransports(structure){return function(dataTypeExpression,func){if(typeof dataTypeExpression!=="string"){func=dataTypeExpression;dataTypeExpression="*";} -if(jQuery.isFunction(func)){var dataTypes=dataTypeExpression.toLowerCase().split(rspacesAjax),i=0,length=dataTypes.length,dataType,list,placeBefore;for(;i=0){var selector=url.slice(off,url.length);url=url.slice(0,off);} -var type="GET";if(params){if(jQuery.isFunction(params)){callback=params;params=undefined;}else if(typeof params==="object"){params=jQuery.param(params,jQuery.ajaxSettings.traditional);type="POST";}} -var self=this;jQuery.ajax({url:url,type:type,dataType:"html",data:params,complete:function(jqXHR,status,responseText){responseText=jqXHR.responseText;if(jqXHR.isResolved()){jqXHR.done(function(r){responseText=r;});self.html(selector?jQuery("
    ").append(responseText.replace(rscript,"")).find(selector):responseText);} -if(callback){self.each(callback,[responseText,status,jqXHR]);}}});return this;},serialize:function(){return jQuery.param(this.serializeArray());},serializeArray:function(){return this.map(function(){return this.elements?jQuery.makeArray(this.elements):this;}).filter(function(){return this.name&&!this.disabled&&(this.checked||rselectTextarea.test(this.nodeName)||rinput.test(this.type));}).map(function(i,elem){var val=jQuery(this).val();return val==null?null:jQuery.isArray(val)?jQuery.map(val,function(val,i){return{name:elem.name,value:val.replace(rCRLF,"\r\n")};}):{name:elem.name,value:val.replace(rCRLF,"\r\n")};}).get();}});jQuery.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),function(i,o){jQuery.fn[o]=function(f){return this.on(o,f);};});jQuery.each(["get","post"],function(i,method){jQuery[method]=function(url,data,callback,type){if(jQuery.isFunction(data)){type=type||callback;callback=data;data=undefined;} -return jQuery.ajax({type:method,url:url,data:data,success:callback,dataType:type});};});jQuery.extend({getScript:function(url,callback){return jQuery.get(url,undefined,callback,"script");},getJSON:function(url,data,callback){return jQuery.get(url,data,callback,"json");},ajaxSetup:function(target,settings){if(settings){ajaxExtend(target,jQuery.ajaxSettings);}else{settings=target;target=jQuery.ajaxSettings;} -ajaxExtend(target,settings);return target;},ajaxSettings:{url:ajaxLocation,isLocal:rlocalProtocol.test(ajaxLocParts[1]),global:true,type:"GET",contentType:"application/x-www-form-urlencoded; charset=UTF-8",processData:true,async:true,accepts:{xml:"application/xml, text/xml",html:"text/html",text:"text/plain",json:"application/json, text/javascript","*":allTypes},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText"},converters:{"* text":window.String,"text html":true,"text json":jQuery.parseJSON,"text xml":jQuery.parseXML},flatOptions:{context:true,url:true}},ajaxPrefilter:addToPrefiltersOrTransports(prefilters),ajaxTransport:addToPrefiltersOrTransports(transports),ajax:function(url,options){if(typeof url==="object"){options=url;url=undefined;} -options=options||{};var -s=jQuery.ajaxSetup({},options),callbackContext=s.context||s,globalEventContext=callbackContext!==s&&(callbackContext.nodeType||callbackContext instanceof jQuery)?jQuery(callbackContext):jQuery.event,deferred=jQuery.Deferred(),completeDeferred=jQuery.Callbacks("once memory"),statusCode=s.statusCode||{},ifModifiedKey,requestHeaders={},requestHeadersNames={},responseHeadersString,responseHeaders,transport,timeoutTimer,parts,state=0,fireGlobals,i,jqXHR={readyState:0,setRequestHeader:function(name,value){if(!state){var lname=name.toLowerCase();name=requestHeadersNames[lname]=requestHeadersNames[lname]||name;requestHeaders[name]=value;} -return this;},getAllResponseHeaders:function(){return state===2?responseHeadersString:null;},getResponseHeader:function(key){var match;if(state===2){if(!responseHeaders){responseHeaders={};while((match=rheaders.exec(responseHeadersString))){responseHeaders[match[1].toLowerCase()]=match[2];}} -match=responseHeaders[key.toLowerCase()];} -return match===undefined?null:match;},overrideMimeType:function(type){if(!state){s.mimeType=type;} -return this;},abort:function(statusText){statusText=statusText||"abort";if(transport){transport.abort(statusText);} -done(0,statusText);return this;}};function done(status,nativeStatusText,responses,headers){if(state===2){return;} -state=2;if(timeoutTimer){clearTimeout(timeoutTimer);} -transport=undefined;responseHeadersString=headers||"";jqXHR.readyState=status>0?4:0;var isSuccess,success,error,statusText=nativeStatusText,response=responses?ajaxHandleResponses(s,jqXHR,responses):undefined,lastModified,etag;if(status>=200&&status<300||status===304){if(s.ifModified){if((lastModified=jqXHR.getResponseHeader("Last-Modified"))){jQuery.lastModified[ifModifiedKey]=lastModified;} -if((etag=jqXHR.getResponseHeader("Etag"))){jQuery.etag[ifModifiedKey]=etag;}} -if(status===304){statusText="notmodified";isSuccess=true;}else{try{success=ajaxConvert(s,response);statusText="success";isSuccess=true;}catch(e){statusText="parsererror";error=e;}}}else{error=statusText;if(!statusText||status){statusText="error";if(status<0){status=0;}}} -jqXHR.status=status;jqXHR.statusText=""+(nativeStatusText||statusText);if(isSuccess){deferred.resolveWith(callbackContext,[success,statusText,jqXHR]);}else{deferred.rejectWith(callbackContext,[jqXHR,statusText,error]);} -jqXHR.statusCode(statusCode);statusCode=undefined;if(fireGlobals){globalEventContext.trigger("ajax"+(isSuccess?"Success":"Error"),[jqXHR,s,isSuccess?success:error]);} -completeDeferred.fireWith(callbackContext,[jqXHR,statusText]);if(fireGlobals){globalEventContext.trigger("ajaxComplete",[jqXHR,s]);if(!(--jQuery.active)){jQuery.event.trigger("ajaxStop");}}} -deferred.promise(jqXHR);jqXHR.success=jqXHR.done;jqXHR.error=jqXHR.fail;jqXHR.complete=completeDeferred.add;jqXHR.statusCode=function(map){if(map){var tmp;if(state<2){for(tmp in map){statusCode[tmp]=[statusCode[tmp],map[tmp]];}}else{tmp=map[jqXHR.status];jqXHR.then(tmp,tmp);}} -return this;};s.url=((url||s.url)+"").replace(rhash,"").replace(rprotocol,ajaxLocParts[1]+"//");s.dataTypes=jQuery.trim(s.dataType||"*").toLowerCase().split(rspacesAjax);if(s.crossDomain==null){parts=rurl.exec(s.url.toLowerCase());s.crossDomain=!!(parts&&(parts[1]!=ajaxLocParts[1]||parts[2]!=ajaxLocParts[2]||(parts[3]||(parts[1]==="http:"?80:443))!=(ajaxLocParts[3]||(ajaxLocParts[1]==="http:"?80:443))));} -if(s.data&&s.processData&&typeof s.data!=="string"){s.data=jQuery.param(s.data,s.traditional);} -inspectPrefiltersOrTransports(prefilters,s,options,jqXHR);if(state===2){return false;} -fireGlobals=s.global;s.type=s.type.toUpperCase();s.hasContent=!rnoContent.test(s.type);if(fireGlobals&&jQuery.active++===0){jQuery.event.trigger("ajaxStart");} -if(!s.hasContent){if(s.data){s.url+=(rquery.test(s.url)?"&":"?")+s.data;delete s.data;} -ifModifiedKey=s.url;if(s.cache===false){var ts=jQuery.now(),ret=s.url.replace(rts,"$1_="+ts);s.url=ret+((ret===s.url)?(rquery.test(s.url)?"&":"?")+"_="+ts:"");}} -if(s.data&&s.hasContent&&s.contentType!==false||options.contentType){jqXHR.setRequestHeader("Content-Type",s.contentType);} -if(s.ifModified){ifModifiedKey=ifModifiedKey||s.url;if(jQuery.lastModified[ifModifiedKey]){jqXHR.setRequestHeader("If-Modified-Since",jQuery.lastModified[ifModifiedKey]);} -if(jQuery.etag[ifModifiedKey]){jqXHR.setRequestHeader("If-None-Match",jQuery.etag[ifModifiedKey]);}} -jqXHR.setRequestHeader("Accept",s.dataTypes[0]&&s.accepts[s.dataTypes[0]]?s.accepts[s.dataTypes[0]]+(s.dataTypes[0]!=="*"?", "+allTypes+"; q=0.01":""):s.accepts["*"]);for(i in s.headers){jqXHR.setRequestHeader(i,s.headers[i]);} -if(s.beforeSend&&(s.beforeSend.call(callbackContext,jqXHR,s)===false||state===2)){jqXHR.abort();return false;} -for(i in{success:1,error:1,complete:1}){jqXHR[i](s[i]);} -transport=inspectPrefiltersOrTransports(transports,s,options,jqXHR);if(!transport){done(-1,"No Transport");}else{jqXHR.readyState=1;if(fireGlobals){globalEventContext.trigger("ajaxSend",[jqXHR,s]);} -if(s.async&&s.timeout>0){timeoutTimer=setTimeout(function(){jqXHR.abort("timeout");},s.timeout);} -try{state=1;transport.send(requestHeaders,done);}catch(e){if(state<2){done(-1,e);}else{throw e;}}} -return jqXHR;},param:function(a,traditional){var s=[],add=function(key,value){value=jQuery.isFunction(value)?value():value;s[s.length]=encodeURIComponent(key)+"="+encodeURIComponent(value);};if(traditional===undefined){traditional=jQuery.ajaxSettings.traditional;} -if(jQuery.isArray(a)||(a.jquery&&!jQuery.isPlainObject(a))){jQuery.each(a,function(){add(this.name,this.value);});}else{for(var prefix in a){buildParams(prefix,a[prefix],traditional,add);}} -return s.join("&").replace(r20,"+");}});function buildParams(prefix,obj,traditional,add){if(jQuery.isArray(obj)){jQuery.each(obj,function(i,v){if(traditional||rbracket.test(prefix)){add(prefix,v);}else{buildParams(prefix+"["+(typeof v==="object"?i:"")+"]",v,traditional,add);}});}else if(!traditional&&jQuery.type(obj)==="object"){for(var name in obj){buildParams(prefix+"["+name+"]",obj[name],traditional,add);}}else{add(prefix,obj);}} -jQuery.extend({active:0,lastModified:{},etag:{}});function ajaxHandleResponses(s,jqXHR,responses){var contents=s.contents,dataTypes=s.dataTypes,responseFields=s.responseFields,ct,type,finalDataType,firstDataType;for(type in responseFields){if(type in responses){jqXHR[responseFields[type]]=responses[type];}} -while(dataTypes[0]==="*"){dataTypes.shift();if(ct===undefined){ct=s.mimeType||jqXHR.getResponseHeader("content-type");}} -if(ct){for(type in contents){if(contents[type]&&contents[type].test(ct)){dataTypes.unshift(type);break;}}} -if(dataTypes[0]in responses){finalDataType=dataTypes[0];}else{for(type in responses){if(!dataTypes[0]||s.converters[type+" "+dataTypes[0]]){finalDataType=type;break;} -if(!firstDataType){firstDataType=type;}} -finalDataType=finalDataType||firstDataType;} -if(finalDataType){if(finalDataType!==dataTypes[0]){dataTypes.unshift(finalDataType);} -return responses[finalDataType];}} -function ajaxConvert(s,response){if(s.dataFilter){response=s.dataFilter(response,s.dataType);} -var dataTypes=s.dataTypes,converters={},i,key,length=dataTypes.length,tmp,current=dataTypes[0],prev,conversion,conv,conv1,conv2;for(i=1;i=options.duration+this.startTime){this.now=this.end;this.pos=this.state=1;this.update();options.animatedProperties[this.prop]=true;for(p in options.animatedProperties){if(options.animatedProperties[p]!==true){done=false;}} -if(done){if(options.overflow!=null&&!jQuery.support.shrinkWrapBlocks){jQuery.each(["","X","Y"],function(index,value){elem.style["overflow"+value]=options.overflow[index];});} -if(options.hide){jQuery(elem).hide();} -if(options.hide||options.show){for(p in options.animatedProperties){jQuery.style(elem,p,options.orig[p]);jQuery.removeData(elem,"fxshow"+p,true);jQuery.removeData(elem,"toggle"+p,true);}} -complete=options.complete;if(complete){options.complete=false;complete.call(elem);}} -return false;}else{if(options.duration==Infinity){this.now=t;}else{n=t-this.startTime;this.state=n/options.duration;this.pos=jQuery.easing[options.animatedProperties[this.prop]](this.state,n,0,1,options.duration);this.now=this.start+((this.end-this.start)*this.pos);} -this.update();} -return true;}};jQuery.extend(jQuery.fx,{tick:function(){var timer,timers=jQuery.timers,i=0;for(;i").appendTo(body),display=elem.css("display");elem.remove();if(display==="none"||display===""){if(!iframe){iframe=document.createElement("iframe");iframe.frameBorder=iframe.width=iframe.height=0;} -body.appendChild(iframe);if(!iframeDoc||!iframe.createElement){iframeDoc=(iframe.contentWindow||iframe.contentDocument).document;iframeDoc.write((jQuery.support.boxModel?"":"")+"");iframeDoc.close();} -elem=iframeDoc.createElement(nodeName);iframeDoc.body.appendChild(elem);display=jQuery.css(elem,"display");body.removeChild(iframe);} -elemdisplay[nodeName]=display;} -return elemdisplay[nodeName];} -var getOffset,rtable=/^t(?:able|d|h)$/i,rroot=/^(?:body|html)$/i;if("getBoundingClientRect"in document.documentElement){getOffset=function(elem,doc,docElem,box){try{box=elem.getBoundingClientRect();}catch(e){} -if(!box||!jQuery.contains(docElem,elem)){return box?{top:box.top,left:box.left}:{top:0,left:0};} -var body=doc.body,win=getWindow(doc),clientTop=docElem.clientTop||body.clientTop||0,clientLeft=docElem.clientLeft||body.clientLeft||0,scrollTop=win.pageYOffset||jQuery.support.boxModel&&docElem.scrollTop||body.scrollTop,scrollLeft=win.pageXOffset||jQuery.support.boxModel&&docElem.scrollLeft||body.scrollLeft,top=box.top+scrollTop-clientTop,left=box.left+scrollLeft-clientLeft;return{top:top,left:left};};}else{getOffset=function(elem,doc,docElem){var computedStyle,offsetParent=elem.offsetParent,prevOffsetParent=elem,body=doc.body,defaultView=doc.defaultView,prevComputedStyle=defaultView?defaultView.getComputedStyle(elem,null):elem.currentStyle,top=elem.offsetTop,left=elem.offsetLeft;while((elem=elem.parentNode)&&elem!==body&&elem!==docElem){if(jQuery.support.fixedPosition&&prevComputedStyle.position==="fixed"){break;} -computedStyle=defaultView?defaultView.getComputedStyle(elem,null):elem.currentStyle;top-=elem.scrollTop;left-=elem.scrollLeft;if(elem===offsetParent){top+=elem.offsetTop;left+=elem.offsetLeft;if(jQuery.support.doesNotAddBorder&&!(jQuery.support.doesAddBorderForTableAndCells&&rtable.test(elem.nodeName))){top+=parseFloat(computedStyle.borderTopWidth)||0;left+=parseFloat(computedStyle.borderLeftWidth)||0;} -prevOffsetParent=offsetParent;offsetParent=elem.offsetParent;} -if(jQuery.support.subtractsBorderForOverflowNotVisible&&computedStyle.overflow!=="visible"){top+=parseFloat(computedStyle.borderTopWidth)||0;left+=parseFloat(computedStyle.borderLeftWidth)||0;} -prevComputedStyle=computedStyle;} -if(prevComputedStyle.position==="relative"||prevComputedStyle.position==="static"){top+=body.offsetTop;left+=body.offsetLeft;} -if(jQuery.support.fixedPosition&&prevComputedStyle.position==="fixed"){top+=Math.max(docElem.scrollTop,body.scrollTop);left+=Math.max(docElem.scrollLeft,body.scrollLeft);} -return{top:top,left:left};};} -jQuery.fn.offset=function(options){if(arguments.length){return options===undefined?this:this.each(function(i){jQuery.offset.setOffset(this,options,i);});} -var elem=this[0],doc=elem&&elem.ownerDocument;if(!doc){return null;} -if(elem===doc.body){return jQuery.offset.bodyOffset(elem);} -return getOffset(elem,doc,doc.documentElement);};jQuery.offset={bodyOffset:function(body){var top=body.offsetTop,left=body.offsetLeft;if(jQuery.support.doesNotIncludeMarginInBodyOffset){top+=parseFloat(jQuery.css(body,"marginTop"))||0;left+=parseFloat(jQuery.css(body,"marginLeft"))||0;} -return{top:top,left:left};},setOffset:function(elem,options,i){var position=jQuery.css(elem,"position");if(position==="static"){elem.style.position="relative";} -var curElem=jQuery(elem),curOffset=curElem.offset(),curCSSTop=jQuery.css(elem,"top"),curCSSLeft=jQuery.css(elem,"left"),calculatePosition=(position==="absolute"||position==="fixed")&&jQuery.inArray("auto",[curCSSTop,curCSSLeft])>-1,props={},curPosition={},curTop,curLeft;if(calculatePosition){curPosition=curElem.position();curTop=curPosition.top;curLeft=curPosition.left;}else{curTop=parseFloat(curCSSTop)||0;curLeft=parseFloat(curCSSLeft)||0;} -if(jQuery.isFunction(options)){options=options.call(elem,i,curOffset);} -if(options.top!=null){props.top=(options.top-curOffset.top)+curTop;} -if(options.left!=null){props.left=(options.left-curOffset.left)+curLeft;} -if("using"in options){options.using.call(elem,props);}else{curElem.css(props);}}};jQuery.fn.extend({position:function(){if(!this[0]){return null;} -var elem=this[0],offsetParent=this.offsetParent(),offset=this.offset(),parentOffset=rroot.test(offsetParent[0].nodeName)?{top:0,left:0}:offsetParent.offset();offset.top-=parseFloat(jQuery.css(elem,"marginTop"))||0;offset.left-=parseFloat(jQuery.css(elem,"marginLeft"))||0;parentOffset.top+=parseFloat(jQuery.css(offsetParent[0],"borderTopWidth"))||0;parentOffset.left+=parseFloat(jQuery.css(offsetParent[0],"borderLeftWidth"))||0;return{top:offset.top-parentOffset.top,left:offset.left-parentOffset.left};},offsetParent:function(){return this.map(function(){var offsetParent=this.offsetParent||document.body;while(offsetParent&&(!rroot.test(offsetParent.nodeName)&&jQuery.css(offsetParent,"position")==="static")){offsetParent=offsetParent.offsetParent;} -return offsetParent;});}});jQuery.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(method,prop){var top=/Y/.test(prop);jQuery.fn[method]=function(val){return jQuery.access(this,function(elem,method,val){var win=getWindow(elem);if(val===undefined){return win?(prop in win)?win[prop]:jQuery.support.boxModel&&win.document.documentElement[method]||win.document.body[method]:elem[method];} -if(win){win.scrollTo(!top?val:jQuery(win).scrollLeft(),top?val:jQuery(win).scrollTop());}else{elem[method]=val;}},method,val,arguments.length,null);};});function getWindow(elem){return jQuery.isWindow(elem)?elem:elem.nodeType===9?elem.defaultView||elem.parentWindow:false;} -jQuery.each({Height:"height",Width:"width"},function(name,type){var clientProp="client"+name,scrollProp="scroll"+name,offsetProp="offset"+name;jQuery.fn["inner"+name]=function(){var elem=this[0];return elem?elem.style?parseFloat(jQuery.css(elem,type,"padding")):this[type]():null;};jQuery.fn["outer"+name]=function(margin){var elem=this[0];return elem?elem.style?parseFloat(jQuery.css(elem,type,margin?"margin":"border")):this[type]():null;};jQuery.fn[type]=function(value){return jQuery.access(this,function(elem,type,value){var doc,docElemProp,orig,ret;if(jQuery.isWindow(elem)){doc=elem.document;docElemProp=doc.documentElement[clientProp];return jQuery.support.boxModel&&docElemProp||doc.body&&doc.body[clientProp]||docElemProp;} -if(elem.nodeType===9){doc=elem.documentElement;if(doc[clientProp]>=doc[scrollProp]){return doc[clientProp];} -return Math.max(elem.body[scrollProp],doc[scrollProp],elem.body[offsetProp],doc[offsetProp]);} -if(value===undefined){orig=jQuery.css(elem,type);ret=parseFloat(orig);return jQuery.isNumeric(ret)?ret:orig;} -jQuery(elem).css(type,value);},type,value,arguments.length,null);};});window.jQuery=window.$=jQuery;if(typeof define==="function"&&define.amd&&define.amd.jQuery){define("jquery",[],function(){return jQuery;});}})(window); \ No newline at end of file +/*! jQuery v1.10.2 | (c) 2005, 2013 jQuery Foundation, Inc. | jquery.org/license +//@ sourceMappingURL=jquery-1.10.2.min.map +*/ +(function(e,t){var n,r,i=typeof t,o=e.location,a=e.document,s=a.documentElement,l=e.jQuery,u=e.$,c={},p=[],f="1.10.2",d=p.concat,h=p.push,g=p.slice,m=p.indexOf,y=c.toString,v=c.hasOwnProperty,b=f.trim,x=function(e,t){return new x.fn.init(e,t,r)},w=/[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/.source,T=/\S+/g,C=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,N=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/,k=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,E=/^[\],:{}\s]*$/,S=/(?:^|:|,)(?:\s*\[)+/g,A=/\\(?:["\\\/bfnrt]|u[\da-fA-F]{4})/g,j=/"[^"\\\r\n]*"|true|false|null|-?(?:\d+\.|)\d+(?:[eE][+-]?\d+|)/g,D=/^-ms-/,L=/-([\da-z])/gi,H=function(e,t){return t.toUpperCase()},q=function(e){(a.addEventListener||"load"===e.type||"complete"===a.readyState)&&(_(),x.ready())},_=function(){a.addEventListener?(a.removeEventListener("DOMContentLoaded",q,!1),e.removeEventListener("load",q,!1)):(a.detachEvent("onreadystatechange",q),e.detachEvent("onload",q))};x.fn=x.prototype={jquery:f,constructor:x,init:function(e,n,r){var i,o;if(!e)return this;if("string"==typeof e){if(i="<"===e.charAt(0)&&">"===e.charAt(e.length-1)&&e.length>=3?[null,e,null]:N.exec(e),!i||!i[1]&&n)return!n||n.jquery?(n||r).find(e):this.constructor(n).find(e);if(i[1]){if(n=n instanceof x?n[0]:n,x.merge(this,x.parseHTML(i[1],n&&n.nodeType?n.ownerDocument||n:a,!0)),k.test(i[1])&&x.isPlainObject(n))for(i in n)x.isFunction(this[i])?this[i](n[i]):this.attr(i,n[i]);return this}if(o=a.getElementById(i[2]),o&&o.parentNode){if(o.id!==i[2])return r.find(e);this.length=1,this[0]=o}return this.context=a,this.selector=e,this}return e.nodeType?(this.context=this[0]=e,this.length=1,this):x.isFunction(e)?r.ready(e):(e.selector!==t&&(this.selector=e.selector,this.context=e.context),x.makeArray(e,this))},selector:"",length:0,toArray:function(){return g.call(this)},get:function(e){return null==e?this.toArray():0>e?this[this.length+e]:this[e]},pushStack:function(e){var t=x.merge(this.constructor(),e);return t.prevObject=this,t.context=this.context,t},each:function(e,t){return x.each(this,e,t)},ready:function(e){return x.ready.promise().done(e),this},slice:function(){return this.pushStack(g.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(e){var t=this.length,n=+e+(0>e?t:0);return this.pushStack(n>=0&&t>n?[this[n]]:[])},map:function(e){return this.pushStack(x.map(this,function(t,n){return e.call(t,n,t)}))},end:function(){return this.prevObject||this.constructor(null)},push:h,sort:[].sort,splice:[].splice},x.fn.init.prototype=x.fn,x.extend=x.fn.extend=function(){var e,n,r,i,o,a,s=arguments[0]||{},l=1,u=arguments.length,c=!1;for("boolean"==typeof s&&(c=s,s=arguments[1]||{},l=2),"object"==typeof s||x.isFunction(s)||(s={}),u===l&&(s=this,--l);u>l;l++)if(null!=(o=arguments[l]))for(i in o)e=s[i],r=o[i],s!==r&&(c&&r&&(x.isPlainObject(r)||(n=x.isArray(r)))?(n?(n=!1,a=e&&x.isArray(e)?e:[]):a=e&&x.isPlainObject(e)?e:{},s[i]=x.extend(c,a,r)):r!==t&&(s[i]=r));return s},x.extend({expando:"jQuery"+(f+Math.random()).replace(/\D/g,""),noConflict:function(t){return e.$===x&&(e.$=u),t&&e.jQuery===x&&(e.jQuery=l),x},isReady:!1,readyWait:1,holdReady:function(e){e?x.readyWait++:x.ready(!0)},ready:function(e){if(e===!0?!--x.readyWait:!x.isReady){if(!a.body)return setTimeout(x.ready);x.isReady=!0,e!==!0&&--x.readyWait>0||(n.resolveWith(a,[x]),x.fn.trigger&&x(a).trigger("ready").off("ready"))}},isFunction:function(e){return"function"===x.type(e)},isArray:Array.isArray||function(e){return"array"===x.type(e)},isWindow:function(e){return null!=e&&e==e.window},isNumeric:function(e){return!isNaN(parseFloat(e))&&isFinite(e)},type:function(e){return null==e?e+"":"object"==typeof e||"function"==typeof e?c[y.call(e)]||"object":typeof e},isPlainObject:function(e){var n;if(!e||"object"!==x.type(e)||e.nodeType||x.isWindow(e))return!1;try{if(e.constructor&&!v.call(e,"constructor")&&!v.call(e.constructor.prototype,"isPrototypeOf"))return!1}catch(r){return!1}if(x.support.ownLast)for(n in e)return v.call(e,n);for(n in e);return n===t||v.call(e,n)},isEmptyObject:function(e){var t;for(t in e)return!1;return!0},error:function(e){throw Error(e)},parseHTML:function(e,t,n){if(!e||"string"!=typeof e)return null;"boolean"==typeof t&&(n=t,t=!1),t=t||a;var r=k.exec(e),i=!n&&[];return r?[t.createElement(r[1])]:(r=x.buildFragment([e],t,i),i&&x(i).remove(),x.merge([],r.childNodes))},parseJSON:function(n){return e.JSON&&e.JSON.parse?e.JSON.parse(n):null===n?n:"string"==typeof n&&(n=x.trim(n),n&&E.test(n.replace(A,"@").replace(j,"]").replace(S,"")))?Function("return "+n)():(x.error("Invalid JSON: "+n),t)},parseXML:function(n){var r,i;if(!n||"string"!=typeof n)return null;try{e.DOMParser?(i=new DOMParser,r=i.parseFromString(n,"text/xml")):(r=new ActiveXObject("Microsoft.XMLDOM"),r.async="false",r.loadXML(n))}catch(o){r=t}return r&&r.documentElement&&!r.getElementsByTagName("parsererror").length||x.error("Invalid XML: "+n),r},noop:function(){},globalEval:function(t){t&&x.trim(t)&&(e.execScript||function(t){e.eval.call(e,t)})(t)},camelCase:function(e){return e.replace(D,"ms-").replace(L,H)},nodeName:function(e,t){return e.nodeName&&e.nodeName.toLowerCase()===t.toLowerCase()},each:function(e,t,n){var r,i=0,o=e.length,a=M(e);if(n){if(a){for(;o>i;i++)if(r=t.apply(e[i],n),r===!1)break}else for(i in e)if(r=t.apply(e[i],n),r===!1)break}else if(a){for(;o>i;i++)if(r=t.call(e[i],i,e[i]),r===!1)break}else for(i in e)if(r=t.call(e[i],i,e[i]),r===!1)break;return e},trim:b&&!b.call("\ufeff\u00a0")?function(e){return null==e?"":b.call(e)}:function(e){return null==e?"":(e+"").replace(C,"")},makeArray:function(e,t){var n=t||[];return null!=e&&(M(Object(e))?x.merge(n,"string"==typeof e?[e]:e):h.call(n,e)),n},inArray:function(e,t,n){var r;if(t){if(m)return m.call(t,e,n);for(r=t.length,n=n?0>n?Math.max(0,r+n):n:0;r>n;n++)if(n in t&&t[n]===e)return n}return-1},merge:function(e,n){var r=n.length,i=e.length,o=0;if("number"==typeof r)for(;r>o;o++)e[i++]=n[o];else while(n[o]!==t)e[i++]=n[o++];return e.length=i,e},grep:function(e,t,n){var r,i=[],o=0,a=e.length;for(n=!!n;a>o;o++)r=!!t(e[o],o),n!==r&&i.push(e[o]);return i},map:function(e,t,n){var r,i=0,o=e.length,a=M(e),s=[];if(a)for(;o>i;i++)r=t(e[i],i,n),null!=r&&(s[s.length]=r);else for(i in e)r=t(e[i],i,n),null!=r&&(s[s.length]=r);return d.apply([],s)},guid:1,proxy:function(e,n){var r,i,o;return"string"==typeof n&&(o=e[n],n=e,e=o),x.isFunction(e)?(r=g.call(arguments,2),i=function(){return e.apply(n||this,r.concat(g.call(arguments)))},i.guid=e.guid=e.guid||x.guid++,i):t},access:function(e,n,r,i,o,a,s){var l=0,u=e.length,c=null==r;if("object"===x.type(r)){o=!0;for(l in r)x.access(e,n,l,r[l],!0,a,s)}else if(i!==t&&(o=!0,x.isFunction(i)||(s=!0),c&&(s?(n.call(e,i),n=null):(c=n,n=function(e,t,n){return c.call(x(e),n)})),n))for(;u>l;l++)n(e[l],r,s?i:i.call(e[l],l,n(e[l],r)));return o?e:c?n.call(e):u?n(e[0],r):a},now:function(){return(new Date).getTime()},swap:function(e,t,n,r){var i,o,a={};for(o in t)a[o]=e.style[o],e.style[o]=t[o];i=n.apply(e,r||[]);for(o in t)e.style[o]=a[o];return i}}),x.ready.promise=function(t){if(!n)if(n=x.Deferred(),"complete"===a.readyState)setTimeout(x.ready);else if(a.addEventListener)a.addEventListener("DOMContentLoaded",q,!1),e.addEventListener("load",q,!1);else{a.attachEvent("onreadystatechange",q),e.attachEvent("onload",q);var r=!1;try{r=null==e.frameElement&&a.documentElement}catch(i){}r&&r.doScroll&&function o(){if(!x.isReady){try{r.doScroll("left")}catch(e){return setTimeout(o,50)}_(),x.ready()}}()}return n.promise(t)},x.each("Boolean Number String Function Array Date RegExp Object Error".split(" "),function(e,t){c["[object "+t+"]"]=t.toLowerCase()});function M(e){var t=e.length,n=x.type(e);return x.isWindow(e)?!1:1===e.nodeType&&t?!0:"array"===n||"function"!==n&&(0===t||"number"==typeof t&&t>0&&t-1 in e)}r=x(a),function(e,t){var n,r,i,o,a,s,l,u,c,p,f,d,h,g,m,y,v,b="sizzle"+-new Date,w=e.document,T=0,C=0,N=st(),k=st(),E=st(),S=!1,A=function(e,t){return e===t?(S=!0,0):0},j=typeof t,D=1<<31,L={}.hasOwnProperty,H=[],q=H.pop,_=H.push,M=H.push,O=H.slice,F=H.indexOf||function(e){var t=0,n=this.length;for(;n>t;t++)if(this[t]===e)return t;return-1},B="checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",P="[\\x20\\t\\r\\n\\f]",R="(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",W=R.replace("w","w#"),$="\\["+P+"*("+R+")"+P+"*(?:([*^$|!~]?=)"+P+"*(?:(['\"])((?:\\\\.|[^\\\\])*?)\\3|("+W+")|)|)"+P+"*\\]",I=":("+R+")(?:\\(((['\"])((?:\\\\.|[^\\\\])*?)\\3|((?:\\\\.|[^\\\\()[\\]]|"+$.replace(3,8)+")*)|.*)\\)|)",z=RegExp("^"+P+"+|((?:^|[^\\\\])(?:\\\\.)*)"+P+"+$","g"),X=RegExp("^"+P+"*,"+P+"*"),U=RegExp("^"+P+"*([>+~]|"+P+")"+P+"*"),V=RegExp(P+"*[+~]"),Y=RegExp("="+P+"*([^\\]'\"]*)"+P+"*\\]","g"),J=RegExp(I),G=RegExp("^"+W+"$"),Q={ID:RegExp("^#("+R+")"),CLASS:RegExp("^\\.("+R+")"),TAG:RegExp("^("+R.replace("w","w*")+")"),ATTR:RegExp("^"+$),PSEUDO:RegExp("^"+I),CHILD:RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+P+"*(even|odd|(([+-]|)(\\d*)n|)"+P+"*(?:([+-]|)"+P+"*(\\d+)|))"+P+"*\\)|)","i"),bool:RegExp("^(?:"+B+")$","i"),needsContext:RegExp("^"+P+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+P+"*((?:-\\d)?\\d*)"+P+"*\\)|)(?=[^-]|$)","i")},K=/^[^{]+\{\s*\[native \w/,Z=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,et=/^(?:input|select|textarea|button)$/i,tt=/^h\d$/i,nt=/'|\\/g,rt=RegExp("\\\\([\\da-f]{1,6}"+P+"?|("+P+")|.)","ig"),it=function(e,t,n){var r="0x"+t-65536;return r!==r||n?t:0>r?String.fromCharCode(r+65536):String.fromCharCode(55296|r>>10,56320|1023&r)};try{M.apply(H=O.call(w.childNodes),w.childNodes),H[w.childNodes.length].nodeType}catch(ot){M={apply:H.length?function(e,t){_.apply(e,O.call(t))}:function(e,t){var n=e.length,r=0;while(e[n++]=t[r++]);e.length=n-1}}}function at(e,t,n,i){var o,a,s,l,u,c,d,m,y,x;if((t?t.ownerDocument||t:w)!==f&&p(t),t=t||f,n=n||[],!e||"string"!=typeof e)return n;if(1!==(l=t.nodeType)&&9!==l)return[];if(h&&!i){if(o=Z.exec(e))if(s=o[1]){if(9===l){if(a=t.getElementById(s),!a||!a.parentNode)return n;if(a.id===s)return n.push(a),n}else if(t.ownerDocument&&(a=t.ownerDocument.getElementById(s))&&v(t,a)&&a.id===s)return n.push(a),n}else{if(o[2])return M.apply(n,t.getElementsByTagName(e)),n;if((s=o[3])&&r.getElementsByClassName&&t.getElementsByClassName)return M.apply(n,t.getElementsByClassName(s)),n}if(r.qsa&&(!g||!g.test(e))){if(m=d=b,y=t,x=9===l&&e,1===l&&"object"!==t.nodeName.toLowerCase()){c=mt(e),(d=t.getAttribute("id"))?m=d.replace(nt,"\\$&"):t.setAttribute("id",m),m="[id='"+m+"'] ",u=c.length;while(u--)c[u]=m+yt(c[u]);y=V.test(e)&&t.parentNode||t,x=c.join(",")}if(x)try{return M.apply(n,y.querySelectorAll(x)),n}catch(T){}finally{d||t.removeAttribute("id")}}}return kt(e.replace(z,"$1"),t,n,i)}function st(){var e=[];function t(n,r){return e.push(n+=" ")>o.cacheLength&&delete t[e.shift()],t[n]=r}return t}function lt(e){return e[b]=!0,e}function ut(e){var t=f.createElement("div");try{return!!e(t)}catch(n){return!1}finally{t.parentNode&&t.parentNode.removeChild(t),t=null}}function ct(e,t){var n=e.split("|"),r=e.length;while(r--)o.attrHandle[n[r]]=t}function pt(e,t){var n=t&&e,r=n&&1===e.nodeType&&1===t.nodeType&&(~t.sourceIndex||D)-(~e.sourceIndex||D);if(r)return r;if(n)while(n=n.nextSibling)if(n===t)return-1;return e?1:-1}function ft(e){return function(t){var n=t.nodeName.toLowerCase();return"input"===n&&t.type===e}}function dt(e){return function(t){var n=t.nodeName.toLowerCase();return("input"===n||"button"===n)&&t.type===e}}function ht(e){return lt(function(t){return t=+t,lt(function(n,r){var i,o=e([],n.length,t),a=o.length;while(a--)n[i=o[a]]&&(n[i]=!(r[i]=n[i]))})})}s=at.isXML=function(e){var t=e&&(e.ownerDocument||e).documentElement;return t?"HTML"!==t.nodeName:!1},r=at.support={},p=at.setDocument=function(e){var n=e?e.ownerDocument||e:w,i=n.defaultView;return n!==f&&9===n.nodeType&&n.documentElement?(f=n,d=n.documentElement,h=!s(n),i&&i.attachEvent&&i!==i.top&&i.attachEvent("onbeforeunload",function(){p()}),r.attributes=ut(function(e){return e.className="i",!e.getAttribute("className")}),r.getElementsByTagName=ut(function(e){return e.appendChild(n.createComment("")),!e.getElementsByTagName("*").length}),r.getElementsByClassName=ut(function(e){return e.innerHTML="
    ",e.firstChild.className="i",2===e.getElementsByClassName("i").length}),r.getById=ut(function(e){return d.appendChild(e).id=b,!n.getElementsByName||!n.getElementsByName(b).length}),r.getById?(o.find.ID=function(e,t){if(typeof t.getElementById!==j&&h){var n=t.getElementById(e);return n&&n.parentNode?[n]:[]}},o.filter.ID=function(e){var t=e.replace(rt,it);return function(e){return e.getAttribute("id")===t}}):(delete o.find.ID,o.filter.ID=function(e){var t=e.replace(rt,it);return function(e){var n=typeof e.getAttributeNode!==j&&e.getAttributeNode("id");return n&&n.value===t}}),o.find.TAG=r.getElementsByTagName?function(e,n){return typeof n.getElementsByTagName!==j?n.getElementsByTagName(e):t}:function(e,t){var n,r=[],i=0,o=t.getElementsByTagName(e);if("*"===e){while(n=o[i++])1===n.nodeType&&r.push(n);return r}return o},o.find.CLASS=r.getElementsByClassName&&function(e,n){return typeof n.getElementsByClassName!==j&&h?n.getElementsByClassName(e):t},m=[],g=[],(r.qsa=K.test(n.querySelectorAll))&&(ut(function(e){e.innerHTML="",e.querySelectorAll("[selected]").length||g.push("\\["+P+"*(?:value|"+B+")"),e.querySelectorAll(":checked").length||g.push(":checked")}),ut(function(e){var t=n.createElement("input");t.setAttribute("type","hidden"),e.appendChild(t).setAttribute("t",""),e.querySelectorAll("[t^='']").length&&g.push("[*^$]="+P+"*(?:''|\"\")"),e.querySelectorAll(":enabled").length||g.push(":enabled",":disabled"),e.querySelectorAll("*,:x"),g.push(",.*:")})),(r.matchesSelector=K.test(y=d.webkitMatchesSelector||d.mozMatchesSelector||d.oMatchesSelector||d.msMatchesSelector))&&ut(function(e){r.disconnectedMatch=y.call(e,"div"),y.call(e,"[s!='']:x"),m.push("!=",I)}),g=g.length&&RegExp(g.join("|")),m=m.length&&RegExp(m.join("|")),v=K.test(d.contains)||d.compareDocumentPosition?function(e,t){var n=9===e.nodeType?e.documentElement:e,r=t&&t.parentNode;return e===r||!(!r||1!==r.nodeType||!(n.contains?n.contains(r):e.compareDocumentPosition&&16&e.compareDocumentPosition(r)))}:function(e,t){if(t)while(t=t.parentNode)if(t===e)return!0;return!1},A=d.compareDocumentPosition?function(e,t){if(e===t)return S=!0,0;var i=t.compareDocumentPosition&&e.compareDocumentPosition&&e.compareDocumentPosition(t);return i?1&i||!r.sortDetached&&t.compareDocumentPosition(e)===i?e===n||v(w,e)?-1:t===n||v(w,t)?1:c?F.call(c,e)-F.call(c,t):0:4&i?-1:1:e.compareDocumentPosition?-1:1}:function(e,t){var r,i=0,o=e.parentNode,a=t.parentNode,s=[e],l=[t];if(e===t)return S=!0,0;if(!o||!a)return e===n?-1:t===n?1:o?-1:a?1:c?F.call(c,e)-F.call(c,t):0;if(o===a)return pt(e,t);r=e;while(r=r.parentNode)s.unshift(r);r=t;while(r=r.parentNode)l.unshift(r);while(s[i]===l[i])i++;return i?pt(s[i],l[i]):s[i]===w?-1:l[i]===w?1:0},n):f},at.matches=function(e,t){return at(e,null,null,t)},at.matchesSelector=function(e,t){if((e.ownerDocument||e)!==f&&p(e),t=t.replace(Y,"='$1']"),!(!r.matchesSelector||!h||m&&m.test(t)||g&&g.test(t)))try{var n=y.call(e,t);if(n||r.disconnectedMatch||e.document&&11!==e.document.nodeType)return n}catch(i){}return at(t,f,null,[e]).length>0},at.contains=function(e,t){return(e.ownerDocument||e)!==f&&p(e),v(e,t)},at.attr=function(e,n){(e.ownerDocument||e)!==f&&p(e);var i=o.attrHandle[n.toLowerCase()],a=i&&L.call(o.attrHandle,n.toLowerCase())?i(e,n,!h):t;return a===t?r.attributes||!h?e.getAttribute(n):(a=e.getAttributeNode(n))&&a.specified?a.value:null:a},at.error=function(e){throw Error("Syntax error, unrecognized expression: "+e)},at.uniqueSort=function(e){var t,n=[],i=0,o=0;if(S=!r.detectDuplicates,c=!r.sortStable&&e.slice(0),e.sort(A),S){while(t=e[o++])t===e[o]&&(i=n.push(o));while(i--)e.splice(n[i],1)}return e},a=at.getText=function(e){var t,n="",r=0,i=e.nodeType;if(i){if(1===i||9===i||11===i){if("string"==typeof e.textContent)return e.textContent;for(e=e.firstChild;e;e=e.nextSibling)n+=a(e)}else if(3===i||4===i)return e.nodeValue}else for(;t=e[r];r++)n+=a(t);return n},o=at.selectors={cacheLength:50,createPseudo:lt,match:Q,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(rt,it),e[3]=(e[4]||e[5]||"").replace(rt,it),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||at.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&at.error(e[0]),e},PSEUDO:function(e){var n,r=!e[5]&&e[2];return Q.CHILD.test(e[0])?null:(e[3]&&e[4]!==t?e[2]=e[4]:r&&J.test(r)&&(n=mt(r,!0))&&(n=r.indexOf(")",r.length-n)-r.length)&&(e[0]=e[0].slice(0,n),e[2]=r.slice(0,n)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(rt,it).toLowerCase();return"*"===e?function(){return!0}:function(e){return e.nodeName&&e.nodeName.toLowerCase()===t}},CLASS:function(e){var t=N[e+" "];return t||(t=RegExp("(^|"+P+")"+e+"("+P+"|$)"))&&N(e,function(e){return t.test("string"==typeof e.className&&e.className||typeof e.getAttribute!==j&&e.getAttribute("class")||"")})},ATTR:function(e,t,n){return function(r){var i=at.attr(r,e);return null==i?"!="===t:t?(i+="","="===t?i===n:"!="===t?i!==n:"^="===t?n&&0===i.indexOf(n):"*="===t?n&&i.indexOf(n)>-1:"$="===t?n&&i.slice(-n.length)===n:"~="===t?(" "+i+" ").indexOf(n)>-1:"|="===t?i===n||i.slice(0,n.length+1)===n+"-":!1):!0}},CHILD:function(e,t,n,r,i){var o="nth"!==e.slice(0,3),a="last"!==e.slice(-4),s="of-type"===t;return 1===r&&0===i?function(e){return!!e.parentNode}:function(t,n,l){var u,c,p,f,d,h,g=o!==a?"nextSibling":"previousSibling",m=t.parentNode,y=s&&t.nodeName.toLowerCase(),v=!l&&!s;if(m){if(o){while(g){p=t;while(p=p[g])if(s?p.nodeName.toLowerCase()===y:1===p.nodeType)return!1;h=g="only"===e&&!h&&"nextSibling"}return!0}if(h=[a?m.firstChild:m.lastChild],a&&v){c=m[b]||(m[b]={}),u=c[e]||[],d=u[0]===T&&u[1],f=u[0]===T&&u[2],p=d&&m.childNodes[d];while(p=++d&&p&&p[g]||(f=d=0)||h.pop())if(1===p.nodeType&&++f&&p===t){c[e]=[T,d,f];break}}else if(v&&(u=(t[b]||(t[b]={}))[e])&&u[0]===T)f=u[1];else while(p=++d&&p&&p[g]||(f=d=0)||h.pop())if((s?p.nodeName.toLowerCase()===y:1===p.nodeType)&&++f&&(v&&((p[b]||(p[b]={}))[e]=[T,f]),p===t))break;return f-=i,f===r||0===f%r&&f/r>=0}}},PSEUDO:function(e,t){var n,r=o.pseudos[e]||o.setFilters[e.toLowerCase()]||at.error("unsupported pseudo: "+e);return r[b]?r(t):r.length>1?(n=[e,e,"",t],o.setFilters.hasOwnProperty(e.toLowerCase())?lt(function(e,n){var i,o=r(e,t),a=o.length;while(a--)i=F.call(e,o[a]),e[i]=!(n[i]=o[a])}):function(e){return r(e,0,n)}):r}},pseudos:{not:lt(function(e){var t=[],n=[],r=l(e.replace(z,"$1"));return r[b]?lt(function(e,t,n,i){var o,a=r(e,null,i,[]),s=e.length;while(s--)(o=a[s])&&(e[s]=!(t[s]=o))}):function(e,i,o){return t[0]=e,r(t,null,o,n),!n.pop()}}),has:lt(function(e){return function(t){return at(e,t).length>0}}),contains:lt(function(e){return function(t){return(t.textContent||t.innerText||a(t)).indexOf(e)>-1}}),lang:lt(function(e){return G.test(e||"")||at.error("unsupported lang: "+e),e=e.replace(rt,it).toLowerCase(),function(t){var n;do if(n=h?t.lang:t.getAttribute("xml:lang")||t.getAttribute("lang"))return n=n.toLowerCase(),n===e||0===n.indexOf(e+"-");while((t=t.parentNode)&&1===t.nodeType);return!1}}),target:function(t){var n=e.location&&e.location.hash;return n&&n.slice(1)===t.id},root:function(e){return e===d},focus:function(e){return e===f.activeElement&&(!f.hasFocus||f.hasFocus())&&!!(e.type||e.href||~e.tabIndex)},enabled:function(e){return e.disabled===!1},disabled:function(e){return e.disabled===!0},checked:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&!!e.checked||"option"===t&&!!e.selected},selected:function(e){return e.parentNode&&e.parentNode.selectedIndex,e.selected===!0},empty:function(e){for(e=e.firstChild;e;e=e.nextSibling)if(e.nodeName>"@"||3===e.nodeType||4===e.nodeType)return!1;return!0},parent:function(e){return!o.pseudos.empty(e)},header:function(e){return tt.test(e.nodeName)},input:function(e){return et.test(e.nodeName)},button:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&"button"===e.type||"button"===t},text:function(e){var t;return"input"===e.nodeName.toLowerCase()&&"text"===e.type&&(null==(t=e.getAttribute("type"))||t.toLowerCase()===e.type)},first:ht(function(){return[0]}),last:ht(function(e,t){return[t-1]}),eq:ht(function(e,t,n){return[0>n?n+t:n]}),even:ht(function(e,t){var n=0;for(;t>n;n+=2)e.push(n);return e}),odd:ht(function(e,t){var n=1;for(;t>n;n+=2)e.push(n);return e}),lt:ht(function(e,t,n){var r=0>n?n+t:n;for(;--r>=0;)e.push(r);return e}),gt:ht(function(e,t,n){var r=0>n?n+t:n;for(;t>++r;)e.push(r);return e})}},o.pseudos.nth=o.pseudos.eq;for(n in{radio:!0,checkbox:!0,file:!0,password:!0,image:!0})o.pseudos[n]=ft(n);for(n in{submit:!0,reset:!0})o.pseudos[n]=dt(n);function gt(){}gt.prototype=o.filters=o.pseudos,o.setFilters=new gt;function mt(e,t){var n,r,i,a,s,l,u,c=k[e+" "];if(c)return t?0:c.slice(0);s=e,l=[],u=o.preFilter;while(s){(!n||(r=X.exec(s)))&&(r&&(s=s.slice(r[0].length)||s),l.push(i=[])),n=!1,(r=U.exec(s))&&(n=r.shift(),i.push({value:n,type:r[0].replace(z," ")}),s=s.slice(n.length));for(a in o.filter)!(r=Q[a].exec(s))||u[a]&&!(r=u[a](r))||(n=r.shift(),i.push({value:n,type:a,matches:r}),s=s.slice(n.length));if(!n)break}return t?s.length:s?at.error(e):k(e,l).slice(0)}function yt(e){var t=0,n=e.length,r="";for(;n>t;t++)r+=e[t].value;return r}function vt(e,t,n){var r=t.dir,o=n&&"parentNode"===r,a=C++;return t.first?function(t,n,i){while(t=t[r])if(1===t.nodeType||o)return e(t,n,i)}:function(t,n,s){var l,u,c,p=T+" "+a;if(s){while(t=t[r])if((1===t.nodeType||o)&&e(t,n,s))return!0}else while(t=t[r])if(1===t.nodeType||o)if(c=t[b]||(t[b]={}),(u=c[r])&&u[0]===p){if((l=u[1])===!0||l===i)return l===!0}else if(u=c[r]=[p],u[1]=e(t,n,s)||i,u[1]===!0)return!0}}function bt(e){return e.length>1?function(t,n,r){var i=e.length;while(i--)if(!e[i](t,n,r))return!1;return!0}:e[0]}function xt(e,t,n,r,i){var o,a=[],s=0,l=e.length,u=null!=t;for(;l>s;s++)(o=e[s])&&(!n||n(o,r,i))&&(a.push(o),u&&t.push(s));return a}function wt(e,t,n,r,i,o){return r&&!r[b]&&(r=wt(r)),i&&!i[b]&&(i=wt(i,o)),lt(function(o,a,s,l){var u,c,p,f=[],d=[],h=a.length,g=o||Nt(t||"*",s.nodeType?[s]:s,[]),m=!e||!o&&t?g:xt(g,f,e,s,l),y=n?i||(o?e:h||r)?[]:a:m;if(n&&n(m,y,s,l),r){u=xt(y,d),r(u,[],s,l),c=u.length;while(c--)(p=u[c])&&(y[d[c]]=!(m[d[c]]=p))}if(o){if(i||e){if(i){u=[],c=y.length;while(c--)(p=y[c])&&u.push(m[c]=p);i(null,y=[],u,l)}c=y.length;while(c--)(p=y[c])&&(u=i?F.call(o,p):f[c])>-1&&(o[u]=!(a[u]=p))}}else y=xt(y===a?y.splice(h,y.length):y),i?i(null,a,y,l):M.apply(a,y)})}function Tt(e){var t,n,r,i=e.length,a=o.relative[e[0].type],s=a||o.relative[" "],l=a?1:0,c=vt(function(e){return e===t},s,!0),p=vt(function(e){return F.call(t,e)>-1},s,!0),f=[function(e,n,r){return!a&&(r||n!==u)||((t=n).nodeType?c(e,n,r):p(e,n,r))}];for(;i>l;l++)if(n=o.relative[e[l].type])f=[vt(bt(f),n)];else{if(n=o.filter[e[l].type].apply(null,e[l].matches),n[b]){for(r=++l;i>r;r++)if(o.relative[e[r].type])break;return wt(l>1&&bt(f),l>1&&yt(e.slice(0,l-1).concat({value:" "===e[l-2].type?"*":""})).replace(z,"$1"),n,r>l&&Tt(e.slice(l,r)),i>r&&Tt(e=e.slice(r)),i>r&&yt(e))}f.push(n)}return bt(f)}function Ct(e,t){var n=0,r=t.length>0,a=e.length>0,s=function(s,l,c,p,d){var h,g,m,y=[],v=0,b="0",x=s&&[],w=null!=d,C=u,N=s||a&&o.find.TAG("*",d&&l.parentNode||l),k=T+=null==C?1:Math.random()||.1;for(w&&(u=l!==f&&l,i=n);null!=(h=N[b]);b++){if(a&&h){g=0;while(m=e[g++])if(m(h,l,c)){p.push(h);break}w&&(T=k,i=++n)}r&&((h=!m&&h)&&v--,s&&x.push(h))}if(v+=b,r&&b!==v){g=0;while(m=t[g++])m(x,y,l,c);if(s){if(v>0)while(b--)x[b]||y[b]||(y[b]=q.call(p));y=xt(y)}M.apply(p,y),w&&!s&&y.length>0&&v+t.length>1&&at.uniqueSort(p)}return w&&(T=k,u=C),x};return r?lt(s):s}l=at.compile=function(e,t){var n,r=[],i=[],o=E[e+" "];if(!o){t||(t=mt(e)),n=t.length;while(n--)o=Tt(t[n]),o[b]?r.push(o):i.push(o);o=E(e,Ct(i,r))}return o};function Nt(e,t,n){var r=0,i=t.length;for(;i>r;r++)at(e,t[r],n);return n}function kt(e,t,n,i){var a,s,u,c,p,f=mt(e);if(!i&&1===f.length){if(s=f[0]=f[0].slice(0),s.length>2&&"ID"===(u=s[0]).type&&r.getById&&9===t.nodeType&&h&&o.relative[s[1].type]){if(t=(o.find.ID(u.matches[0].replace(rt,it),t)||[])[0],!t)return n;e=e.slice(s.shift().value.length)}a=Q.needsContext.test(e)?0:s.length;while(a--){if(u=s[a],o.relative[c=u.type])break;if((p=o.find[c])&&(i=p(u.matches[0].replace(rt,it),V.test(s[0].type)&&t.parentNode||t))){if(s.splice(a,1),e=i.length&&yt(s),!e)return M.apply(n,i),n;break}}}return l(e,f)(i,t,!h,n,V.test(e)),n}r.sortStable=b.split("").sort(A).join("")===b,r.detectDuplicates=S,p(),r.sortDetached=ut(function(e){return 1&e.compareDocumentPosition(f.createElement("div"))}),ut(function(e){return e.innerHTML="","#"===e.firstChild.getAttribute("href")})||ct("type|href|height|width",function(e,n,r){return r?t:e.getAttribute(n,"type"===n.toLowerCase()?1:2)}),r.attributes&&ut(function(e){return e.innerHTML="",e.firstChild.setAttribute("value",""),""===e.firstChild.getAttribute("value")})||ct("value",function(e,n,r){return r||"input"!==e.nodeName.toLowerCase()?t:e.defaultValue}),ut(function(e){return null==e.getAttribute("disabled")})||ct(B,function(e,n,r){var i;return r?t:(i=e.getAttributeNode(n))&&i.specified?i.value:e[n]===!0?n.toLowerCase():null}),x.find=at,x.expr=at.selectors,x.expr[":"]=x.expr.pseudos,x.unique=at.uniqueSort,x.text=at.getText,x.isXMLDoc=at.isXML,x.contains=at.contains}(e);var O={};function F(e){var t=O[e]={};return x.each(e.match(T)||[],function(e,n){t[n]=!0}),t}x.Callbacks=function(e){e="string"==typeof e?O[e]||F(e):x.extend({},e);var n,r,i,o,a,s,l=[],u=!e.once&&[],c=function(t){for(r=e.memory&&t,i=!0,a=s||0,s=0,o=l.length,n=!0;l&&o>a;a++)if(l[a].apply(t[0],t[1])===!1&&e.stopOnFalse){r=!1;break}n=!1,l&&(u?u.length&&c(u.shift()):r?l=[]:p.disable())},p={add:function(){if(l){var t=l.length;(function i(t){x.each(t,function(t,n){var r=x.type(n);"function"===r?e.unique&&p.has(n)||l.push(n):n&&n.length&&"string"!==r&&i(n)})})(arguments),n?o=l.length:r&&(s=t,c(r))}return this},remove:function(){return l&&x.each(arguments,function(e,t){var r;while((r=x.inArray(t,l,r))>-1)l.splice(r,1),n&&(o>=r&&o--,a>=r&&a--)}),this},has:function(e){return e?x.inArray(e,l)>-1:!(!l||!l.length)},empty:function(){return l=[],o=0,this},disable:function(){return l=u=r=t,this},disabled:function(){return!l},lock:function(){return u=t,r||p.disable(),this},locked:function(){return!u},fireWith:function(e,t){return!l||i&&!u||(t=t||[],t=[e,t.slice?t.slice():t],n?u.push(t):c(t)),this},fire:function(){return p.fireWith(this,arguments),this},fired:function(){return!!i}};return p},x.extend({Deferred:function(e){var t=[["resolve","done",x.Callbacks("once memory"),"resolved"],["reject","fail",x.Callbacks("once memory"),"rejected"],["notify","progress",x.Callbacks("memory")]],n="pending",r={state:function(){return n},always:function(){return i.done(arguments).fail(arguments),this},then:function(){var e=arguments;return x.Deferred(function(n){x.each(t,function(t,o){var a=o[0],s=x.isFunction(e[t])&&e[t];i[o[1]](function(){var e=s&&s.apply(this,arguments);e&&x.isFunction(e.promise)?e.promise().done(n.resolve).fail(n.reject).progress(n.notify):n[a+"With"](this===r?n.promise():this,s?[e]:arguments)})}),e=null}).promise()},promise:function(e){return null!=e?x.extend(e,r):r}},i={};return r.pipe=r.then,x.each(t,function(e,o){var a=o[2],s=o[3];r[o[1]]=a.add,s&&a.add(function(){n=s},t[1^e][2].disable,t[2][2].lock),i[o[0]]=function(){return i[o[0]+"With"](this===i?r:this,arguments),this},i[o[0]+"With"]=a.fireWith}),r.promise(i),e&&e.call(i,i),i},when:function(e){var t=0,n=g.call(arguments),r=n.length,i=1!==r||e&&x.isFunction(e.promise)?r:0,o=1===i?e:x.Deferred(),a=function(e,t,n){return function(r){t[e]=this,n[e]=arguments.length>1?g.call(arguments):r,n===s?o.notifyWith(t,n):--i||o.resolveWith(t,n)}},s,l,u;if(r>1)for(s=Array(r),l=Array(r),u=Array(r);r>t;t++)n[t]&&x.isFunction(n[t].promise)?n[t].promise().done(a(t,u,n)).fail(o.reject).progress(a(t,l,s)):--i;return i||o.resolveWith(u,n),o.promise()}}),x.support=function(t){var n,r,o,s,l,u,c,p,f,d=a.createElement("div");if(d.setAttribute("className","t"),d.innerHTML="
    a",n=d.getElementsByTagName("*")||[],r=d.getElementsByTagName("a")[0],!r||!r.style||!n.length)return t;s=a.createElement("select"),u=s.appendChild(a.createElement("option")),o=d.getElementsByTagName("input")[0],r.style.cssText="top:1px;float:left;opacity:.5",t.getSetAttribute="t"!==d.className,t.leadingWhitespace=3===d.firstChild.nodeType,t.tbody=!d.getElementsByTagName("tbody").length,t.htmlSerialize=!!d.getElementsByTagName("link").length,t.style=/top/.test(r.getAttribute("style")),t.hrefNormalized="/a"===r.getAttribute("href"),t.opacity=/^0.5/.test(r.style.opacity),t.cssFloat=!!r.style.cssFloat,t.checkOn=!!o.value,t.optSelected=u.selected,t.enctype=!!a.createElement("form").enctype,t.html5Clone="<:nav>"!==a.createElement("nav").cloneNode(!0).outerHTML,t.inlineBlockNeedsLayout=!1,t.shrinkWrapBlocks=!1,t.pixelPosition=!1,t.deleteExpando=!0,t.noCloneEvent=!0,t.reliableMarginRight=!0,t.boxSizingReliable=!0,o.checked=!0,t.noCloneChecked=o.cloneNode(!0).checked,s.disabled=!0,t.optDisabled=!u.disabled;try{delete d.test}catch(h){t.deleteExpando=!1}o=a.createElement("input"),o.setAttribute("value",""),t.input=""===o.getAttribute("value"),o.value="t",o.setAttribute("type","radio"),t.radioValue="t"===o.value,o.setAttribute("checked","t"),o.setAttribute("name","t"),l=a.createDocumentFragment(),l.appendChild(o),t.appendChecked=o.checked,t.checkClone=l.cloneNode(!0).cloneNode(!0).lastChild.checked,d.attachEvent&&(d.attachEvent("onclick",function(){t.noCloneEvent=!1}),d.cloneNode(!0).click());for(f in{submit:!0,change:!0,focusin:!0})d.setAttribute(c="on"+f,"t"),t[f+"Bubbles"]=c in e||d.attributes[c].expando===!1;d.style.backgroundClip="content-box",d.cloneNode(!0).style.backgroundClip="",t.clearCloneStyle="content-box"===d.style.backgroundClip;for(f in x(t))break;return t.ownLast="0"!==f,x(function(){var n,r,o,s="padding:0;margin:0;border:0;display:block;box-sizing:content-box;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;",l=a.getElementsByTagName("body")[0];l&&(n=a.createElement("div"),n.style.cssText="border:0;width:0;height:0;position:absolute;top:0;left:-9999px;margin-top:1px",l.appendChild(n).appendChild(d),d.innerHTML="
    t
    ",o=d.getElementsByTagName("td"),o[0].style.cssText="padding:0;margin:0;border:0;display:none",p=0===o[0].offsetHeight,o[0].style.display="",o[1].style.display="none",t.reliableHiddenOffsets=p&&0===o[0].offsetHeight,d.innerHTML="",d.style.cssText="box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;padding:1px;border:1px;display:block;width:4px;margin-top:1%;position:absolute;top:1%;",x.swap(l,null!=l.style.zoom?{zoom:1}:{},function(){t.boxSizing=4===d.offsetWidth}),e.getComputedStyle&&(t.pixelPosition="1%"!==(e.getComputedStyle(d,null)||{}).top,t.boxSizingReliable="4px"===(e.getComputedStyle(d,null)||{width:"4px"}).width,r=d.appendChild(a.createElement("div")),r.style.cssText=d.style.cssText=s,r.style.marginRight=r.style.width="0",d.style.width="1px",t.reliableMarginRight=!parseFloat((e.getComputedStyle(r,null)||{}).marginRight)),typeof d.style.zoom!==i&&(d.innerHTML="",d.style.cssText=s+"width:1px;padding:1px;display:inline;zoom:1",t.inlineBlockNeedsLayout=3===d.offsetWidth,d.style.display="block",d.innerHTML="
    ",d.firstChild.style.width="5px",t.shrinkWrapBlocks=3!==d.offsetWidth,t.inlineBlockNeedsLayout&&(l.style.zoom=1)),l.removeChild(n),n=d=o=r=null)}),n=s=l=u=r=o=null,t +}({});var B=/(?:\{[\s\S]*\}|\[[\s\S]*\])$/,P=/([A-Z])/g;function R(e,n,r,i){if(x.acceptData(e)){var o,a,s=x.expando,l=e.nodeType,u=l?x.cache:e,c=l?e[s]:e[s]&&s;if(c&&u[c]&&(i||u[c].data)||r!==t||"string"!=typeof n)return c||(c=l?e[s]=p.pop()||x.guid++:s),u[c]||(u[c]=l?{}:{toJSON:x.noop}),("object"==typeof n||"function"==typeof n)&&(i?u[c]=x.extend(u[c],n):u[c].data=x.extend(u[c].data,n)),a=u[c],i||(a.data||(a.data={}),a=a.data),r!==t&&(a[x.camelCase(n)]=r),"string"==typeof n?(o=a[n],null==o&&(o=a[x.camelCase(n)])):o=a,o}}function W(e,t,n){if(x.acceptData(e)){var r,i,o=e.nodeType,a=o?x.cache:e,s=o?e[x.expando]:x.expando;if(a[s]){if(t&&(r=n?a[s]:a[s].data)){x.isArray(t)?t=t.concat(x.map(t,x.camelCase)):t in r?t=[t]:(t=x.camelCase(t),t=t in r?[t]:t.split(" ")),i=t.length;while(i--)delete r[t[i]];if(n?!I(r):!x.isEmptyObject(r))return}(n||(delete a[s].data,I(a[s])))&&(o?x.cleanData([e],!0):x.support.deleteExpando||a!=a.window?delete a[s]:a[s]=null)}}}x.extend({cache:{},noData:{applet:!0,embed:!0,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"},hasData:function(e){return e=e.nodeType?x.cache[e[x.expando]]:e[x.expando],!!e&&!I(e)},data:function(e,t,n){return R(e,t,n)},removeData:function(e,t){return W(e,t)},_data:function(e,t,n){return R(e,t,n,!0)},_removeData:function(e,t){return W(e,t,!0)},acceptData:function(e){if(e.nodeType&&1!==e.nodeType&&9!==e.nodeType)return!1;var t=e.nodeName&&x.noData[e.nodeName.toLowerCase()];return!t||t!==!0&&e.getAttribute("classid")===t}}),x.fn.extend({data:function(e,n){var r,i,o=null,a=0,s=this[0];if(e===t){if(this.length&&(o=x.data(s),1===s.nodeType&&!x._data(s,"parsedAttrs"))){for(r=s.attributes;r.length>a;a++)i=r[a].name,0===i.indexOf("data-")&&(i=x.camelCase(i.slice(5)),$(s,i,o[i]));x._data(s,"parsedAttrs",!0)}return o}return"object"==typeof e?this.each(function(){x.data(this,e)}):arguments.length>1?this.each(function(){x.data(this,e,n)}):s?$(s,e,x.data(s,e)):null},removeData:function(e){return this.each(function(){x.removeData(this,e)})}});function $(e,n,r){if(r===t&&1===e.nodeType){var i="data-"+n.replace(P,"-$1").toLowerCase();if(r=e.getAttribute(i),"string"==typeof r){try{r="true"===r?!0:"false"===r?!1:"null"===r?null:+r+""===r?+r:B.test(r)?x.parseJSON(r):r}catch(o){}x.data(e,n,r)}else r=t}return r}function I(e){var t;for(t in e)if(("data"!==t||!x.isEmptyObject(e[t]))&&"toJSON"!==t)return!1;return!0}x.extend({queue:function(e,n,r){var i;return e?(n=(n||"fx")+"queue",i=x._data(e,n),r&&(!i||x.isArray(r)?i=x._data(e,n,x.makeArray(r)):i.push(r)),i||[]):t},dequeue:function(e,t){t=t||"fx";var n=x.queue(e,t),r=n.length,i=n.shift(),o=x._queueHooks(e,t),a=function(){x.dequeue(e,t)};"inprogress"===i&&(i=n.shift(),r--),i&&("fx"===t&&n.unshift("inprogress"),delete o.stop,i.call(e,a,o)),!r&&o&&o.empty.fire()},_queueHooks:function(e,t){var n=t+"queueHooks";return x._data(e,n)||x._data(e,n,{empty:x.Callbacks("once memory").add(function(){x._removeData(e,t+"queue"),x._removeData(e,n)})})}}),x.fn.extend({queue:function(e,n){var r=2;return"string"!=typeof e&&(n=e,e="fx",r--),r>arguments.length?x.queue(this[0],e):n===t?this:this.each(function(){var t=x.queue(this,e,n);x._queueHooks(this,e),"fx"===e&&"inprogress"!==t[0]&&x.dequeue(this,e)})},dequeue:function(e){return this.each(function(){x.dequeue(this,e)})},delay:function(e,t){return e=x.fx?x.fx.speeds[e]||e:e,t=t||"fx",this.queue(t,function(t,n){var r=setTimeout(t,e);n.stop=function(){clearTimeout(r)}})},clearQueue:function(e){return this.queue(e||"fx",[])},promise:function(e,n){var r,i=1,o=x.Deferred(),a=this,s=this.length,l=function(){--i||o.resolveWith(a,[a])};"string"!=typeof e&&(n=e,e=t),e=e||"fx";while(s--)r=x._data(a[s],e+"queueHooks"),r&&r.empty&&(i++,r.empty.add(l));return l(),o.promise(n)}});var z,X,U=/[\t\r\n\f]/g,V=/\r/g,Y=/^(?:input|select|textarea|button|object)$/i,J=/^(?:a|area)$/i,G=/^(?:checked|selected)$/i,Q=x.support.getSetAttribute,K=x.support.input;x.fn.extend({attr:function(e,t){return x.access(this,x.attr,e,t,arguments.length>1)},removeAttr:function(e){return this.each(function(){x.removeAttr(this,e)})},prop:function(e,t){return x.access(this,x.prop,e,t,arguments.length>1)},removeProp:function(e){return e=x.propFix[e]||e,this.each(function(){try{this[e]=t,delete this[e]}catch(n){}})},addClass:function(e){var t,n,r,i,o,a=0,s=this.length,l="string"==typeof e&&e;if(x.isFunction(e))return this.each(function(t){x(this).addClass(e.call(this,t,this.className))});if(l)for(t=(e||"").match(T)||[];s>a;a++)if(n=this[a],r=1===n.nodeType&&(n.className?(" "+n.className+" ").replace(U," "):" ")){o=0;while(i=t[o++])0>r.indexOf(" "+i+" ")&&(r+=i+" ");n.className=x.trim(r)}return this},removeClass:function(e){var t,n,r,i,o,a=0,s=this.length,l=0===arguments.length||"string"==typeof e&&e;if(x.isFunction(e))return this.each(function(t){x(this).removeClass(e.call(this,t,this.className))});if(l)for(t=(e||"").match(T)||[];s>a;a++)if(n=this[a],r=1===n.nodeType&&(n.className?(" "+n.className+" ").replace(U," "):"")){o=0;while(i=t[o++])while(r.indexOf(" "+i+" ")>=0)r=r.replace(" "+i+" "," ");n.className=e?x.trim(r):""}return this},toggleClass:function(e,t){var n=typeof e;return"boolean"==typeof t&&"string"===n?t?this.addClass(e):this.removeClass(e):x.isFunction(e)?this.each(function(n){x(this).toggleClass(e.call(this,n,this.className,t),t)}):this.each(function(){if("string"===n){var t,r=0,o=x(this),a=e.match(T)||[];while(t=a[r++])o.hasClass(t)?o.removeClass(t):o.addClass(t)}else(n===i||"boolean"===n)&&(this.className&&x._data(this,"__className__",this.className),this.className=this.className||e===!1?"":x._data(this,"__className__")||"")})},hasClass:function(e){var t=" "+e+" ",n=0,r=this.length;for(;r>n;n++)if(1===this[n].nodeType&&(" "+this[n].className+" ").replace(U," ").indexOf(t)>=0)return!0;return!1},val:function(e){var n,r,i,o=this[0];{if(arguments.length)return i=x.isFunction(e),this.each(function(n){var o;1===this.nodeType&&(o=i?e.call(this,n,x(this).val()):e,null==o?o="":"number"==typeof o?o+="":x.isArray(o)&&(o=x.map(o,function(e){return null==e?"":e+""})),r=x.valHooks[this.type]||x.valHooks[this.nodeName.toLowerCase()],r&&"set"in r&&r.set(this,o,"value")!==t||(this.value=o))});if(o)return r=x.valHooks[o.type]||x.valHooks[o.nodeName.toLowerCase()],r&&"get"in r&&(n=r.get(o,"value"))!==t?n:(n=o.value,"string"==typeof n?n.replace(V,""):null==n?"":n)}}}),x.extend({valHooks:{option:{get:function(e){var t=x.find.attr(e,"value");return null!=t?t:e.text}},select:{get:function(e){var t,n,r=e.options,i=e.selectedIndex,o="select-one"===e.type||0>i,a=o?null:[],s=o?i+1:r.length,l=0>i?s:o?i:0;for(;s>l;l++)if(n=r[l],!(!n.selected&&l!==i||(x.support.optDisabled?n.disabled:null!==n.getAttribute("disabled"))||n.parentNode.disabled&&x.nodeName(n.parentNode,"optgroup"))){if(t=x(n).val(),o)return t;a.push(t)}return a},set:function(e,t){var n,r,i=e.options,o=x.makeArray(t),a=i.length;while(a--)r=i[a],(r.selected=x.inArray(x(r).val(),o)>=0)&&(n=!0);return n||(e.selectedIndex=-1),o}}},attr:function(e,n,r){var o,a,s=e.nodeType;if(e&&3!==s&&8!==s&&2!==s)return typeof e.getAttribute===i?x.prop(e,n,r):(1===s&&x.isXMLDoc(e)||(n=n.toLowerCase(),o=x.attrHooks[n]||(x.expr.match.bool.test(n)?X:z)),r===t?o&&"get"in o&&null!==(a=o.get(e,n))?a:(a=x.find.attr(e,n),null==a?t:a):null!==r?o&&"set"in o&&(a=o.set(e,r,n))!==t?a:(e.setAttribute(n,r+""),r):(x.removeAttr(e,n),t))},removeAttr:function(e,t){var n,r,i=0,o=t&&t.match(T);if(o&&1===e.nodeType)while(n=o[i++])r=x.propFix[n]||n,x.expr.match.bool.test(n)?K&&Q||!G.test(n)?e[r]=!1:e[x.camelCase("default-"+n)]=e[r]=!1:x.attr(e,n,""),e.removeAttribute(Q?n:r)},attrHooks:{type:{set:function(e,t){if(!x.support.radioValue&&"radio"===t&&x.nodeName(e,"input")){var n=e.value;return e.setAttribute("type",t),n&&(e.value=n),t}}}},propFix:{"for":"htmlFor","class":"className"},prop:function(e,n,r){var i,o,a,s=e.nodeType;if(e&&3!==s&&8!==s&&2!==s)return a=1!==s||!x.isXMLDoc(e),a&&(n=x.propFix[n]||n,o=x.propHooks[n]),r!==t?o&&"set"in o&&(i=o.set(e,r,n))!==t?i:e[n]=r:o&&"get"in o&&null!==(i=o.get(e,n))?i:e[n]},propHooks:{tabIndex:{get:function(e){var t=x.find.attr(e,"tabindex");return t?parseInt(t,10):Y.test(e.nodeName)||J.test(e.nodeName)&&e.href?0:-1}}}}),X={set:function(e,t,n){return t===!1?x.removeAttr(e,n):K&&Q||!G.test(n)?e.setAttribute(!Q&&x.propFix[n]||n,n):e[x.camelCase("default-"+n)]=e[n]=!0,n}},x.each(x.expr.match.bool.source.match(/\w+/g),function(e,n){var r=x.expr.attrHandle[n]||x.find.attr;x.expr.attrHandle[n]=K&&Q||!G.test(n)?function(e,n,i){var o=x.expr.attrHandle[n],a=i?t:(x.expr.attrHandle[n]=t)!=r(e,n,i)?n.toLowerCase():null;return x.expr.attrHandle[n]=o,a}:function(e,n,r){return r?t:e[x.camelCase("default-"+n)]?n.toLowerCase():null}}),K&&Q||(x.attrHooks.value={set:function(e,n,r){return x.nodeName(e,"input")?(e.defaultValue=n,t):z&&z.set(e,n,r)}}),Q||(z={set:function(e,n,r){var i=e.getAttributeNode(r);return i||e.setAttributeNode(i=e.ownerDocument.createAttribute(r)),i.value=n+="","value"===r||n===e.getAttribute(r)?n:t}},x.expr.attrHandle.id=x.expr.attrHandle.name=x.expr.attrHandle.coords=function(e,n,r){var i;return r?t:(i=e.getAttributeNode(n))&&""!==i.value?i.value:null},x.valHooks.button={get:function(e,n){var r=e.getAttributeNode(n);return r&&r.specified?r.value:t},set:z.set},x.attrHooks.contenteditable={set:function(e,t,n){z.set(e,""===t?!1:t,n)}},x.each(["width","height"],function(e,n){x.attrHooks[n]={set:function(e,r){return""===r?(e.setAttribute(n,"auto"),r):t}}})),x.support.hrefNormalized||x.each(["href","src"],function(e,t){x.propHooks[t]={get:function(e){return e.getAttribute(t,4)}}}),x.support.style||(x.attrHooks.style={get:function(e){return e.style.cssText||t},set:function(e,t){return e.style.cssText=t+""}}),x.support.optSelected||(x.propHooks.selected={get:function(e){var t=e.parentNode;return t&&(t.selectedIndex,t.parentNode&&t.parentNode.selectedIndex),null}}),x.each(["tabIndex","readOnly","maxLength","cellSpacing","cellPadding","rowSpan","colSpan","useMap","frameBorder","contentEditable"],function(){x.propFix[this.toLowerCase()]=this}),x.support.enctype||(x.propFix.enctype="encoding"),x.each(["radio","checkbox"],function(){x.valHooks[this]={set:function(e,n){return x.isArray(n)?e.checked=x.inArray(x(e).val(),n)>=0:t}},x.support.checkOn||(x.valHooks[this].get=function(e){return null===e.getAttribute("value")?"on":e.value})});var Z=/^(?:input|select|textarea)$/i,et=/^key/,tt=/^(?:mouse|contextmenu)|click/,nt=/^(?:focusinfocus|focusoutblur)$/,rt=/^([^.]*)(?:\.(.+)|)$/;function it(){return!0}function ot(){return!1}function at(){try{return a.activeElement}catch(e){}}x.event={global:{},add:function(e,n,r,o,a){var s,l,u,c,p,f,d,h,g,m,y,v=x._data(e);if(v){r.handler&&(c=r,r=c.handler,a=c.selector),r.guid||(r.guid=x.guid++),(l=v.events)||(l=v.events={}),(f=v.handle)||(f=v.handle=function(e){return typeof x===i||e&&x.event.triggered===e.type?t:x.event.dispatch.apply(f.elem,arguments)},f.elem=e),n=(n||"").match(T)||[""],u=n.length;while(u--)s=rt.exec(n[u])||[],g=y=s[1],m=(s[2]||"").split(".").sort(),g&&(p=x.event.special[g]||{},g=(a?p.delegateType:p.bindType)||g,p=x.event.special[g]||{},d=x.extend({type:g,origType:y,data:o,handler:r,guid:r.guid,selector:a,needsContext:a&&x.expr.match.needsContext.test(a),namespace:m.join(".")},c),(h=l[g])||(h=l[g]=[],h.delegateCount=0,p.setup&&p.setup.call(e,o,m,f)!==!1||(e.addEventListener?e.addEventListener(g,f,!1):e.attachEvent&&e.attachEvent("on"+g,f))),p.add&&(p.add.call(e,d),d.handler.guid||(d.handler.guid=r.guid)),a?h.splice(h.delegateCount++,0,d):h.push(d),x.event.global[g]=!0);e=null}},remove:function(e,t,n,r,i){var o,a,s,l,u,c,p,f,d,h,g,m=x.hasData(e)&&x._data(e);if(m&&(c=m.events)){t=(t||"").match(T)||[""],u=t.length;while(u--)if(s=rt.exec(t[u])||[],d=g=s[1],h=(s[2]||"").split(".").sort(),d){p=x.event.special[d]||{},d=(r?p.delegateType:p.bindType)||d,f=c[d]||[],s=s[2]&&RegExp("(^|\\.)"+h.join("\\.(?:.*\\.|)")+"(\\.|$)"),l=o=f.length;while(o--)a=f[o],!i&&g!==a.origType||n&&n.guid!==a.guid||s&&!s.test(a.namespace)||r&&r!==a.selector&&("**"!==r||!a.selector)||(f.splice(o,1),a.selector&&f.delegateCount--,p.remove&&p.remove.call(e,a));l&&!f.length&&(p.teardown&&p.teardown.call(e,h,m.handle)!==!1||x.removeEvent(e,d,m.handle),delete c[d])}else for(d in c)x.event.remove(e,d+t[u],n,r,!0);x.isEmptyObject(c)&&(delete m.handle,x._removeData(e,"events"))}},trigger:function(n,r,i,o){var s,l,u,c,p,f,d,h=[i||a],g=v.call(n,"type")?n.type:n,m=v.call(n,"namespace")?n.namespace.split("."):[];if(u=f=i=i||a,3!==i.nodeType&&8!==i.nodeType&&!nt.test(g+x.event.triggered)&&(g.indexOf(".")>=0&&(m=g.split("."),g=m.shift(),m.sort()),l=0>g.indexOf(":")&&"on"+g,n=n[x.expando]?n:new x.Event(g,"object"==typeof n&&n),n.isTrigger=o?2:3,n.namespace=m.join("."),n.namespace_re=n.namespace?RegExp("(^|\\.)"+m.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,n.result=t,n.target||(n.target=i),r=null==r?[n]:x.makeArray(r,[n]),p=x.event.special[g]||{},o||!p.trigger||p.trigger.apply(i,r)!==!1)){if(!o&&!p.noBubble&&!x.isWindow(i)){for(c=p.delegateType||g,nt.test(c+g)||(u=u.parentNode);u;u=u.parentNode)h.push(u),f=u;f===(i.ownerDocument||a)&&h.push(f.defaultView||f.parentWindow||e)}d=0;while((u=h[d++])&&!n.isPropagationStopped())n.type=d>1?c:p.bindType||g,s=(x._data(u,"events")||{})[n.type]&&x._data(u,"handle"),s&&s.apply(u,r),s=l&&u[l],s&&x.acceptData(u)&&s.apply&&s.apply(u,r)===!1&&n.preventDefault();if(n.type=g,!o&&!n.isDefaultPrevented()&&(!p._default||p._default.apply(h.pop(),r)===!1)&&x.acceptData(i)&&l&&i[g]&&!x.isWindow(i)){f=i[l],f&&(i[l]=null),x.event.triggered=g;try{i[g]()}catch(y){}x.event.triggered=t,f&&(i[l]=f)}return n.result}},dispatch:function(e){e=x.event.fix(e);var n,r,i,o,a,s=[],l=g.call(arguments),u=(x._data(this,"events")||{})[e.type]||[],c=x.event.special[e.type]||{};if(l[0]=e,e.delegateTarget=this,!c.preDispatch||c.preDispatch.call(this,e)!==!1){s=x.event.handlers.call(this,e,u),n=0;while((o=s[n++])&&!e.isPropagationStopped()){e.currentTarget=o.elem,a=0;while((i=o.handlers[a++])&&!e.isImmediatePropagationStopped())(!e.namespace_re||e.namespace_re.test(i.namespace))&&(e.handleObj=i,e.data=i.data,r=((x.event.special[i.origType]||{}).handle||i.handler).apply(o.elem,l),r!==t&&(e.result=r)===!1&&(e.preventDefault(),e.stopPropagation()))}return c.postDispatch&&c.postDispatch.call(this,e),e.result}},handlers:function(e,n){var r,i,o,a,s=[],l=n.delegateCount,u=e.target;if(l&&u.nodeType&&(!e.button||"click"!==e.type))for(;u!=this;u=u.parentNode||this)if(1===u.nodeType&&(u.disabled!==!0||"click"!==e.type)){for(o=[],a=0;l>a;a++)i=n[a],r=i.selector+" ",o[r]===t&&(o[r]=i.needsContext?x(r,this).index(u)>=0:x.find(r,this,null,[u]).length),o[r]&&o.push(i);o.length&&s.push({elem:u,handlers:o})}return n.length>l&&s.push({elem:this,handlers:n.slice(l)}),s},fix:function(e){if(e[x.expando])return e;var t,n,r,i=e.type,o=e,s=this.fixHooks[i];s||(this.fixHooks[i]=s=tt.test(i)?this.mouseHooks:et.test(i)?this.keyHooks:{}),r=s.props?this.props.concat(s.props):this.props,e=new x.Event(o),t=r.length;while(t--)n=r[t],e[n]=o[n];return e.target||(e.target=o.srcElement||a),3===e.target.nodeType&&(e.target=e.target.parentNode),e.metaKey=!!e.metaKey,s.filter?s.filter(e,o):e},props:"altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),fixHooks:{},keyHooks:{props:"char charCode key keyCode".split(" "),filter:function(e,t){return null==e.which&&(e.which=null!=t.charCode?t.charCode:t.keyCode),e}},mouseHooks:{props:"button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "),filter:function(e,n){var r,i,o,s=n.button,l=n.fromElement;return null==e.pageX&&null!=n.clientX&&(i=e.target.ownerDocument||a,o=i.documentElement,r=i.body,e.pageX=n.clientX+(o&&o.scrollLeft||r&&r.scrollLeft||0)-(o&&o.clientLeft||r&&r.clientLeft||0),e.pageY=n.clientY+(o&&o.scrollTop||r&&r.scrollTop||0)-(o&&o.clientTop||r&&r.clientTop||0)),!e.relatedTarget&&l&&(e.relatedTarget=l===e.target?n.toElement:l),e.which||s===t||(e.which=1&s?1:2&s?3:4&s?2:0),e}},special:{load:{noBubble:!0},focus:{trigger:function(){if(this!==at()&&this.focus)try{return this.focus(),!1}catch(e){}},delegateType:"focusin"},blur:{trigger:function(){return this===at()&&this.blur?(this.blur(),!1):t},delegateType:"focusout"},click:{trigger:function(){return x.nodeName(this,"input")&&"checkbox"===this.type&&this.click?(this.click(),!1):t},_default:function(e){return x.nodeName(e.target,"a")}},beforeunload:{postDispatch:function(e){e.result!==t&&(e.originalEvent.returnValue=e.result)}}},simulate:function(e,t,n,r){var i=x.extend(new x.Event,n,{type:e,isSimulated:!0,originalEvent:{}});r?x.event.trigger(i,null,t):x.event.dispatch.call(t,i),i.isDefaultPrevented()&&n.preventDefault()}},x.removeEvent=a.removeEventListener?function(e,t,n){e.removeEventListener&&e.removeEventListener(t,n,!1)}:function(e,t,n){var r="on"+t;e.detachEvent&&(typeof e[r]===i&&(e[r]=null),e.detachEvent(r,n))},x.Event=function(e,n){return this instanceof x.Event?(e&&e.type?(this.originalEvent=e,this.type=e.type,this.isDefaultPrevented=e.defaultPrevented||e.returnValue===!1||e.getPreventDefault&&e.getPreventDefault()?it:ot):this.type=e,n&&x.extend(this,n),this.timeStamp=e&&e.timeStamp||x.now(),this[x.expando]=!0,t):new x.Event(e,n)},x.Event.prototype={isDefaultPrevented:ot,isPropagationStopped:ot,isImmediatePropagationStopped:ot,preventDefault:function(){var e=this.originalEvent;this.isDefaultPrevented=it,e&&(e.preventDefault?e.preventDefault():e.returnValue=!1)},stopPropagation:function(){var e=this.originalEvent;this.isPropagationStopped=it,e&&(e.stopPropagation&&e.stopPropagation(),e.cancelBubble=!0)},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=it,this.stopPropagation()}},x.each({mouseenter:"mouseover",mouseleave:"mouseout"},function(e,t){x.event.special[e]={delegateType:t,bindType:t,handle:function(e){var n,r=this,i=e.relatedTarget,o=e.handleObj;return(!i||i!==r&&!x.contains(r,i))&&(e.type=o.origType,n=o.handler.apply(this,arguments),e.type=t),n}}}),x.support.submitBubbles||(x.event.special.submit={setup:function(){return x.nodeName(this,"form")?!1:(x.event.add(this,"click._submit keypress._submit",function(e){var n=e.target,r=x.nodeName(n,"input")||x.nodeName(n,"button")?n.form:t;r&&!x._data(r,"submitBubbles")&&(x.event.add(r,"submit._submit",function(e){e._submit_bubble=!0}),x._data(r,"submitBubbles",!0))}),t)},postDispatch:function(e){e._submit_bubble&&(delete e._submit_bubble,this.parentNode&&!e.isTrigger&&x.event.simulate("submit",this.parentNode,e,!0))},teardown:function(){return x.nodeName(this,"form")?!1:(x.event.remove(this,"._submit"),t)}}),x.support.changeBubbles||(x.event.special.change={setup:function(){return Z.test(this.nodeName)?(("checkbox"===this.type||"radio"===this.type)&&(x.event.add(this,"propertychange._change",function(e){"checked"===e.originalEvent.propertyName&&(this._just_changed=!0)}),x.event.add(this,"click._change",function(e){this._just_changed&&!e.isTrigger&&(this._just_changed=!1),x.event.simulate("change",this,e,!0)})),!1):(x.event.add(this,"beforeactivate._change",function(e){var t=e.target;Z.test(t.nodeName)&&!x._data(t,"changeBubbles")&&(x.event.add(t,"change._change",function(e){!this.parentNode||e.isSimulated||e.isTrigger||x.event.simulate("change",this.parentNode,e,!0)}),x._data(t,"changeBubbles",!0))}),t)},handle:function(e){var n=e.target;return this!==n||e.isSimulated||e.isTrigger||"radio"!==n.type&&"checkbox"!==n.type?e.handleObj.handler.apply(this,arguments):t},teardown:function(){return x.event.remove(this,"._change"),!Z.test(this.nodeName)}}),x.support.focusinBubbles||x.each({focus:"focusin",blur:"focusout"},function(e,t){var n=0,r=function(e){x.event.simulate(t,e.target,x.event.fix(e),!0)};x.event.special[t]={setup:function(){0===n++&&a.addEventListener(e,r,!0)},teardown:function(){0===--n&&a.removeEventListener(e,r,!0)}}}),x.fn.extend({on:function(e,n,r,i,o){var a,s;if("object"==typeof e){"string"!=typeof n&&(r=r||n,n=t);for(a in e)this.on(a,n,r,e[a],o);return this}if(null==r&&null==i?(i=n,r=n=t):null==i&&("string"==typeof n?(i=r,r=t):(i=r,r=n,n=t)),i===!1)i=ot;else if(!i)return this;return 1===o&&(s=i,i=function(e){return x().off(e),s.apply(this,arguments)},i.guid=s.guid||(s.guid=x.guid++)),this.each(function(){x.event.add(this,e,i,r,n)})},one:function(e,t,n,r){return this.on(e,t,n,r,1)},off:function(e,n,r){var i,o;if(e&&e.preventDefault&&e.handleObj)return i=e.handleObj,x(e.delegateTarget).off(i.namespace?i.origType+"."+i.namespace:i.origType,i.selector,i.handler),this;if("object"==typeof e){for(o in e)this.off(o,n,e[o]);return this}return(n===!1||"function"==typeof n)&&(r=n,n=t),r===!1&&(r=ot),this.each(function(){x.event.remove(this,e,r,n)})},trigger:function(e,t){return this.each(function(){x.event.trigger(e,t,this)})},triggerHandler:function(e,n){var r=this[0];return r?x.event.trigger(e,n,r,!0):t}});var st=/^.[^:#\[\.,]*$/,lt=/^(?:parents|prev(?:Until|All))/,ut=x.expr.match.needsContext,ct={children:!0,contents:!0,next:!0,prev:!0};x.fn.extend({find:function(e){var t,n=[],r=this,i=r.length;if("string"!=typeof e)return this.pushStack(x(e).filter(function(){for(t=0;i>t;t++)if(x.contains(r[t],this))return!0}));for(t=0;i>t;t++)x.find(e,r[t],n);return n=this.pushStack(i>1?x.unique(n):n),n.selector=this.selector?this.selector+" "+e:e,n},has:function(e){var t,n=x(e,this),r=n.length;return this.filter(function(){for(t=0;r>t;t++)if(x.contains(this,n[t]))return!0})},not:function(e){return this.pushStack(ft(this,e||[],!0))},filter:function(e){return this.pushStack(ft(this,e||[],!1))},is:function(e){return!!ft(this,"string"==typeof e&&ut.test(e)?x(e):e||[],!1).length},closest:function(e,t){var n,r=0,i=this.length,o=[],a=ut.test(e)||"string"!=typeof e?x(e,t||this.context):0;for(;i>r;r++)for(n=this[r];n&&n!==t;n=n.parentNode)if(11>n.nodeType&&(a?a.index(n)>-1:1===n.nodeType&&x.find.matchesSelector(n,e))){n=o.push(n);break}return this.pushStack(o.length>1?x.unique(o):o)},index:function(e){return e?"string"==typeof e?x.inArray(this[0],x(e)):x.inArray(e.jquery?e[0]:e,this):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(e,t){var n="string"==typeof e?x(e,t):x.makeArray(e&&e.nodeType?[e]:e),r=x.merge(this.get(),n);return this.pushStack(x.unique(r))},addBack:function(e){return this.add(null==e?this.prevObject:this.prevObject.filter(e))}});function pt(e,t){do e=e[t];while(e&&1!==e.nodeType);return e}x.each({parent:function(e){var t=e.parentNode;return t&&11!==t.nodeType?t:null},parents:function(e){return x.dir(e,"parentNode")},parentsUntil:function(e,t,n){return x.dir(e,"parentNode",n)},next:function(e){return pt(e,"nextSibling")},prev:function(e){return pt(e,"previousSibling")},nextAll:function(e){return x.dir(e,"nextSibling")},prevAll:function(e){return x.dir(e,"previousSibling")},nextUntil:function(e,t,n){return x.dir(e,"nextSibling",n)},prevUntil:function(e,t,n){return x.dir(e,"previousSibling",n)},siblings:function(e){return x.sibling((e.parentNode||{}).firstChild,e)},children:function(e){return x.sibling(e.firstChild)},contents:function(e){return x.nodeName(e,"iframe")?e.contentDocument||e.contentWindow.document:x.merge([],e.childNodes)}},function(e,t){x.fn[e]=function(n,r){var i=x.map(this,t,n);return"Until"!==e.slice(-5)&&(r=n),r&&"string"==typeof r&&(i=x.filter(r,i)),this.length>1&&(ct[e]||(i=x.unique(i)),lt.test(e)&&(i=i.reverse())),this.pushStack(i)}}),x.extend({filter:function(e,t,n){var r=t[0];return n&&(e=":not("+e+")"),1===t.length&&1===r.nodeType?x.find.matchesSelector(r,e)?[r]:[]:x.find.matches(e,x.grep(t,function(e){return 1===e.nodeType}))},dir:function(e,n,r){var i=[],o=e[n];while(o&&9!==o.nodeType&&(r===t||1!==o.nodeType||!x(o).is(r)))1===o.nodeType&&i.push(o),o=o[n];return i},sibling:function(e,t){var n=[];for(;e;e=e.nextSibling)1===e.nodeType&&e!==t&&n.push(e);return n}});function ft(e,t,n){if(x.isFunction(t))return x.grep(e,function(e,r){return!!t.call(e,r,e)!==n});if(t.nodeType)return x.grep(e,function(e){return e===t!==n});if("string"==typeof t){if(st.test(t))return x.filter(t,e,n);t=x.filter(t,e)}return x.grep(e,function(e){return x.inArray(e,t)>=0!==n})}function dt(e){var t=ht.split("|"),n=e.createDocumentFragment();if(n.createElement)while(t.length)n.createElement(t.pop());return n}var ht="abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",gt=/ jQuery\d+="(?:null|\d+)"/g,mt=RegExp("<(?:"+ht+")[\\s/>]","i"),yt=/^\s+/,vt=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,bt=/<([\w:]+)/,xt=/\s*$/g,At={option:[1,""],legend:[1,"
    ","
    "],area:[1,"",""],param:[1,"",""],thead:[1,"","
    "],tr:[2,"","
    "],col:[2,"","
    "],td:[3,"","
    "],_default:x.support.htmlSerialize?[0,"",""]:[1,"X
    ","
    "]},jt=dt(a),Dt=jt.appendChild(a.createElement("div"));At.optgroup=At.option,At.tbody=At.tfoot=At.colgroup=At.caption=At.thead,At.th=At.td,x.fn.extend({text:function(e){return x.access(this,function(e){return e===t?x.text(this):this.empty().append((this[0]&&this[0].ownerDocument||a).createTextNode(e))},null,e,arguments.length)},append:function(){return this.domManip(arguments,function(e){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var t=Lt(this,e);t.appendChild(e)}})},prepend:function(){return this.domManip(arguments,function(e){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var t=Lt(this,e);t.insertBefore(e,t.firstChild)}})},before:function(){return this.domManip(arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this)})},after:function(){return this.domManip(arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this.nextSibling)})},remove:function(e,t){var n,r=e?x.filter(e,this):this,i=0;for(;null!=(n=r[i]);i++)t||1!==n.nodeType||x.cleanData(Ft(n)),n.parentNode&&(t&&x.contains(n.ownerDocument,n)&&_t(Ft(n,"script")),n.parentNode.removeChild(n));return this},empty:function(){var e,t=0;for(;null!=(e=this[t]);t++){1===e.nodeType&&x.cleanData(Ft(e,!1));while(e.firstChild)e.removeChild(e.firstChild);e.options&&x.nodeName(e,"select")&&(e.options.length=0)}return this},clone:function(e,t){return e=null==e?!1:e,t=null==t?e:t,this.map(function(){return x.clone(this,e,t)})},html:function(e){return x.access(this,function(e){var n=this[0]||{},r=0,i=this.length;if(e===t)return 1===n.nodeType?n.innerHTML.replace(gt,""):t;if(!("string"!=typeof e||Tt.test(e)||!x.support.htmlSerialize&&mt.test(e)||!x.support.leadingWhitespace&&yt.test(e)||At[(bt.exec(e)||["",""])[1].toLowerCase()])){e=e.replace(vt,"<$1>");try{for(;i>r;r++)n=this[r]||{},1===n.nodeType&&(x.cleanData(Ft(n,!1)),n.innerHTML=e);n=0}catch(o){}}n&&this.empty().append(e)},null,e,arguments.length)},replaceWith:function(){var e=x.map(this,function(e){return[e.nextSibling,e.parentNode]}),t=0;return this.domManip(arguments,function(n){var r=e[t++],i=e[t++];i&&(r&&r.parentNode!==i&&(r=this.nextSibling),x(this).remove(),i.insertBefore(n,r))},!0),t?this:this.remove()},detach:function(e){return this.remove(e,!0)},domManip:function(e,t,n){e=d.apply([],e);var r,i,o,a,s,l,u=0,c=this.length,p=this,f=c-1,h=e[0],g=x.isFunction(h);if(g||!(1>=c||"string"!=typeof h||x.support.checkClone)&&Nt.test(h))return this.each(function(r){var i=p.eq(r);g&&(e[0]=h.call(this,r,i.html())),i.domManip(e,t,n)});if(c&&(l=x.buildFragment(e,this[0].ownerDocument,!1,!n&&this),r=l.firstChild,1===l.childNodes.length&&(l=r),r)){for(a=x.map(Ft(l,"script"),Ht),o=a.length;c>u;u++)i=l,u!==f&&(i=x.clone(i,!0,!0),o&&x.merge(a,Ft(i,"script"))),t.call(this[u],i,u);if(o)for(s=a[a.length-1].ownerDocument,x.map(a,qt),u=0;o>u;u++)i=a[u],kt.test(i.type||"")&&!x._data(i,"globalEval")&&x.contains(s,i)&&(i.src?x._evalUrl(i.src):x.globalEval((i.text||i.textContent||i.innerHTML||"").replace(St,"")));l=r=null}return this}});function Lt(e,t){return x.nodeName(e,"table")&&x.nodeName(1===t.nodeType?t:t.firstChild,"tr")?e.getElementsByTagName("tbody")[0]||e.appendChild(e.ownerDocument.createElement("tbody")):e}function Ht(e){return e.type=(null!==x.find.attr(e,"type"))+"/"+e.type,e}function qt(e){var t=Et.exec(e.type);return t?e.type=t[1]:e.removeAttribute("type"),e}function _t(e,t){var n,r=0;for(;null!=(n=e[r]);r++)x._data(n,"globalEval",!t||x._data(t[r],"globalEval"))}function Mt(e,t){if(1===t.nodeType&&x.hasData(e)){var n,r,i,o=x._data(e),a=x._data(t,o),s=o.events;if(s){delete a.handle,a.events={};for(n in s)for(r=0,i=s[n].length;i>r;r++)x.event.add(t,n,s[n][r])}a.data&&(a.data=x.extend({},a.data))}}function Ot(e,t){var n,r,i;if(1===t.nodeType){if(n=t.nodeName.toLowerCase(),!x.support.noCloneEvent&&t[x.expando]){i=x._data(t);for(r in i.events)x.removeEvent(t,r,i.handle);t.removeAttribute(x.expando)}"script"===n&&t.text!==e.text?(Ht(t).text=e.text,qt(t)):"object"===n?(t.parentNode&&(t.outerHTML=e.outerHTML),x.support.html5Clone&&e.innerHTML&&!x.trim(t.innerHTML)&&(t.innerHTML=e.innerHTML)):"input"===n&&Ct.test(e.type)?(t.defaultChecked=t.checked=e.checked,t.value!==e.value&&(t.value=e.value)):"option"===n?t.defaultSelected=t.selected=e.defaultSelected:("input"===n||"textarea"===n)&&(t.defaultValue=e.defaultValue)}}x.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(e,t){x.fn[e]=function(e){var n,r=0,i=[],o=x(e),a=o.length-1;for(;a>=r;r++)n=r===a?this:this.clone(!0),x(o[r])[t](n),h.apply(i,n.get());return this.pushStack(i)}});function Ft(e,n){var r,o,a=0,s=typeof e.getElementsByTagName!==i?e.getElementsByTagName(n||"*"):typeof e.querySelectorAll!==i?e.querySelectorAll(n||"*"):t;if(!s)for(s=[],r=e.childNodes||e;null!=(o=r[a]);a++)!n||x.nodeName(o,n)?s.push(o):x.merge(s,Ft(o,n));return n===t||n&&x.nodeName(e,n)?x.merge([e],s):s}function Bt(e){Ct.test(e.type)&&(e.defaultChecked=e.checked)}x.extend({clone:function(e,t,n){var r,i,o,a,s,l=x.contains(e.ownerDocument,e);if(x.support.html5Clone||x.isXMLDoc(e)||!mt.test("<"+e.nodeName+">")?o=e.cloneNode(!0):(Dt.innerHTML=e.outerHTML,Dt.removeChild(o=Dt.firstChild)),!(x.support.noCloneEvent&&x.support.noCloneChecked||1!==e.nodeType&&11!==e.nodeType||x.isXMLDoc(e)))for(r=Ft(o),s=Ft(e),a=0;null!=(i=s[a]);++a)r[a]&&Ot(i,r[a]);if(t)if(n)for(s=s||Ft(e),r=r||Ft(o),a=0;null!=(i=s[a]);a++)Mt(i,r[a]);else Mt(e,o);return r=Ft(o,"script"),r.length>0&&_t(r,!l&&Ft(e,"script")),r=s=i=null,o},buildFragment:function(e,t,n,r){var i,o,a,s,l,u,c,p=e.length,f=dt(t),d=[],h=0;for(;p>h;h++)if(o=e[h],o||0===o)if("object"===x.type(o))x.merge(d,o.nodeType?[o]:o);else if(wt.test(o)){s=s||f.appendChild(t.createElement("div")),l=(bt.exec(o)||["",""])[1].toLowerCase(),c=At[l]||At._default,s.innerHTML=c[1]+o.replace(vt,"<$1>")+c[2],i=c[0];while(i--)s=s.lastChild;if(!x.support.leadingWhitespace&&yt.test(o)&&d.push(t.createTextNode(yt.exec(o)[0])),!x.support.tbody){o="table"!==l||xt.test(o)?""!==c[1]||xt.test(o)?0:s:s.firstChild,i=o&&o.childNodes.length;while(i--)x.nodeName(u=o.childNodes[i],"tbody")&&!u.childNodes.length&&o.removeChild(u)}x.merge(d,s.childNodes),s.textContent="";while(s.firstChild)s.removeChild(s.firstChild);s=f.lastChild}else d.push(t.createTextNode(o));s&&f.removeChild(s),x.support.appendChecked||x.grep(Ft(d,"input"),Bt),h=0;while(o=d[h++])if((!r||-1===x.inArray(o,r))&&(a=x.contains(o.ownerDocument,o),s=Ft(f.appendChild(o),"script"),a&&_t(s),n)){i=0;while(o=s[i++])kt.test(o.type||"")&&n.push(o)}return s=null,f},cleanData:function(e,t){var n,r,o,a,s=0,l=x.expando,u=x.cache,c=x.support.deleteExpando,f=x.event.special;for(;null!=(n=e[s]);s++)if((t||x.acceptData(n))&&(o=n[l],a=o&&u[o])){if(a.events)for(r in a.events)f[r]?x.event.remove(n,r):x.removeEvent(n,r,a.handle); +u[o]&&(delete u[o],c?delete n[l]:typeof n.removeAttribute!==i?n.removeAttribute(l):n[l]=null,p.push(o))}},_evalUrl:function(e){return x.ajax({url:e,type:"GET",dataType:"script",async:!1,global:!1,"throws":!0})}}),x.fn.extend({wrapAll:function(e){if(x.isFunction(e))return this.each(function(t){x(this).wrapAll(e.call(this,t))});if(this[0]){var t=x(e,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&t.insertBefore(this[0]),t.map(function(){var e=this;while(e.firstChild&&1===e.firstChild.nodeType)e=e.firstChild;return e}).append(this)}return this},wrapInner:function(e){return x.isFunction(e)?this.each(function(t){x(this).wrapInner(e.call(this,t))}):this.each(function(){var t=x(this),n=t.contents();n.length?n.wrapAll(e):t.append(e)})},wrap:function(e){var t=x.isFunction(e);return this.each(function(n){x(this).wrapAll(t?e.call(this,n):e)})},unwrap:function(){return this.parent().each(function(){x.nodeName(this,"body")||x(this).replaceWith(this.childNodes)}).end()}});var Pt,Rt,Wt,$t=/alpha\([^)]*\)/i,It=/opacity\s*=\s*([^)]*)/,zt=/^(top|right|bottom|left)$/,Xt=/^(none|table(?!-c[ea]).+)/,Ut=/^margin/,Vt=RegExp("^("+w+")(.*)$","i"),Yt=RegExp("^("+w+")(?!px)[a-z%]+$","i"),Jt=RegExp("^([+-])=("+w+")","i"),Gt={BODY:"block"},Qt={position:"absolute",visibility:"hidden",display:"block"},Kt={letterSpacing:0,fontWeight:400},Zt=["Top","Right","Bottom","Left"],en=["Webkit","O","Moz","ms"];function tn(e,t){if(t in e)return t;var n=t.charAt(0).toUpperCase()+t.slice(1),r=t,i=en.length;while(i--)if(t=en[i]+n,t in e)return t;return r}function nn(e,t){return e=t||e,"none"===x.css(e,"display")||!x.contains(e.ownerDocument,e)}function rn(e,t){var n,r,i,o=[],a=0,s=e.length;for(;s>a;a++)r=e[a],r.style&&(o[a]=x._data(r,"olddisplay"),n=r.style.display,t?(o[a]||"none"!==n||(r.style.display=""),""===r.style.display&&nn(r)&&(o[a]=x._data(r,"olddisplay",ln(r.nodeName)))):o[a]||(i=nn(r),(n&&"none"!==n||!i)&&x._data(r,"olddisplay",i?n:x.css(r,"display"))));for(a=0;s>a;a++)r=e[a],r.style&&(t&&"none"!==r.style.display&&""!==r.style.display||(r.style.display=t?o[a]||"":"none"));return e}x.fn.extend({css:function(e,n){return x.access(this,function(e,n,r){var i,o,a={},s=0;if(x.isArray(n)){for(o=Rt(e),i=n.length;i>s;s++)a[n[s]]=x.css(e,n[s],!1,o);return a}return r!==t?x.style(e,n,r):x.css(e,n)},e,n,arguments.length>1)},show:function(){return rn(this,!0)},hide:function(){return rn(this)},toggle:function(e){return"boolean"==typeof e?e?this.show():this.hide():this.each(function(){nn(this)?x(this).show():x(this).hide()})}}),x.extend({cssHooks:{opacity:{get:function(e,t){if(t){var n=Wt(e,"opacity");return""===n?"1":n}}}},cssNumber:{columnCount:!0,fillOpacity:!0,fontWeight:!0,lineHeight:!0,opacity:!0,order:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":x.support.cssFloat?"cssFloat":"styleFloat"},style:function(e,n,r,i){if(e&&3!==e.nodeType&&8!==e.nodeType&&e.style){var o,a,s,l=x.camelCase(n),u=e.style;if(n=x.cssProps[l]||(x.cssProps[l]=tn(u,l)),s=x.cssHooks[n]||x.cssHooks[l],r===t)return s&&"get"in s&&(o=s.get(e,!1,i))!==t?o:u[n];if(a=typeof r,"string"===a&&(o=Jt.exec(r))&&(r=(o[1]+1)*o[2]+parseFloat(x.css(e,n)),a="number"),!(null==r||"number"===a&&isNaN(r)||("number"!==a||x.cssNumber[l]||(r+="px"),x.support.clearCloneStyle||""!==r||0!==n.indexOf("background")||(u[n]="inherit"),s&&"set"in s&&(r=s.set(e,r,i))===t)))try{u[n]=r}catch(c){}}},css:function(e,n,r,i){var o,a,s,l=x.camelCase(n);return n=x.cssProps[l]||(x.cssProps[l]=tn(e.style,l)),s=x.cssHooks[n]||x.cssHooks[l],s&&"get"in s&&(a=s.get(e,!0,r)),a===t&&(a=Wt(e,n,i)),"normal"===a&&n in Kt&&(a=Kt[n]),""===r||r?(o=parseFloat(a),r===!0||x.isNumeric(o)?o||0:a):a}}),e.getComputedStyle?(Rt=function(t){return e.getComputedStyle(t,null)},Wt=function(e,n,r){var i,o,a,s=r||Rt(e),l=s?s.getPropertyValue(n)||s[n]:t,u=e.style;return s&&(""!==l||x.contains(e.ownerDocument,e)||(l=x.style(e,n)),Yt.test(l)&&Ut.test(n)&&(i=u.width,o=u.minWidth,a=u.maxWidth,u.minWidth=u.maxWidth=u.width=l,l=s.width,u.width=i,u.minWidth=o,u.maxWidth=a)),l}):a.documentElement.currentStyle&&(Rt=function(e){return e.currentStyle},Wt=function(e,n,r){var i,o,a,s=r||Rt(e),l=s?s[n]:t,u=e.style;return null==l&&u&&u[n]&&(l=u[n]),Yt.test(l)&&!zt.test(n)&&(i=u.left,o=e.runtimeStyle,a=o&&o.left,a&&(o.left=e.currentStyle.left),u.left="fontSize"===n?"1em":l,l=u.pixelLeft+"px",u.left=i,a&&(o.left=a)),""===l?"auto":l});function on(e,t,n){var r=Vt.exec(t);return r?Math.max(0,r[1]-(n||0))+(r[2]||"px"):t}function an(e,t,n,r,i){var o=n===(r?"border":"content")?4:"width"===t?1:0,a=0;for(;4>o;o+=2)"margin"===n&&(a+=x.css(e,n+Zt[o],!0,i)),r?("content"===n&&(a-=x.css(e,"padding"+Zt[o],!0,i)),"margin"!==n&&(a-=x.css(e,"border"+Zt[o]+"Width",!0,i))):(a+=x.css(e,"padding"+Zt[o],!0,i),"padding"!==n&&(a+=x.css(e,"border"+Zt[o]+"Width",!0,i)));return a}function sn(e,t,n){var r=!0,i="width"===t?e.offsetWidth:e.offsetHeight,o=Rt(e),a=x.support.boxSizing&&"border-box"===x.css(e,"boxSizing",!1,o);if(0>=i||null==i){if(i=Wt(e,t,o),(0>i||null==i)&&(i=e.style[t]),Yt.test(i))return i;r=a&&(x.support.boxSizingReliable||i===e.style[t]),i=parseFloat(i)||0}return i+an(e,t,n||(a?"border":"content"),r,o)+"px"}function ln(e){var t=a,n=Gt[e];return n||(n=un(e,t),"none"!==n&&n||(Pt=(Pt||x("