aggiungo plugin mancanti da ckan 2.6. form danno ancora errore 400 - bad request

This commit is contained in:
Elia Bellavista 2024-05-22 14:42:47 +02:00
parent 94c75b28bf
commit b461d36f86
207 changed files with 86356 additions and 242 deletions

3
.env
View File

@ -78,7 +78,8 @@ NGINX_PORT=80
NGINX_SSLPORT=443
# Extensions
CKAN__PLUGINS="envvars image_view text_view recline_view datastore datapusher d4science_theme activity dcat dcat_rdf_harvester dcat_json_harvester dcat_json_interface structured_data harvest ckan_harvester spatial_metadata spatial_query"
CKAN__PLUGINS="envvars image_view text_view recline_view datastore datapusher d4science_theme dcat dcat_rdf_harvester dcat_json_harvester dcat_json_interface structured_data harvest ckan_harvester spatial_metadata spatial_query activity audio_view chained_functions datatables_view multilingual_dataset multilingual_group multilingual_tag multilingual_resource recline_grid recline_graph recline_map resource_proxy stats video_view webpage_view "
# plugin rimossi in dev: expire_api_token
CKAN__HARVEST__MQ__TYPE=redis
CKAN__HARVEST__MQ__HOSTNAME=redis
CKAN__HARVEST__MQ__PORT=6379

1
.gitignore vendored
View File

@ -1,6 +1,7 @@
# generic
.DS_Store
.vagrant
*.pyc
# code & config
_service-provider/*

View File

@ -12,9 +12,12 @@
<div class="module-content">
{% block page_primary_action %}
{% if h.check_access('package_create') %}
<div class="page_primary_action">
{{ h.snippet ('snippets/add_dataset.html', dataset_type=dataset_type) }}
</div>
{# ADDED BY FRANCESCO MANGIACRAPA, 'ADD DATASET' IS SHOWN ONLY TO USER SYSADMIN' #7188 #}
{% if c.userobj and c.userobj.sysadmin %}
<div class="page_primary_action">
{{ h.snippet ('snippets/add_dataset.html', dataset_type=dataset_type) }}
</div>
{% endif %}
{% endif %}
{% endblock %}
{% block form %}
@ -49,18 +52,21 @@
<div class="module-content">
{% block package_search_results_api_inner %}
<small>
{% set api_link = h.link_to(_('API'), h.url_for('api.get_api', ver=3)) %}
{% set api_doc_link = h.link_to(_('API Docs'), 'http://docs.ckan.org/en/{0}/api/'.format(g.ckan_doc_version)) %}
{% if g.dumps_url -%}
{% set dump_link = h.link_to(_('full {format} dump').format(format=g.dumps_format), g.dumps_url) %}
{% trans %}
You can also access this registry using the {{ api_link }} (see {{ api_doc_link }}) or download a {{ dump_link }}.
{% endtrans %}
{% else %}
{% trans %}
You can also access this registry using the {{ api_link }} (see {{ api_doc_link}}).
{% endtrans %}
{%- endif %}
{# Commented by Francesco, see Support #18126 #}
{#
{% set api_link = h.link_to(_('API'), h.url_for('api.get_api', ver=3)) %}
{% set api_doc_link = h.link_to(_('API Docs'), 'http://docs.ckan.org/en/{0}/api/'.format(g.ckan_doc_version)) %}
{% if g.dumps_url -%}
{% set dump_link = h.link_to(_('full {format} dump').format(format=g.dumps_format), g.dumps_url) %}
{% trans %}
You can also access this registry using the {{ api_link }} (see {{ api_doc_link }}) or download a {{ dump_link }}.
{% endtrans %}
{% else %}
{% trans %}
You can also access this registry using the {{ api_link }} (see {{ api_doc_link}}).
{% endtrans %}
{%- endif %}
#}
</small>
{% endblock %}
</div>
@ -72,6 +78,9 @@
{% block secondary_content %}
<div class="filters">
<div>
<!--ADDED BY FRANCESCO MANGIACRAPA-->
{% snippet "spatial/snippets/spatial_query.html" %}
<!--END ADD-->
{% for facet in facet_titles %}
{{ h.snippet('snippets/facet_list.html', title=facet_titles[facet], name=facet, search_facets=search_facets) }}
{% endfor %}

View File

@ -1,91 +1,100 @@
{#
Construct a facet module populated with links to filtered results.
name
The field name identifying the facet field, eg. "tags"
title
The title of the facet, eg. "Tags", or "Tag Cloud"
label_function
Renders the human-readable label for each facet value.
If defined, this should be a callable that accepts a `facet_item`.
eg. lambda facet_item: facet_item.display_name.upper()
By default it displays the facet item's display name, which should
usually be good enough
if_empty
A string, which if defined, and the list of possible facet items is empty,
is displayed in lieu of an empty list.
count_label
A callable which accepts an integer, and returns a string. This controls
how a facet-item's count is displayed.
extras
Extra info passed into the add/remove params to make the url
alternative_url
URL to use when building the necessary URLs, instead of the default
ones returned by url_for. Useful eg for dataset types.
hide_empty
Do not show facet if there are none, Default: false.
search_facets
Dictionary with search facets
#}
{% block facet_list %}
{% set hide_empty = hide_empty or false %}
{% with items = items or h.get_facet_items_dict(name, search_facets) %}
{% if items or not hide_empty %}
{% block facet_list_item %}
<section class="module module-narrow module-shallow">
{% block facet_list_heading %}
<h2 class="module-heading">
<i class="fa fa-filter"></i>
{{ title }}
</h2>
{% endblock %}
{% block facet_list_items %}
{% with items = items or h.get_facet_items_dict(name, search_facets) %}
{% if items %}
<nav aria-label="{{ title }}">
<ul class="list-unstyled nav nav-simple nav-facet">
{% for item in items %}
{% set href = h.remove_url_param(name, item.name, extras=extras, alternative_url=alternative_url) if item.active else h.add_url_param(new_params={name: item.name}, extras=extras, alternative_url=alternative_url) %}
{% set label = label_function(item) if label_function else item.display_name %}
{% set label_truncated = label|truncate(22) if not label_function else label %}
{% set count = count_label(item['count']) if count_label else ('%d' % item['count']) %}
<li class="nav-item {% if item.active %} active{% endif %}">
<a href="{{ href }}" title="{{ label if label != label_truncated else '' }}">
<span class="item-label">{{ label_truncated }}</span>
<span class="hidden separator"> - </span>
<span class="item-count badge">{{ count }}</span>
{% if item.active %}<span class="facet-close">x</span>{% endif %}
</a>
</li>
{% endfor %}
</ul>
</nav>
<p class="module-footer">
{% if h.get_param_int('_%s_limit' % name) %}
{% if h.has_more_facets(name, search_facets) %}
<a href="{{ h.remove_url_param('_%s_limit' % name, replace=0, extras=extras, alternative_url=alternative_url) }}" class="read-more">{{ _('Show More {facet_type}').format(facet_type=title) }}</a>
Construct a facet module populated with links to filtered results.
name
The field name identifying the facet field, eg. "tags"
title
The title of the facet, eg. "Tags", or "Tag Cloud"
label_function
Renders the human-readable label for each facet value.
If defined, this should be a callable that accepts a `facet_item`.
eg. lambda facet_item: facet_item.display_name.upper()
By default it displays the facet item's display name, which should
usually be good enough
if_empty
A string, which if defined, and the list of possible facet items is empty,
is displayed in lieu of an empty list.
count_label
A callable which accepts an integer, and returns a string. This controls
how a facet-item's count is displayed.
extras
Extra info passed into the add/remove params to make the url
alternative_url
URL to use when building the necessary URLs, instead of the default
ones returned by url_for. Useful eg for dataset types.
hide_empty
Do not show facet if there are none, Default: false.
within_tertiary
Boolean for when a facet list should appear in the the right column of the
page and not the left column.
#}
{% block facet_list %}
{% set hide_empty = hide_empty or false %}
{% with items = items or h.get_facet_items_dict(name) %}
{% if items or not hide_empty %}
{% if within_tertiary %}
{% set nav_class = 'nav nav-pills nav-stacked' %}
{% set nav_item_class = ' ' %}
{% set wrapper_class = 'nav-facet nav-facet-tertiary' %}
{% endif %}
{% block facet_list_item %}
<section class="{{ wrapper_class or 'module module-narrow module-shallow' }}">
{% block facet_list_heading %}
<h2 class="module-heading">
<i class="icon-medium icon-filter"></i>
{% set title = title or h.get_facet_title(name) %}
{{ title }}
</h2>
{% endblock %}
{% block facet_list_items %}
{% with items = items or h.get_facet_items_dict(name) %}
{% if items %}
<nav>
<ul class="{{ nav_class or 'unstyled nav nav-simple nav-facet' }}">
{% for item in items %}
{% set href = h.remove_url_param(name, item.name, extras=extras, alternative_url=alternative_url) if item.active else h.add_url_param(new_params={name: item.name}, extras=extras, alternative_url=alternative_url) %}
{% set label = label_function(item) if label_function else item.display_name %}
{# Updated by Francesco Mangiacrapa, see #11747 #}
{#
{% set label_truncated = h.truncate(label, 22) if not label_function else label %}
#}
{% set count = count_label(item['count']) if count_label else ('(%d)' % item['count']) %}
<li class="{{ nav_item_class or 'nav-item' }}{% if item.active %} active{% endif %}">
<a href="{{ href }}" title="{{ label if label != label_truncated else '' }}">
<span>{{ label }} </span><span style="font-size: 12px">{{ count }}</span>
</a>
</li>
{% endfor %}
</ul>
</nav>
<p class="module-footer">
{% if h.get_param_int('_%s_limit' % name) %}
{% if h.has_more_facets(name) %}
<a href="{{ h.remove_url_param('_%s_limit' % name, replace=0, extras=extras, alternative_url=alternative_url) }}" class="read-more">{{ _('Show More {facet_type}').format(facet_type=title) }}</a>
{% endif %}
{% else %}
<a href="{{ h.remove_url_param('_%s_limit' % name, extras=extras, alternative_url=alternative_url) }}" class="read-more">{{ _('Show Only Popular {facet_type}').format(facet_type=title) }}</a>
{% endif %}
{% else %}
<a href="{{ h.remove_url_param('_%s_limit' % name, extras=extras, alternative_url=alternative_url) }}" class="read-more">{{ _('Show Only Popular {facet_type}').format(facet_type=title) }}</a>
{% endif %}
</p>
{% else %}
<p class="module-content empty">{{ _('There are no {facet_type} that match this search').format(facet_type=title) }}</p>
{% endif %}
{% endwith %}
{% endblock %}
</section>
{% endblock %}
{% endif %}
{% endwith %}
{% endblock %}
</p>
{% else %}
<p class="module-content empty">{{ _('There are no {facet_type} that match this search').format(facet_type=title) }}</p>
{% endif %}
{% endwith %}
{% endblock %}
</section>
{% endblock %}
{% endif %}
{% endwith %}
{% endblock %}

View File

@ -1,15 +0,0 @@
{% extends "group/read_base.html" %}
{% block subtitle %}{{ _('Activity Stream') }} {{ g.template_title_delimiter }} {{ super() }}{% endblock %}
{% block primary_content_inner %}
{% if activity_types is defined %}
{% snippet 'snippets/activity_type_selector.html', id=id, activity_type=activity_type, activity_types=activity_types, blueprint='activity.group_activity' %}
{% endif %}
{% snippet 'snippets/stream.html', activity_stream=activity_stream, id=id, object_type='group' %}
{% snippet 'snippets/pagination.html', newer_activities_url=newer_activities_url, older_activities_url=older_activities_url %}
{% endblock %}

View File

@ -1,64 +0,0 @@
{% extends "group/read_base.html" %}
{% block subtitle %}{{ group_dict.name }} {{ g.template_title_delimiter }} Changes {{ g.template_title_delimiter }} {{ super() }}{% endblock %}
{% block breadcrumb_content_selected %}{% endblock %}
{% block breadcrumb_content %}
{{ super() }}
<li>{% link_for _('Changes'), named_route='activity.group_activity', id=group_dict.name %}</li>
<li class="active">{% link_for activity_diffs[0].activities[1].id|truncate(30), named_route='activity.group_changes', id=activity_diffs[0].activities[1].id %}</li>
{% endblock %}
{% block primary %}
<article class="module">
<div class="module-content">
{% block group_changes_header %}
<h1 class="page-heading">{{ _('Changes') }}</h1>
{% endblock %}
{% set select_list1 = h.activity_list_select(group_activity_list, activity_diffs[-1].activities[0].id) %}
{% set select_list2 = h.activity_list_select(group_activity_list, activity_diffs[0].activities[1].id) %}
<form id="range_form" action="{{ h.url_for('activity.group_changes_multiple') }}" data-module="select-switch" data-module-target="">
<input type="hidden" name="current_old_id" value="{{ activity_diffs[-1].activities[0].id }}">
<input type="hidden" name="current_new_id" value="{{ activity_diffs[0].activities[1].id }}">
View changes from
<select class="form-control select-time" form="range_form" name="old_id">
<pre>
{{ select_list1[1:]|join }}
</pre>
</select> to
<select class="form-control select-time" form="range_form" name="new_id">
<pre>
{{ select_list2|join }}
</pre>
</select>
</form>
<br>
{# iterate through the list of activity diffs #}
<hr>
{% for i in range(activity_diffs|length) %}
{% snippet "group/snippets/item_group.html", activity_diff=activity_diffs[i], group_dict=group_dict %}
{# TODO: display metadata for more than most recent change #}
{% if i == 0 %}
{# button to show JSON metadata diff for the most recent change - not shown by default #}
<input type="button" data-module="metadata-button" data-module-target="" class="btn" value="Show metadata diff" id="metadata_button"></input>
<div id="metadata_diff" style="display:none;">
{% block group_changes_diff %}
<pre>
{{ activity_diffs[0]['diff']|safe }}
</pre>
{% endblock %}
</div>
{% endif %}
<hr>
{% endfor %}
</div>
</article>
{% endblock %}
{% block secondary %}{% endblock %}

View File

@ -1,6 +1,36 @@
{% ckan_extends %}
{% extends "page.html" %}
{% block subtitle %}{{ c.group_dict.display_name }} - {{ _('Groups') }}{% endblock %}
{% block breadcrumb_content %}
<li>{% link_for _('Groups'), controller='group', action='index' %}</li>
<li class="active">{% link_for c.group_dict.display_name|truncate(35), controller='group', action='read', id=c.group_dict.name %}</li>
{% endblock %}
{% block content_action %}
{% if h.check_access('group_update', {'id': c.group_dict.id}) %}
{% link_for _('Manage'), controller='group', action='edit', id=c.group_dict.name, class_='btn', icon='wrench' %}
{% endif %}
{% endblock %}
{% block content_primary_nav %}
{{ h.build_nav_icon('group.read', _('Datasets'), id=c.group_dict.name) }}
<!-- Added by Francesco Mangiacrapa. see: #6572 -->
{% if h.check_access('group_update', {'id': c.group_dict.id}) %}
{% set role_for_user = h.d4science_theme_get_user_role_for_group_or_org(c.group_dict.id, c.userobj.name) %}
{% if (role_for_user and role_for_user == 'admin') or c.userobj.sysadmin %}
<!-- activity in generale sembra non essere più supportato in cakan 2.10 -->
{#{{ h.build_nav_icon('group.activity', _('Activity Stream'), id=c.group_dict.name, offset=0) }}#}
{% endif %}
{% endif %}
{{ h.build_nav_icon('group.about', _('About'), id=c.group_dict.name) }}
{% endblock %}
{% block secondary_content %}
{% snippet "group/snippets/info.html", group=c.group_dict, show_nums=true %}
{% endblock %}
{% block links %}
{{ super() }}
{{ h.build_nav_icon('activity.group_activity', _('Activity Stream'), id=group_dict.name, offset=0, icon='clock') }}
{% endblock content_primary_nav %}
{% include "group/snippets/feeds.html" %}
{% endblock %}

View File

@ -1,10 +0,0 @@
<strong>{{ gettext('On %(timestamp)s, %(username)s:', timestamp=h.render_datetime(activity_diff.activities[1].timestamp, with_hours=True, with_seconds=True), username=h.linked_user(activity_diff.activities[1].user_id)) }}</strong>
{% set changes = h.compare_group_dicts(activity_diff.activities[0].data.group, activity_diff.activities[1].data.group, activity_diff.activities[0].id) %}
<ul>
{% for change in changes %}
{% snippet "snippets/group_changes/{}.html".format(
change.type), change=change %}
<br>
{% endfor %}
</ul>

View File

@ -1,36 +0,0 @@
{% extends "page.html" %}
{% block subtitle %}{{ c.group_dict.display_name }} - {{ _('Groups') }}{% endblock %}
{% block breadcrumb_content %}
<li>{% link_for _('Groups'), controller='group', action='index' %}</li>
<li class="active">{% link_for c.group_dict.display_name|truncate(35), controller='group', action='read', id=c.group_dict.name %}</li>
{% endblock %}
{% block content_action %}
{% if h.check_access('group_update', {'id': c.group_dict.id}) %}
{% link_for _('Manage'), controller='group', action='edit', id=c.group_dict.name, class_='btn', icon='wrench' %}
{% endif %}
{% endblock %}
{% block content_primary_nav %}
{{ h.build_nav_icon('group.read', _('Datasets'), id=c.group_dict.name) }}
<!-- Added by Francesco Mangiacrapa. see: #6572 -->
{% if h.check_access('group_update', {'id': c.group_dict.id}) %}
{% set role_for_user = h.d4science_theme_get_user_role_for_group_or_org(c.group_dict.id, c.userobj.name) %}
{% if (role_for_user and role_for_user == 'admin') or c.userobj.sysadmin %}
<!-- activity in generale sembra non essere più supportato in cakan 2.10 -->
{#{{ h.build_nav_icon('group.activity', _('Activity Stream'), id=c.group_dict.name, offset=0) }}#}
{% endif %}
{% endif %}
{{ h.build_nav_icon('group.about', _('About'), id=c.group_dict.name) }}
{% endblock %}
{% block secondary_content %}
{% snippet "group/snippets/info.html", group=c.group_dict, show_nums=true %}
{% endblock %}
{% block links %}
{{ super() }}
{% include "group/snippets/feeds.html" %}
{% endblock %}

View File

@ -0,0 +1,413 @@
# encoding: utf-8
from __future__ import annotations
from ckan.types import Context
from typing import Any, cast
import ckan
import ckan.lib.navl.dictization_functions
import ckan.model
import ckan.plugins as plugins
from ckan.common import request, config, g
from ckan.logic import get_action
def translate_data_dict(data_dict: dict[str, Any]):
'''Return the given dict (e.g. a dataset dict) with as many of its fields
as possible translated into the desired or the fallback language.
'''
desired_lang_code = request.environ['CKAN_LANG']
fallback_lang_code = config.get('ckan.locale_default')
# Get a flattened copy of data_dict to do the translation on.
flattened = ckan.lib.navl.dictization_functions.flatten_dict(
data_dict)
# Get a simple flat list of all the terms to be translated, from the
# flattened data dict.
terms = set()
for (key, value) in flattened.items():
if value in (None, True, False):
continue
elif isinstance(value, str):
terms.add(value)
elif isinstance(value, int):
continue
else:
for item in value:
if isinstance(value, dict):
if key == (u'organization',) and item == 'description':
terms.add(value[item])
else:
terms.add(item)
else:
terms.add(item)
# Get the translations of all the terms (as a list of dictionaries).
translations = get_action('term_translation_show')(
cast(Context, {'model': ckan.model}),
{'terms': terms,
'lang_codes': (desired_lang_code, fallback_lang_code)})
# Transform the translations into a more convenient structure.
desired_translations = {}
fallback_translations = {}
for translation in translations:
if translation['lang_code'] == desired_lang_code:
desired_translations[translation['term']] = (
translation['term_translation'])
else:
assert translation['lang_code'] == fallback_lang_code
fallback_translations[translation['term']] = (
translation['term_translation'])
# Make a copy of the flattened data dict with all the terms replaced by
# their translations, where available.
translated_flattened = {}
for (key, value) in flattened.items():
# Don't translate names that are used for form URLs.
if key == ('name',):
translated_flattened[key] = value
elif (key[0] in ('tags', 'groups') and len(key) == 3
and key[2] == 'name'):
translated_flattened[key] = value
elif value in (None, True, False):
# Don't try to translate values that aren't strings.
translated_flattened[key] = value
elif isinstance(value, str):
if value in desired_translations:
translated_flattened[key] = desired_translations[value]
else:
translated_flattened[key] = fallback_translations.get(
value, value)
elif isinstance(value, (int, dict)):
if key == (u'organization',):
assert isinstance(value, dict)
translated_flattened[key] = translate_data_dict(value);
else:
translated_flattened[key] = value
else:
translated_value = []
for item in value:
if item in desired_translations:
translated_value.append(desired_translations[item])
else:
translated_value.append(
fallback_translations.get(item, item)
)
translated_flattened[key] = translated_value
# Finally unflatten and return the translated data dict.
translated_data_dict = (ckan.lib.navl.dictization_functions
.unflatten(translated_flattened))
return translated_data_dict
def translate_resource_data_dict(data_dict: dict[str, Any]):
'''Return the given dict with as many of its fields
as possible translated into the desired or the fallback language.
'''
desired_lang_code = request.environ['CKAN_LANG']
fallback_lang_code = config.get('ckan.locale_default')
# Get a flattened copy of data_dict to do the translation on.
flattened = ckan.lib.navl.dictization_functions.flatten_dict(
data_dict)
# Get a simple flat list of all the terms to be translated, from the
# flattened data dict.
terms = set()
for (key, value) in flattened.items():
if value in (None, True, False):
continue
elif isinstance(value, str):
terms.add(value)
elif isinstance(value, int):
continue
else:
for item in value:
terms.add(item)
# Get the translations of all the terms (as a list of dictionaries).
translations = get_action('term_translation_show')(
cast(Context, {'model': ckan.model}),
{'terms': terms,
'lang_codes': (desired_lang_code, fallback_lang_code)})
# Transform the translations into a more convenient structure.
desired_translations = {}
fallback_translations = {}
for translation in translations:
if translation['lang_code'] == desired_lang_code:
desired_translations[translation['term']] = (
translation['term_translation'])
else:
assert translation['lang_code'] == fallback_lang_code
fallback_translations[translation['term']] = (
translation['term_translation'])
# Make a copy of the flattened data dict with all the terms replaced by
# their translations, where available.
translated_flattened = {}
for (key, value) in flattened.items():
# Don't translate names that are used for form URLs.
if key == ('name',):
if value in desired_translations:
translated_flattened[key] = desired_translations[value]
elif value in fallback_translations:
translated_flattened[key] = fallback_translations.get(
value, value)
else:
translated_flattened[key] = value
elif value in (None, True, False):
# Don't try to translate values that aren't strings.
translated_flattened[key] = value
elif isinstance(value, str):
if value in desired_translations:
translated_flattened[key] = desired_translations[value]
else:
translated_flattened[key] = fallback_translations.get(
value, value)
elif isinstance(value, (int, dict)):
translated_flattened[key] = value
else:
translated_value = []
for item in value:
if item in desired_translations:
translated_value.append(desired_translations[item])
else:
translated_value.append(
fallback_translations.get(item, item)
)
translated_flattened[key] = translated_value
# Finally unflatten and return the translated data dict.
translated_data_dict = (ckan.lib.navl.dictization_functions
.unflatten(translated_flattened))
return translated_data_dict
KEYS_TO_IGNORE = ['state', 'revision_id', 'id', #title done seperately
'metadata_created', 'metadata_modified', 'site_id']
class MultilingualDataset(plugins.SingletonPlugin):
plugins.implements(plugins.IPackageController, inherit=True)
LANGS = config.get('ckan.locale_order') or ["en"]
def before_dataset_index(self, search_data: dict[str, Any]):
default_lang = search_data.get(
'lang_code',
config.get('ckan.locale_default')
)
## translate title
title = search_data.get('title')
search_data['title_' + default_lang] = title
title_translations = get_action('term_translation_show')(
cast(Context, {'model': ckan.model}),
{'terms': [title],
'lang_codes': self.LANGS})
for translation in title_translations:
title_field = 'title_' + translation['lang_code']
search_data[title_field] = translation['term_translation']
## translate rest
all_terms = []
for key, value in sorted(search_data.items()):
if key in KEYS_TO_IGNORE or key.startswith('title'):
continue
if not isinstance(value, list):
value = [value]
for item in value:
if isinstance(item, str):
all_terms.append(item)
field_translations = get_action('term_translation_show')(
cast(Context, {'model': ckan.model}),
{'terms': all_terms,
'lang_codes': self.LANGS})
text_field_items = dict(('text_' + lang, []) for lang in self.LANGS)
text_field_items['text_' + default_lang].extend(all_terms)
for translation in sorted(
field_translations,
key=lambda tr: all_terms.index(tr['term'])):
lang_field = 'text_' + translation['lang_code']
text_field_items[lang_field].append(translation['term_translation'])
for key, value in text_field_items.items():
search_data[key] = ' '.join(value)
return search_data
def before_dataset_search(self, search_params: dict[str, Any]):
lang_set = set(self.LANGS)
try:
current_lang: str = request.environ['CKAN_LANG']
except TypeError as err:
if str(err) == ('No object (name: request) has been registered '
'for this thread'):
# This happens when this code gets called as part of a paster
# command rather then as part of an HTTP request.
current_lang = config.get('ckan.locale_default')
else:
raise
except KeyError:
current_lang = config.get('ckan.locale_default')
# fallback to default locale if locale not in suported langs
if not current_lang in lang_set:
current_lang = config.get('ckan.locale_default')
# fallback to english if default locale is not supported
if not current_lang in lang_set:
current_lang = 'en'
# treat current lang differenly so remove from set
lang_set.remove(current_lang)
# weight current lang more highly
query_fields = 'title_%s^8 text_%s^4' % (current_lang, current_lang)
for lang in lang_set:
query_fields += ' title_%s^2 text_%s' % (lang, lang)
search_params['qf'] = query_fields
return search_params
def after_dataset_search(self, search_results: dict[str, Any],
search_params: dict[str, Any]):
# Translate the unselected search facets.
facets = search_results.get('search_facets')
if not facets:
return search_results
desired_lang_code = request.environ['CKAN_LANG']
fallback_lang_code = config.get('ckan.locale_default')
# Look up translations for all of the facets in one db query.
terms = set()
for facet in facets.values():
for item in facet['items']:
terms.add(item['display_name'])
translations = get_action('term_translation_show')(
cast(Context, {'model': ckan.model}),
{'terms': terms,
'lang_codes': (desired_lang_code, fallback_lang_code)})
# Replace facet display names with translated ones.
for facet in facets.values():
for item in facet['items']:
matching_translations = [translation for
translation in translations
if translation['term'] == item['display_name']
and translation['lang_code'] == desired_lang_code]
if not matching_translations:
matching_translations = [translation for
translation in translations
if translation['term'] == item['display_name']
and translation['lang_code'] == fallback_lang_code]
if matching_translations:
assert len(matching_translations) == 1
item['display_name'] = (
matching_translations[0]['term_translation'])
return search_results
def before_dataset_view(self, dataset_dict: dict[str, Any]):
# Translate any selected search facets (e.g. if we are rendering a
# group read page or the dataset index page): lookup translations of
# all the terms in c.fields (c.fields contains the selected facets)
# and save them in c.translated_fields where the templates can
# retrieve them later.
desired_lang_code = request.environ['CKAN_LANG']
fallback_lang_code = config.get('ckan.locale_default')
try:
fields = g.fields
except AttributeError:
return translate_data_dict(dataset_dict)
terms = [value for _param, value in fields]
translations = get_action('term_translation_show')(
cast(Context, {'model': ckan.model}),
{'terms': terms,
'lang_codes': (desired_lang_code, fallback_lang_code)})
g.translated_fields = {}
for param, value in fields:
matching_translations = [translation for translation in
translations if translation['term'] == value and
translation['lang_code'] == desired_lang_code]
if not matching_translations:
matching_translations = [translation for translation in
translations if translation['term'] == value and
translation['lang_code'] == fallback_lang_code]
if matching_translations:
assert len(matching_translations) == 1
translation = matching_translations[0]['term_translation']
g.translated_fields[(param, value)] = translation
# Now translate the fields of the dataset itself.
return translate_data_dict(dataset_dict)
class MultilingualGroup(plugins.SingletonPlugin):
'''The MultilingualGroup plugin translates group names and other group
fields on group read pages and on the group index page.
For example on the page /de/group/david the title "Dave's Books" at the
top of the page might be translated to "Dave's Bucher".
Datasets are also shown on group pages, but these are translated by the
MultilingualDataset plugin.
'''
plugins.implements(plugins.IGroupController, inherit=True)
plugins.implements(plugins.IOrganizationController, inherit=True)
def before_view(self, data_dict: dict[str, Any]):
translated_data_dict = translate_data_dict(data_dict)
return translated_data_dict
class MultilingualTag(plugins.SingletonPlugin):
'''The MultilingualTag plugin translates tag names on tag read pages and
on the tag index page.
For example on the page /de/tag/tolstoy the title "Tag: tolstoy" at the
top of the page might be translated to "Tag: Tolstoi".
Datasets are also shown on tag pages, but these are translated by the
MultilingualDataset plugin.
'''
plugins.implements(plugins.ITagController, inherit=True)
def before_view(self, data_dict: dict[str, Any]):
translated_data_dict = translate_data_dict(data_dict)
return translated_data_dict
class MultilingualResource(plugins.SingletonPlugin):
'''The MultilinguaResource plugin translate the selected resource name and
description on resource preview page.
'''
plugins.implements(plugins.IResourceController, inherit=True)
def before_resource_show(self, data_dict: dict[str, Any]):
translated_data_dict = translate_resource_data_dict(data_dict)
return translated_data_dict

View File

@ -0,0 +1,117 @@
| From svn.tartarus.org/snowball/trunk/website/algorithms/dutch/stop.txt
| This file is distributed under the BSD License.
| See http://snowball.tartarus.org/license.php
| Also see http://www.opensource.org/licenses/bsd-license.html
| - Encoding was converted to UTF-8.
| - This notice was added.
| A Dutch stop word list. Comments begin with vertical bar. Each stop
| word is at the start of a line.
| This is a ranked list (commonest to rarest) of stopwords derived from
| a large sample of Dutch text.
| Dutch stop words frequently exhibit homonym clashes. These are indicated
| clearly below.
de | the
en | and
van | of, from
ik | I, the ego
te | (1) chez, at etc, (2) to, (3) too
dat | that, which
die | that, those, who, which
in | in, inside
een | a, an, one
hij | he
het | the, it
niet | not, nothing, naught
zijn | (1) to be, being, (2) his, one's, its
is | is
was | (1) was, past tense of all persons sing. of 'zijn' (to be) (2) wax, (3) the washing, (4) rise of river
op | on, upon, at, in, up, used up
aan | on, upon, to (as dative)
met | with, by
als | like, such as, when
voor | (1) before, in front of, (2) furrow
had | had, past tense all persons sing. of 'hebben' (have)
er | there
maar | but, only
om | round, about, for etc
hem | him
dan | then
zou | should/would, past tense all persons sing. of 'zullen'
of | or, whether, if
wat | what, something, anything
mijn | possessive and noun 'mine'
men | people, 'one'
dit | this
zo | so, thus, in this way
door | through by
over | over, across
ze | she, her, they, them
zich | oneself
bij | (1) a bee, (2) by, near, at
ook | also, too
tot | till, until
je | you
mij | me
uit | out of, from
der | Old Dutch form of 'van der' still found in surnames
daar | (1) there, (2) because
haar | (1) her, their, them, (2) hair
naar | (1) unpleasant, unwell etc, (2) towards, (3) as
heb | present first person sing. of 'to have'
hoe | how, why
heeft | present third person sing. of 'to have'
hebben | 'to have' and various parts thereof
deze | this
u | you
want | (1) for, (2) mitten, (3) rigging
nog | yet, still
zal | 'shall', first and third person sing. of verb 'zullen' (will)
me | me
zij | she, they
nu | now
ge | 'thou', still used in Belgium and south Netherlands
geen | none
omdat | because
iets | something, somewhat
worden | to become, grow, get
toch | yet, still
al | all, every, each
waren | (1) 'were' (2) to wander, (3) wares, (3)
veel | much, many
meer | (1) more, (2) lake
doen | to do, to make
toen | then, when
moet | noun 'spot/mote' and present form of 'to must'
ben | (1) am, (2) 'are' in interrogative second person singular of 'to be'
zonder | without
kan | noun 'can' and present form of 'to be able'
hun | their, them
dus | so, consequently
alles | all, everything, anything
onder | under, beneath
ja | yes, of course
eens | once, one day
hier | here
wie | who
werd | imperfect third person sing. of 'become'
altijd | always
doch | yet, but etc
wordt | present third person sing. of 'become'
wezen | (1) to be, (2) 'been' as in 'been fishing', (3) orphans
kunnen | to be able
ons | us/our
zelf | self
tegen | against, towards, at
na | after, near
reeds | already
wil | (1) present tense of 'want', (2) 'will', noun, (3) fender
kon | could; past tense of 'to be able'
niets | nothing
uw | your
iemand | somebody
geweest | been; past participle of 'be'
andere | other

View File

@ -0,0 +1,317 @@
| From svn.tartarus.org/snowball/trunk/website/algorithms/english/stop.txt
| This file is distributed under the BSD License.
| See http://snowball.tartarus.org/license.php
| Also see http://www.opensource.org/licenses/bsd-license.html
| - Encoding was converted to UTF-8.
| - This notice was added.
| An English stop word list. Comments begin with vertical bar. Each stop
| word is at the start of a line.
| Many of the forms below are quite rare (e.g. "yourselves") but included for
| completeness.
| PRONOUNS FORMS
| 1st person sing
i | subject, always in upper case of course
me | object
my | possessive adjective
| the possessive pronoun `mine' is best suppressed, because of the
| sense of coal-mine etc.
myself | reflexive
| 1st person plural
we | subject
| us | object
| care is required here because US = United States. It is usually
| safe to remove it if it is in lower case.
our | possessive adjective
ours | possessive pronoun
ourselves | reflexive
| second person (archaic `thou' forms not included)
you | subject and object
your | possessive adjective
yours | possessive pronoun
yourself | reflexive (singular)
yourselves | reflexive (plural)
| third person singular
he | subject
him | object
his | possessive adjective and pronoun
himself | reflexive
she | subject
her | object and possessive adjective
hers | possessive pronoun
herself | reflexive
it | subject and object
its | possessive adjective
itself | reflexive
| third person plural
they | subject
them | object
their | possessive adjective
theirs | possessive pronoun
themselves | reflexive
| other forms (demonstratives, interrogatives)
what
which
who
whom
this
that
these
those
| VERB FORMS (using F.R. Palmer's nomenclature)
| BE
am | 1st person, present
is | -s form (3rd person, present)
are | present
was | 1st person, past
were | past
be | infinitive
been | past participle
being | -ing form
| HAVE
have | simple
has | -s form
had | past
having | -ing form
| DO
do | simple
does | -s form
did | past
doing | -ing form
| The forms below are, I believe, best omitted, because of the significant
| homonym forms:
| He made a WILL
| old tin CAN
| merry month of MAY
| a smell of MUST
| fight the good fight with all thy MIGHT
| would, could, should, ought might however be included
| | AUXILIARIES
| | WILL
|will
would
| | SHALL
|shall
should
| | CAN
|can
could
| | MAY
|may
|might
| | MUST
|must
| | OUGHT
ought
| COMPOUND FORMS, increasingly encountered nowadays in 'formal' writing
| pronoun + verb
i'm
you're
he's
she's
it's
we're
they're
i've
you've
we've
they've
i'd
you'd
he'd
she'd
we'd
they'd
i'll
you'll
he'll
she'll
we'll
they'll
| verb + negation
isn't
aren't
wasn't
weren't
hasn't
haven't
hadn't
doesn't
don't
didn't
| auxiliary + negation
won't
wouldn't
shan't
shouldn't
can't
cannot
couldn't
mustn't
| miscellaneous forms
let's
that's
who's
what's
here's
there's
when's
where's
why's
how's
| rarer forms
| daren't needn't
| doubtful forms
| oughtn't mightn't
| ARTICLES
a
an
the
| THE REST (Overlap among prepositions, conjunctions, adverbs etc is so
| high, that classification is pointless.)
and
but
if
or
because
as
until
while
of
at
by
for
with
about
against
between
into
through
during
before
after
above
below
to
from
up
down
in
out
on
off
over
under
again
further
then
once
here
there
when
where
why
how
all
any
both
each
few
more
most
other
some
such
no
nor
not
only
own
same
so
than
too
very
| Just for the record, the following words are among the commonest in English
| one
| every
| least
| less
| many
| now
| ever
| never
| say
| says
| said
| also
| get
| go
| goes
| just
| made
| make
| put
| see
| seen
| whether
| like
| well
| back
| even
| still
| way
| take
| since
| another
| however
| two
| three
| four
| five
| first
| second
| new
| old
| high
| long

View File

@ -0,0 +1,8 @@
c
d
j
l
m
n
s
t

View File

@ -0,0 +1,183 @@
| From svn.tartarus.org/snowball/trunk/website/algorithms/french/stop.txt
| This file is distributed under the BSD License.
| See http://snowball.tartarus.org/license.php
| Also see http://www.opensource.org/licenses/bsd-license.html
| - Encoding was converted to UTF-8.
| - This notice was added.
| A French stop word list. Comments begin with vertical bar. Each stop
| word is at the start of a line.
au | a + le
aux | a + les
avec | with
ce | this
ces | these
dans | with
de | of
des | de + les
du | de + le
elle | she
en | `of them' etc
et | and
eux | them
il | he
je | I
la | the
le | the
leur | their
lui | him
ma | my (fem)
mais | but
me | me
même | same; as in moi-même (myself) etc
mes | me (pl)
moi | me
mon | my (masc)
ne | not
nos | our (pl)
notre | our
nous | we
on | one
ou | where
par | by
pas | not
pour | for
qu | que before vowel
que | that
qui | who
sa | his, her (fem)
se | oneself
ses | his (pl)
son | his, her (masc)
sur | on
ta | thy (fem)
te | thee
tes | thy (pl)
toi | thee
ton | thy (masc)
tu | thou
un | a
une | a
vos | your (pl)
votre | your
vous | you
| single letter forms
c | c'
d | d'
j | j'
l | l'
à | to, at
m | m'
n | n'
s | s'
t | t'
y | there
| forms of être (not including the infinitive):
été
étée
étées
étés
étant
suis
es
est
sommes
êtes
sont
serai
seras
sera
serons
serez
seront
serais
serait
serions
seriez
seraient
étais
était
étions
étiez
étaient
fus
fut
fûmes
fûtes
furent
sois
soit
soyons
soyez
soient
fusse
fusses
fût
fussions
fussiez
fussent
| forms of avoir (not including the infinitive):
ayant
eu
eue
eues
eus
ai
as
avons
avez
ont
aurai
auras
aura
aurons
aurez
auront
aurais
aurait
aurions
auriez
auraient
avais
avait
avions
aviez
avaient
eut
eûmes
eûtes
eurent
aie
aies
ait
ayons
ayez
aient
eusse
eusses
eût
eussions
eussiez
eussent
| Later additions (from Jean-Christophe Deschamps)
ceci | this
celà  | that
cet | this
cette | this
ici | here
ils | they
les | the (pl)
leurs | their (pl)
quel | which
quels | which
quelle | which
quelles | which
sans | without
soi | oneself

View File

@ -0,0 +1,292 @@
| From svn.tartarus.org/snowball/trunk/website/algorithms/german/stop.txt
| This file is distributed under the BSD License.
| See http://snowball.tartarus.org/license.php
| Also see http://www.opensource.org/licenses/bsd-license.html
| - Encoding was converted to UTF-8.
| - This notice was added.
| A German stop word list. Comments begin with vertical bar. Each stop
| word is at the start of a line.
| The number of forms in this list is reduced significantly by passing it
| through the German stemmer.
aber | but
alle | all
allem
allen
aller
alles
als | than, as
also | so
am | an + dem
an | at
ander | other
andere
anderem
anderen
anderer
anderes
anderm
andern
anderr
anders
auch | also
auf | on
aus | out of
bei | by
bin | am
bis | until
bist | art
da | there
damit | with it
dann | then
der | the
den
des
dem
die
das
daß | that
derselbe | the same
derselben
denselben
desselben
demselben
dieselbe
dieselben
dasselbe
dazu | to that
dein | thy
deine
deinem
deinen
deiner
deines
denn | because
derer | of those
dessen | of him
dich | thee
dir | to thee
du | thou
dies | this
diese
diesem
diesen
dieser
dieses
doch | (several meanings)
dort | (over) there
durch | through
ein | a
eine
einem
einen
einer
eines
einig | some
einige
einigem
einigen
einiger
einiges
einmal | once
er | he
ihn | him
ihm | to him
es | it
etwas | something
euer | your
eure
eurem
euren
eurer
eures
für | for
gegen | towards
gewesen | p.p. of sein
hab | have
habe | have
haben | have
hat | has
hatte | had
hatten | had
hier | here
hin | there
hinter | behind
ich | I
mich | me
mir | to me
ihr | you, to her
ihre
ihrem
ihren
ihrer
ihres
euch | to you
im | in + dem
in | in
indem | while
ins | in + das
ist | is
jede | each, every
jedem
jeden
jeder
jedes
jene | that
jenem
jenen
jener
jenes
jetzt | now
kann | can
kein | no
keine
keinem
keinen
keiner
keines
können | can
könnte | could
machen | do
man | one
manche | some, many a
manchem
manchen
mancher
manches
mein | my
meine
meinem
meinen
meiner
meines
mit | with
muss | must
musste | had to
nach | to(wards)
nicht | not
nichts | nothing
noch | still, yet
nun | now
nur | only
ob | whether
oder | or
ohne | without
sehr | very
sein | his
seine
seinem
seinen
seiner
seines
selbst | self
sich | herself
sie | they, she
ihnen | to them
sind | are
so | so
solche | such
solchem
solchen
solcher
solches
soll | shall
sollte | should
sondern | but
sonst | else
über | over
um | about, around
und | and
uns | us
unse
unsem
unsen
unser
unses
unter | under
viel | much
vom | von + dem
von | from
vor | before
während | while
war | was
waren | were
warst | wast
was | what
weg | away, off
weil | because
weiter | further
welche | which
welchem
welchen
welcher
welches
wenn | when
werde | will
werden | will
wie | how
wieder | again
will | want
wir | we
wird | will
wirst | willst
wo | where
wollen | want
wollte | wanted
würde | would
würden | would
zu | to
zum | zu + dem
zur | zu + der
zwar | indeed
zwischen | between

View File

@ -0,0 +1,76 @@
# Lucene Greek Stopwords list
ο
η
το
οι
τα
του
τησ
των
τον
την
και
κι
κ
ειμαι
εισαι
ειναι
ειμαστε
ειστε
στο
στον
στη
στην
μα
αλλα
απο
για
προσ
με
σε
ωσ
παρα
αντι
κατα
μετα
θα
να
δε
δεν
μη
μην
επι
ενω
εαν
αν
τοτε
που
πωσ
ποιοσ
ποια
ποιο
ποιοι
ποιεσ
ποιων
ποιουσ
αυτοσ
αυτη
αυτο
αυτοι
αυτων
αυτουσ
αυτεσ
αυτα
εκεινοσ
εκεινη
εκεινο
εκεινοι
εκεινεσ
εκεινα
εκεινων
εκεινουσ
οπωσ
ομωσ
ισωσ
οσο
οτι

View File

@ -0,0 +1,301 @@
| From svn.tartarus.org/snowball/trunk/website/algorithms/italian/stop.txt
| This file is distributed under the BSD License.
| See http://snowball.tartarus.org/license.php
| Also see http://www.opensource.org/licenses/bsd-license.html
| - Encoding was converted to UTF-8.
| - This notice was added.
| An Italian stop word list. Comments begin with vertical bar. Each stop
| word is at the start of a line.
ad | a (to) before vowel
al | a + il
allo | a + lo
ai | a + i
agli | a + gli
all | a + l'
agl | a + gl'
alla | a + la
alle | a + le
con | with
col | con + il
coi | con + i (forms collo, cogli etc are now very rare)
da | from
dal | da + il
dallo | da + lo
dai | da + i
dagli | da + gli
dall | da + l'
dagl | da + gll'
dalla | da + la
dalle | da + le
di | of
del | di + il
dello | di + lo
dei | di + i
degli | di + gli
dell | di + l'
degl | di + gl'
della | di + la
delle | di + le
in | in
nel | in + el
nello | in + lo
nei | in + i
negli | in + gli
nell | in + l'
negl | in + gl'
nella | in + la
nelle | in + le
su | on
sul | su + il
sullo | su + lo
sui | su + i
sugli | su + gli
sull | su + l'
sugl | su + gl'
sulla | su + la
sulle | su + le
per | through, by
tra | among
contro | against
io | I
tu | thou
lui | he
lei | she
noi | we
voi | you
loro | they
mio | my
mia |
miei |
mie |
tuo |
tua |
tuoi | thy
tue |
suo |
sua |
suoi | his, her
sue |
nostro | our
nostra |
nostri |
nostre |
vostro | your
vostra |
vostri |
vostre |
mi | me
ti | thee
ci | us, there
vi | you, there
lo | him, the
la | her, the
li | them
le | them, the
gli | to him, the
ne | from there etc
il | the
un | a
uno | a
una | a
ma | but
ed | and
se | if
perché | why, because
anche | also
come | how
dov | where (as dov')
dove | where
che | who, that
chi | who
cui | whom
non | not
più | more
quale | who, that
quanto | how much
quanti |
quanta |
quante |
quello | that
quelli |
quella |
quelle |
questo | this
questi |
questa |
queste |
si | yes
tutto | all
tutti | all
| single letter forms:
a | at
c | as c' for ce or ci
e | and
i | the
l | as l'
o | or
| forms of avere, to have (not including the infinitive):
ho
hai
ha
abbiamo
avete
hanno
abbia
abbiate
abbiano
avrò
avrai
avrà
avremo
avrete
avranno
avrei
avresti
avrebbe
avremmo
avreste
avrebbero
avevo
avevi
aveva
avevamo
avevate
avevano
ebbi
avesti
ebbe
avemmo
aveste
ebbero
avessi
avesse
avessimo
avessero
avendo
avuto
avuta
avuti
avute
| forms of essere, to be (not including the infinitive):
sono
sei
è
siamo
siete
sia
siate
siano
sarò
sarai
sarà
saremo
sarete
saranno
sarei
saresti
sarebbe
saremmo
sareste
sarebbero
ero
eri
era
eravamo
eravate
erano
fui
fosti
fu
fummo
foste
furono
fossi
fosse
fossimo
fossero
essendo
| forms of fare, to do (not including the infinitive, fa, fat-):
faccio
fai
facciamo
fanno
faccia
facciate
facciano
farò
farai
farà
faremo
farete
faranno
farei
faresti
farebbe
faremmo
fareste
farebbero
facevo
facevi
faceva
facevamo
facevate
facevano
feci
facesti
fece
facemmo
faceste
fecero
facessi
facesse
facessimo
facessero
facendo
| forms of stare, to be (not including the infinitive):
sto
stai
sta
stiamo
stanno
stia
stiate
stiano
starò
starai
starà
staremo
starete
staranno
starei
staresti
starebbe
staremmo
stareste
starebbero
stavo
stavi
stava
stavamo
stavate
stavano
stetti
stesti
stette
stemmo
steste
stettero
stessi
stesse
stessimo
stessero
stando

View File

@ -0,0 +1,186 @@
# This file was created from the carrot2 project and is distributed under the BSD license.
# See http://project.carrot2.org/license.html
# Also see http://www.opensource.org/licenses/bsd-license.html
# From trunk/core/carrot2-util-text/src-resources/stopwords.pl
vol
o.o.
mgr
godz
www
pl
ul
tel
hab
prof
inż
dr
i
u
aby
albo
ale
ani
bardzo
bez
bo
bowiem
by
byli
bym
był
była
było
były
być
będzie
będą
chce
choć
co
coraz
coś
czy
czyli
często
dla
do
gdy
gdyby
gdyż
gdzie
go
ich
im
inne
ja
jak
jakie
jako
je
jednak
jednym
jedynie
jego
jej
jest
jeszcze
jeśli
jeżeli
już
kiedy
kilku
kto
która
które
którego
której
który
których
którym
którzy
lat
lecz
lub
ma
mają
mamy
mi
miał
mimo
mnie
mogą
może
można
mu
musi
na
nad
nam
nas
nawet
nic
nich
nie
niej
nim
niż
no
nowe
np
nr
o
od
ok
on
one
oraz
pan
po
pod
ponad
ponieważ
poza
przed
przede
przez
przy
raz
razie
roku
również
się
sobie
sposób
swoje
ta
tak
takich
takie
także
tam
te
tego
tej
temu
ten
teraz
też
to
trzeba
tu
tych
tylko
tym
tys
tzw
w
we
wie
więc
wszystko
wśród
właśnie
z
za
zaś
ze
że
żeby
ii
iii
iv
vi
vii
viii
ix
xi
xii
xiii
xiv
xv

View File

@ -0,0 +1,251 @@
| From svn.tartarus.org/snowball/trunk/website/algorithms/portuguese/stop.txt
| This file is distributed under the BSD License.
| See http://snowball.tartarus.org/license.php
| Also see http://www.opensource.org/licenses/bsd-license.html
| - Encoding was converted to UTF-8.
| - This notice was added.
| A Portuguese stop word list. Comments begin with vertical bar. Each stop
| word is at the start of a line.
| The following is a ranked list (commonest to rarest) of stopwords
| deriving from a large sample of text.
| Extra words have been added at the end.
de | of, from
a | the; to, at; her
o | the; him
que | who, that
e | and
do | de + o
da | de + a
em | in
um | a
para | for
| é from SER
com | with
não | not, no
uma | a
os | the; them
no | em + o
se | himself etc
na | em + a
por | for
mais | more
as | the; them
dos | de + os
como | as, like
mas | but
| foi from SER
ao | a + o
ele | he
das | de + as
| tem from TER
à | a + a
seu | his
sua | her
ou | or
| ser from SER
quando | when
muito | much
| há from HAV
nos | em + os; us
já | already, now
| está from EST
eu | I
também | also
só | only, just
pelo | per + o
pela | per + a
até | up to
isso | that
ela | he
entre | between
| era from SER
depois | after
sem | without
mesmo | same
aos | a + os
| ter from TER
seus | his
quem | whom
nas | em + as
me | me
esse | that
eles | they
| estão from EST
você | you
| tinha from TER
| foram from SER
essa | that
num | em + um
nem | nor
suas | her
meu | my
às | a + as
minha | my
| têm from TER
numa | em + uma
pelos | per + os
elas | they
| havia from HAV
| seja from SER
qual | which
| será from SER
nós | we
| tenho from TER
lhe | to him, her
deles | of them
essas | those
esses | those
pelas | per + as
este | this
| fosse from SER
dele | of him
| other words. There are many contractions such as naquele = em+aquele,
| mo = me+o, but they are rare.
| Indefinite article plural forms are also rare.
tu | thou
te | thee
vocês | you (plural)
vos | you
lhes | to them
meus | my
minhas
teu | thy
tua
teus
tuas
nosso | our
nossa
nossos
nossas
dela | of her
delas | of them
esta | this
estes | these
estas | these
aquele | that
aquela | that
aqueles | those
aquelas | those
isto | this
aquilo | that
| forms of estar, to be (not including the infinitive):
estou
está
estamos
estão
estive
esteve
estivemos
estiveram
estava
estávamos
estavam
estivera
estivéramos
esteja
estejamos
estejam
estivesse
estivéssemos
estivessem
estiver
estivermos
estiverem
| forms of haver, to have (not including the infinitive):
hei
havemos
hão
houve
houvemos
houveram
houvera
houvéramos
haja
hajamos
hajam
houvesse
houvéssemos
houvessem
houver
houvermos
houverem
houverei
houverá
houveremos
houverão
houveria
houveríamos
houveriam
| forms of ser, to be (not including the infinitive):
sou
somos
são
era
éramos
eram
fui
foi
fomos
foram
fora
fôramos
seja
sejamos
sejam
fosse
fôssemos
fossem
for
formos
forem
serei
será
seremos
serão
seria
seríamos
seriam
| forms of ter, to have (not including the infinitive):
tenho
tem
temos
tém
tinha
tínhamos
tinham
tive
teve
tivemos
tiveram
tivera
tivéramos
tenha
tenhamos
tenham
tivesse
tivéssemos
tivessem
tiver
tivermos
tiverem
terei
terá
teremos
terão
teria
teríamos
teriam

View File

@ -0,0 +1,233 @@
# This file was created by Jacques Savoy and is distributed under the BSD license.
# See http://members.unine.ch/jacques.savoy/clef/index.html.
# Also see http://www.opensource.org/licenses/bsd-license.html
acea
aceasta
această
aceea
acei
aceia
acel
acela
acele
acelea
acest
acesta
aceste
acestea
aceşti
aceştia
acolo
acum
ai
aia
aibă
aici
al
ăla
ale
alea
ălea
altceva
altcineva
am
ar
are
aşadar
asemenea
asta
ăsta
astăzi
astea
ăstea
ăştia
asupra
aţi
au
avea
avem
aveţi
azi
bine
bucur
bună
ca
căci
când
care
cărei
căror
cărui
cât
câte
câţi
către
câtva
ce
cel
ceva
chiar
cînd
cine
cineva
cît
cîte
cîţi
cîtva
contra
cu
cum
cumva
curând
curînd
da
dacă
dar
datorită
de
deci
deja
deoarece
departe
deşi
din
dinaintea
dintr
dintre
drept
după
ea
ei
el
ele
eram
este
eşti
eu
face
fără
fi
fie
fiecare
fii
fim
fiţi
iar
ieri
îi
îl
îmi
împotriva
în
înainte
înaintea
încât
încît
încotro
între
întrucât
întrucît
îţi
la
lângă
le
li
lîngă
lor
lui
mâine
mea
mei
mele
mereu
meu
mi
mine
mult
multă
mulţi
ne
nicăieri
nici
nimeni
nişte
noastră
noastre
noi
noştri
nostru
nu
ori
oricând
oricare
oricât
orice
oricînd
oricine
oricît
oricum
oriunde
până
pe
pentru
peste
pînă
poate
pot
prea
prima
primul
prin
printr
sa
săi
sale
sau
său
se
şi
sînt
sîntem
sînteţi
spre
sub
sunt
suntem
sunteţi
ta
tăi
tale
tău
te
ţi
ţie
tine
toată
toate
tot
toţi
totuşi
tu
un
una
unde
undeva
unei
unele
uneori
unor
vi
voastră
voastre
voi
voştri
vostru
vouă
vreo
vreun

View File

@ -0,0 +1,486 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!--
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<schema name="ckan" version="2.3">
<types>
<fieldType name="string" class="solr.StrField" sortMissingLast="true" omitNorms="true"/>
<fieldType name="boolean" class="solr.BoolField" sortMissingLast="true" omitNorms="true"/>
<fieldtype name="binary" class="solr.BinaryField"/>
<fieldType name="int" class="solr.TrieIntField" precisionStep="0" omitNorms="true" positionIncrementGap="0"/>
<fieldType name="float" class="solr.TrieFloatField" precisionStep="0" omitNorms="true" positionIncrementGap="0"/>
<fieldType name="long" class="solr.TrieLongField" precisionStep="0" omitNorms="true" positionIncrementGap="0"/>
<fieldType name="double" class="solr.TrieDoubleField" precisionStep="0" omitNorms="true" positionIncrementGap="0"/>
<fieldType name="tint" class="solr.TrieIntField" precisionStep="8" omitNorms="true" positionIncrementGap="0"/>
<fieldType name="tfloat" class="solr.TrieFloatField" precisionStep="8" omitNorms="true" positionIncrementGap="0"/>
<fieldType name="tlong" class="solr.TrieLongField" precisionStep="8" omitNorms="true" positionIncrementGap="0"/>
<fieldType name="tdouble" class="solr.TrieDoubleField" precisionStep="8" omitNorms="true" positionIncrementGap="0"/>
<fieldType name="date" class="solr.TrieDateField" omitNorms="true" precisionStep="0" positionIncrementGap="0"/>
<fieldType name="tdate" class="solr.TrieDateField" omitNorms="true" precisionStep="6" positionIncrementGap="0"/>
<fieldType name="text" class="solr.TextField" positionIncrementGap="100">
<analyzer type="index">
<tokenizer class="solr.WhitespaceTokenizerFactory"/>
<!-- in this example, we will only use synonyms at query time
<filter class="solr.SynonymFilterFactory" synonyms="index_synonyms.txt" ignoreCase="true" expand="false"/>
-->
<!-- Case insensitive stop word removal.
add enablePositionIncrements=true in both the index and query
analyzers to leave a 'gap' for more accurate phrase queries.
-->
<filter class="solr.StopFilterFactory"
ignoreCase="true"
words="stopwords.txt"
enablePositionIncrements="true"
/>
<filter class="solr.WordDelimiterGraphFilterFactory" generateWordParts="1" generateNumberParts="1" catenateWords="1" catenateNumbers="1" catenateAll="0" splitOnCaseChange="1"/>
<filter class="solr.FlattenGraphFilterFactory"/> <!-- required on index analyzers after graph filters -->
<filter class="solr.LowerCaseFilterFactory"/>
<filter class="solr.SnowballPorterFilterFactory" language="English" protected="protwords.txt"/>
<filter class="solr.ASCIIFoldingFilterFactory"/>
</analyzer>
<analyzer type="query">
<tokenizer class="solr.WhitespaceTokenizerFactory"/>
<filter class="solr.SynonymGraphFilterFactory" synonyms="synonyms.txt" ignoreCase="true" expand="true"/>
<filter class="solr.StopFilterFactory"
ignoreCase="true"
words="stopwords.txt"
enablePositionIncrements="true"
/>
<filter class="solr.WordDelimiterGraphFilterFactory" generateWordParts="1" generateNumberParts="1" catenateWords="0" catenateNumbers="0" catenateAll="0" splitOnCaseChange="1"/>
<filter class="solr.LowerCaseFilterFactory"/>
<filter class="solr.SnowballPorterFilterFactory" language="English" protected="protwords.txt"/>
<filter class="solr.ASCIIFoldingFilterFactory"/>
</analyzer>
</fieldType>
<!-- A general unstemmed text field - good if one does not know the language of the field -->
<fieldType name="textgen" class="solr.TextField" positionIncrementGap="100">
<analyzer type="index">
<tokenizer class="solr.WhitespaceTokenizerFactory"/>
<filter class="solr.StopFilterFactory" ignoreCase="true" words="stopwords.txt" enablePositionIncrements="true" />
<filter class="solr.WordDelimiterGraphFilterFactory" generateWordParts="1" generateNumberParts="1" catenateWords="1" catenateNumbers="1" catenateAll="0" splitOnCaseChange="0"/>
<filter class="solr.FlattenGraphFilterFactory"/> <!-- required on index analyzers after graph filters -->
<filter class="solr.LowerCaseFilterFactory"/>
</analyzer>
<analyzer type="query">
<tokenizer class="solr.WhitespaceTokenizerFactory"/>
<filter class="solr.SynonymGraphFilterFactory" synonyms="synonyms.txt" ignoreCase="true" expand="true"/>
<filter class="solr.StopFilterFactory"
ignoreCase="true"
words="stopwords.txt"
enablePositionIncrements="true"
/>
<filter class="solr.WordDelimiterGraphFilterFactory" generateWordParts="1" generateNumberParts="1" catenateWords="0" catenateNumbers="0" catenateAll="0" splitOnCaseChange="0"/>
<filter class="solr.LowerCaseFilterFactory"/>
</analyzer>
</fieldType>
<!-- English -->
<fieldType name="text_en" class="solr.TextField" positionIncrementGap="100">
<analyzer type="index">
<tokenizer class="solr.WhitespaceTokenizerFactory"/>
<filter class="solr.StopFilterFactory"
ignoreCase="true"
words="stopwords.txt"
enablePositionIncrements="true"
/>
<filter class="solr.WordDelimiterGraphFilterFactory" generateWordParts="1" generateNumberParts="1" catenateWords="1" catenateNumbers="1" catenateAll="0" splitOnCaseChange="1"/>
<filter class="solr.FlattenGraphFilterFactory"/> <!-- required on index analyzers after graph filters -->
<filter class="solr.LowerCaseFilterFactory"/>
<filter class="solr.SnowballPorterFilterFactory" language="English" protected="protwords.txt"/>
<filter class="solr.ASCIIFoldingFilterFactory"/>
</analyzer>
<analyzer type="query">
<tokenizer class="solr.WhitespaceTokenizerFactory"/>
<filter class="solr.StopFilterFactory"
ignoreCase="true"
words="stopwords.txt"
enablePositionIncrements="true"
/>
<filter class="solr.WordDelimiterGraphFilterFactory" generateWordParts="1" generateNumberParts="1" catenateWords="0" catenateNumbers="0" catenateAll="0" splitOnCaseChange="1"/>
<filter class="solr.LowerCaseFilterFactory"/>
<filter class="solr.SnowballPorterFilterFactory" language="English" protected="protwords.txt"/>
<filter class="solr.ASCIIFoldingFilterFactory"/>
</analyzer>
</fieldType>
<!-- French -->
<fieldType name="text_fr" class="solr.TextField" positionIncrementGap="100">
<analyzer type="index">
<tokenizer class="solr.WhitespaceTokenizerFactory"/>
<filter class="solr.StopFilterFactory"
ignoreCase="true"
words="french_stop.txt"
enablePositionIncrements="true"
/>
<filter class="solr.LowerCaseFilterFactory"/>
<filter class="solr.ElisionFilterFactory" articles="fr_elision.txt"/>
<filter class="solr.WordDelimiterGraphFilterFactory" generateWordParts="1" generateNumberParts="1" catenateWords="1" catenateNumbers="1" catenateAll="0" splitOnCaseChange="1"/>
<filter class="solr.FlattenGraphFilterFactory"/> <!-- required on index analyzers after graph filters -->
<filter class="solr.SnowballPorterFilterFactory" language="French" />
<filter class="solr.ASCIIFoldingFilterFactory"/>
</analyzer>
<analyzer type="query">
<tokenizer class="solr.WhitespaceTokenizerFactory"/>
<filter class="solr.StopFilterFactory"
ignoreCase="true"
words="french_stop.txt"
enablePositionIncrements="true"
/>
<filter class="solr.LowerCaseFilterFactory"/>
<filter class="solr.ElisionFilterFactory" articles="fr_elision.txt"/>
<filter class="solr.WordDelimiterGraphFilterFactory" generateWordParts="1" generateNumberParts="1" catenateWords="1" catenateNumbers="1" catenateAll="0" splitOnCaseChange="1"/>
<filter class="solr.SnowballPorterFilterFactory" language="French" />
<filter class="solr.ASCIIFoldingFilterFactory"/>
</analyzer>
</fieldType>
<!-- German -->
<fieldType name="text_de" class="solr.TextField" positionIncrementGap="100">
<analyzer type="index">
<tokenizer class="solr.WhitespaceTokenizerFactory"/>
<filter class="solr.StopFilterFactory"
ignoreCase="true"
words="german_stop.txt"
enablePositionIncrements="true"
/>
<filter class="solr.LowerCaseFilterFactory"/>
<filter class="solr.WordDelimiterGraphFilterFactory" generateWordParts="1" generateNumberParts="1" catenateWords="1" catenateNumbers="1" catenateAll="0" splitOnCaseChange="1"/>
<filter class="solr.FlattenGraphFilterFactory"/> <!-- required on index analyzers after graph filters -->
<filter class="solr.SnowballPorterFilterFactory" language="German" />
<filter class="solr.ASCIIFoldingFilterFactory"/>
</analyzer>
<analyzer type="query">
<tokenizer class="solr.WhitespaceTokenizerFactory"/>
<filter class="solr.StopFilterFactory"
ignoreCase="true"
words="german_stop.txt"
enablePositionIncrements="true"
/>
<filter class="solr.LowerCaseFilterFactory"/>
<filter class="solr.WordDelimiterGraphFilterFactory" generateWordParts="1" generateNumberParts="1" catenateWords="1" catenateNumbers="1" catenateAll="0" splitOnCaseChange="1"/>
<filter class="solr.SnowballPorterFilterFactory" language="German" />
<filter class="solr.ASCIIFoldingFilterFactory"/>
</analyzer>
</fieldType>
<!-- Spanish -->
<fieldType name="text_es" class="solr.TextField" positionIncrementGap="100">
<analyzer type="index">
<tokenizer class="solr.WhitespaceTokenizerFactory"/>
<filter class="solr.StopFilterFactory"
ignoreCase="true"
words="spanish_stop.txt"
enablePositionIncrements="true"
/>
<filter class="solr.LowerCaseFilterFactory"/>
<filter class="solr.WordDelimiterGraphFilterFactory" generateWordParts="1" generateNumberParts="1" catenateWords="1" catenateNumbers="1" catenateAll="0" splitOnCaseChange="1"/>
<filter class="solr.FlattenGraphFilterFactory"/> <!-- required on index analyzers after graph filters -->
<filter class="solr.SnowballPorterFilterFactory" language="Spanish" />
<filter class="solr.ASCIIFoldingFilterFactory"/>
</analyzer>
<analyzer type="query">
<tokenizer class="solr.WhitespaceTokenizerFactory"/>
<filter class="solr.StopFilterFactory"
ignoreCase="true"
words="spanish_stop.txt"
enablePositionIncrements="true"
/>
<filter class="solr.LowerCaseFilterFactory"/>
<filter class="solr.WordDelimiterGraphFilterFactory" generateWordParts="1" generateNumberParts="1" catenateWords="1" catenateNumbers="1" catenateAll="0" splitOnCaseChange="1"/>
<filter class="solr.SnowballPorterFilterFactory" language="Spanish" />
<filter class="solr.ASCIIFoldingFilterFactory"/>
</analyzer>
</fieldType>
<!-- Italian -->
<fieldType name="text_it" class="solr.TextField" positionIncrementGap="100">
<analyzer type="index">
<tokenizer class="solr.WhitespaceTokenizerFactory"/>
<filter class="solr.StopFilterFactory"
ignoreCase="true"
words="italian_stop.txt"
enablePositionIncrements="true"
/>
<filter class="solr.LowerCaseFilterFactory"/>
<filter class="solr.WordDelimiterGraphFilterFactory" generateWordParts="1" generateNumberParts="1" catenateWords="1" catenateNumbers="1" catenateAll="0" splitOnCaseChange="1"/>
<filter class="solr.FlattenGraphFilterFactory"/> <!-- required on index analyzers after graph filters -->
<filter class="solr.SnowballPorterFilterFactory" language="Italian" />
<filter class="solr.ASCIIFoldingFilterFactory"/>
</analyzer>
<analyzer type="query">
<tokenizer class="solr.WhitespaceTokenizerFactory"/>
<filter class="solr.StopFilterFactory"
ignoreCase="true"
words="italian_stop.txt"
enablePositionIncrements="true"
/>
<filter class="solr.LowerCaseFilterFactory"/>
<filter class="solr.WordDelimiterGraphFilterFactory" generateWordParts="1" generateNumberParts="1" catenateWords="1" catenateNumbers="1" catenateAll="0" splitOnCaseChange="1"/>
<filter class="solr.SnowballPorterFilterFactory" language="Italian" />
<filter class="solr.ASCIIFoldingFilterFactory"/>
</analyzer>
</fieldType>
<!-- Dutch -->
<fieldType name="text_nl" class="solr.TextField" positionIncrementGap="100">
<analyzer type="index">
<tokenizer class="solr.WhitespaceTokenizerFactory"/>
<filter class="solr.StopFilterFactory"
ignoreCase="true"
words="dutch_stop.txt"
enablePositionIncrements="true"
/>
<filter class="solr.LowerCaseFilterFactory"/>
<filter class="solr.WordDelimiterGraphFilterFactory" generateWordParts="1" generateNumberParts="1" catenateWords="1" catenateNumbers="1" catenateAll="0" splitOnCaseChange="1"/>
<filter class="solr.FlattenGraphFilterFactory"/> <!-- required on index analyzers after graph filters -->
<filter class="solr.SnowballPorterFilterFactory" language="Dutch" />
<filter class="solr.ASCIIFoldingFilterFactory"/>
</analyzer>
<analyzer type="query">
<tokenizer class="solr.WhitespaceTokenizerFactory"/>
<filter class="solr.StopFilterFactory"
ignoreCase="true"
words="dutch_stop.txt"
enablePositionIncrements="true"
/>
<filter class="solr.LowerCaseFilterFactory"/>
<filter class="solr.WordDelimiterGraphFilterFactory" generateWordParts="1" generateNumberParts="1" catenateWords="1" catenateNumbers="1" catenateAll="0" splitOnCaseChange="1"/>
<filter class="solr.SnowballPorterFilterFactory" language="Dutch" />
<filter class="solr.ASCIIFoldingFilterFactory"/>
</analyzer>
</fieldType>
<!-- Romanian -->
<fieldType name="text_ro" class="solr.TextField" positionIncrementGap="100">
<analyzer type="index">
<tokenizer class="solr.WhitespaceTokenizerFactory"/>
<filter class="solr.StopFilterFactory"
ignoreCase="true"
words="romanian_stop.txt"
enablePositionIncrements="true"
/>
<filter class="solr.LowerCaseFilterFactory"/>
<filter class="solr.WordDelimiterGraphFilterFactory" generateWordParts="1" generateNumberParts="1" catenateWords="1" catenateNumbers="1" catenateAll="0" splitOnCaseChange="1"/>
<filter class="solr.FlattenGraphFilterFactory"/> <!-- required on index analyzers after graph filters -->
<filter class="solr.SnowballPorterFilterFactory" language="Romanian" />
<filter class="solr.ASCIIFoldingFilterFactory"/>
</analyzer>
<analyzer type="query">
<tokenizer class="solr.WhitespaceTokenizerFactory"/>
<filter class="solr.StopFilterFactory"
ignoreCase="true"
words="romanian_stop.txt"
enablePositionIncrements="true"
/>
<filter class="solr.LowerCaseFilterFactory"/>
<filter class="solr.WordDelimiterGraphFilterFactory" generateWordParts="1" generateNumberParts="1" catenateWords="1" catenateNumbers="1" catenateAll="0" splitOnCaseChange="1"/>
<filter class="solr.SnowballPorterFilterFactory" language="Romanian" />
<filter class="solr.ASCIIFoldingFilterFactory"/>
</analyzer>
</fieldType>
<!-- Portuguese -->
<fieldType name="text_pt" class="solr.TextField" positionIncrementGap="100">
<analyzer type="index">
<tokenizer class="solr.WhitespaceTokenizerFactory"/>
<filter class="solr.StopFilterFactory"
ignoreCase="true"
words="portuguese_stop.txt"
enablePositionIncrements="true"
/>
<filter class="solr.LowerCaseFilterFactory"/>
<filter class="solr.WordDelimiterGraphFilterFactory" generateWordParts="1" generateNumberParts="1" catenateWords="1" catenateNumbers="1" catenateAll="0" splitOnCaseChange="1"/>
<filter class="solr.FlattenGraphFilterFactory"/> <!-- required on index analyzers after graph filters -->
<filter class="solr.SnowballPorterFilterFactory" language="Portuguese" />
<filter class="solr.ASCIIFoldingFilterFactory"/>
</analyzer>
<analyzer type="query">
<tokenizer class="solr.WhitespaceTokenizerFactory"/>
<filter class="solr.StopFilterFactory"
ignoreCase="true"
words="portuguese_stop.txt"
enablePositionIncrements="true"
/>
<filter class="solr.LowerCaseFilterFactory"/>
<filter class="solr.WordDelimiterGraphFilterFactory" generateWordParts="1" generateNumberParts="1" catenateWords="1" catenateNumbers="1" catenateAll="0" splitOnCaseChange="1"/>
<filter class="solr.SnowballPorterFilterFactory" language="Portuguese" />
<filter class="solr.ASCIIFoldingFilterFactory"/>
</analyzer>
</fieldType>
<!-- Polish -->
<fieldType name="text_pl" class="solr.TextField" positionIncrementGap="100">
<analyzer type="index">
<tokenizer class="solr.WhitespaceTokenizerFactory"/>
<filter class="solr.StopFilterFactory" ignoreCase="true" words="polish_stop.txt" enablePositionIncrements="true" />
<filter class="solr.WordDelimiterGraphFilterFactory" generateWordParts="1" generateNumberParts="1" catenateWords="1" catenateNumbers="1" catenateAll="0" splitOnCaseChange="0"/>
<filter class="solr.FlattenGraphFilterFactory"/> <!-- required on index analyzers after graph filters -->
<filter class="solr.LowerCaseFilterFactory"/>
</analyzer>
<analyzer type="query">
<tokenizer class="solr.WhitespaceTokenizerFactory"/>
<filter class="solr.SynonymGraphFilterFactory" synonyms="synonyms.txt" ignoreCase="true" expand="true"/>
<filter class="solr.StopFilterFactory"
ignoreCase="true"
words="polish_stop.txt"
enablePositionIncrements="true"
/>
<filter class="solr.WordDelimiterGraphFilterFactory" generateWordParts="1" generateNumberParts="1" catenateWords="0" catenateNumbers="0" catenateAll="0" splitOnCaseChange="0"/>
<filter class="solr.LowerCaseFilterFactory"/>
</analyzer>
</fieldType>
</types>
<fields>
<field name="index_id" type="string" indexed="true" stored="true" required="true" />
<field name="id" type="string" indexed="true" stored="true" required="true" />
<field name="site_id" type="string" indexed="true" stored="true" required="true" />
<field name="title" type="text" indexed="true" stored="true" />
<field name="entity_type" type="string" indexed="true" stored="true" omitNorms="true" />
<field name="dataset_type" type="string" indexed="true" stored="true" />
<field name="state" type="string" indexed="true" stored="true" omitNorms="true" />
<field name="name" type="string" indexed="true" stored="true" omitNorms="true" />
<field name="version" type="string" indexed="true" stored="true" />
<field name="url" type="string" indexed="true" stored="true" omitNorms="true" />
<field name="ckan_url" type="string" indexed="true" stored="true" omitNorms="true" />
<field name="download_url" type="string" indexed="true" stored="true" omitNorms="true" />
<field name="notes" type="text" indexed="true" stored="true"/>
<field name="author" type="textgen" indexed="true" stored="true" />
<field name="author_email" type="textgen" indexed="true" stored="true" />
<field name="maintainer" type="textgen" indexed="true" stored="true" />
<field name="maintainer_email" type="textgen" indexed="true" stored="true" />
<field name="license" type="string" indexed="true" stored="true" />
<field name="license_id" type="string" indexed="true" stored="true" />
<field name="tags" type="string" indexed="true" stored="true" multiValued="true"/>
<field name="groups" type="string" indexed="true" stored="true" multiValued="true"/>
<field name="organization" type="string" indexed="true" stored="true" multiValued="false"/>
<field name="capacity" type="string" indexed="true" stored="true" multiValued="false"/>
<field name="res_name" type="textgen" indexed="true" stored="true" multiValued="true" />
<field name="res_description" type="textgen" indexed="true" stored="true" multiValued="true"/>
<field name="res_format" type="string" indexed="true" stored="true" multiValued="true"/>
<field name="res_url" type="string" indexed="true" stored="true" multiValued="true"/>
<field name="res_type" type="string" indexed="true" stored="true" multiValued="true"/>
<!-- catchall field, containing all other searchable text fields (implemented
via copyField further on in this schema -->
<field name="text" type="text" indexed="true" stored="false" multiValued="true"/>
<field name="urls" type="text" indexed="true" stored="false" multiValued="true"/>
<field name="depends_on" type="text" indexed="true" stored="false" multiValued="true"/>
<field name="dependency_of" type="text" indexed="true" stored="false" multiValued="true"/>
<field name="derives_from" type="text" indexed="true" stored="false" multiValued="true"/>
<field name="has_derivation" type="text" indexed="true" stored="false" multiValued="true"/>
<field name="links_to" type="text" indexed="true" stored="false" multiValued="true"/>
<field name="linked_from" type="text" indexed="true" stored="false" multiValued="true"/>
<field name="child_of" type="text" indexed="true" stored="false" multiValued="true"/>
<field name="parent_of" type="text" indexed="true" stored="false" multiValued="true"/>
<field name="views_total" type="int" indexed="true" stored="false"/>
<field name="views_recent" type="int" indexed="true" stored="false"/>
<field name="resources_accessed_total" type="int" indexed="true" stored="false"/>
<field name="resources_accessed_recent" type="int" indexed="true" stored="false"/>
<field name="metadata_created" type="date" indexed="true" stored="true" multiValued="false"/>
<field name="metadata_modified" type="date" indexed="true" stored="true" multiValued="false"/>
<field name="indexed_ts" type="date" indexed="true" stored="true" default="NOW" multiValued="false"/>
<!-- Copy the title field into titleString, and treat as a string
(rather than text type). This allows us to sort on the titleString -->
<field name="title_string" type="string" indexed="true" stored="false" />
<!-- Multilingual -->
<field name="text_en" type="text_en" indexed="true" stored="true"/>
<field name="title_en" type="text_en" indexed="true" stored="true"/>
<field name="text_fr" type="text_fr" indexed="true" stored="true"/>
<field name="title_fr" type="text_fr" indexed="true" stored="true"/>
<field name="text_de" type="text_de" indexed="true" stored="true"/>
<field name="title_de" type="text_de" indexed="true" stored="true"/>
<field name="text_es" type="text_es" indexed="true" stored="true"/>
<field name="title_es" type="text_es" indexed="true" stored="true"/>
<field name="text_it" type="text_it" indexed="true" stored="true"/>
<field name="title_it" type="text_it" indexed="true" stored="true"/>
<field name="text_nl" type="text_nl" indexed="true" stored="true"/>
<field name="title_nl" type="text_nl" indexed="true" stored="true"/>
<field name="text_ro" type="text_ro" indexed="true" stored="true"/>
<field name="title_ro" type="text_ro" indexed="true" stored="true"/>
<field name="text_pt" type="text_pt" indexed="true" stored="true"/>
<field name="title_pt" type="text_pt" indexed="true" stored="true"/>
<field name="text_pl" type="text_pl" indexed="true" stored="true"/>
<field name="title_pl" type="text_pl" indexed="true" stored="true"/>
<field name="data_dict" type="string" indexed="false" stored="true" />
<field name="validated_data_dict" type="string" indexed="false" stored="true" />
<field name="_version_" type="string" indexed="true" stored="true"/>
<dynamicField name="*_date" type="date" indexed="true" stored="true" multiValued="false"/>
<dynamicField name="extras_*" type="text" indexed="true" stored="true" multiValued="false"/>
<dynamicField name="res_extras_*" type="text" indexed="true" stored="true" multiValued="true"/>
<dynamicField name="vocab_*" type="string" indexed="true" stored="true" multiValued="true"/>
<dynamicField name="*" type="string" indexed="true" stored="false"/>
</fields>
<uniqueKey>index_id</uniqueKey>
<defaultSearchField>text</defaultSearchField>
<solrQueryParser defaultOperator="AND"/>
<copyField source="url" dest="urls"/>
<copyField source="ckan_url" dest="urls"/>
<copyField source="download_url" dest="urls"/>
<copyField source="res_url" dest="urls"/>
<copyField source="extras_*" dest="text"/>
<copyField source="res_extras_*" dest="text"/>
<copyField source="urls" dest="text"/>
<copyField source="name" dest="text"/>
<copyField source="title" dest="text"/>
<copyField source="text" dest="text"/>
<copyField source="license" dest="text"/>
<copyField source="notes" dest="text"/>
<copyField source="tags" dest="text"/>
<copyField source="groups" dest="text"/>
<copyField source="organization" dest="text"/>
<copyField source="res_name" dest="text"/>
<copyField source="res_description" dest="text"/>
<copyField source="maintainer" dest="text"/>
<copyField source="author" dest="text"/>
</schema>

View File

@ -0,0 +1,354 @@
| From svn.tartarus.org/snowball/trunk/website/algorithms/spanish/stop.txt
| This file is distributed under the BSD License.
| See http://snowball.tartarus.org/license.php
| Also see http://www.opensource.org/licenses/bsd-license.html
| - Encoding was converted to UTF-8.
| - This notice was added.
| A Spanish stop word list. Comments begin with vertical bar. Each stop
| word is at the start of a line.
| The following is a ranked list (commonest to rarest) of stopwords
| deriving from a large sample of text.
| Extra words have been added at the end.
de | from, of
la | the, her
que | who, that
el | the
en | in
y | and
a | to
los | the, them
del | de + el
se | himself, from him etc
las | the, them
por | for, by, etc
un | a
para | for
con | with
no | no
una | a
su | his, her
al | a + el
| es from SER
lo | him
como | how
más | more
pero | pero
sus | su plural
le | to him, her
ya | already
o | or
| fue from SER
este | this
| ha from HABER
sí | himself etc
porque | because
esta | this
| son from SER
entre | between
| está from ESTAR
cuando | when
muy | very
sin | without
sobre | on
| ser from SER
| tiene from TENER
también | also
me | me
hasta | until
hay | there is/are
donde | where
| han from HABER
quien | whom, that
| están from ESTAR
| estado from ESTAR
desde | from
todo | all
nos | us
durante | during
| estados from ESTAR
todos | all
uno | a
les | to them
ni | nor
contra | against
otros | other
| fueron from SER
ese | that
eso | that
| había from HABER
ante | before
ellos | they
e | and (variant of y)
esto | this
mí | me
antes | before
algunos | some
qué | what?
unos | a
yo | I
otro | other
otras | other
otra | other
él | he
tanto | so much, many
esa | that
estos | these
mucho | much, many
quienes | who
nada | nothing
muchos | many
cual | who
| sea from SER
poco | few
ella | she
estar | to be
| haber from HABER
estas | these
| estaba from ESTAR
| estamos from ESTAR
algunas | some
algo | something
nosotros | we
| other forms
mi | me
mis | mi plural
tú | thou
te | thee
ti | thee
tu | thy
tus | tu plural
ellas | they
nosotras | we
vosotros | you
vosotras | you
os | you
mío | mine
mía |
míos |
mías |
tuyo | thine
tuya |
tuyos |
tuyas |
suyo | his, hers, theirs
suya |
suyos |
suyas |
nuestro | ours
nuestra |
nuestros |
nuestras |
vuestro | yours
vuestra |
vuestros |
vuestras |
esos | those
esas | those
| forms of estar, to be (not including the infinitive):
estoy
estás
está
estamos
estáis
están
esté
estés
estemos
estéis
estén
estaré
estarás
estará
estaremos
estaréis
estarán
estaría
estarías
estaríamos
estaríais
estarían
estaba
estabas
estábamos
estabais
estaban
estuve
estuviste
estuvo
estuvimos
estuvisteis
estuvieron
estuviera
estuvieras
estuviéramos
estuvierais
estuvieran
estuviese
estuvieses
estuviésemos
estuvieseis
estuviesen
estando
estado
estada
estados
estadas
estad
| forms of haber, to have (not including the infinitive):
he
has
ha
hemos
habéis
han
haya
hayas
hayamos
hayáis
hayan
habré
habrás
habrá
habremos
habréis
habrán
habría
habrías
habríamos
habríais
habrían
había
habías
habíamos
habíais
habían
hube
hubiste
hubo
hubimos
hubisteis
hubieron
hubiera
hubieras
hubiéramos
hubierais
hubieran
hubiese
hubieses
hubiésemos
hubieseis
hubiesen
habiendo
habido
habida
habidos
habidas
| forms of ser, to be (not including the infinitive):
soy
eres
es
somos
sois
son
sea
seas
seamos
seáis
sean
seré
serás
será
seremos
seréis
serán
sería
serías
seríamos
seríais
serían
era
eras
éramos
erais
eran
fui
fuiste
fue
fuimos
fuisteis
fueron
fuera
fueras
fuéramos
fuerais
fueran
fuese
fueses
fuésemos
fueseis
fuesen
siendo
sido
| sed also means 'thirst'
| forms of tener, to have (not including the infinitive):
tengo
tienes
tiene
tenemos
tenéis
tienen
tenga
tengas
tengamos
tengáis
tengan
tendré
tendrás
tendrá
tendremos
tendréis
tendrán
tendría
tendrías
tendríamos
tendríais
tendrían
tenía
tenías
teníamos
teníais
tenían
tuve
tuviste
tuvo
tuvimos
tuvisteis
tuvieron
tuviera
tuvieras
tuviéramos
tuvierais
tuvieran
tuviese
tuvieses
tuviésemos
tuvieseis
tuviesen
teniendo
tenido
tenida
tenidos
tenidas
tened

View File

@ -0,0 +1,239 @@
# encoding: utf-8
import pytest
import ckan.plugins
import ckanext.multilingual.plugin as mulilingual_plugin
import ckan.lib.helpers as h
import ckan.lib.create_test_data
import ckan.model as model
from ckan.tests.helpers import body_contains, call_action
_create_test_data = ckan.lib.create_test_data
ORG_NAME = "test_org"
@pytest.fixture
def prepare(clean_db, clean_index, with_request_context):
_create_test_data.CreateTestData.create_translations_test_data()
sysadmin_user = model.User.get("testsysadmin")
org = {
"name": ORG_NAME,
"title": "russian",
"description": "Roger likes these books.",
}
context = {"user": sysadmin_user.name}
call_action("organization_create", context, **org)
dataset = {
"name": "test_org_dataset",
"title": "A Novel By Tolstoy",
"owner_org": org["name"],
}
context = {"user": sysadmin_user.name}
call_action("package_create", context, **dataset)
# Add translation terms that match a couple of group names and package
# names. Group names and package names should _not_ get translated even
# if there are terms matching them, because they are used to form URLs.
for term in ("roger", "david", "annakarenina", "warandpeace"):
for lang_code in ("en", "de", "fr"):
data_dict = {
"term": term,
"term_translation": "this should not be rendered",
"lang_code": lang_code,
}
call_action("term_translation_update", **data_dict)
@pytest.mark.usefixtures("prepare", "with_plugins")
@pytest.mark.ckan_config(
"ckan.plugins", "multilingual_dataset multilingual_group multilingual_tag"
)
class TestDatasetTermTranslation:
"Test the translation of datasets by the multilingual_dataset plugin."
def test_user_read_translation(self, app):
"""Test the translation of datasets on user view pages by the
multilingual_dataset plugin.
"""
# It is testsysadmin who created the dataset, so testsysadmin whom
# we'd expect to see the datasets for.
for user_name in ("testsysadmin",):
offset = str(h.url_for("user.read", id=user_name))
for (lang_code, translations) in (
("de", _create_test_data.german_translations),
("fr", _create_test_data.french_translations),
("en", _create_test_data.english_translations),
("pl", {}),
):
response = app.get(
offset,
status=200,
extra_environ={
"CKAN_LANG": lang_code,
"CKAN_CURRENT_URL": offset,
},
)
terms = "A Novel By Tolstoy"
for term in terms:
if term in translations:
assert body_contains(response, translations[term])
elif term in _create_test_data.english_translations:
assert body_contains(
response,
_create_test_data.english_translations[term],
)
else:
assert body_contains(response, term)
assert not body_contains(
response, "this should not be rendered"
)
def test_org_read_translation(self, app):
for (lang_code, translations) in (
("de", _create_test_data.german_translations),
("fr", _create_test_data.french_translations),
("en", _create_test_data.english_translations),
("pl", {}),
):
offset = "/{0}/organization/{1}".format(lang_code, ORG_NAME)
response = app.get(offset, status=200)
terms = (
"A Novel By Tolstoy",
"russian",
"Roger likes these books.",
)
for term in terms:
if term in translations:
assert body_contains(response, translations[term])
elif term in _create_test_data.english_translations:
assert body_contains(
response, _create_test_data.english_translations[term]
)
else:
assert body_contains(response, term)
assert not body_contains(response, "this should not be rendered")
def test_org_index_translation(self, app):
for (lang_code, translations) in (
("de", _create_test_data.german_translations),
("fr", _create_test_data.french_translations),
("en", _create_test_data.english_translations),
("pl", {}),
):
offset = "/{0}/organization".format(lang_code)
response = app.get(offset, status=200)
for term in ("russian", "Roger likes these books."):
if term in translations:
assert body_contains(response, translations[term])
elif term in _create_test_data.english_translations:
assert body_contains(
response, _create_test_data.english_translations[term]
)
else:
assert body_contains(response, term)
assert body_contains(
response, "/{0}/organization/{1}".format(lang_code, ORG_NAME)
)
assert not body_contains(response, "this should not be rendered")
@pytest.mark.ckan_config(
"ckan.plugins", "multilingual_dataset multilingual_group multilingual_tag"
)
@pytest.mark.usefixtures("clean_db", "clean_index", "with_plugins")
class TestDatasetSearchIndex(object):
def test_translate_terms(self):
data_dicts = [
{
"term": "moo",
"term_translation": "french_moo",
"lang_code": "fr",
},
{
"term": "moo",
"term_translation": "this should not be rendered",
"lang_code": "fsdas",
},
{
"term": "an interesting note",
"term_translation": "french note",
"lang_code": "fr",
},
{
"term": "moon",
"term_translation": "french moon",
"lang_code": "fr",
},
{
"term": "boon",
"term_translation": "french boon",
"lang_code": "fr",
},
{
"term": "boon",
"term_translation": "italian boon",
"lang_code": "it",
},
{
"term": "david",
"term_translation": "french david",
"lang_code": "fr",
},
{
"term": "david",
"term_translation": "italian david",
"lang_code": "it",
},
]
for data_dict in data_dicts:
call_action("term_translation_update", **data_dict)
sample_index_data = {
"download_url": u"moo",
"notes": u"an interesting note",
"tags": [u"moon", "boon"],
"title": u"david",
}
result = mulilingual_plugin.MultilingualDataset().before_dataset_index(
sample_index_data
)
assert result == {
"text_sr@latin": "",
"text_fi": "",
"text_de": "",
"text_pt_BR": "",
u"title_fr": u"french david",
"text_fr": u"french_moo french note french moon french boon",
"text_ja": "",
"text_sr": "",
"title": u"david",
"text_ca": "",
"download_url": u"moo",
"text_hu": "",
"text_sa": "",
"text_cs_CZ": "",
"text_nl": "",
"text_no": "",
"text_ko_KR": "",
"text_sk": "",
"text_bg": "",
"text_sv": "",
"tags": [u"moon", "boon"],
"text_el": "",
"title_en": u"david",
"text_en": u"moo an interesting note moon boon",
"text_es": "",
"text_sl": "",
"text_pl": "",
"notes": u"an interesting note",
"text_lv": "",
"text_it": u"italian boon",
u"title_it": u"italian david",
"text_ru": "",
}, result

View File

@ -0,0 +1,14 @@
version: 1
groups:
- annotation: recline_view settings
options:
- key: ckan.recline.dataproxy_url
default: //jsonpdataproxy.appspot.com
example: https://mydataproxy.example.com
description: >
Custom URL to a self-hosted DataProxy instance. The DataProxy is an
external service currently used to stream data in JSON format to the
Recline-based views when data is not on the DataStore. The main instance
is deprecated and will be eventually shut down, so users that require it
can host an instance themselves and use this configuration option to
point Recline to it.

View File

@ -0,0 +1,306 @@
# encoding: utf-8
from __future__ import annotations
import os
import yaml
from ckan.types import Context, Validator
from logging import getLogger
from typing import Any, Callable, Container
from ckan.common import CKANConfig, json, config
import ckan.plugins as p
import ckan.plugins.toolkit as toolkit
from ckan.plugins.toolkit import _
log = getLogger(__name__)
ignore_empty = p.toolkit.get_validator('ignore_empty')
natural_number_validator = p.toolkit.get_validator('natural_number_validator')
Invalid = p.toolkit.Invalid
def get_mapview_config() -> dict[str, Any]:
'''
Extracts and returns map view configuration of the reclineview extension.
'''
namespace = 'ckanext.spatial.common_map.'
return {k.replace(namespace, ''): v
for k, v in config.items()
if k.startswith(namespace)}
def get_dataproxy_url() -> str:
'''
Returns the value of the ckan.recline.dataproxy_url config option
'''
return config.get('ckan.recline.dataproxy_url')
def in_list(list_possible_values: Callable[[], Container[Any]]) -> Validator:
'''
Validator that checks that the input value is one of the given
possible values.
:param list_possible_values: function that returns list of possible values
for validated field
:type possible_values: function
'''
def validate(value: Any):
if value not in list_possible_values():
raise Invalid('"{0}" is not a valid parameter'.format(value))
return validate
def datastore_fields(resource: dict[str, Any],
valid_field_types: Container[str]):
'''
Return a list of all datastore fields for a given resource, as long as
the datastore field type is in valid_field_types.
:param resource: resource dict
:type resource: dict
:param valid_field_types: field types to include in returned list
:type valid_field_types: list of strings
'''
data = {'resource_id': resource['id'], 'limit': 0}
fields = toolkit.get_action('datastore_search')({}, data)['fields']
return [{'value': f['id'], 'text': f['id']} for f in fields
if f['type'] in valid_field_types]
def _load_declaration(declaration: Any):
filename = os.path.join(
os.path.dirname(__file__),
"config_declaration.yaml"
)
with open(filename) as src:
data = yaml.safe_load(src)
try:
declaration.load_dict(data)
except ValueError:
# we a loading two recline plugins that are share config declaration.
pass
class ReclineViewBase(p.SingletonPlugin):
'''
This base class for the Recline view extensions.
'''
p.implements(p.IConfigurer, inherit=True)
p.implements(p.IResourceView, inherit=True)
p.implements(p.ITemplateHelpers, inherit=True)
def update_config(self, config: CKANConfig):
'''
Set up the resource library, public directory and
template directory for the view
'''
toolkit.add_public_directory(config, 'theme/public')
toolkit.add_template_directory(config, 'theme/templates')
toolkit.add_resource('theme/public', 'ckanext-reclineview')
log.warning(
"The Recline-based views are deprecated and"
"will be removed in future versions"
)
def can_view(self, data_dict: dict[str, Any]):
resource = data_dict['resource']
return (resource.get('datastore_active') or
'_datastore_only_resource' in resource.get('url', ''))
def setup_template_variables(self, context: Context,
data_dict: dict[str, Any]):
return {'resource_json': json.dumps(data_dict['resource']),
'resource_view_json': json.dumps(data_dict['resource_view'])}
def view_template(self, context: Context, data_dict: dict[str, Any]):
return 'recline_view.html'
def get_helpers(self) -> dict[str, Callable[..., Any]]:
return {
'get_map_config': get_mapview_config,
'get_dataproxy_url': get_dataproxy_url,
}
class ReclineView(ReclineViewBase):
'''
This extension views resources using a Recline MultiView.
'''
p.implements(p.IConfigDeclaration)
def declare_config_options(self, declaration: Any, key: Any):
_load_declaration(declaration)
def info(self) -> dict[str, Any]:
return {'name': 'recline_view',
'title': _('Data Explorer'),
'filterable': True,
'icon': 'table',
'requires_datastore': False,
'default_title': p.toolkit._('Data Explorer'),
}
def can_view(self, data_dict: dict[str, Any]):
resource = data_dict['resource']
if (resource.get('datastore_active') or
'_datastore_only_resource' in resource.get('url', '')):
return True
resource_format = resource.get('format', None)
if resource_format:
return resource_format.lower() in [
'csv', 'xls', 'xlsx', 'ods', 'tsv'
]
else:
return False
class ReclineGridView(ReclineViewBase):
'''
This extension views resources using a Recline grid.
'''
p.implements(p.IConfigDeclaration)
def declare_config_options(self, declaration: Any, key: Any):
_load_declaration(declaration)
def info(self) -> dict[str, Any]:
return {'name': 'recline_grid_view',
'title': _('Grid'),
'filterable': True,
'icon': 'table',
'requires_datastore': True,
'default_title': p.toolkit._('Table'),
}
class ReclineGraphView(ReclineViewBase):
'''
This extension views resources using a Recline graph.
'''
p.implements(p.IConfigDeclaration)
def declare_config_options(self, declaration: Any, key: Any):
_load_declaration(declaration)
graph_types = [{'value': 'lines-and-points',
'text': 'Lines and points'},
{'value': 'lines', 'text': 'Lines'},
{'value': 'points', 'text': 'Points'},
{'value': 'bars', 'text': 'Bars'},
{'value': 'columns', 'text': 'Columns'}]
datastore_fields = []
datastore_field_types = ['numeric', 'int4', 'timestamp']
def list_graph_types(self):
return [t['value'] for t in self.graph_types]
def list_datastore_fields(self):
return [t['value'] for t in self.datastore_fields]
def info(self) -> dict[str, Any]:
# in_list validator here is passed functions because this
# method does not know what the possible values of the
# datastore fields are (requires a datastore search)
schema = {
'offset': [ignore_empty, natural_number_validator],
'limit': [ignore_empty, natural_number_validator],
'graph_type': [ignore_empty, in_list(self.list_graph_types)],
'group': [ignore_empty, in_list(self.list_datastore_fields)],
'series': [ignore_empty, in_list(self.list_datastore_fields)]
}
return {'name': 'recline_graph_view',
'title': _('Graph'),
'filterable': True,
'icon': 'chart-bar',
'requires_datastore': True,
'schema': schema,
'default_title': p.toolkit._('Graph'),
}
def setup_template_variables(self, context: Context,
data_dict: dict[str, Any]):
self.datastore_fields = datastore_fields(data_dict['resource'],
self.datastore_field_types)
vars: dict[str, Any] = ReclineViewBase.setup_template_variables(
self, context, data_dict)
vars.update({'graph_types': self.graph_types,
'graph_fields': self.datastore_fields})
return vars
def form_template(self, context: Context, data_dict: dict[str, Any]):
return 'recline_graph_form.html'
class ReclineMapView(ReclineViewBase):
'''
This extension views resources using a Recline map.
'''
map_field_types = [{'value': 'lat_long',
'text': 'Latitude / Longitude fields'},
{'value': 'geojson', 'text': 'GeoJSON'}]
datastore_fields = []
datastore_field_latlon_types = ['numeric', 'text']
datastore_field_geojson_types = ['text']
def list_map_field_types(self):
return [t['value'] for t in self.map_field_types]
def list_datastore_fields(self):
return [t['value'] for t in self.datastore_fields]
def info(self) -> dict[str, Any]:
# in_list validator here is passed functions because this
# method does not know what the possible values of the
# datastore fields are (requires a datastore search)
schema = {
'offset': [ignore_empty, natural_number_validator],
'limit': [ignore_empty, natural_number_validator],
'map_field_type': [ignore_empty,
in_list(self.list_map_field_types)],
'latitude_field': [ignore_empty,
in_list(self.list_datastore_fields)],
'longitude_field': [ignore_empty,
in_list(self.list_datastore_fields)],
'geojson_field': [ignore_empty,
in_list(self.list_datastore_fields)],
'auto_zoom': [ignore_empty],
'cluster_markers': [ignore_empty]
}
return {'name': 'recline_map_view',
'title': _('Map'),
'schema': schema,
'filterable': True,
'icon': 'map-marker',
'default_title': p.toolkit._('Map'),
}
def setup_template_variables(self, context: Context,
data_dict: dict[str, Any]):
map_latlon_fields = datastore_fields(
data_dict['resource'], self.datastore_field_latlon_types)
map_geojson_fields = datastore_fields(
data_dict['resource'], self.datastore_field_geojson_types)
self.datastore_fields = map_latlon_fields + map_geojson_fields
vars: dict[str, Any] = ReclineViewBase.setup_template_variables(
self, context, data_dict)
vars.update({'map_field_types': self.map_field_types,
'map_latlon_fields': map_latlon_fields,
'map_geojson_fields': map_geojson_fields
})
return vars
def form_template(self, context: Context, data_dict: dict[str, Any]):
return 'recline_map_form.html'

View File

@ -0,0 +1,152 @@
# encoding: utf-8
import pytest
import ckan.model as model
import ckan.plugins as p
import ckan.lib.helpers as h
import ckanext.reclineview.plugin as plugin
import ckan.lib.create_test_data as create_test_data
from ckan.tests import helpers, factories
@pytest.mark.usefixtures("with_plugins", "with_request_context")
class BaseTestReclineViewBase(object):
@pytest.fixture(autouse=True)
def initial_data(self, clean_db, with_request_context):
create_test_data.CreateTestData.create()
self.p = self.view_class()
self.resource_view, self.package, self.resource_id = \
_create_test_view(self.view_type)
def test_can_view(self):
data_dict = {'resource': {'datastore_active': True}}
assert self.p.can_view(data_dict)
data_dict = {'resource': {'datastore_active': False}}
assert not self.p.can_view(data_dict)
def test_title_description_iframe_shown(self, app):
url = h.url_for('{}_resource.read'.format(self.package.type),
id=self.package.name, resource_id=self.resource_id)
result = app.get(url)
assert self.resource_view['title'] in result
assert self.resource_view['description'] in result
assert 'data-module="data-viewer"' in result.body
@pytest.mark.ckan_config('ckan.plugins', 'recline_view')
class TestReclineView(BaseTestReclineViewBase):
view_type = 'recline_view'
view_class = plugin.ReclineView
def test_it_has_no_schema(self):
schema = self.p.info().get('schema')
assert schema is None, schema
def test_can_view_format_no_datastore(self):
'''
Test can_view with acceptable formats when datastore_active is False
(DataProxy in use).
'''
formats = ['CSV', 'XLS', 'TSV', 'csv', 'xls', 'tsv']
for resource_format in formats:
data_dict = {'resource': {'datastore_active': False,
'format': resource_format}}
assert self.p.can_view(data_dict)
def test_can_view_bad_format_no_datastore(self):
'''
Test can_view with incorrect formats when datastore_active is False.
'''
formats = ['TXT', 'txt', 'doc', 'JSON']
for resource_format in formats:
data_dict = {'resource': {'datastore_active': False,
'format': resource_format}}
assert not self.p.can_view(data_dict)
@pytest.mark.ckan_config('ckan.plugins', 'recline_view datastore')
@pytest.mark.ckan_config('ckan.views.default_views', 'recline_view')
@pytest.mark.usefixtures("clean_db", "with_plugins")
class TestReclineViewDatastoreOnly(object):
def test_create_datastore_only_view(self, app):
dataset = factories.Dataset()
data = {
'resource': {'package_id': dataset['id']},
'fields': [{'id': 'a'}, {'id': 'b'}],
'records': [{'a': 1, 'b': 'xyz'}, {'a': 2, 'b': 'zzz'}]
}
result = helpers.call_action('datastore_create', **data)
resource_id = result['resource_id']
url = h.url_for('{}_resource.read'.format(dataset['type']),
id=dataset['id'], resource_id=resource_id)
result = app.get(url)
assert 'data-module="data-viewer"' in result.body
@pytest.mark.ckan_config('ckan.plugins', 'recline_grid_view')
class TestReclineGridView(BaseTestReclineViewBase):
view_type = 'recline_grid_view'
view_class = plugin.ReclineGridView
def test_it_has_no_schema(self):
schema = self.p.info().get('schema')
assert schema is None, schema
@pytest.mark.ckan_config('ckan.plugins', 'recline_graph_view')
class TestReclineGraphView(BaseTestReclineViewBase):
view_type = 'recline_graph_view'
view_class = plugin.ReclineGraphView
def test_it_has_the_correct_schema_keys(self):
schema = self.p.info().get('schema')
expected_keys = ['offset', 'limit', 'graph_type', 'group', 'series']
_assert_schema_exists_and_has_keys(schema, expected_keys)
@pytest.mark.ckan_config('ckan.plugins', 'recline_map_view')
class TestReclineMapView(BaseTestReclineViewBase):
view_type = 'recline_map_view'
view_class = plugin.ReclineMapView
def test_it_has_the_correct_schema_keys(self):
schema = self.p.info().get('schema')
expected_keys = ['offset', 'limit', 'map_field_type',
'latitude_field', 'longitude_field', 'geojson_field',
'auto_zoom', 'cluster_markers']
_assert_schema_exists_and_has_keys(schema, expected_keys)
def _create_test_view(view_type):
context = {'model': model,
'session': model.Session,
'user': model.User.get('testsysadmin').name}
package = model.Package.get('annakarenina')
resource_id = package.resources[1].id
resource_view = {'resource_id': resource_id,
'view_type': view_type,
'title': u'Test View',
'description': u'A nice test view'}
resource_view = p.toolkit.get_action('resource_view_create')(
context, resource_view)
return resource_view, package, resource_id
def _assert_schema_exists_and_has_keys(schema, expected_keys):
assert schema is not None, schema
keys = list(schema.keys())
keys.sort()
expected_keys.sort()
assert keys == expected_keys, '%s != %s' % (keys, expected_keys)

View File

@ -0,0 +1,380 @@
body {
background-color: #fff;
}
.recline-data-explorer {
position: relative;
overflow: auto;
}
.recline-record-count {
float: left;
margin-left: 10px;
line-height: 26px;
}
.loading-dialog {
width: 120px;
}
.recline-slickgrid {
height: 600px;
}
/*
.recline-timeline .vmm-timeline {
height: 600px;
}
.recline-pager .pagination {
margin: 0;
float: left;
}
.recline-pager .pagination a {
line-height: 26px;
}
.recline-pager .pagination input {
width: 30px;
margin: 0;
padding: 2px 4px;
}
*/
/*
.recline-query-editor {
float: right;
}
*/
.loading-spinner {
float: right;
background-image: url('../img/ajaxload-circle.gif');
width: 32px;
height: 32px;
}
.recline-data-explorer .data-view-sidebar {
float: right;
margin-left: 8px;
width: 220px;
}
.recline-data-explorer .header .navigation {
margin-bottom: 8px;
}
.recline-data-explorer .header .navigation,
.recline-data-explorer .header .pagination,
.recline-data-explorer .header .pagination form
{
display: inline;
}
.recline-data-explorer .header .navigation {
float: left;
}
.recline-data-explorer .header .menu-right {
float: right;
margin-left: 5px;
padding-left: 5px;
}
.recline-results-info {
line-height: 35px;
margin-left: 20px;
float: left;
}
.recline-data-explorer .data-view-sidebar > div {
margin-top: 5px;
margin-bottom: 10px;
}
.recline-data-explorer .radio,
.recline-data-explorer .checkbox {
padding-left: 20px;
}
.recline-data-explorer .editor-update-map {
margin: 30px 0px 20px 0px;
}
.recline-data-explorer label {
font-weight: normal;
}
/**********************************************************
* Query Editor
*********************************************************/
.recline-query-editor {
float: right;
height: 35px;
padding-right: 5px;
margin-right: 5px;
border-right: solid 2px #ddd;
}
.header .input-prepend {
margin-bottom: auto;
}
.header .add-on {
float: left;
}
/* needed for Chrome but not FF */
.header .add-on {
margin-left: -27px;
}
/* needed for FF but not chrome */
.header .input-prepend {
vertical-align: top;
}
.recline-query-editor form button {
vertical-align: top;
}
/* label for screen reader */
.recline-query-editor .form-inline label {
position: absolute;
top:0;
left:-9999px
}
/**********************************************************
* Pager
*********************************************************/
.recline-pager {
float: left;
margin: auto;
display: block;
margin-left: 20px;
}
.recline-pager .pagination li {
display: inline-block;
}
.recline-pager .pagination label {
display:none;
}
.recline-pager .pagination input {
width: 40px;
height: 25px;
padding: 2px 4px;
margin: 0;
margin-top: -2px;
border: 1px solid #cccccc;
box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
transition: border linear 0.2s, box-shadow linear 0.2s;
border-radius: 4px;
-webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
-webkit-transition: border linear 0.2s, box-shadow linear 0.2s;
-webkit-border-radius: 4px;
-moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
-moz-transition: border linear 0.2s, box-shadow linear 0.2s;
-moz-border-radius: 4px;
-o-transition: border linear 0.2s, box-shadow linear 0.2s;
}
.recline-pager .pagination a {
float: none;
margin-left: -5px;
color: #555;
}
.recline-pager .pagination .page-range {
height: 34px;
padding: 5px 8px;
margin-left: -5px;
border: 1px solid #ddd;
}
.recline-pager .pagination .page-range a {
padding: 0px 12px;
border: none;
}
.recline-pager .pagination .page-range a:hover {
background-color: #ffffff;
}
.recline-pager .pagination > li:first-child > a {
border-bottom-left-radius: 4px;
border-top-left-radius: 4px;
border-bottom-right-radius: 0px;
border-top-right-radius: 0px;
height: 34px;
}
.recline-pager .pagination > li:last-child > a {
border-bottom-right-radius: 4px;
border-top-right-radius: 4px;
border-bottom-left-radius: 0px;
border-top-left-radius: 0px;
height: 34px;
}
/**********************************************************
* Filter Editor
*********************************************************/
.recline-filter-editor {
padding: 8px;
display: none;
}
.recline-filter-editor .filters {
margin: 20px 0px;
}
.recline-filter-editor h3 {
margin-top: 4px;
}
.recline-filter-editor .filter {
margin-top: 20px;
}
.recline-filter-editor .filter .form-group {
margin-bottom: 0px;
}
.recline-filter-editor .filter input,
.recline-filter-editor .filter label {
margin: 0px;
}
.recline-filter-editor .js-edit button {
margin: 25px 0px 0px 0px;
}
.recline-filter-editor .filter-term a {
font-size: 18px;
}
.recline-filter-editor input,
.recline-filter-editor select
{
width: 175px;
}
.recline-filter-editor input {
margin-top: 0.5em;
margin-bottom: 10px;
-webkit-border-radius: 4px;
-moz-border-radius: 4px;
border-radius: 4px;
border: 1px solid #cccccc;
}
.recline-filter-editor label {
font-weight: normal;
display: block;
}
.recline-filter-editor legend {
margin-bottom: 5px;
}
.recline-filter-editor .add-filter {
margin-top: 1em;
margin-bottom: 2em;
}
.recline-filter-editor .update-filter {
margin-top: 1em;
}
/**********************************************************
* Fields Widget
*********************************************************/
.recline-fields-view {
display: none;
}
.recline-fields-view .fields-list {
padding: 0;
}
.recline-fields-view .panel {
background-color: #f5f5f5;
border: 1px solid #e5e5e5;
}
.recline-fields-view .panel-group h3 {
padding-left: 10px;
}
.recline-fields-view .fields-list .panel-heading {
padding: 2px 5px;
margin: 1px 0px 1px 5px;
}
.recline-fields-view .panel a,
.recline-fields-view .panel h4 {
display: inline;
}
.recline-fields-view .panel a {
padding: 0;
}
.recline-fields-view .panel h4 {
word-wrap: break-word
}
.recline-fields-view .clear {
clear: both;
}
.recline-fields-view .facet-items {
list-style-type: none;
margin-left: 0;
}
.recline-fields-view .facet-item .term {
font-weight: bold;
}
.recline-fields-view .facet-item .count {
}
/**********************************************************
* Notifications
*********************************************************/
.recline-data-explorer .notification-loader {
width: 18px;
margin-left: 5px;
background-image: url(data:image/gif;base64,R0lGODlhEAAQAPQAAP///wAAAPDw8IqKiuDg4EZGRnp6egAAAFhYWCQkJKysrL6+vhQUFJycnAQEBDY2NmhoaAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH/C05FVFNDQVBFMi4wAwEAAAAh/hpDcmVhdGVkIHdpdGggYWpheGxvYWQuaW5mbwAh+QQJCgAAACwAAAAAEAAQAAAFdyAgAgIJIeWoAkRCCMdBkKtIHIngyMKsErPBYbADpkSCwhDmQCBethRB6Vj4kFCkQPG4IlWDgrNRIwnO4UKBXDufzQvDMaoSDBgFb886MiQadgNABAokfCwzBA8LCg0Egl8jAggGAA1kBIA1BAYzlyILczULC2UhACH5BAkKAAAALAAAAAAQABAAAAV2ICACAmlAZTmOREEIyUEQjLKKxPHADhEvqxlgcGgkGI1DYSVAIAWMx+lwSKkICJ0QsHi9RgKBwnVTiRQQgwF4I4UFDQQEwi6/3YSGWRRmjhEETAJfIgMFCnAKM0KDV4EEEAQLiF18TAYNXDaSe3x6mjidN1s3IQAh+QQJCgAAACwAAAAAEAAQAAAFeCAgAgLZDGU5jgRECEUiCI+yioSDwDJyLKsXoHFQxBSHAoAAFBhqtMJg8DgQBgfrEsJAEAg4YhZIEiwgKtHiMBgtpg3wbUZXGO7kOb1MUKRFMysCChAoggJCIg0GC2aNe4gqQldfL4l/Ag1AXySJgn5LcoE3QXI3IQAh+QQJCgAAACwAAAAAEAAQAAAFdiAgAgLZNGU5joQhCEjxIssqEo8bC9BRjy9Ag7GILQ4QEoE0gBAEBcOpcBA0DoxSK/e8LRIHn+i1cK0IyKdg0VAoljYIg+GgnRrwVS/8IAkICyosBIQpBAMoKy9dImxPhS+GKkFrkX+TigtLlIyKXUF+NjagNiEAIfkECQoAAAAsAAAAABAAEAAABWwgIAICaRhlOY4EIgjH8R7LKhKHGwsMvb4AAy3WODBIBBKCsYA9TjuhDNDKEVSERezQEL0WrhXucRUQGuik7bFlngzqVW9LMl9XWvLdjFaJtDFqZ1cEZUB0dUgvL3dgP4WJZn4jkomWNpSTIyEAIfkECQoAAAAsAAAAABAAEAAABX4gIAICuSxlOY6CIgiD8RrEKgqGOwxwUrMlAoSwIzAGpJpgoSDAGifDY5kopBYDlEpAQBwevxfBtRIUGi8xwWkDNBCIwmC9Vq0aiQQDQuK+VgQPDXV9hCJjBwcFYU5pLwwHXQcMKSmNLQcIAExlbH8JBwttaX0ABAcNbWVbKyEAIfkECQoAAAAsAAAAABAAEAAABXkgIAICSRBlOY7CIghN8zbEKsKoIjdFzZaEgUBHKChMJtRwcWpAWoWnifm6ESAMhO8lQK0EEAV3rFopIBCEcGwDKAqPh4HUrY4ICHH1dSoTFgcHUiZjBhAJB2AHDykpKAwHAwdzf19KkASIPl9cDgcnDkdtNwiMJCshACH5BAkKAAAALAAAAAAQABAAAAV3ICACAkkQZTmOAiosiyAoxCq+KPxCNVsSMRgBsiClWrLTSWFoIQZHl6pleBh6suxKMIhlvzbAwkBWfFWrBQTxNLq2RG2yhSUkDs2b63AYDAoJXAcFRwADeAkJDX0AQCsEfAQMDAIPBz0rCgcxky0JRWE1AmwpKyEAIfkECQoAAAAsAAAAABAAEAAABXkgIAICKZzkqJ4nQZxLqZKv4NqNLKK2/Q4Ek4lFXChsg5ypJjs1II3gEDUSRInEGYAw6B6zM4JhrDAtEosVkLUtHA7RHaHAGJQEjsODcEg0FBAFVgkQJQ1pAwcDDw8KcFtSInwJAowCCA6RIwqZAgkPNgVpWndjdyohACH5BAkKAAAALAAAAAAQABAAAAV5ICACAimc5KieLEuUKvm2xAKLqDCfC2GaO9eL0LABWTiBYmA06W6kHgvCqEJiAIJiu3gcvgUsscHUERm+kaCxyxa+zRPk0SgJEgfIvbAdIAQLCAYlCj4DBw0IBQsMCjIqBAcPAooCBg9pKgsJLwUFOhCZKyQDA3YqIQAh+QQJCgAAACwAAAAAEAAQAAAFdSAgAgIpnOSonmxbqiThCrJKEHFbo8JxDDOZYFFb+A41E4H4OhkOipXwBElYITDAckFEOBgMQ3arkMkUBdxIUGZpEb7kaQBRlASPg0FQQHAbEEMGDSVEAA1QBhAED1E0NgwFAooCDWljaQIQCE5qMHcNhCkjIQAh+QQJCgAAACwAAAAAEAAQAAAFeSAgAgIpnOSoLgxxvqgKLEcCC65KEAByKK8cSpA4DAiHQ/DkKhGKh4ZCtCyZGo6F6iYYPAqFgYy02xkSaLEMV34tELyRYNEsCQyHlvWkGCzsPgMCEAY7Cg04Uk48LAsDhRA8MVQPEF0GAgqYYwSRlycNcWskCkApIyEAOwAAAAAAAAAAAA%3D%3D);
display: inline-block;
background-repeat: no-repeat;
}
.recline-data-explorer .alert-loader {
position: absolute;
width: 200px;
left: 50%;
margin-left: -100px;
z-index: 10000;
padding: 40px 0px 40px 0px;
margin-top: -10px;
text-align: center;
font-size: 16px;
font-weight: bold;
-webkit-border-radius: 0px;
-moz-border-radius: 0px;
border-radius: 0px;
border-top: none;
}

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

View File

@ -0,0 +1,247 @@
this.ckan.module('recline_view', function (jQuery) {
return {
options: {
site_url: "",
controlsClassName: "controls",
dataproxyUrl: "//jsonpdataproxy.appspot.com"
},
initialize: function () {
jQuery.proxyAll(this, /_on/);
this.options.resource = JSON.parse(this.options.resource);
this.options.resourceView = JSON.parse(this.options.resourceView);
this.el.ready(this._onReady);
// hack to make leaflet use a particular location to look for images
L.Icon.Default.imagePath = this.options.site_url + 'vendor/leaflet/0.7.7/images';
},
_onReady: function() {
var resourceData = this.options.resource,
resourceView = this.options.resourceView;
this.loadView(resourceData, resourceView);
},
loadView: function (resourceData, reclineView) {
var self = this;
function showError(msg){
msg = msg || self._('error loading view');
window.parent.ckan.pubsub.publish('data-viewer-error', msg);
}
if (resourceData.formatNormalized === '') {
var tmp = resourceData.url.split('/');
tmp = tmp[tmp.length - 1];
tmp = tmp.split('?'); // query strings
tmp = tmp[0];
var ext = tmp.split('.');
if (ext.length > 1) {
resourceData.formatNormalized = ext[ext.length-1];
}
}
var errorMsg, dataset, map_config;
if (!resourceData.datastore_active) {
recline.Backend.DataProxy.timeout = 10000;
recline.Backend.DataProxy.dataproxy_url = this.options.dataproxyUrl;
resourceData.backend = 'dataproxy';
} else {
resourceData.backend = 'ckan';
resourceData.endpoint = jQuery('body').data('site-root') + 'api';
}
dataset = new recline.Model.Dataset(resourceData);
map_config = this.options.map_config;
var query = new recline.Model.Query();
query.set({ size: reclineView.limit || 100 });
query.set({ from: reclineView.offset || 0 });
var urlFilters = {};
try {
if (window.parent.ckan.views && window.parent.ckan.views.filters) {
urlFilters = window.parent.ckan.views.filters.get();
}
} catch(e) {}
var defaultFilters = reclineView.filters || {},
filters = jQuery.extend({}, defaultFilters, urlFilters);
jQuery.each(filters, function (field,values) {
query.addFilter({type: 'term', field: field, term: values});
});
dataset.queryState.set(query.toJSON(), {silent: true});
errorMsg = this._('Could not load view') + ': ';
if (resourceData.backend == 'ckan') {
errorMsg += this._('DataStore returned an error');
} else if (resourceData.backend == 'dataproxy'){
errorMsg += this._('DataProxy returned an error');
}
dataset.fetch()
.done(function(dataset){
self.initializeView(dataset, reclineView);
})
.fail(function(error){
if (error.message) errorMsg += ' (' + error.message + ')';
showError(errorMsg);
});
},
initializeView: function (dataset, reclineView) {
var view,
state,
controls = [];
if(reclineView.view_type === "recline_graph_view") {
state = {
"graphType": reclineView.graph_type,
"group": reclineView.group,
"series": [reclineView.series]
};
view = new recline.View.Graph({model: dataset, state: state});
} else if(reclineView.view_type === "recline_map_view") {
state = {
geomField: null,
latField: null,
lonField: null,
autoZoom: Boolean(reclineView.auto_zoom),
cluster: Boolean(reclineView.cluster_markers)
};
if(reclineView.map_field_type === "geojson") {
state.geomField = reclineView.geojson_field;
} else {
state.latField = reclineView.latitude_field;
state.lonField = reclineView.longitude_field;
}
view = new recline.View.Map($.extend(this._reclineMapViewOptions(dataset, this.options.map_config), {state:state}));
} else if(reclineView.view_type === "recline_view") {
view = this._newDataExplorer(dataset, this.options.map_config);
} else {
// default to Grid
view = new recline.View.SlickGrid({model: dataset});
controls = [
new recline.View.Pager({model: view.model}),
new recline.View.RecordCount({model: dataset}),
new recline.View.QueryEditor({model: view.model.queryState})
];
}
// recline_view automatically adds itself to the DOM, so we don't
// need to bother with it.
if(reclineView.view_type !== 'recline_view') {
var newElements = jQuery('<div />');
this._renderControls(newElements, controls, this.options.controlsClassName);
newElements.append(view.el);
jQuery(this.el).html(newElements);
view.visible = true;
view.render();
}
if(reclineView.view_type === "recline_graph_view") {
view.redraw();
}
},
_reclineMapViewOptions: function(dataset, map_config) {
var tile_url, attribution, subdomains;
tile_url = attribution = subdomains = '';
if (map_config.type == 'mapbox') {
// MapBox base map
if (!map_config['mapbox.map_id'] || !map_config['mapbox.access_token']) {
throw '[CKAN Map Widgets] You need to provide a map ID ' +
'([account].[handle]) and an access token when using a ' +
'MapBox layer. See ' +
'http://www.mapbox.com/developers/api-overview/ for details';
}
tile_url = '//{s}.tiles.mapbox.com/v4/' +
map_config['mapbox.map_id'] +
'/{z}/{x}/{y}.png?access_token=' +
map_config['mapbox.access_token'];
handle = map_config['mapbox.map_id'];
subdomains = map_config.subdomains || 'abcd';
attribution = map_config.attribution ||
'Data: <a href="http://osm.org/copyright" ' +
'target="_blank">OpenStreetMap</a>, Design: <a ' +
'href="http://mapbox.com/about/maps" ' +
'target="_blank">MapBox</a>';
} else if (map_config.type == 'custom') {
// Custom XYZ layer
tile_url = map_config['custom.url'] || '';
attribution = map_config.attribution || '';
subdomains = map_config.subdomains || '';
if (map_config['custom.tms'])
var tms = map_config['custom.tms'];
}
return {
model: dataset,
mapTilesURL: tile_url,
mapTilesAttribution: attribution,
mapTilesSubdomains: subdomains
};
},
_newDataExplorer: function (dataset, map_config) {
var views = [
{
id: 'grid',
label: this._('Grid'),
view: new recline.View.SlickGrid({
model: dataset
})
},
{
id: 'graph',
label: this._('Graph'),
view: new recline.View.Graph({
model: dataset
})
},
{
id: 'map',
label: this._('Map'),
view: new recline.View.Map(this._reclineMapViewOptions(dataset, map_config))
}
];
var sidebarViews = [
{
id: 'valueFilter',
label: this._('Filters'),
view: new recline.View.ValueFilter({
model: dataset
})
}
];
var dataExplorer = new recline.View.MultiView({
el: this.el,
model: dataset,
views: views,
sidebarViews: sidebarViews,
config: {
readOnly: true
}
});
return dataExplorer;
},
_renderControls: function (el, controls, className) {
var controlsEl = jQuery("<div class=\"clearfix " + className + "\" />");
for (var i = 0; i < controls.length; i++) {
controlsEl.append(controls[i].el);
}
jQuery(el).append(controlsEl);
}
};
});

View File

@ -0,0 +1,15 @@
this.ckan.module('recline_view',function(jQuery){return{options:{site_url:"",controlsClassName:"controls"},initialize:function(){jQuery.proxyAll(this,/_on/);this.options.resource=JSON.parse(this.options.resource);this.options.resourceView=JSON.parse(this.options.resourceView);this.el.ready(this._onReady);L.Icon.Default.imagePath=this.options.site_url+'vendor/leaflet/0.7.7/images';},_onReady:function(){var resourceData=this.options.resource,resourceView=this.options.resourceView;this.loadView(resourceData,resourceView);},loadView:function(resourceData,reclineView){var self=this;function showError(msg){msg=msg||self._('error loading view');window.parent.ckan.pubsub.publish('data-viewer-error',msg);}
if(resourceData.formatNormalized===''){var tmp=resourceData.url.split('/');tmp=tmp[tmp.length-1];tmp=tmp.split('?');tmp=tmp[0];var ext=tmp.split('.');if(ext.length>1){resourceData.formatNormalized=ext[ext.length-1];}}
var errorMsg,dataset,map_config;if(!resourceData.datastore_active){recline.Backend.DataProxy.timeout=10000;resourceData.backend='dataproxy';}else{resourceData.backend='ckan';resourceData.endpoint=jQuery('body').data('site-root')+'api';}
dataset=new recline.Model.Dataset(resourceData);map_config=this.options.map_config;var query=new recline.Model.Query();query.set({size:reclineView.limit||100});query.set({from:reclineView.offset||0});var urlFilters={};try{if(window.parent.ckan.views&&window.parent.ckan.views.filters){urlFilters=window.parent.ckan.views.filters.get();}}catch(e){}
var defaultFilters=reclineView.filters||{},filters=jQuery.extend({},defaultFilters,urlFilters);jQuery.each(filters,function(field,values){query.addFilter({type:'term',field:field,term:values});});dataset.queryState.set(query.toJSON(),{silent:true});errorMsg=this._('Could not load view')+': ';if(resourceData.backend=='ckan'){errorMsg+=this._('DataStore returned an error');}else if(resourceData.backend=='dataproxy'){errorMsg+=this._('DataProxy returned an error');}
dataset.fetch().done(function(dataset){self.initializeView(dataset,reclineView);}).fail(function(error){if(error.message)errorMsg+=' ('+error.message+')';showError(errorMsg);});},initializeView:function(dataset,reclineView){var view,state,controls=[];if(reclineView.view_type==="recline_graph_view"){state={"graphType":reclineView.graph_type,"group":reclineView.group,"series":[reclineView.series]};view=new recline.View.Graph({model:dataset,state:state});}else if(reclineView.view_type==="recline_map_view"){state={geomField:null,latField:null,lonField:null,autoZoom:Boolean(reclineView.auto_zoom),cluster:Boolean(reclineView.cluster_markers)};if(reclineView.map_field_type==="geojson"){state.geomField=reclineView.geojson_field;}else{state.latField=reclineView.latitude_field;state.lonField=reclineView.longitude_field;}
view=new recline.View.Map(this._reclineMapViewOptions(dataset,this.options.map_config));}else if(reclineView.view_type==="recline_view"){view=this._newDataExplorer(dataset,this.options.map_config);}else{view=new recline.View.SlickGrid({model:dataset});controls=[new recline.View.Pager({model:view.model}),new recline.View.RecordCount({model:dataset}),new recline.View.QueryEditor({model:view.model.queryState})];}
if(reclineView.view_type!=='recline_view'){var newElements=jQuery('<div />');this._renderControls(newElements,controls,this.options.controlsClassName);newElements.append(view.el);jQuery(this.el).html(newElements);view.visible=true;view.render();}
if(reclineView.view_type==="recline_graph_view"){view.redraw();}},_reclineMapViewOptions:function(dataset,map_config){var tile_url,attribution,subdomains;tile_url=attribution=subdomains='';if(map_config.type=='mapbox'){if(!map_config['mapbox.map_id']||!map_config['mapbox.access_token']){throw'[CKAN Map Widgets] You need to provide a map ID '+'([account].[handle]) and an access token when using a '+'MapBox layer. See '+'http://www.mapbox.com/developers/api-overview/ for details';}
tile_url='//{s}.tiles.mapbox.com/v4/'+
map_config['mapbox.map_id']+'/{z}/{x}/{y}.png?access_token='+
map_config['mapbox.access_token'];handle=map_config['mapbox.map_id'];subdomains=map_config.subdomains||'abcd';attribution=map_config.attribution||'Data: <a href="http://osm.org/copyright" '+'target="_blank">OpenStreetMap</a>, Design: <a '+'href="http://mapbox.com/about/maps" '+'target="_blank">MapBox</a>';}else if(map_config.type=='custom'){tile_url=map_config['custom.url']||'';attribution=map_config.attribution||'';subdomains=map_config.subdomains||'';if(map_config['custom.tms'])
var tms=map_config['custom.tms'];}
return{model:dataset,mapTilesURL:tile_url,mapTilesAttribution:attribution,mapTilesSubdomains:subdomains};},_newDataExplorer:function(dataset,map_config){var views=[{id:'grid',label:this._('Grid'),view:new recline.View.SlickGrid({model:dataset})},{id:'graph',label:this._('Graph'),view:new recline.View.Graph({model:dataset})},{id:'map',label:this._('Map'),view:new recline.View.Map(this._reclineMapViewOptions(dataset,map_config))}];var sidebarViews=[{id:'valueFilter',label:this._('Filters'),view:new recline.View.ValueFilter({model:dataset})}];var dataExplorer=new recline.View.MultiView({el:this.el,model:dataset,views:views,sidebarViews:sidebarViews,config:{readOnly:true}});return dataExplorer;},_renderControls:function(el,controls,className){var controlsEl=jQuery("<div class=\"clearfix "+className+"\" />");for(var i=0;i<controls.length;i++){controlsEl.append(controls[i].el);}
jQuery(el).append(controlsEl);}};});

View File

@ -0,0 +1,15 @@
[IE conditional]
lte IE 7 =
vendor/json/json2.js
lte IE 8 =
vendor/flot/excanvas.js
[depends]
main = base/main
[groups]
main =

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,442 @@
/*!
* Bootstrap v3.2.0 (http://getbootstrap.com)
* Copyright 2011-2014 Twitter, Inc.
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
*/
.btn-default,
.btn-primary,
.btn-success,
.btn-info,
.btn-warning,
.btn-danger {
text-shadow: 0 -1px 0 rgba(0, 0, 0, .2);
-webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 1px rgba(0, 0, 0, .075);
box-shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 1px rgba(0, 0, 0, .075);
}
.btn-default:active,
.btn-primary:active,
.btn-success:active,
.btn-info:active,
.btn-warning:active,
.btn-danger:active,
.btn-default.active,
.btn-primary.active,
.btn-success.active,
.btn-info.active,
.btn-warning.active,
.btn-danger.active {
-webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);
box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);
}
.btn:active,
.btn.active {
background-image: none;
}
.btn-default {
text-shadow: 0 1px 0 #fff;
background-image: -webkit-linear-gradient(top, #fff 0%, #e0e0e0 100%);
background-image: -o-linear-gradient(top, #fff 0%, #e0e0e0 100%);
background-image: -webkit-gradient(linear, left top, left bottom, from(#fff), to(#e0e0e0));
background-image: linear-gradient(to bottom, #fff 0%, #e0e0e0 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe0e0e0', GradientType=0);
filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
background-repeat: repeat-x;
border-color: #dbdbdb;
border-color: #ccc;
}
.btn-default:hover,
.btn-default:focus {
background-color: #e0e0e0;
background-position: 0 -15px;
}
.btn-default:active,
.btn-default.active {
background-color: #e0e0e0;
border-color: #dbdbdb;
}
.btn-default:disabled,
.btn-default[disabled] {
background-color: #e0e0e0;
background-image: none;
}
.btn-primary {
background-image: -webkit-linear-gradient(top, #428bca 0%, #2d6ca2 100%);
background-image: -o-linear-gradient(top, #428bca 0%, #2d6ca2 100%);
background-image: -webkit-gradient(linear, left top, left bottom, from(#428bca), to(#2d6ca2));
background-image: linear-gradient(to bottom, #428bca 0%, #2d6ca2 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff2d6ca2', GradientType=0);
filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
background-repeat: repeat-x;
border-color: #2b669a;
}
.btn-primary:hover,
.btn-primary:focus {
background-color: #2d6ca2;
background-position: 0 -15px;
}
.btn-primary:active,
.btn-primary.active {
background-color: #2d6ca2;
border-color: #2b669a;
}
.btn-primary:disabled,
.btn-primary[disabled] {
background-color: #2d6ca2;
background-image: none;
}
.btn-success {
background-image: -webkit-linear-gradient(top, #5cb85c 0%, #419641 100%);
background-image: -o-linear-gradient(top, #5cb85c 0%, #419641 100%);
background-image: -webkit-gradient(linear, left top, left bottom, from(#5cb85c), to(#419641));
background-image: linear-gradient(to bottom, #5cb85c 0%, #419641 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff419641', GradientType=0);
filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
background-repeat: repeat-x;
border-color: #3e8f3e;
}
.btn-success:hover,
.btn-success:focus {
background-color: #419641;
background-position: 0 -15px;
}
.btn-success:active,
.btn-success.active {
background-color: #419641;
border-color: #3e8f3e;
}
.btn-success:disabled,
.btn-success[disabled] {
background-color: #419641;
background-image: none;
}
.btn-info {
background-image: -webkit-linear-gradient(top, #5bc0de 0%, #2aabd2 100%);
background-image: -o-linear-gradient(top, #5bc0de 0%, #2aabd2 100%);
background-image: -webkit-gradient(linear, left top, left bottom, from(#5bc0de), to(#2aabd2));
background-image: linear-gradient(to bottom, #5bc0de 0%, #2aabd2 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff2aabd2', GradientType=0);
filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
background-repeat: repeat-x;
border-color: #28a4c9;
}
.btn-info:hover,
.btn-info:focus {
background-color: #2aabd2;
background-position: 0 -15px;
}
.btn-info:active,
.btn-info.active {
background-color: #2aabd2;
border-color: #28a4c9;
}
.btn-info:disabled,
.btn-info[disabled] {
background-color: #2aabd2;
background-image: none;
}
.btn-warning {
background-image: -webkit-linear-gradient(top, #f0ad4e 0%, #eb9316 100%);
background-image: -o-linear-gradient(top, #f0ad4e 0%, #eb9316 100%);
background-image: -webkit-gradient(linear, left top, left bottom, from(#f0ad4e), to(#eb9316));
background-image: linear-gradient(to bottom, #f0ad4e 0%, #eb9316 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffeb9316', GradientType=0);
filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
background-repeat: repeat-x;
border-color: #e38d13;
}
.btn-warning:hover,
.btn-warning:focus {
background-color: #eb9316;
background-position: 0 -15px;
}
.btn-warning:active,
.btn-warning.active {
background-color: #eb9316;
border-color: #e38d13;
}
.btn-warning:disabled,
.btn-warning[disabled] {
background-color: #eb9316;
background-image: none;
}
.btn-danger {
background-image: -webkit-linear-gradient(top, #d9534f 0%, #c12e2a 100%);
background-image: -o-linear-gradient(top, #d9534f 0%, #c12e2a 100%);
background-image: -webkit-gradient(linear, left top, left bottom, from(#d9534f), to(#c12e2a));
background-image: linear-gradient(to bottom, #d9534f 0%, #c12e2a 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc12e2a', GradientType=0);
filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
background-repeat: repeat-x;
border-color: #b92c28;
}
.btn-danger:hover,
.btn-danger:focus {
background-color: #c12e2a;
background-position: 0 -15px;
}
.btn-danger:active,
.btn-danger.active {
background-color: #c12e2a;
border-color: #b92c28;
}
.btn-danger:disabled,
.btn-danger[disabled] {
background-color: #c12e2a;
background-image: none;
}
.thumbnail,
.img-thumbnail {
-webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, .075);
box-shadow: 0 1px 2px rgba(0, 0, 0, .075);
}
.dropdown-menu > li > a:hover,
.dropdown-menu > li > a:focus {
background-color: #e8e8e8;
background-image: -webkit-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%);
background-image: -o-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%);
background-image: -webkit-gradient(linear, left top, left bottom, from(#f5f5f5), to(#e8e8e8));
background-image: linear-gradient(to bottom, #f5f5f5 0%, #e8e8e8 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0);
background-repeat: repeat-x;
}
.dropdown-menu > .active > a,
.dropdown-menu > .active > a:hover,
.dropdown-menu > .active > a:focus {
background-color: #357ebd;
background-image: -webkit-linear-gradient(top, #428bca 0%, #357ebd 100%);
background-image: -o-linear-gradient(top, #428bca 0%, #357ebd 100%);
background-image: -webkit-gradient(linear, left top, left bottom, from(#428bca), to(#357ebd));
background-image: linear-gradient(to bottom, #428bca 0%, #357ebd 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff357ebd', GradientType=0);
background-repeat: repeat-x;
}
.navbar-default {
background-image: -webkit-linear-gradient(top, #fff 0%, #f8f8f8 100%);
background-image: -o-linear-gradient(top, #fff 0%, #f8f8f8 100%);
background-image: -webkit-gradient(linear, left top, left bottom, from(#fff), to(#f8f8f8));
background-image: linear-gradient(to bottom, #fff 0%, #f8f8f8 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff8f8f8', GradientType=0);
filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
background-repeat: repeat-x;
border-radius: 4px;
-webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 5px rgba(0, 0, 0, .075);
box-shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 5px rgba(0, 0, 0, .075);
}
.navbar-default .navbar-nav > .active > a {
background-image: -webkit-linear-gradient(top, #ebebeb 0%, #f3f3f3 100%);
background-image: -o-linear-gradient(top, #ebebeb 0%, #f3f3f3 100%);
background-image: -webkit-gradient(linear, left top, left bottom, from(#ebebeb), to(#f3f3f3));
background-image: linear-gradient(to bottom, #ebebeb 0%, #f3f3f3 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb', endColorstr='#fff3f3f3', GradientType=0);
background-repeat: repeat-x;
-webkit-box-shadow: inset 0 3px 9px rgba(0, 0, 0, .075);
box-shadow: inset 0 3px 9px rgba(0, 0, 0, .075);
}
.navbar-brand,
.navbar-nav > li > a {
text-shadow: 0 1px 0 rgba(255, 255, 255, .25);
}
.navbar-inverse {
background-image: -webkit-linear-gradient(top, #3c3c3c 0%, #222 100%);
background-image: -o-linear-gradient(top, #3c3c3c 0%, #222 100%);
background-image: -webkit-gradient(linear, left top, left bottom, from(#3c3c3c), to(#222));
background-image: linear-gradient(to bottom, #3c3c3c 0%, #222 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff3c3c3c', endColorstr='#ff222222', GradientType=0);
filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
background-repeat: repeat-x;
}
.navbar-inverse .navbar-nav > .active > a {
background-image: -webkit-linear-gradient(top, #222 0%, #282828 100%);
background-image: -o-linear-gradient(top, #222 0%, #282828 100%);
background-image: -webkit-gradient(linear, left top, left bottom, from(#222), to(#282828));
background-image: linear-gradient(to bottom, #222 0%, #282828 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff222222', endColorstr='#ff282828', GradientType=0);
background-repeat: repeat-x;
-webkit-box-shadow: inset 0 3px 9px rgba(0, 0, 0, .25);
box-shadow: inset 0 3px 9px rgba(0, 0, 0, .25);
}
.navbar-inverse .navbar-brand,
.navbar-inverse .navbar-nav > li > a {
text-shadow: 0 -1px 0 rgba(0, 0, 0, .25);
}
.navbar-static-top,
.navbar-fixed-top,
.navbar-fixed-bottom {
border-radius: 0;
}
.alert {
text-shadow: 0 1px 0 rgba(255, 255, 255, .2);
-webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .25), 0 1px 2px rgba(0, 0, 0, .05);
box-shadow: inset 0 1px 0 rgba(255, 255, 255, .25), 0 1px 2px rgba(0, 0, 0, .05);
}
.alert-success {
background-image: -webkit-linear-gradient(top, #dff0d8 0%, #c8e5bc 100%);
background-image: -o-linear-gradient(top, #dff0d8 0%, #c8e5bc 100%);
background-image: -webkit-gradient(linear, left top, left bottom, from(#dff0d8), to(#c8e5bc));
background-image: linear-gradient(to bottom, #dff0d8 0%, #c8e5bc 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffc8e5bc', GradientType=0);
background-repeat: repeat-x;
border-color: #b2dba1;
}
.alert-info {
background-image: -webkit-linear-gradient(top, #d9edf7 0%, #b9def0 100%);
background-image: -o-linear-gradient(top, #d9edf7 0%, #b9def0 100%);
background-image: -webkit-gradient(linear, left top, left bottom, from(#d9edf7), to(#b9def0));
background-image: linear-gradient(to bottom, #d9edf7 0%, #b9def0 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffb9def0', GradientType=0);
background-repeat: repeat-x;
border-color: #9acfea;
}
.alert-warning {
background-image: -webkit-linear-gradient(top, #fcf8e3 0%, #f8efc0 100%);
background-image: -o-linear-gradient(top, #fcf8e3 0%, #f8efc0 100%);
background-image: -webkit-gradient(linear, left top, left bottom, from(#fcf8e3), to(#f8efc0));
background-image: linear-gradient(to bottom, #fcf8e3 0%, #f8efc0 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fff8efc0', GradientType=0);
background-repeat: repeat-x;
border-color: #f5e79e;
}
.alert-danger {
background-image: -webkit-linear-gradient(top, #f2dede 0%, #e7c3c3 100%);
background-image: -o-linear-gradient(top, #f2dede 0%, #e7c3c3 100%);
background-image: -webkit-gradient(linear, left top, left bottom, from(#f2dede), to(#e7c3c3));
background-image: linear-gradient(to bottom, #f2dede 0%, #e7c3c3 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffe7c3c3', GradientType=0);
background-repeat: repeat-x;
border-color: #dca7a7;
}
.progress {
background-image: -webkit-linear-gradient(top, #ebebeb 0%, #f5f5f5 100%);
background-image: -o-linear-gradient(top, #ebebeb 0%, #f5f5f5 100%);
background-image: -webkit-gradient(linear, left top, left bottom, from(#ebebeb), to(#f5f5f5));
background-image: linear-gradient(to bottom, #ebebeb 0%, #f5f5f5 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb', endColorstr='#fff5f5f5', GradientType=0);
background-repeat: repeat-x;
}
.progress-bar {
background-image: -webkit-linear-gradient(top, #428bca 0%, #3071a9 100%);
background-image: -o-linear-gradient(top, #428bca 0%, #3071a9 100%);
background-image: -webkit-gradient(linear, left top, left bottom, from(#428bca), to(#3071a9));
background-image: linear-gradient(to bottom, #428bca 0%, #3071a9 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff3071a9', GradientType=0);
background-repeat: repeat-x;
}
.progress-bar-success {
background-image: -webkit-linear-gradient(top, #5cb85c 0%, #449d44 100%);
background-image: -o-linear-gradient(top, #5cb85c 0%, #449d44 100%);
background-image: -webkit-gradient(linear, left top, left bottom, from(#5cb85c), to(#449d44));
background-image: linear-gradient(to bottom, #5cb85c 0%, #449d44 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff449d44', GradientType=0);
background-repeat: repeat-x;
}
.progress-bar-info {
background-image: -webkit-linear-gradient(top, #5bc0de 0%, #31b0d5 100%);
background-image: -o-linear-gradient(top, #5bc0de 0%, #31b0d5 100%);
background-image: -webkit-gradient(linear, left top, left bottom, from(#5bc0de), to(#31b0d5));
background-image: linear-gradient(to bottom, #5bc0de 0%, #31b0d5 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff31b0d5', GradientType=0);
background-repeat: repeat-x;
}
.progress-bar-warning {
background-image: -webkit-linear-gradient(top, #f0ad4e 0%, #ec971f 100%);
background-image: -o-linear-gradient(top, #f0ad4e 0%, #ec971f 100%);
background-image: -webkit-gradient(linear, left top, left bottom, from(#f0ad4e), to(#ec971f));
background-image: linear-gradient(to bottom, #f0ad4e 0%, #ec971f 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffec971f', GradientType=0);
background-repeat: repeat-x;
}
.progress-bar-danger {
background-image: -webkit-linear-gradient(top, #d9534f 0%, #c9302c 100%);
background-image: -o-linear-gradient(top, #d9534f 0%, #c9302c 100%);
background-image: -webkit-gradient(linear, left top, left bottom, from(#d9534f), to(#c9302c));
background-image: linear-gradient(to bottom, #d9534f 0%, #c9302c 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc9302c', GradientType=0);
background-repeat: repeat-x;
}
.progress-bar-striped {
background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);
background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);
background-image: linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);
}
.list-group {
border-radius: 4px;
-webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, .075);
box-shadow: 0 1px 2px rgba(0, 0, 0, .075);
}
.list-group-item.active,
.list-group-item.active:hover,
.list-group-item.active:focus {
text-shadow: 0 -1px 0 #3071a9;
background-image: -webkit-linear-gradient(top, #428bca 0%, #3278b3 100%);
background-image: -o-linear-gradient(top, #428bca 0%, #3278b3 100%);
background-image: -webkit-gradient(linear, left top, left bottom, from(#428bca), to(#3278b3));
background-image: linear-gradient(to bottom, #428bca 0%, #3278b3 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff3278b3', GradientType=0);
background-repeat: repeat-x;
border-color: #3278b3;
}
.panel {
-webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, .05);
box-shadow: 0 1px 2px rgba(0, 0, 0, .05);
}
.panel-default > .panel-heading {
background-image: -webkit-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%);
background-image: -o-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%);
background-image: -webkit-gradient(linear, left top, left bottom, from(#f5f5f5), to(#e8e8e8));
background-image: linear-gradient(to bottom, #f5f5f5 0%, #e8e8e8 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0);
background-repeat: repeat-x;
}
.panel-primary > .panel-heading {
background-image: -webkit-linear-gradient(top, #428bca 0%, #357ebd 100%);
background-image: -o-linear-gradient(top, #428bca 0%, #357ebd 100%);
background-image: -webkit-gradient(linear, left top, left bottom, from(#428bca), to(#357ebd));
background-image: linear-gradient(to bottom, #428bca 0%, #357ebd 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff357ebd', GradientType=0);
background-repeat: repeat-x;
}
.panel-success > .panel-heading {
background-image: -webkit-linear-gradient(top, #dff0d8 0%, #d0e9c6 100%);
background-image: -o-linear-gradient(top, #dff0d8 0%, #d0e9c6 100%);
background-image: -webkit-gradient(linear, left top, left bottom, from(#dff0d8), to(#d0e9c6));
background-image: linear-gradient(to bottom, #dff0d8 0%, #d0e9c6 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffd0e9c6', GradientType=0);
background-repeat: repeat-x;
}
.panel-info > .panel-heading {
background-image: -webkit-linear-gradient(top, #d9edf7 0%, #c4e3f3 100%);
background-image: -o-linear-gradient(top, #d9edf7 0%, #c4e3f3 100%);
background-image: -webkit-gradient(linear, left top, left bottom, from(#d9edf7), to(#c4e3f3));
background-image: linear-gradient(to bottom, #d9edf7 0%, #c4e3f3 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffc4e3f3', GradientType=0);
background-repeat: repeat-x;
}
.panel-warning > .panel-heading {
background-image: -webkit-linear-gradient(top, #fcf8e3 0%, #faf2cc 100%);
background-image: -o-linear-gradient(top, #fcf8e3 0%, #faf2cc 100%);
background-image: -webkit-gradient(linear, left top, left bottom, from(#fcf8e3), to(#faf2cc));
background-image: linear-gradient(to bottom, #fcf8e3 0%, #faf2cc 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fffaf2cc', GradientType=0);
background-repeat: repeat-x;
}
.panel-danger > .panel-heading {
background-image: -webkit-linear-gradient(top, #f2dede 0%, #ebcccc 100%);
background-image: -o-linear-gradient(top, #f2dede 0%, #ebcccc 100%);
background-image: -webkit-gradient(linear, left top, left bottom, from(#f2dede), to(#ebcccc));
background-image: linear-gradient(to bottom, #f2dede 0%, #ebcccc 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffebcccc', GradientType=0);
background-repeat: repeat-x;
}
.well {
background-image: -webkit-linear-gradient(top, #e8e8e8 0%, #f5f5f5 100%);
background-image: -o-linear-gradient(top, #e8e8e8 0%, #f5f5f5 100%);
background-image: -webkit-gradient(linear, left top, left bottom, from(#e8e8e8), to(#f5f5f5));
background-image: linear-gradient(to bottom, #e8e8e8 0%, #f5f5f5 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffe8e8e8', endColorstr='#fff5f5f5', GradientType=0);
background-repeat: repeat-x;
border-color: #dcdcdc;
-webkit-box-shadow: inset 0 1px 3px rgba(0, 0, 0, .05), 0 1px 0 rgba(255, 255, 255, .1);
box-shadow: inset 0 1px 3px rgba(0, 0, 0, .05), 0 1px 0 rgba(255, 255, 255, .1);
}
/*# sourceMappingURL=bootstrap-theme.css.map */

View File

@ -0,0 +1,229 @@
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" >
<svg xmlns="http://www.w3.org/2000/svg">
<metadata></metadata>
<defs>
<font id="glyphicons_halflingsregular" horiz-adv-x="1200" >
<font-face units-per-em="1200" ascent="960" descent="-240" />
<missing-glyph horiz-adv-x="500" />
<glyph />
<glyph />
<glyph unicode="&#xd;" />
<glyph unicode=" " />
<glyph unicode="*" d="M100 500v200h259l-183 183l141 141l183 -183v259h200v-259l183 183l141 -141l-183 -183h259v-200h-259l183 -183l-141 -141l-183 183v-259h-200v259l-183 -183l-141 141l183 183h-259z" />
<glyph unicode="+" d="M0 400v300h400v400h300v-400h400v-300h-400v-400h-300v400h-400z" />
<glyph unicode="&#xa0;" />
<glyph unicode="&#x2000;" horiz-adv-x="652" />
<glyph unicode="&#x2001;" horiz-adv-x="1304" />
<glyph unicode="&#x2002;" horiz-adv-x="652" />
<glyph unicode="&#x2003;" horiz-adv-x="1304" />
<glyph unicode="&#x2004;" horiz-adv-x="434" />
<glyph unicode="&#x2005;" horiz-adv-x="326" />
<glyph unicode="&#x2006;" horiz-adv-x="217" />
<glyph unicode="&#x2007;" horiz-adv-x="217" />
<glyph unicode="&#x2008;" horiz-adv-x="163" />
<glyph unicode="&#x2009;" horiz-adv-x="260" />
<glyph unicode="&#x200a;" horiz-adv-x="72" />
<glyph unicode="&#x202f;" horiz-adv-x="260" />
<glyph unicode="&#x205f;" horiz-adv-x="326" />
<glyph unicode="&#x20ac;" d="M100 500l100 100h113q0 47 5 100h-218l100 100h135q37 167 112 257q117 141 297 141q242 0 354 -189q60 -103 66 -209h-181q0 55 -25.5 99t-63.5 68t-75 36.5t-67 12.5q-24 0 -52.5 -10t-62.5 -32t-65.5 -67t-50.5 -107h379l-100 -100h-300q-6 -46 -6 -100h406l-100 -100 h-300q9 -74 33 -132t52.5 -91t62 -54.5t59 -29t46.5 -7.5q29 0 66 13t75 37t63.5 67.5t25.5 96.5h174q-31 -172 -128 -278q-107 -117 -274 -117q-205 0 -324 158q-36 46 -69 131.5t-45 205.5h-217z" />
<glyph unicode="&#x2212;" d="M200 400h900v300h-900v-300z" />
<glyph unicode="&#x25fc;" horiz-adv-x="500" d="M0 0z" />
<glyph unicode="&#x2601;" d="M-14 494q0 -80 56.5 -137t135.5 -57h750q120 0 205 86.5t85 207.5t-85 207t-205 86q-46 0 -90 -14q-44 97 -134.5 156.5t-200.5 59.5q-152 0 -260 -107.5t-108 -260.5q0 -25 2 -37q-66 -14 -108.5 -67.5t-42.5 -122.5z" />
<glyph unicode="&#x2709;" d="M0 100l400 400l200 -200l200 200l400 -400h-1200zM0 300v600l300 -300zM0 1100l600 -603l600 603h-1200zM900 600l300 300v-600z" />
<glyph unicode="&#x270f;" d="M-13 -13l333 112l-223 223zM187 403l214 -214l614 614l-214 214zM887 1103l214 -214l99 92q13 13 13 32.5t-13 33.5l-153 153q-15 13 -33 13t-33 -13z" />
<glyph unicode="&#xe001;" d="M0 1200h1200l-500 -550v-550h300v-100h-800v100h300v550z" />
<glyph unicode="&#xe002;" d="M14 84q18 -55 86 -75.5t147 5.5q65 21 109 69t44 90v606l600 155v-521q-64 16 -138 -7q-79 -26 -122.5 -83t-25.5 -111q18 -55 86 -75.5t147 4.5q70 23 111.5 63.5t41.5 95.5v881q0 10 -7 15.5t-17 2.5l-752 -193q-10 -3 -17 -12.5t-7 -19.5v-689q-64 17 -138 -7 q-79 -25 -122.5 -82t-25.5 -112z" />
<glyph unicode="&#xe003;" d="M23 693q0 200 142 342t342 142t342 -142t142 -342q0 -142 -78 -261l300 -300q7 -8 7 -18t-7 -18l-109 -109q-8 -7 -18 -7t-18 7l-300 300q-119 -78 -261 -78q-200 0 -342 142t-142 342zM176 693q0 -136 97 -233t234 -97t233.5 96.5t96.5 233.5t-96.5 233.5t-233.5 96.5 t-234 -97t-97 -233z" />
<glyph unicode="&#xe005;" d="M100 784q0 64 28 123t73 100.5t104.5 64t119 20.5t120 -38.5t104.5 -104.5q48 69 109.5 105t121.5 38t118.5 -20.5t102.5 -64t71 -100.5t27 -123q0 -57 -33.5 -117.5t-94 -124.5t-126.5 -127.5t-150 -152.5t-146 -174q-62 85 -145.5 174t-149.5 152.5t-126.5 127.5 t-94 124.5t-33.5 117.5z" />
<glyph unicode="&#xe006;" d="M-72 800h479l146 400h2l146 -400h472l-382 -278l145 -449l-384 275l-382 -275l146 447zM168 71l2 1z" />
<glyph unicode="&#xe007;" d="M-72 800h479l146 400h2l146 -400h472l-382 -278l145 -449l-384 275l-382 -275l146 447zM168 71l2 1zM237 700l196 -142l-73 -226l192 140l195 -141l-74 229l193 140h-235l-77 211l-78 -211h-239z" />
<glyph unicode="&#xe008;" d="M0 0v143l400 257v100q-37 0 -68.5 74.5t-31.5 125.5v200q0 124 88 212t212 88t212 -88t88 -212v-200q0 -51 -31.5 -125.5t-68.5 -74.5v-100l400 -257v-143h-1200z" />
<glyph unicode="&#xe009;" d="M0 0v1100h1200v-1100h-1200zM100 100h100v100h-100v-100zM100 300h100v100h-100v-100zM100 500h100v100h-100v-100zM100 700h100v100h-100v-100zM100 900h100v100h-100v-100zM300 100h600v400h-600v-400zM300 600h600v400h-600v-400zM1000 100h100v100h-100v-100z M1000 300h100v100h-100v-100zM1000 500h100v100h-100v-100zM1000 700h100v100h-100v-100zM1000 900h100v100h-100v-100z" />
<glyph unicode="&#xe010;" d="M0 50v400q0 21 14.5 35.5t35.5 14.5h400q21 0 35.5 -14.5t14.5 -35.5v-400q0 -21 -14.5 -35.5t-35.5 -14.5h-400q-21 0 -35.5 14.5t-14.5 35.5zM0 650v400q0 21 14.5 35.5t35.5 14.5h400q21 0 35.5 -14.5t14.5 -35.5v-400q0 -21 -14.5 -35.5t-35.5 -14.5h-400 q-21 0 -35.5 14.5t-14.5 35.5zM600 50v400q0 21 14.5 35.5t35.5 14.5h400q21 0 35.5 -14.5t14.5 -35.5v-400q0 -21 -14.5 -35.5t-35.5 -14.5h-400q-21 0 -35.5 14.5t-14.5 35.5zM600 650v400q0 21 14.5 35.5t35.5 14.5h400q21 0 35.5 -14.5t14.5 -35.5v-400 q0 -21 -14.5 -35.5t-35.5 -14.5h-400q-21 0 -35.5 14.5t-14.5 35.5z" />
<glyph unicode="&#xe011;" d="M0 50v200q0 21 14.5 35.5t35.5 14.5h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5zM0 450v200q0 21 14.5 35.5t35.5 14.5h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200 q-21 0 -35.5 14.5t-14.5 35.5zM0 850v200q0 21 14.5 35.5t35.5 14.5h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5zM400 50v200q0 21 14.5 35.5t35.5 14.5h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5 t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5zM400 450v200q0 21 14.5 35.5t35.5 14.5h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5zM400 850v200q0 21 14.5 35.5t35.5 14.5h200q21 0 35.5 -14.5t14.5 -35.5 v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5zM800 50v200q0 21 14.5 35.5t35.5 14.5h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5zM800 450v200q0 21 14.5 35.5t35.5 14.5h200 q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5zM800 850v200q0 21 14.5 35.5t35.5 14.5h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5z" />
<glyph unicode="&#xe012;" d="M0 50v200q0 21 14.5 35.5t35.5 14.5h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5zM0 450q0 -21 14.5 -35.5t35.5 -14.5h200q21 0 35.5 14.5t14.5 35.5v200q0 21 -14.5 35.5t-35.5 14.5h-200q-21 0 -35.5 -14.5 t-14.5 -35.5v-200zM0 850v200q0 21 14.5 35.5t35.5 14.5h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5zM400 50v200q0 21 14.5 35.5t35.5 14.5h700q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5 t-35.5 -14.5h-700q-21 0 -35.5 14.5t-14.5 35.5zM400 450v200q0 21 14.5 35.5t35.5 14.5h700q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-700q-21 0 -35.5 14.5t-14.5 35.5zM400 850v200q0 21 14.5 35.5t35.5 14.5h700q21 0 35.5 -14.5t14.5 -35.5 v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-700q-21 0 -35.5 14.5t-14.5 35.5z" />
<glyph unicode="&#xe013;" d="M29 454l419 -420l818 820l-212 212l-607 -607l-206 207z" />
<glyph unicode="&#xe014;" d="M106 318l282 282l-282 282l212 212l282 -282l282 282l212 -212l-282 -282l282 -282l-212 -212l-282 282l-282 -282z" />
<glyph unicode="&#xe015;" d="M23 693q0 200 142 342t342 142t342 -142t142 -342q0 -142 -78 -261l300 -300q7 -8 7 -18t-7 -18l-109 -109q-8 -7 -18 -7t-18 7l-300 300q-119 -78 -261 -78q-200 0 -342 142t-142 342zM176 693q0 -136 97 -233t234 -97t233.5 96.5t96.5 233.5t-96.5 233.5t-233.5 96.5 t-234 -97t-97 -233zM300 600v200h100v100h200v-100h100v-200h-100v-100h-200v100h-100z" />
<glyph unicode="&#xe016;" d="M23 694q0 200 142 342t342 142t342 -142t142 -342q0 -141 -78 -262l300 -299q7 -7 7 -18t-7 -18l-109 -109q-8 -8 -18 -8t-18 8l-300 300q-119 -78 -261 -78q-200 0 -342 142t-142 342zM176 694q0 -136 97 -233t234 -97t233.5 97t96.5 233t-96.5 233t-233.5 97t-234 -97 t-97 -233zM300 601h400v200h-400v-200z" />
<glyph unicode="&#xe017;" d="M23 600q0 183 105 331t272 210v-166q-103 -55 -165 -155t-62 -220q0 -177 125 -302t302 -125t302 125t125 302q0 120 -62 220t-165 155v166q167 -62 272 -210t105 -331q0 -118 -45.5 -224.5t-123 -184t-184 -123t-224.5 -45.5t-224.5 45.5t-184 123t-123 184t-45.5 224.5 zM500 750q0 -21 14.5 -35.5t35.5 -14.5h100q21 0 35.5 14.5t14.5 35.5v400q0 21 -14.5 35.5t-35.5 14.5h-100q-21 0 -35.5 -14.5t-14.5 -35.5v-400z" />
<glyph unicode="&#xe018;" d="M100 1h200v300h-200v-300zM400 1v500h200v-500h-200zM700 1v800h200v-800h-200zM1000 1v1200h200v-1200h-200z" />
<glyph unicode="&#xe019;" d="M26 601q0 -33 6 -74l151 -38l2 -6q14 -49 38 -93l3 -5l-80 -134q45 -59 105 -105l133 81l5 -3q45 -26 94 -39l5 -2l38 -151q40 -5 74 -5q27 0 74 5l38 151l6 2q46 13 93 39l5 3l134 -81q56 44 104 105l-80 134l3 5q24 44 39 93l1 6l152 38q5 40 5 74q0 28 -5 73l-152 38 l-1 6q-16 51 -39 93l-3 5l80 134q-44 58 -104 105l-134 -81l-5 3q-45 25 -93 39l-6 1l-38 152q-40 5 -74 5q-27 0 -74 -5l-38 -152l-5 -1q-50 -14 -94 -39l-5 -3l-133 81q-59 -47 -105 -105l80 -134l-3 -5q-25 -47 -38 -93l-2 -6l-151 -38q-6 -48 -6 -73zM385 601 q0 88 63 151t152 63t152 -63t63 -151q0 -89 -63 -152t-152 -63t-152 63t-63 152z" />
<glyph unicode="&#xe020;" d="M100 1025v50q0 10 7.5 17.5t17.5 7.5h275v100q0 41 29.5 70.5t70.5 29.5h300q41 0 70.5 -29.5t29.5 -70.5v-100h275q10 0 17.5 -7.5t7.5 -17.5v-50q0 -11 -7 -18t-18 -7h-1050q-11 0 -18 7t-7 18zM200 100v800h900v-800q0 -41 -29.5 -71t-70.5 -30h-700q-41 0 -70.5 30 t-29.5 71zM300 100h100v700h-100v-700zM500 100h100v700h-100v-700zM500 1100h300v100h-300v-100zM700 100h100v700h-100v-700zM900 100h100v700h-100v-700z" />
<glyph unicode="&#xe021;" d="M1 601l656 644l644 -644h-200v-600h-300v400h-300v-400h-300v600h-200z" />
<glyph unicode="&#xe022;" d="M100 25v1150q0 11 7 18t18 7h475v-500h400v-675q0 -11 -7 -18t-18 -7h-850q-11 0 -18 7t-7 18zM700 800v300l300 -300h-300z" />
<glyph unicode="&#xe023;" d="M4 600q0 162 80 299t217 217t299 80t299 -80t217 -217t80 -299t-80 -299t-217 -217t-299 -80t-299 80t-217 217t-80 299zM186 600q0 -171 121.5 -292.5t292.5 -121.5t292.5 121.5t121.5 292.5t-121.5 292.5t-292.5 121.5t-292.5 -121.5t-121.5 -292.5zM500 500v400h100 v-300h200v-100h-300z" />
<glyph unicode="&#xe024;" d="M-100 0l431 1200h209l-21 -300h162l-20 300h208l431 -1200h-538l-41 400h-242l-40 -400h-539zM488 500h224l-27 300h-170z" />
<glyph unicode="&#xe025;" d="M0 0v400h490l-290 300h200v500h300v-500h200l-290 -300h490v-400h-1100zM813 200h175v100h-175v-100z" />
<glyph unicode="&#xe026;" d="M1 600q0 122 47.5 233t127.5 191t191 127.5t233 47.5t233 -47.5t191 -127.5t127.5 -191t47.5 -233t-47.5 -233t-127.5 -191t-191 -127.5t-233 -47.5t-233 47.5t-191 127.5t-127.5 191t-47.5 233zM188 600q0 -170 121 -291t291 -121t291 121t121 291t-121 291t-291 121 t-291 -121t-121 -291zM350 600h150v300h200v-300h150l-250 -300z" />
<glyph unicode="&#xe027;" d="M4 600q0 162 80 299t217 217t299 80t299 -80t217 -217t80 -299t-80 -299t-217 -217t-299 -80t-299 80t-217 217t-80 299zM186 600q0 -171 121.5 -292.5t292.5 -121.5t292.5 121.5t121.5 292.5t-121.5 292.5t-292.5 121.5t-292.5 -121.5t-121.5 -292.5zM350 600l250 300 l250 -300h-150v-300h-200v300h-150z" />
<glyph unicode="&#xe028;" d="M0 25v475l200 700h800l199 -700l1 -475q0 -11 -7 -18t-18 -7h-1150q-11 0 -18 7t-7 18zM200 500h200l50 -200h300l50 200h200l-97 500h-606z" />
<glyph unicode="&#xe029;" d="M4 600q0 162 80 299t217 217t299 80t299 -80t217 -217t80 -299t-80 -299t-217 -217t-299 -80t-299 80t-217 217t-80 299zM186 600q0 -172 121.5 -293t292.5 -121t292.5 121t121.5 293q0 171 -121.5 292.5t-292.5 121.5t-292.5 -121.5t-121.5 -292.5zM500 397v401 l297 -200z" />
<glyph unicode="&#xe030;" d="M23 600q0 -118 45.5 -224.5t123 -184t184 -123t224.5 -45.5t224.5 45.5t184 123t123 184t45.5 224.5h-150q0 -177 -125 -302t-302 -125t-302 125t-125 302t125 302t302 125q136 0 246 -81l-146 -146h400v400l-145 -145q-157 122 -355 122q-118 0 -224.5 -45.5t-184 -123 t-123 -184t-45.5 -224.5z" />
<glyph unicode="&#xe031;" d="M23 600q0 118 45.5 224.5t123 184t184 123t224.5 45.5q198 0 355 -122l145 145v-400h-400l147 147q-112 80 -247 80q-177 0 -302 -125t-125 -302h-150zM100 0v400h400l-147 -147q112 -80 247 -80q177 0 302 125t125 302h150q0 -118 -45.5 -224.5t-123 -184t-184 -123 t-224.5 -45.5q-198 0 -355 122z" />
<glyph unicode="&#xe032;" d="M100 0h1100v1200h-1100v-1200zM200 100v900h900v-900h-900zM300 200v100h100v-100h-100zM300 400v100h100v-100h-100zM300 600v100h100v-100h-100zM300 800v100h100v-100h-100zM500 200h500v100h-500v-100zM500 400v100h500v-100h-500zM500 600v100h500v-100h-500z M500 800v100h500v-100h-500z" />
<glyph unicode="&#xe033;" d="M0 100v600q0 41 29.5 70.5t70.5 29.5h100v200q0 82 59 141t141 59h300q82 0 141 -59t59 -141v-200h100q41 0 70.5 -29.5t29.5 -70.5v-600q0 -41 -29.5 -70.5t-70.5 -29.5h-900q-41 0 -70.5 29.5t-29.5 70.5zM400 800h300v150q0 21 -14.5 35.5t-35.5 14.5h-200 q-21 0 -35.5 -14.5t-14.5 -35.5v-150z" />
<glyph unicode="&#xe034;" d="M100 0v1100h100v-1100h-100zM300 400q60 60 127.5 84t127.5 17.5t122 -23t119 -30t110 -11t103 42t91 120.5v500q-40 -81 -101.5 -115.5t-127.5 -29.5t-138 25t-139.5 40t-125.5 25t-103 -29.5t-65 -115.5v-500z" />
<glyph unicode="&#xe035;" d="M0 275q0 -11 7 -18t18 -7h50q11 0 18 7t7 18v300q0 127 70.5 231.5t184.5 161.5t245 57t245 -57t184.5 -161.5t70.5 -231.5v-300q0 -11 7 -18t18 -7h50q11 0 18 7t7 18v300q0 116 -49.5 227t-131 192.5t-192.5 131t-227 49.5t-227 -49.5t-192.5 -131t-131 -192.5 t-49.5 -227v-300zM200 20v460q0 8 6 14t14 6h160q8 0 14 -6t6 -14v-460q0 -8 -6 -14t-14 -6h-160q-8 0 -14 6t-6 14zM800 20v460q0 8 6 14t14 6h160q8 0 14 -6t6 -14v-460q0 -8 -6 -14t-14 -6h-160q-8 0 -14 6t-6 14z" />
<glyph unicode="&#xe036;" d="M0 400h300l300 -200v800l-300 -200h-300v-400zM688 459l141 141l-141 141l71 71l141 -141l141 141l71 -71l-141 -141l141 -141l-71 -71l-141 141l-141 -141z" />
<glyph unicode="&#xe037;" d="M0 400h300l300 -200v800l-300 -200h-300v-400zM700 857l69 53q111 -135 111 -310q0 -169 -106 -302l-67 54q86 110 86 248q0 146 -93 257z" />
<glyph unicode="&#xe038;" d="M0 401v400h300l300 200v-800l-300 200h-300zM702 858l69 53q111 -135 111 -310q0 -170 -106 -303l-67 55q86 110 86 248q0 145 -93 257zM889 951l7 -8q123 -151 123 -344q0 -189 -119 -339l-7 -8l81 -66l6 8q142 178 142 405q0 230 -144 408l-6 8z" />
<glyph unicode="&#xe039;" d="M0 0h500v500h-200v100h-100v-100h-200v-500zM0 600h100v100h400v100h100v100h-100v300h-500v-600zM100 100v300h300v-300h-300zM100 800v300h300v-300h-300zM200 200v100h100v-100h-100zM200 900h100v100h-100v-100zM500 500v100h300v-300h200v-100h-100v-100h-200v100 h-100v100h100v200h-200zM600 0v100h100v-100h-100zM600 1000h100v-300h200v-300h300v200h-200v100h200v500h-600v-200zM800 800v300h300v-300h-300zM900 0v100h300v-100h-300zM900 900v100h100v-100h-100zM1100 200v100h100v-100h-100z" />
<glyph unicode="&#xe040;" d="M0 200h100v1000h-100v-1000zM100 0v100h300v-100h-300zM200 200v1000h100v-1000h-100zM500 0v91h100v-91h-100zM500 200v1000h200v-1000h-200zM700 0v91h100v-91h-100zM800 200v1000h100v-1000h-100zM900 0v91h200v-91h-200zM1000 200v1000h200v-1000h-200z" />
<glyph unicode="&#xe041;" d="M0 700l1 475q0 10 7.5 17.5t17.5 7.5h474l700 -700l-500 -500zM148 953q0 -42 29 -71q30 -30 71.5 -30t71.5 30q29 29 29 71t-29 71q-30 30 -71.5 30t-71.5 -30q-29 -29 -29 -71z" />
<glyph unicode="&#xe042;" d="M1 700l1 475q0 11 7 18t18 7h474l700 -700l-500 -500zM148 953q0 -42 30 -71q29 -30 71 -30t71 30q30 29 30 71t-30 71q-29 30 -71 30t-71 -30q-30 -29 -30 -71zM701 1200h100l700 -700l-500 -500l-50 50l450 450z" />
<glyph unicode="&#xe043;" d="M100 0v1025l175 175h925v-1000l-100 -100v1000h-750l-100 -100h750v-1000h-900z" />
<glyph unicode="&#xe044;" d="M200 0l450 444l450 -443v1150q0 20 -14.5 35t-35.5 15h-800q-21 0 -35.5 -15t-14.5 -35v-1151z" />
<glyph unicode="&#xe045;" d="M0 100v700h200l100 -200h600l100 200h200v-700h-200v200h-800v-200h-200zM253 829l40 -124h592l62 124l-94 346q-2 11 -10 18t-18 7h-450q-10 0 -18 -7t-10 -18zM281 24l38 152q2 10 11.5 17t19.5 7h500q10 0 19.5 -7t11.5 -17l38 -152q2 -10 -3.5 -17t-15.5 -7h-600 q-10 0 -15.5 7t-3.5 17z" />
<glyph unicode="&#xe046;" d="M0 200q0 -41 29.5 -70.5t70.5 -29.5h1000q41 0 70.5 29.5t29.5 70.5v600q0 41 -29.5 70.5t-70.5 29.5h-150q-4 8 -11.5 21.5t-33 48t-53 61t-69 48t-83.5 21.5h-200q-41 0 -82 -20.5t-70 -50t-52 -59t-34 -50.5l-12 -20h-150q-41 0 -70.5 -29.5t-29.5 -70.5v-600z M356 500q0 100 72 172t172 72t172 -72t72 -172t-72 -172t-172 -72t-172 72t-72 172zM494 500q0 -44 31 -75t75 -31t75 31t31 75t-31 75t-75 31t-75 -31t-31 -75zM900 700v100h100v-100h-100z" />
<glyph unicode="&#xe047;" d="M53 0h365v66q-41 0 -72 11t-49 38t1 71l92 234h391l82 -222q16 -45 -5.5 -88.5t-74.5 -43.5v-66h417v66q-34 1 -74 43q-18 19 -33 42t-21 37l-6 13l-385 998h-93l-399 -1006q-24 -48 -52 -75q-12 -12 -33 -25t-36 -20l-15 -7v-66zM416 521l178 457l46 -140l116 -317h-340 z" />
<glyph unicode="&#xe048;" d="M100 0v89q41 7 70.5 32.5t29.5 65.5v827q0 28 -1 39.5t-5.5 26t-15.5 21t-29 14t-49 14.5v71l471 -1q120 0 213 -88t93 -228q0 -55 -11.5 -101.5t-28 -74t-33.5 -47.5t-28 -28l-12 -7q8 -3 21.5 -9t48 -31.5t60.5 -58t47.5 -91.5t21.5 -129q0 -84 -59 -156.5t-142 -111 t-162 -38.5h-500zM400 200h161q89 0 153 48.5t64 132.5q0 90 -62.5 154.5t-156.5 64.5h-159v-400zM400 700h139q76 0 130 61.5t54 138.5q0 82 -84 130.5t-239 48.5v-379z" />
<glyph unicode="&#xe049;" d="M200 0v57q77 7 134.5 40.5t65.5 80.5l173 849q10 56 -10 74t-91 37q-6 1 -10.5 2.5t-9.5 2.5v57h425l2 -57q-33 -8 -62 -25.5t-46 -37t-29.5 -38t-17.5 -30.5l-5 -12l-128 -825q-10 -52 14 -82t95 -36v-57h-500z" />
<glyph unicode="&#xe050;" d="M-75 200h75v800h-75l125 167l125 -167h-75v-800h75l-125 -167zM300 900v300h150h700h150v-300h-50q0 29 -8 48.5t-18.5 30t-33.5 15t-39.5 5.5t-50.5 1h-200v-850l100 -50v-100h-400v100l100 50v850h-200q-34 0 -50.5 -1t-40 -5.5t-33.5 -15t-18.5 -30t-8.5 -48.5h-49z " />
<glyph unicode="&#xe051;" d="M33 51l167 125v-75h800v75l167 -125l-167 -125v75h-800v-75zM100 901v300h150h700h150v-300h-50q0 29 -8 48.5t-18 30t-33.5 15t-40 5.5t-50.5 1h-200v-650l100 -50v-100h-400v100l100 50v650h-200q-34 0 -50.5 -1t-39.5 -5.5t-33.5 -15t-18.5 -30t-8 -48.5h-50z" />
<glyph unicode="&#xe052;" d="M0 50q0 -20 14.5 -35t35.5 -15h1100q21 0 35.5 15t14.5 35v100q0 21 -14.5 35.5t-35.5 14.5h-1100q-21 0 -35.5 -14.5t-14.5 -35.5v-100zM0 350q0 -20 14.5 -35t35.5 -15h800q21 0 35.5 15t14.5 35v100q0 21 -14.5 35.5t-35.5 14.5h-800q-21 0 -35.5 -14.5t-14.5 -35.5 v-100zM0 650q0 -20 14.5 -35t35.5 -15h1000q21 0 35.5 15t14.5 35v100q0 21 -14.5 35.5t-35.5 14.5h-1000q-21 0 -35.5 -14.5t-14.5 -35.5v-100zM0 950q0 -20 14.5 -35t35.5 -15h600q21 0 35.5 15t14.5 35v100q0 21 -14.5 35.5t-35.5 14.5h-600q-21 0 -35.5 -14.5 t-14.5 -35.5v-100z" />
<glyph unicode="&#xe053;" d="M0 50q0 -20 14.5 -35t35.5 -15h1100q21 0 35.5 15t14.5 35v100q0 21 -14.5 35.5t-35.5 14.5h-1100q-21 0 -35.5 -14.5t-14.5 -35.5v-100zM0 650q0 -20 14.5 -35t35.5 -15h1100q21 0 35.5 15t14.5 35v100q0 21 -14.5 35.5t-35.5 14.5h-1100q-21 0 -35.5 -14.5t-14.5 -35.5 v-100zM200 350q0 -20 14.5 -35t35.5 -15h700q21 0 35.5 15t14.5 35v100q0 21 -14.5 35.5t-35.5 14.5h-700q-21 0 -35.5 -14.5t-14.5 -35.5v-100zM200 950q0 -20 14.5 -35t35.5 -15h700q21 0 35.5 15t14.5 35v100q0 21 -14.5 35.5t-35.5 14.5h-700q-21 0 -35.5 -14.5 t-14.5 -35.5v-100z" />
<glyph unicode="&#xe054;" d="M0 50v100q0 21 14.5 35.5t35.5 14.5h1100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-1100q-21 0 -35.5 15t-14.5 35zM100 650v100q0 21 14.5 35.5t35.5 14.5h1000q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-1000q-21 0 -35.5 15 t-14.5 35zM300 350v100q0 21 14.5 35.5t35.5 14.5h800q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-800q-21 0 -35.5 15t-14.5 35zM500 950v100q0 21 14.5 35.5t35.5 14.5h600q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-600 q-21 0 -35.5 15t-14.5 35z" />
<glyph unicode="&#xe055;" d="M0 50v100q0 21 14.5 35.5t35.5 14.5h1100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-1100q-21 0 -35.5 15t-14.5 35zM0 350v100q0 21 14.5 35.5t35.5 14.5h1100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-1100q-21 0 -35.5 15 t-14.5 35zM0 650v100q0 21 14.5 35.5t35.5 14.5h1100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-1100q-21 0 -35.5 15t-14.5 35zM0 950v100q0 21 14.5 35.5t35.5 14.5h1100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-1100 q-21 0 -35.5 15t-14.5 35z" />
<glyph unicode="&#xe056;" d="M0 50v100q0 21 14.5 35.5t35.5 14.5h100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-100q-21 0 -35.5 15t-14.5 35zM0 350v100q0 21 14.5 35.5t35.5 14.5h100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-100q-21 0 -35.5 15 t-14.5 35zM0 650v100q0 21 14.5 35.5t35.5 14.5h100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-100q-21 0 -35.5 15t-14.5 35zM0 950v100q0 21 14.5 35.5t35.5 14.5h100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-100q-21 0 -35.5 15 t-14.5 35zM300 50v100q0 21 14.5 35.5t35.5 14.5h800q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-800q-21 0 -35.5 15t-14.5 35zM300 350v100q0 21 14.5 35.5t35.5 14.5h800q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-800 q-21 0 -35.5 15t-14.5 35zM300 650v100q0 21 14.5 35.5t35.5 14.5h800q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-800q-21 0 -35.5 15t-14.5 35zM300 950v100q0 21 14.5 35.5t35.5 14.5h800q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15 h-800q-21 0 -35.5 15t-14.5 35z" />
<glyph unicode="&#xe057;" d="M-101 500v100h201v75l166 -125l-166 -125v75h-201zM300 0h100v1100h-100v-1100zM500 50q0 -20 14.5 -35t35.5 -15h600q20 0 35 15t15 35v100q0 21 -15 35.5t-35 14.5h-600q-21 0 -35.5 -14.5t-14.5 -35.5v-100zM500 350q0 -20 14.5 -35t35.5 -15h300q20 0 35 15t15 35 v100q0 21 -15 35.5t-35 14.5h-300q-21 0 -35.5 -14.5t-14.5 -35.5v-100zM500 650q0 -20 14.5 -35t35.5 -15h500q20 0 35 15t15 35v100q0 21 -15 35.5t-35 14.5h-500q-21 0 -35.5 -14.5t-14.5 -35.5v-100zM500 950q0 -20 14.5 -35t35.5 -15h100q20 0 35 15t15 35v100 q0 21 -15 35.5t-35 14.5h-100q-21 0 -35.5 -14.5t-14.5 -35.5v-100z" />
<glyph unicode="&#xe058;" d="M1 50q0 -20 14.5 -35t35.5 -15h600q20 0 35 15t15 35v100q0 21 -15 35.5t-35 14.5h-600q-21 0 -35.5 -14.5t-14.5 -35.5v-100zM1 350q0 -20 14.5 -35t35.5 -15h300q20 0 35 15t15 35v100q0 21 -15 35.5t-35 14.5h-300q-21 0 -35.5 -14.5t-14.5 -35.5v-100zM1 650 q0 -20 14.5 -35t35.5 -15h500q20 0 35 15t15 35v100q0 21 -15 35.5t-35 14.5h-500q-21 0 -35.5 -14.5t-14.5 -35.5v-100zM1 950q0 -20 14.5 -35t35.5 -15h100q20 0 35 15t15 35v100q0 21 -15 35.5t-35 14.5h-100q-21 0 -35.5 -14.5t-14.5 -35.5v-100zM801 0v1100h100v-1100 h-100zM934 550l167 -125v75h200v100h-200v75z" />
<glyph unicode="&#xe059;" d="M0 275v650q0 31 22 53t53 22h750q31 0 53 -22t22 -53v-650q0 -31 -22 -53t-53 -22h-750q-31 0 -53 22t-22 53zM900 600l300 300v-600z" />
<glyph unicode="&#xe060;" d="M0 44v1012q0 18 13 31t31 13h1112q19 0 31.5 -13t12.5 -31v-1012q0 -18 -12.5 -31t-31.5 -13h-1112q-18 0 -31 13t-13 31zM100 263l247 182l298 -131l-74 156l293 318l236 -288v500h-1000v-737zM208 750q0 56 39 95t95 39t95 -39t39 -95t-39 -95t-95 -39t-95 39t-39 95z " />
<glyph unicode="&#xe062;" d="M148 745q0 124 60.5 231.5t165 172t226.5 64.5q123 0 227 -63t164.5 -169.5t60.5 -229.5t-73 -272q-73 -114 -166.5 -237t-150.5 -189l-57 -66q-10 9 -27 26t-66.5 70.5t-96 109t-104 135.5t-100.5 155q-63 139 -63 262zM342 772q0 -107 75.5 -182.5t181.5 -75.5 q107 0 182.5 75.5t75.5 182.5t-75.5 182t-182.5 75t-182 -75.5t-75 -181.5z" />
<glyph unicode="&#xe063;" d="M1 600q0 122 47.5 233t127.5 191t191 127.5t233 47.5t233 -47.5t191 -127.5t127.5 -191t47.5 -233t-47.5 -233t-127.5 -191t-191 -127.5t-233 -47.5t-233 47.5t-191 127.5t-127.5 191t-47.5 233zM173 600q0 -177 125.5 -302t301.5 -125v854q-176 0 -301.5 -125 t-125.5 -302z" />
<glyph unicode="&#xe064;" d="M117 406q0 94 34 186t88.5 172.5t112 159t115 177t87.5 194.5q21 -71 57.5 -142.5t76 -130.5t83 -118.5t82 -117t70 -116t50 -125.5t18.5 -136q0 -89 -39 -165.5t-102 -126.5t-140 -79.5t-156 -33.5q-114 6 -211.5 53t-161.5 139t-64 210zM243 414q14 -82 59.5 -136 t136.5 -80l16 98q-7 6 -18 17t-34 48t-33 77q-15 73 -14 143.5t10 122.5l9 51q-92 -110 -119.5 -185t-12.5 -156z" />
<glyph unicode="&#xe065;" d="M0 400v300q0 165 117.5 282.5t282.5 117.5q366 -6 397 -14l-186 -186h-311q-41 0 -70.5 -29.5t-29.5 -70.5v-500q0 -41 29.5 -70.5t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5v125l200 200v-225q0 -165 -117.5 -282.5t-282.5 -117.5h-300q-165 0 -282.5 117.5 t-117.5 282.5zM436 341l161 50l412 412l-114 113l-405 -405zM995 1015l113 -113l113 113l-21 85l-92 28z" />
<glyph unicode="&#xe066;" d="M0 400v300q0 165 117.5 282.5t282.5 117.5h261l2 -80q-133 -32 -218 -120h-145q-41 0 -70.5 -29.5t-29.5 -70.5v-500q0 -41 29.5 -70.5t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5l200 153v-53q0 -165 -117.5 -282.5t-282.5 -117.5h-300q-165 0 -282.5 117.5t-117.5 282.5 zM423 524q30 38 81.5 64t103 35.5t99 14t77.5 3.5l29 -1v-209l360 324l-359 318v-216q-7 0 -19 -1t-48 -8t-69.5 -18.5t-76.5 -37t-76.5 -59t-62 -88t-39.5 -121.5z" />
<glyph unicode="&#xe067;" d="M0 400v300q0 165 117.5 282.5t282.5 117.5h300q61 0 127 -23l-178 -177h-349q-41 0 -70.5 -29.5t-29.5 -70.5v-500q0 -41 29.5 -70.5t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5v69l200 200v-169q0 -165 -117.5 -282.5t-282.5 -117.5h-300q-165 0 -282.5 117.5 t-117.5 282.5zM342 632l283 -284l567 567l-137 137l-430 -431l-146 147z" />
<glyph unicode="&#xe068;" d="M0 603l300 296v-198h200v200h-200l300 300l295 -300h-195v-200h200v198l300 -296l-300 -300v198h-200v-200h195l-295 -300l-300 300h200v200h-200v-198z" />
<glyph unicode="&#xe069;" d="M200 50v1000q0 21 14.5 35.5t35.5 14.5h100q21 0 35.5 -14.5t14.5 -35.5v-437l500 487v-1100l-500 488v-438q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5z" />
<glyph unicode="&#xe070;" d="M0 50v1000q0 21 14.5 35.5t35.5 14.5h100q21 0 35.5 -14.5t14.5 -35.5v-437l500 487v-487l500 487v-1100l-500 488v-488l-500 488v-438q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5z" />
<glyph unicode="&#xe071;" d="M136 550l564 550v-487l500 487v-1100l-500 488v-488z" />
<glyph unicode="&#xe072;" d="M200 0l900 550l-900 550v-1100z" />
<glyph unicode="&#xe073;" d="M200 150q0 -21 14.5 -35.5t35.5 -14.5h200q21 0 35.5 14.5t14.5 35.5v800q0 21 -14.5 35.5t-35.5 14.5h-200q-21 0 -35.5 -14.5t-14.5 -35.5v-800zM600 150q0 -21 14.5 -35.5t35.5 -14.5h200q21 0 35.5 14.5t14.5 35.5v800q0 21 -14.5 35.5t-35.5 14.5h-200 q-21 0 -35.5 -14.5t-14.5 -35.5v-800z" />
<glyph unicode="&#xe074;" d="M200 150q0 -20 14.5 -35t35.5 -15h800q21 0 35.5 15t14.5 35v800q0 21 -14.5 35.5t-35.5 14.5h-800q-21 0 -35.5 -14.5t-14.5 -35.5v-800z" />
<glyph unicode="&#xe075;" d="M0 0v1100l500 -487v487l564 -550l-564 -550v488z" />
<glyph unicode="&#xe076;" d="M0 0v1100l500 -487v487l500 -487v437q0 21 14.5 35.5t35.5 14.5h100q21 0 35.5 -14.5t14.5 -35.5v-1000q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v438l-500 -488v488z" />
<glyph unicode="&#xe077;" d="M300 0v1100l500 -487v437q0 21 14.5 35.5t35.5 14.5h100q21 0 35.5 -14.5t14.5 -35.5v-1000q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v438z" />
<glyph unicode="&#xe078;" d="M100 250v100q0 21 14.5 35.5t35.5 14.5h1000q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-1000q-21 0 -35.5 14.5t-14.5 35.5zM100 500h1100l-550 564z" />
<glyph unicode="&#xe079;" d="M185 599l592 -592l240 240l-353 353l353 353l-240 240z" />
<glyph unicode="&#xe080;" d="M272 194l353 353l-353 353l241 240l572 -571l21 -22l-1 -1v-1l-592 -591z" />
<glyph unicode="&#xe081;" d="M3 600q0 162 80 299.5t217.5 217.5t299.5 80t299.5 -80t217.5 -217.5t80 -299.5t-80 -299.5t-217.5 -217.5t-299.5 -80t-299.5 80t-217.5 217.5t-80 299.5zM300 500h200v-200h200v200h200v200h-200v200h-200v-200h-200v-200z" />
<glyph unicode="&#xe082;" d="M3 600q0 162 80 299.5t217.5 217.5t299.5 80t299.5 -80t217.5 -217.5t80 -299.5t-80 -299.5t-217.5 -217.5t-299.5 -80t-299.5 80t-217.5 217.5t-80 299.5zM300 500h600v200h-600v-200z" />
<glyph unicode="&#xe083;" d="M3 600q0 162 80 299.5t217.5 217.5t299.5 80t299.5 -80t217.5 -217.5t80 -299.5t-80 -299.5t-217.5 -217.5t-299.5 -80t-299.5 80t-217.5 217.5t-80 299.5zM246 459l213 -213l141 142l141 -142l213 213l-142 141l142 141l-213 212l-141 -141l-141 142l-212 -213l141 -141 z" />
<glyph unicode="&#xe084;" d="M3 600q0 162 80 299.5t217.5 217.5t299.5 80t299.5 -80t217.5 -217.5t80 -299.5t-80 -299.5t-217.5 -217.5t-299.5 -80t-299.5 80t-217.5 217.5t-80 299.5zM270 551l276 -277l411 411l-175 174l-236 -236l-102 102z" />
<glyph unicode="&#xe085;" d="M3 600q0 162 80 299.5t217.5 217.5t299.5 80t299.5 -80t217.5 -217.5t80 -299.5t-80 -299.5t-217.5 -217.5t-299.5 -80t-299.5 80t-217.5 217.5t-80 299.5zM364 700h143q4 0 11.5 -1t11 -1t6.5 3t3 9t1 11t3.5 8.5t3.5 6t5.5 4t6.5 2.5t9 1.5t9 0.5h11.5h12.5 q19 0 30 -10t11 -26q0 -22 -4 -28t-27 -22q-5 -1 -12.5 -3t-27 -13.5t-34 -27t-26.5 -46t-11 -68.5h200q5 3 14 8t31.5 25.5t39.5 45.5t31 69t14 94q0 51 -17.5 89t-42 58t-58.5 32t-58.5 15t-51.5 3q-50 0 -90.5 -12t-75 -38.5t-53.5 -74.5t-19 -114zM500 300h200v100h-200 v-100z" />
<glyph unicode="&#xe086;" d="M3 600q0 162 80 299.5t217.5 217.5t299.5 80t299.5 -80t217.5 -217.5t80 -299.5t-80 -299.5t-217.5 -217.5t-299.5 -80t-299.5 80t-217.5 217.5t-80 299.5zM400 300h400v100h-100v300h-300v-100h100v-200h-100v-100zM500 800h200v100h-200v-100z" />
<glyph unicode="&#xe087;" d="M0 500v200h195q31 125 98.5 199.5t206.5 100.5v200h200v-200q54 -20 113 -60t112.5 -105.5t71.5 -134.5h203v-200h-203q-25 -102 -116.5 -186t-180.5 -117v-197h-200v197q-140 27 -208 102.5t-98 200.5h-194zM290 500q24 -73 79.5 -127.5t130.5 -78.5v206h200v-206 q149 48 201 206h-201v200h200q-25 74 -75.5 127t-124.5 77v-204h-200v203q-75 -23 -130 -77t-79 -126h209v-200h-210z" />
<glyph unicode="&#xe088;" d="M4 600q0 162 80 299t217 217t299 80t299 -80t217 -217t80 -299t-80 -299t-217 -217t-299 -80t-299 80t-217 217t-80 299zM186 600q0 -171 121.5 -292.5t292.5 -121.5t292.5 121.5t121.5 292.5t-121.5 292.5t-292.5 121.5t-292.5 -121.5t-121.5 -292.5zM356 465l135 135 l-135 135l109 109l135 -135l135 135l109 -109l-135 -135l135 -135l-109 -109l-135 135l-135 -135z" />
<glyph unicode="&#xe089;" d="M4 600q0 162 80 299t217 217t299 80t299 -80t217 -217t80 -299t-80 -299t-217 -217t-299 -80t-299 80t-217 217t-80 299zM186 600q0 -171 121.5 -292.5t292.5 -121.5t292.5 121.5t121.5 292.5t-121.5 292.5t-292.5 121.5t-292.5 -121.5t-121.5 -292.5zM322 537l141 141 l87 -87l204 205l142 -142l-346 -345z" />
<glyph unicode="&#xe090;" d="M4 600q0 162 80 299t217 217t299 80t299 -80t217 -217t80 -299t-80 -299t-217 -217t-299 -80t-299 80t-217 217t-80 299zM186 600q0 -115 62 -215l568 567q-100 62 -216 62q-171 0 -292.5 -121.5t-121.5 -292.5zM391 245q97 -59 209 -59q171 0 292.5 121.5t121.5 292.5 q0 112 -59 209z" />
<glyph unicode="&#xe091;" d="M0 547l600 453v-300h600v-300h-600v-301z" />
<glyph unicode="&#xe092;" d="M0 400v300h600v300l600 -453l-600 -448v301h-600z" />
<glyph unicode="&#xe093;" d="M204 600l450 600l444 -600h-298v-600h-300v600h-296z" />
<glyph unicode="&#xe094;" d="M104 600h296v600h300v-600h298l-449 -600z" />
<glyph unicode="&#xe095;" d="M0 200q6 132 41 238.5t103.5 193t184 138t271.5 59.5v271l600 -453l-600 -448v301q-95 -2 -183 -20t-170 -52t-147 -92.5t-100 -135.5z" />
<glyph unicode="&#xe096;" d="M0 0v400l129 -129l294 294l142 -142l-294 -294l129 -129h-400zM635 777l142 -142l294 294l129 -129v400h-400l129 -129z" />
<glyph unicode="&#xe097;" d="M34 176l295 295l-129 129h400v-400l-129 130l-295 -295zM600 600v400l129 -129l295 295l142 -141l-295 -295l129 -130h-400z" />
<glyph unicode="&#xe101;" d="M23 600q0 118 45.5 224.5t123 184t184 123t224.5 45.5t224.5 -45.5t184 -123t123 -184t45.5 -224.5t-45.5 -224.5t-123 -184t-184 -123t-224.5 -45.5t-224.5 45.5t-184 123t-123 184t-45.5 224.5zM456 851l58 -302q4 -20 21.5 -34.5t37.5 -14.5h54q20 0 37.5 14.5 t21.5 34.5l58 302q4 20 -8 34.5t-32 14.5h-207q-21 0 -33 -14.5t-8 -34.5zM500 300h200v100h-200v-100z" />
<glyph unicode="&#xe102;" d="M0 800h100v-200h400v300h200v-300h400v200h100v100h-111q1 1 1 6.5t-1.5 15t-3.5 17.5l-34 172q-11 39 -41.5 63t-69.5 24q-32 0 -61 -17l-239 -144q-22 -13 -40 -35q-19 24 -40 36l-238 144q-33 18 -62 18q-39 0 -69.5 -23t-40.5 -61l-35 -177q-2 -8 -3 -18t-1 -15v-6 h-111v-100zM100 0h400v400h-400v-400zM200 900q-3 0 14 48t36 96l18 47l213 -191h-281zM700 0v400h400v-400h-400zM731 900l202 197q5 -12 12 -32.5t23 -64t25 -72t7 -28.5h-269z" />
<glyph unicode="&#xe103;" d="M0 -22v143l216 193q-9 53 -13 83t-5.5 94t9 113t38.5 114t74 124q47 60 99.5 102.5t103 68t127.5 48t145.5 37.5t184.5 43.5t220 58.5q0 -189 -22 -343t-59 -258t-89 -181.5t-108.5 -120t-122 -68t-125.5 -30t-121.5 -1.5t-107.5 12.5t-87.5 17t-56.5 7.5l-99 -55z M238.5 300.5q19.5 -6.5 86.5 76.5q55 66 367 234q70 38 118.5 69.5t102 79t99 111.5t86.5 148q22 50 24 60t-6 19q-7 5 -17 5t-26.5 -14.5t-33.5 -39.5q-35 -51 -113.5 -108.5t-139.5 -89.5l-61 -32q-369 -197 -458 -401q-48 -111 -28.5 -117.5z" />
<glyph unicode="&#xe104;" d="M111 408q0 -33 5 -63q9 -56 44 -119.5t105 -108.5q31 -21 64 -16t62 23.5t57 49.5t48 61.5t35 60.5q32 66 39 184.5t-13 157.5q79 -80 122 -164t26 -184q-5 -33 -20.5 -69.5t-37.5 -80.5q-10 -19 -14.5 -29t-12 -26t-9 -23.5t-3 -19t2.5 -15.5t11 -9.5t19.5 -5t30.5 2.5 t42 8q57 20 91 34t87.5 44.5t87 64t65.5 88.5t47 122q38 172 -44.5 341.5t-246.5 278.5q22 -44 43 -129q39 -159 -32 -154q-15 2 -33 9q-79 33 -120.5 100t-44 175.5t48.5 257.5q-13 -8 -34 -23.5t-72.5 -66.5t-88.5 -105.5t-60 -138t-8 -166.5q2 -12 8 -41.5t8 -43t6 -39.5 t3.5 -39.5t-1 -33.5t-6 -31.5t-13.5 -24t-21 -20.5t-31 -12q-38 -10 -67 13t-40.5 61.5t-15 81.5t10.5 75q-52 -46 -83.5 -101t-39 -107t-7.5 -85z" />
<glyph unicode="&#xe105;" d="M-61 600l26 40q6 10 20 30t49 63.5t74.5 85.5t97 90t116.5 83.5t132.5 59t145.5 23.5t145.5 -23.5t132.5 -59t116.5 -83.5t97 -90t74.5 -85.5t49 -63.5t20 -30l26 -40l-26 -40q-6 -10 -20 -30t-49 -63.5t-74.5 -85.5t-97 -90t-116.5 -83.5t-132.5 -59t-145.5 -23.5 t-145.5 23.5t-132.5 59t-116.5 83.5t-97 90t-74.5 85.5t-49 63.5t-20 30zM120 600q7 -10 40.5 -58t56 -78.5t68 -77.5t87.5 -75t103 -49.5t125 -21.5t123.5 20t100.5 45.5t85.5 71.5t66.5 75.5t58 81.5t47 66q-1 1 -28.5 37.5t-42 55t-43.5 53t-57.5 63.5t-58.5 54 q49 -74 49 -163q0 -124 -88 -212t-212 -88t-212 88t-88 212q0 85 46 158q-102 -87 -226 -258zM377 656q49 -124 154 -191l105 105q-37 24 -75 72t-57 84l-20 36z" />
<glyph unicode="&#xe106;" d="M-61 600l26 40q6 10 20 30t49 63.5t74.5 85.5t97 90t116.5 83.5t132.5 59t145.5 23.5q61 0 121 -17l37 142h148l-314 -1200h-148l37 143q-82 21 -165 71.5t-140 102t-109.5 112t-72 88.5t-29.5 43zM120 600q210 -282 393 -336l37 141q-107 18 -178.5 101.5t-71.5 193.5 q0 85 46 158q-102 -87 -226 -258zM377 656q49 -124 154 -191l47 47l23 87q-30 28 -59 69t-44 68l-14 26zM780 161l38 145q22 15 44.5 34t46 44t40.5 44t41 50.5t33.5 43.5t33 44t24.5 34q-97 127 -140 175l39 146q67 -54 131.5 -125.5t87.5 -103.5t36 -52l26 -40l-26 -40 q-7 -12 -25.5 -38t-63.5 -79.5t-95.5 -102.5t-124 -100t-146.5 -79z" />
<glyph unicode="&#xe107;" d="M-97.5 34q13.5 -34 50.5 -34h1294q37 0 50.5 35.5t-7.5 67.5l-642 1056q-20 34 -48 36.5t-48 -29.5l-642 -1066q-21 -32 -7.5 -66zM155 200l445 723l445 -723h-345v100h-200v-100h-345zM500 600l100 -300l100 300v100h-200v-100z" />
<glyph unicode="&#xe108;" d="M100 262v41q0 20 11 44.5t26 38.5l363 325v339q0 62 44 106t106 44t106 -44t44 -106v-339l363 -325q15 -14 26 -38.5t11 -44.5v-41q0 -20 -12 -26.5t-29 5.5l-359 249v-263q100 -91 100 -113v-64q0 -20 -13 -28.5t-32 0.5l-94 78h-222l-94 -78q-19 -9 -32 -0.5t-13 28.5 v64q0 22 100 113v263l-359 -249q-17 -12 -29 -5.5t-12 26.5z" />
<glyph unicode="&#xe109;" d="M0 50q0 -20 14.5 -35t35.5 -15h1000q21 0 35.5 15t14.5 35v750h-1100v-750zM0 900h1100v150q0 21 -14.5 35.5t-35.5 14.5h-150v100h-100v-100h-500v100h-100v-100h-150q-21 0 -35.5 -14.5t-14.5 -35.5v-150zM100 100v100h100v-100h-100zM100 300v100h100v-100h-100z M100 500v100h100v-100h-100zM300 100v100h100v-100h-100zM300 300v100h100v-100h-100zM300 500v100h100v-100h-100zM500 100v100h100v-100h-100zM500 300v100h100v-100h-100zM500 500v100h100v-100h-100zM700 100v100h100v-100h-100zM700 300v100h100v-100h-100zM700 500 v100h100v-100h-100zM900 100v100h100v-100h-100zM900 300v100h100v-100h-100zM900 500v100h100v-100h-100z" />
<glyph unicode="&#xe110;" d="M0 200v200h259l600 600h241v198l300 -295l-300 -300v197h-159l-600 -600h-341zM0 800h259l122 -122l141 142l-181 180h-341v-200zM678 381l141 142l122 -123h159v198l300 -295l-300 -300v197h-241z" />
<glyph unicode="&#xe111;" d="M0 400v600q0 41 29.5 70.5t70.5 29.5h1000q41 0 70.5 -29.5t29.5 -70.5v-600q0 -41 -29.5 -70.5t-70.5 -29.5h-596l-304 -300v300h-100q-41 0 -70.5 29.5t-29.5 70.5z" />
<glyph unicode="&#xe112;" d="M100 600v200h300v-250q0 -113 6 -145q17 -92 102 -117q39 -11 92 -11q37 0 66.5 5.5t50 15.5t36 24t24 31.5t14 37.5t7 42t2.5 45t0 47v25v250h300v-200q0 -42 -3 -83t-15 -104t-31.5 -116t-58 -109.5t-89 -96.5t-129 -65.5t-174.5 -25.5t-174.5 25.5t-129 65.5t-89 96.5 t-58 109.5t-31.5 116t-15 104t-3 83zM100 900v300h300v-300h-300zM800 900v300h300v-300h-300z" />
<glyph unicode="&#xe113;" d="M-30 411l227 -227l352 353l353 -353l226 227l-578 579z" />
<glyph unicode="&#xe114;" d="M70 797l580 -579l578 579l-226 227l-353 -353l-352 353z" />
<glyph unicode="&#xe115;" d="M-198 700l299 283l300 -283h-203v-400h385l215 -200h-800v600h-196zM402 1000l215 -200h381v-400h-198l299 -283l299 283h-200v600h-796z" />
<glyph unicode="&#xe116;" d="M18 939q-5 24 10 42q14 19 39 19h896l38 162q5 17 18.5 27.5t30.5 10.5h94q20 0 35 -14.5t15 -35.5t-15 -35.5t-35 -14.5h-54l-201 -961q-2 -4 -6 -10.5t-19 -17.5t-33 -11h-31v-50q0 -20 -14.5 -35t-35.5 -15t-35.5 15t-14.5 35v50h-300v-50q0 -20 -14.5 -35t-35.5 -15 t-35.5 15t-14.5 35v50h-50q-21 0 -35.5 15t-14.5 35q0 21 14.5 35.5t35.5 14.5h535l48 200h-633q-32 0 -54.5 21t-27.5 43z" />
<glyph unicode="&#xe117;" d="M0 0v800h1200v-800h-1200zM0 900v100h200q0 41 29.5 70.5t70.5 29.5h300q41 0 70.5 -29.5t29.5 -70.5h500v-100h-1200z" />
<glyph unicode="&#xe118;" d="M1 0l300 700h1200l-300 -700h-1200zM1 400v600h200q0 41 29.5 70.5t70.5 29.5h300q41 0 70.5 -29.5t29.5 -70.5h500v-200h-1000z" />
<glyph unicode="&#xe119;" d="M302 300h198v600h-198l298 300l298 -300h-198v-600h198l-298 -300z" />
<glyph unicode="&#xe120;" d="M0 600l300 298v-198h600v198l300 -298l-300 -297v197h-600v-197z" />
<glyph unicode="&#xe121;" d="M0 100v100q0 41 29.5 70.5t70.5 29.5h1000q41 0 70.5 -29.5t29.5 -70.5v-100q0 -41 -29.5 -70.5t-70.5 -29.5h-1000q-41 0 -70.5 29.5t-29.5 70.5zM31 400l172 739q5 22 23 41.5t38 19.5h672q19 0 37.5 -22.5t23.5 -45.5l172 -732h-1138zM800 100h100v100h-100v-100z M1000 100h100v100h-100v-100z" />
<glyph unicode="&#xe122;" d="M-101 600v50q0 24 25 49t50 38l25 13v-250l-11 5.5t-24 14t-30 21.5t-24 27.5t-11 31.5zM100 500v250v8v8v7t0.5 7t1.5 5.5t2 5t3 4t4.5 3.5t6 1.5t7.5 0.5h200l675 250v-850l-675 200h-38l47 -276q2 -12 -3 -17.5t-11 -6t-21 -0.5h-8h-83q-20 0 -34.5 14t-18.5 35 q-55 337 -55 351zM1100 200v850q0 21 14.5 35.5t35.5 14.5q20 0 35 -14.5t15 -35.5v-850q0 -20 -15 -35t-35 -15q-21 0 -35.5 15t-14.5 35z" />
<glyph unicode="&#xe123;" d="M74 350q0 21 13.5 35.5t33.5 14.5h18l117 173l63 327q15 77 76 140t144 83l-18 32q-6 19 3 32t29 13h94q20 0 29 -10.5t3 -29.5q-18 -36 -18 -37q83 -19 144 -82.5t76 -140.5l63 -327l118 -173h17q20 0 33.5 -14.5t13.5 -35.5q0 -20 -13 -40t-31 -27q-8 -3 -23 -8.5 t-65 -20t-103 -25t-132.5 -19.5t-158.5 -9q-125 0 -245.5 20.5t-178.5 40.5l-58 20q-18 7 -31 27.5t-13 40.5zM497 110q12 -49 40 -79.5t63 -30.5t63 30.5t39 79.5q-48 -6 -102 -6t-103 6z" />
<glyph unicode="&#xe124;" d="M21 445l233 -45l-78 -224l224 78l45 -233l155 179l155 -179l45 233l224 -78l-78 224l234 45l-180 155l180 156l-234 44l78 225l-224 -78l-45 233l-155 -180l-155 180l-45 -233l-224 78l78 -225l-233 -44l179 -156z" />
<glyph unicode="&#xe125;" d="M0 200h200v600h-200v-600zM300 275q0 -75 100 -75h61q124 -100 139 -100h250q46 0 83 57l238 344q29 31 29 74v100q0 44 -30.5 84.5t-69.5 40.5h-328q28 118 28 125v150q0 44 -30.5 84.5t-69.5 40.5h-50q-27 0 -51 -20t-38 -48l-96 -198l-145 -196q-20 -26 -20 -63v-400z M400 300v375l150 213l100 212h50v-175l-50 -225h450v-125l-250 -375h-214l-136 100h-100z" />
<glyph unicode="&#xe126;" d="M0 400v600h200v-600h-200zM300 525v400q0 75 100 75h61q124 100 139 100h250q46 0 83 -57l238 -344q29 -31 29 -74v-100q0 -44 -30.5 -84.5t-69.5 -40.5h-328q28 -118 28 -125v-150q0 -44 -30.5 -84.5t-69.5 -40.5h-50q-27 0 -51 20t-38 48l-96 198l-145 196 q-20 26 -20 63zM400 525l150 -212l100 -213h50v175l-50 225h450v125l-250 375h-214l-136 -100h-100v-375z" />
<glyph unicode="&#xe127;" d="M8 200v600h200v-600h-200zM308 275v525q0 17 14 35.5t28 28.5l14 9l362 230q14 6 25 6q17 0 29 -12l109 -112q14 -14 14 -34q0 -18 -11 -32l-85 -121h302q85 0 138.5 -38t53.5 -110t-54.5 -111t-138.5 -39h-107l-130 -339q-7 -22 -20.5 -41.5t-28.5 -19.5h-341 q-7 0 -90 81t-83 94zM408 289l100 -89h293l131 339q6 21 19.5 41t28.5 20h203q16 0 25 15t9 36q0 20 -9 34.5t-25 14.5h-457h-6.5h-7.5t-6.5 0.5t-6 1t-5 1.5t-5.5 2.5t-4 4t-4 5.5q-5 12 -5 20q0 14 10 27l147 183l-86 83l-339 -236v-503z" />
<glyph unicode="&#xe128;" d="M-101 651q0 72 54 110t139 38l302 -1l-85 121q-11 16 -11 32q0 21 14 34l109 113q13 12 29 12q11 0 25 -6l365 -230q7 -4 17 -10.5t26.5 -26t16.5 -36.5v-526q0 -13 -86 -93.5t-94 -80.5h-341q-16 0 -29.5 20t-19.5 41l-130 339h-107q-84 0 -139 39t-55 111zM-1 601h222 q15 0 28.5 -20.5t19.5 -40.5l131 -339h293l107 89v502l-343 237l-87 -83l145 -184q10 -11 10 -26q0 -11 -5 -20q-1 -3 -3.5 -5.5l-4 -4t-5 -2.5t-5.5 -1.5t-6.5 -1t-6.5 -0.5h-7.5h-6.5h-476v-100zM1000 201v600h200v-600h-200z" />
<glyph unicode="&#xe129;" d="M97 719l230 -363q4 -6 10.5 -15.5t26 -25t36.5 -15.5h525q13 0 94 83t81 90v342q0 15 -20 28.5t-41 19.5l-339 131v106q0 84 -39 139t-111 55t-110 -53.5t-38 -138.5v-302l-121 84q-15 12 -33.5 11.5t-32.5 -13.5l-112 -110q-22 -22 -6 -53zM172 739l83 86l183 -146 q22 -18 47 -5q3 1 5.5 3.5l4 4t2.5 5t1.5 5.5t1 6.5t0.5 6.5v7.5v6.5v456q0 22 25 31t50 -0.5t25 -30.5v-202q0 -16 20 -29.5t41 -19.5l339 -130v-294l-89 -100h-503zM400 0v200h600v-200h-600z" />
<glyph unicode="&#xe130;" d="M2 585q-16 -31 6 -53l112 -110q13 -13 32 -13.5t34 10.5l121 85q0 -51 -0.5 -153.5t-0.5 -148.5q0 -84 38.5 -138t110.5 -54t111 55t39 139v106l339 131q20 6 40.5 19.5t20.5 28.5v342q0 7 -81 90t-94 83h-525q-17 0 -35.5 -14t-28.5 -28l-10 -15zM77 565l236 339h503 l89 -100v-294l-340 -130q-20 -6 -40 -20t-20 -29v-202q0 -22 -25 -31t-50 0t-25 31v456v14.5t-1.5 11.5t-5 12t-9.5 7q-24 13 -46 -5l-184 -146zM305 1104v200h600v-200h-600z" />
<glyph unicode="&#xe131;" d="M5 597q0 122 47.5 232.5t127.5 190.5t190.5 127.5t232.5 47.5q162 0 299.5 -80t217.5 -218t80 -300t-80 -299.5t-217.5 -217.5t-299.5 -80t-300 80t-218 217.5t-80 299.5zM298 701l2 -201h300l-2 -194l402 294l-402 298v-197h-300z" />
<glyph unicode="&#xe132;" d="M0 597q0 122 47.5 232.5t127.5 190.5t190.5 127.5t231.5 47.5q122 0 232.5 -47.5t190.5 -127.5t127.5 -190.5t47.5 -232.5q0 -162 -80 -299.5t-218 -217.5t-300 -80t-299.5 80t-217.5 217.5t-80 299.5zM200 600l402 -294l-2 194h300l2 201h-300v197z" />
<glyph unicode="&#xe133;" d="M5 597q0 122 47.5 232.5t127.5 190.5t190.5 127.5t232.5 47.5q162 0 299.5 -80t217.5 -218t80 -300t-80 -299.5t-217.5 -217.5t-299.5 -80t-300 80t-218 217.5t-80 299.5zM300 600h200v-300h200v300h200l-300 400z" />
<glyph unicode="&#xe134;" d="M5 597q0 122 47.5 232.5t127.5 190.5t190.5 127.5t232.5 47.5q162 0 299.5 -80t217.5 -218t80 -300t-80 -299.5t-217.5 -217.5t-299.5 -80t-300 80t-218 217.5t-80 299.5zM300 600l300 -400l300 400h-200v300h-200v-300h-200z" />
<glyph unicode="&#xe135;" d="M5 597q0 122 47.5 232.5t127.5 190.5t190.5 127.5t232.5 47.5q121 0 231.5 -47.5t190.5 -127.5t127.5 -190.5t47.5 -232.5q0 -162 -80 -299.5t-217.5 -217.5t-299.5 -80t-300 80t-218 217.5t-80 299.5zM254 780q-8 -33 5.5 -92.5t7.5 -87.5q0 -9 17 -44t16 -60 q12 0 23 -5.5t23 -15t20 -13.5q24 -12 108 -42q22 -8 53 -31.5t59.5 -38.5t57.5 -11q8 -18 -15 -55t-20 -57q42 -71 87 -80q0 -6 -3 -15.5t-3.5 -14.5t4.5 -17q104 -3 221 112q30 29 47 47t34.5 49t20.5 62q-14 9 -37 9.5t-36 7.5q-14 7 -49 15t-52 19q-9 0 -39.5 -0.5 t-46.5 -1.5t-39 -6.5t-39 -16.5q-50 -35 -66 -12q-4 2 -3.5 25.5t0.5 25.5q-6 13 -26.5 17t-24.5 7q2 22 -2 41t-16.5 28t-38.5 -20q-23 -25 -42 4q-19 28 -8 58q6 16 22 22q6 -1 26 -1.5t33.5 -4t19.5 -13.5q12 -19 32 -37.5t34 -27.5l14 -8q0 3 9.5 39.5t5.5 57.5 q-4 23 14.5 44.5t22.5 31.5q5 14 10 35t8.5 31t15.5 22.5t34 21.5q-6 18 10 37q8 0 23.5 -1.5t24.5 -1.5t20.5 4.5t20.5 15.5q-10 23 -30.5 42.5t-38 30t-49 26.5t-43.5 23q11 39 2 44q31 -13 58 -14.5t39 3.5l11 4q7 36 -16.5 53.5t-64.5 28.5t-56 23q-19 -3 -37 0 q-15 -12 -36.5 -21t-34.5 -12t-44 -8t-39 -6q-15 -3 -45.5 0.5t-45.5 -2.5q-21 -7 -52 -26.5t-34 -34.5q-3 -11 6.5 -22.5t8.5 -18.5q-3 -34 -27.5 -90.5t-29.5 -79.5zM518 916q3 12 16 30t16 25q10 -10 18.5 -10t14 6t14.5 14.5t16 12.5q0 -24 17 -66.5t17 -43.5 q-9 2 -31 5t-36 5t-32 8t-30 14zM692 1003h1h-1z" />
<glyph unicode="&#xe136;" d="M0 164.5q0 21.5 15 37.5l600 599q-33 101 6 201.5t135 154.5q164 92 306 -9l-259 -138l145 -232l251 126q13 -175 -151 -267q-123 -70 -253 -23l-596 -596q-15 -16 -36.5 -16t-36.5 16l-111 110q-15 15 -15 36.5z" />
<glyph unicode="&#xe137;" horiz-adv-x="1220" d="M0 196v100q0 41 29.5 70.5t70.5 29.5h1000q41 0 70.5 -29.5t29.5 -70.5v-100q0 -41 -29.5 -70.5t-70.5 -29.5h-1000q-41 0 -70.5 29.5t-29.5 70.5zM0 596v100q0 41 29.5 70.5t70.5 29.5h1000q41 0 70.5 -29.5t29.5 -70.5v-100q0 -41 -29.5 -70.5t-70.5 -29.5h-1000 q-41 0 -70.5 29.5t-29.5 70.5zM0 996v100q0 41 29.5 70.5t70.5 29.5h1000q41 0 70.5 -29.5t29.5 -70.5v-100q0 -41 -29.5 -70.5t-70.5 -29.5h-1000q-41 0 -70.5 29.5t-29.5 70.5zM600 596h500v100h-500v-100zM800 196h300v100h-300v-100zM900 996h200v100h-200v-100z" />
<glyph unicode="&#xe138;" d="M100 1100v100h1000v-100h-1000zM150 1000h900l-350 -500v-300l-200 -200v500z" />
<glyph unicode="&#xe139;" d="M0 200v200h1200v-200q0 -41 -29.5 -70.5t-70.5 -29.5h-1000q-41 0 -70.5 29.5t-29.5 70.5zM0 500v400q0 41 29.5 70.5t70.5 29.5h300v100q0 41 29.5 70.5t70.5 29.5h200q41 0 70.5 -29.5t29.5 -70.5v-100h300q41 0 70.5 -29.5t29.5 -70.5v-400h-500v100h-200v-100h-500z M500 1000h200v100h-200v-100z" />
<glyph unicode="&#xe140;" d="M0 0v400l129 -129l200 200l142 -142l-200 -200l129 -129h-400zM0 800l129 129l200 -200l142 142l-200 200l129 129h-400v-400zM729 329l142 142l200 -200l129 129v-400h-400l129 129zM729 871l200 200l-129 129h400v-400l-129 129l-200 -200z" />
<glyph unicode="&#xe141;" d="M0 596q0 162 80 299t217 217t299 80t299 -80t217 -217t80 -299t-80 -299t-217 -217t-299 -80t-299 80t-217 217t-80 299zM182 596q0 -172 121.5 -293t292.5 -121t292.5 121t121.5 293q0 171 -121.5 292.5t-292.5 121.5t-292.5 -121.5t-121.5 -292.5zM291 655 q0 23 15.5 38.5t38.5 15.5t39 -16t16 -38q0 -23 -16 -39t-39 -16q-22 0 -38 16t-16 39zM400 850q0 22 16 38.5t39 16.5q22 0 38 -16t16 -39t-16 -39t-38 -16q-23 0 -39 16.5t-16 38.5zM514 609q0 32 20.5 56.5t51.5 29.5l122 126l1 1q-9 14 -9 28q0 22 16 38.5t39 16.5 q22 0 38 -16t16 -39t-16 -39t-38 -16q-14 0 -29 10l-55 -145q17 -22 17 -51q0 -36 -25.5 -61.5t-61.5 -25.5t-61.5 25.5t-25.5 61.5zM800 655q0 22 16 38t39 16t38.5 -15.5t15.5 -38.5t-16 -39t-38 -16q-23 0 -39 16t-16 39z" />
<glyph unicode="&#xe142;" d="M-40 375q-13 -95 35 -173q35 -57 94 -89t129 -32q63 0 119 28q33 16 65 40.5t52.5 45.5t59.5 64q40 44 57 61l394 394q35 35 47 84t-3 96q-27 87 -117 104q-20 2 -29 2q-46 0 -78.5 -16.5t-67.5 -51.5l-389 -396l-7 -7l69 -67l377 373q20 22 39 38q23 23 50 23 q38 0 53 -36q16 -39 -20 -75l-547 -547q-52 -52 -125 -52q-55 0 -100 33t-54 96q-5 35 2.5 66t31.5 63t42 50t56 54q24 21 44 41l348 348q52 52 82.5 79.5t84 54t107.5 26.5q25 0 48 -4q95 -17 154 -94.5t51 -175.5q-7 -101 -98 -192l-252 -249l-253 -256l7 -7l69 -60 l517 511q67 67 95 157t11 183q-16 87 -67 154t-130 103q-69 33 -152 33q-107 0 -197 -55q-40 -24 -111 -95l-512 -512q-68 -68 -81 -163z" />
<glyph unicode="&#xe143;" d="M80 784q0 131 98.5 229.5t230.5 98.5q143 0 241 -129q103 129 246 129q129 0 226 -98.5t97 -229.5q0 -46 -17.5 -91t-61 -99t-77 -89.5t-104.5 -105.5q-197 -191 -293 -322l-17 -23l-16 23q-43 58 -100 122.5t-92 99.5t-101 100q-71 70 -104.5 105.5t-77 89.5t-61 99 t-17.5 91zM250 784q0 -27 30.5 -70t61.5 -75.5t95 -94.5l22 -22q93 -90 190 -201q82 92 195 203l12 12q64 62 97.5 97t64.5 79t31 72q0 71 -48 119.5t-105 48.5q-74 0 -132 -83l-118 -171l-114 174q-51 80 -123 80q-60 0 -109.5 -49.5t-49.5 -118.5z" />
<glyph unicode="&#xe144;" d="M57 353q0 -95 66 -159l141 -142q68 -66 159 -66q93 0 159 66l283 283q66 66 66 159t-66 159l-141 141q-8 9 -19 17l-105 -105l212 -212l-389 -389l-247 248l95 95l-18 18q-46 45 -75 101l-55 -55q-66 -66 -66 -159zM269 706q0 -93 66 -159l141 -141q7 -7 19 -17l105 105 l-212 212l389 389l247 -247l-95 -96l18 -17q47 -49 77 -100l29 29q35 35 62.5 88t27.5 96q0 93 -66 159l-141 141q-66 66 -159 66q-95 0 -159 -66l-283 -283q-66 -64 -66 -159z" />
<glyph unicode="&#xe145;" d="M200 100v953q0 21 30 46t81 48t129 38t163 15t162 -15t127 -38t79 -48t29 -46v-953q0 -41 -29.5 -70.5t-70.5 -29.5h-600q-41 0 -70.5 29.5t-29.5 70.5zM300 300h600v700h-600v-700zM496 150q0 -43 30.5 -73.5t73.5 -30.5t73.5 30.5t30.5 73.5t-30.5 73.5t-73.5 30.5 t-73.5 -30.5t-30.5 -73.5z" />
<glyph unicode="&#xe146;" d="M0 0l303 380l207 208l-210 212h300l267 279l-35 36q-15 14 -15 35t15 35q14 15 35 15t35 -15l283 -282q15 -15 15 -36t-15 -35q-14 -15 -35 -15t-35 15l-36 35l-279 -267v-300l-212 210l-208 -207z" />
<glyph unicode="&#xe148;" d="M295 433h139q5 -77 48.5 -126.5t117.5 -64.5v335q-6 1 -15.5 4t-11.5 3q-46 14 -79 26.5t-72 36t-62.5 52t-40 72.5t-16.5 99q0 92 44 159.5t109 101t144 40.5v78h100v-79q38 -4 72.5 -13.5t75.5 -31.5t71 -53.5t51.5 -84t24.5 -118.5h-159q-8 72 -35 109.5t-101 50.5 v-307l64 -14q34 -7 64 -16.5t70 -31.5t67.5 -52t47.5 -80.5t20 -112.5q0 -139 -89 -224t-244 -96v-77h-100v78q-152 17 -237 104q-40 40 -52.5 93.5t-15.5 139.5zM466 889q0 -29 8 -51t16.5 -34t29.5 -22.5t31 -13.5t38 -10q7 -2 11 -3v274q-61 -8 -97.5 -37.5t-36.5 -102.5 zM700 237q170 18 170 151q0 64 -44 99.5t-126 60.5v-311z" />
<glyph unicode="&#xe149;" d="M100 600v100h166q-24 49 -44 104q-10 26 -14.5 55.5t-3 72.5t25 90t68.5 87q97 88 263 88q129 0 230 -89t101 -208h-153q0 52 -34 89.5t-74 51.5t-76 14q-37 0 -79 -14.5t-62 -35.5q-41 -44 -41 -101q0 -28 16.5 -69.5t28 -62.5t41.5 -72h241v-100h-197q8 -50 -2.5 -115 t-31.5 -94q-41 -59 -99 -113q35 11 84 18t70 7q33 1 103 -16t103 -17q76 0 136 30l50 -147q-41 -25 -80.5 -36.5t-59 -13t-61.5 -1.5q-23 0 -128 33t-155 29q-39 -4 -82 -17t-66 -25l-24 -11l-55 145l16.5 11t15.5 10t13.5 9.5t14.5 12t14.5 14t17.5 18.5q48 55 54 126.5 t-30 142.5h-221z" />
<glyph unicode="&#xe150;" d="M2 300l298 -300l298 300h-198v900h-200v-900h-198zM602 900l298 300l298 -300h-198v-900h-200v900h-198z" />
<glyph unicode="&#xe151;" d="M2 300h198v900h200v-900h198l-298 -300zM700 0v200h100v-100h200v-100h-300zM700 400v100h300v-200h-99v-100h-100v100h99v100h-200zM700 700v500h300v-500h-100v100h-100v-100h-100zM801 900h100v200h-100v-200z" />
<glyph unicode="&#xe152;" d="M2 300h198v900h200v-900h198l-298 -300zM700 0v500h300v-500h-100v100h-100v-100h-100zM700 700v200h100v-100h200v-100h-300zM700 1100v100h300v-200h-99v-100h-100v100h99v100h-200zM801 200h100v200h-100v-200z" />
<glyph unicode="&#xe153;" d="M2 300l298 -300l298 300h-198v900h-200v-900h-198zM800 100v400h300v-500h-100v100h-200zM800 1100v100h200v-500h-100v400h-100zM901 200h100v200h-100v-200z" />
<glyph unicode="&#xe154;" d="M2 300l298 -300l298 300h-198v900h-200v-900h-198zM800 400v100h200v-500h-100v400h-100zM800 800v400h300v-500h-100v100h-200zM901 900h100v200h-100v-200z" />
<glyph unicode="&#xe155;" d="M2 300l298 -300l298 300h-198v900h-200v-900h-198zM700 100v200h500v-200h-500zM700 400v200h400v-200h-400zM700 700v200h300v-200h-300zM700 1000v200h200v-200h-200z" />
<glyph unicode="&#xe156;" d="M2 300l298 -300l298 300h-198v900h-200v-900h-198zM700 100v200h200v-200h-200zM700 400v200h300v-200h-300zM700 700v200h400v-200h-400zM700 1000v200h500v-200h-500z" />
<glyph unicode="&#xe157;" d="M0 400v300q0 165 117.5 282.5t282.5 117.5h300q162 0 281 -118.5t119 -281.5v-300q0 -165 -118.5 -282.5t-281.5 -117.5h-300q-165 0 -282.5 117.5t-117.5 282.5zM200 300q0 -41 29.5 -70.5t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5v500q0 41 -29.5 70.5t-70.5 29.5 h-500q-41 0 -70.5 -29.5t-29.5 -70.5v-500z" />
<glyph unicode="&#xe158;" d="M0 400v300q0 163 119 281.5t281 118.5h300q165 0 282.5 -117.5t117.5 -282.5v-300q0 -165 -117.5 -282.5t-282.5 -117.5h-300q-163 0 -281.5 117.5t-118.5 282.5zM200 300q0 -41 29.5 -70.5t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5v500q0 41 -29.5 70.5t-70.5 29.5 h-500q-41 0 -70.5 -29.5t-29.5 -70.5v-500zM400 300l333 250l-333 250v-500z" />
<glyph unicode="&#xe159;" d="M0 400v300q0 163 117.5 281.5t282.5 118.5h300q163 0 281.5 -119t118.5 -281v-300q0 -165 -117.5 -282.5t-282.5 -117.5h-300q-165 0 -282.5 117.5t-117.5 282.5zM200 300q0 -41 29.5 -70.5t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5v500q0 41 -29.5 70.5t-70.5 29.5 h-500q-41 0 -70.5 -29.5t-29.5 -70.5v-500zM300 700l250 -333l250 333h-500z" />
<glyph unicode="&#xe160;" d="M0 400v300q0 165 117.5 282.5t282.5 117.5h300q165 0 282.5 -117.5t117.5 -282.5v-300q0 -162 -118.5 -281t-281.5 -119h-300q-165 0 -282.5 118.5t-117.5 281.5zM200 300q0 -41 29.5 -70.5t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5v500q0 41 -29.5 70.5t-70.5 29.5 h-500q-41 0 -70.5 -29.5t-29.5 -70.5v-500zM300 400h500l-250 333z" />
<glyph unicode="&#xe161;" d="M0 400v300h300v200l400 -350l-400 -350v200h-300zM500 0v200h500q41 0 70.5 29.5t29.5 70.5v500q0 41 -29.5 70.5t-70.5 29.5h-500v200h400q165 0 282.5 -117.5t117.5 -282.5v-300q0 -165 -117.5 -282.5t-282.5 -117.5h-400z" />
<glyph unicode="&#xe162;" d="M217 519q8 -19 31 -19h302q-155 -438 -160 -458q-5 -21 4 -32l9 -8h9q14 0 26 15q11 13 274.5 321.5t264.5 308.5q14 19 5 36q-8 17 -31 17l-301 -1q1 4 78 219.5t79 227.5q2 15 -5 27l-9 9h-9q-15 0 -25 -16q-4 -6 -98 -111.5t-228.5 -257t-209.5 -237.5q-16 -19 -6 -41 z" />
<glyph unicode="&#xe163;" d="M0 400q0 -165 117.5 -282.5t282.5 -117.5h300q47 0 100 15v185h-500q-41 0 -70.5 29.5t-29.5 70.5v500q0 41 29.5 70.5t70.5 29.5h500v185q-14 4 -114 7.5t-193 5.5l-93 2q-165 0 -282.5 -117.5t-117.5 -282.5v-300zM600 400v300h300v200l400 -350l-400 -350v200h-300z " />
<glyph unicode="&#xe164;" d="M0 400q0 -165 117.5 -282.5t282.5 -117.5h300q163 0 281.5 117.5t118.5 282.5v98l-78 73l-122 -123v-148q0 -41 -29.5 -70.5t-70.5 -29.5h-500q-41 0 -70.5 29.5t-29.5 70.5v500q0 41 29.5 70.5t70.5 29.5h156l118 122l-74 78h-100q-165 0 -282.5 -117.5t-117.5 -282.5 v-300zM496 709l353 342l-149 149h500v-500l-149 149l-342 -353z" />
<glyph unicode="&#xe165;" d="M4 600q0 162 80 299t217 217t299 80t299 -80t217 -217t80 -299t-80 -299t-217 -217t-299 -80t-299 80t-217 217t-80 299zM186 600q0 -171 121.5 -292.5t292.5 -121.5t292.5 121.5t121.5 292.5t-121.5 292.5t-292.5 121.5t-292.5 -121.5t-121.5 -292.5zM406 600 q0 80 57 137t137 57t137 -57t57 -137t-57 -137t-137 -57t-137 57t-57 137z" />
<glyph unicode="&#xe166;" d="M0 0v275q0 11 7 18t18 7h1048q11 0 19 -7.5t8 -17.5v-275h-1100zM100 800l445 -500l450 500h-295v400h-300v-400h-300zM900 150h100v50h-100v-50z" />
<glyph unicode="&#xe167;" d="M0 0v275q0 11 7 18t18 7h1048q11 0 19 -7.5t8 -17.5v-275h-1100zM100 700h300v-300h300v300h295l-445 500zM900 150h100v50h-100v-50z" />
<glyph unicode="&#xe168;" d="M0 0v275q0 11 7 18t18 7h1048q11 0 19 -7.5t8 -17.5v-275h-1100zM100 705l305 -305l596 596l-154 155l-442 -442l-150 151zM900 150h100v50h-100v-50z" />
<glyph unicode="&#xe169;" d="M0 0v275q0 11 7 18t18 7h1048q11 0 19 -7.5t8 -17.5v-275h-1100zM100 988l97 -98l212 213l-97 97zM200 400l697 1l3 699l-250 -239l-149 149l-212 -212l149 -149zM900 150h100v50h-100v-50z" />
<glyph unicode="&#xe170;" d="M0 0v275q0 11 7 18t18 7h1048q11 0 19 -7.5t8 -17.5v-275h-1100zM200 612l212 -212l98 97l-213 212zM300 1200l239 -250l-149 -149l212 -212l149 148l249 -237l-1 697zM900 150h100v50h-100v-50z" />
<glyph unicode="&#xe171;" d="M23 415l1177 784v-1079l-475 272l-310 -393v416h-392zM494 210l672 938l-672 -712v-226z" />
<glyph unicode="&#xe172;" d="M0 150v1000q0 20 14.5 35t35.5 15h250v-300h500v300h100l200 -200v-850q0 -21 -15 -35.5t-35 -14.5h-150v400h-700v-400h-150q-21 0 -35.5 14.5t-14.5 35.5zM600 1000h100v200h-100v-200z" />
<glyph unicode="&#xe173;" d="M0 150v1000q0 20 14.5 35t35.5 15h250v-300h500v300h100l200 -200v-218l-276 -275l-120 120l-126 -127h-378v-400h-150q-21 0 -35.5 14.5t-14.5 35.5zM581 306l123 123l120 -120l353 352l123 -123l-475 -476zM600 1000h100v200h-100v-200z" />
<glyph unicode="&#xe174;" d="M0 150v1000q0 20 14.5 35t35.5 15h250v-300h500v300h100l200 -200v-269l-103 -103l-170 170l-298 -298h-329v-400h-150q-21 0 -35.5 14.5t-14.5 35.5zM600 1000h100v200h-100v-200zM700 133l170 170l-170 170l127 127l170 -170l170 170l127 -128l-170 -169l170 -170 l-127 -127l-170 170l-170 -170z" />
<glyph unicode="&#xe175;" d="M0 150v1000q0 20 14.5 35t35.5 15h250v-300h500v300h100l200 -200v-300h-400v-200h-500v-400h-150q-21 0 -35.5 14.5t-14.5 35.5zM600 300l300 -300l300 300h-200v300h-200v-300h-200zM600 1000v200h100v-200h-100z" />
<glyph unicode="&#xe176;" d="M0 150v1000q0 20 14.5 35t35.5 15h250v-300h500v300h100l200 -200v-402l-200 200l-298 -298h-402v-400h-150q-21 0 -35.5 14.5t-14.5 35.5zM600 300h200v-300h200v300h200l-300 300zM600 1000v200h100v-200h-100z" />
<glyph unicode="&#xe177;" d="M0 250q0 -21 14.5 -35.5t35.5 -14.5h1100q21 0 35.5 14.5t14.5 35.5v550h-1200v-550zM0 900h1200v150q0 21 -14.5 35.5t-35.5 14.5h-1100q-21 0 -35.5 -14.5t-14.5 -35.5v-150zM100 300v200h400v-200h-400z" />
<glyph unicode="&#xe178;" d="M0 400l300 298v-198h400v-200h-400v-198zM100 800v200h100v-200h-100zM300 800v200h100v-200h-100zM500 800v200h400v198l300 -298l-300 -298v198h-400zM800 300v200h100v-200h-100zM1000 300h100v200h-100v-200z" />
<glyph unicode="&#xe179;" d="M100 700v400l50 100l50 -100v-300h100v300l50 100l50 -100v-300h100v300l50 100l50 -100v-400l-100 -203v-447q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v447zM800 597q0 -29 10.5 -55.5t25 -43t29 -28.5t25.5 -18l10 -5v-397q0 -21 14.5 -35.5 t35.5 -14.5h200q21 0 35.5 14.5t14.5 35.5v1106q0 31 -18 40.5t-44 -7.5l-276 -116q-25 -17 -43.5 -51.5t-18.5 -65.5v-359z" />
<glyph unicode="&#xe180;" d="M100 0h400v56q-75 0 -87.5 6t-12.5 44v394h500v-394q0 -38 -12.5 -44t-87.5 -6v-56h400v56q-4 0 -11 0.5t-24 3t-30 7t-24 15t-11 24.5v888q0 22 25 34.5t50 13.5l25 2v56h-400v-56q75 0 87.5 -6t12.5 -44v-394h-500v394q0 38 12.5 44t87.5 6v56h-400v-56q4 0 11 -0.5 t24 -3t30 -7t24 -15t11 -24.5v-888q0 -22 -25 -34.5t-50 -13.5l-25 -2v-56z" />
<glyph unicode="&#xe181;" d="M0 300q0 -41 29.5 -70.5t70.5 -29.5h300q41 0 70.5 29.5t29.5 70.5v500q0 41 -29.5 70.5t-70.5 29.5h-300q-41 0 -70.5 -29.5t-29.5 -70.5v-500zM100 100h400l200 200h105l295 98v-298h-425l-100 -100h-375zM100 300v200h300v-200h-300zM100 600v200h300v-200h-300z M100 1000h400l200 -200v-98l295 98h105v200h-425l-100 100h-375zM700 402v163l400 133v-163z" />
<glyph unicode="&#xe182;" d="M16.5 974.5q0.5 -21.5 16 -90t46.5 -140t104 -177.5t175 -208q103 -103 207.5 -176t180 -103.5t137 -47t92.5 -16.5l31 1l163 162q17 18 13.5 41t-22.5 37l-192 136q-19 14 -45 12t-42 -19l-118 -118q-142 101 -268 227t-227 268l118 118q17 17 20 41.5t-11 44.5 l-139 194q-14 19 -36.5 22t-40.5 -14l-162 -162q-1 -11 -0.5 -32.5z" />
<glyph unicode="&#xe183;" d="M0 50v212q0 20 10.5 45.5t24.5 39.5l365 303v50q0 4 1 10.5t12 22.5t30 28.5t60 23t97 10.5t97 -10t60 -23.5t30 -27.5t12 -24l1 -10v-50l365 -303q14 -14 24.5 -39.5t10.5 -45.5v-212q0 -21 -14.5 -35.5t-35.5 -14.5h-1100q-20 0 -35 14.5t-15 35.5zM0 712 q0 -21 14.5 -33.5t34.5 -8.5l202 33q20 4 34.5 21t14.5 38v146q141 24 300 24t300 -24v-146q0 -21 14.5 -38t34.5 -21l202 -33q20 -4 34.5 8.5t14.5 33.5v200q-6 8 -19 20.5t-63 45t-112 57t-171 45t-235 20.5q-92 0 -175 -10.5t-141.5 -27t-108.5 -36.5t-81.5 -40 t-53.5 -36.5t-31 -27.5l-9 -10v-200z" />
<glyph unicode="&#xe184;" d="M100 0v100h1100v-100h-1100zM175 200h950l-125 150v250l100 100v400h-100v-200h-100v200h-200v-200h-100v200h-200v-200h-100v200h-100v-400l100 -100v-250z" />
<glyph unicode="&#xe185;" d="M100 0h300v400q0 41 -29.5 70.5t-70.5 29.5h-100q-41 0 -70.5 -29.5t-29.5 -70.5v-400zM500 0v1000q0 41 29.5 70.5t70.5 29.5h100q41 0 70.5 -29.5t29.5 -70.5v-1000h-300zM900 0v700q0 41 29.5 70.5t70.5 29.5h100q41 0 70.5 -29.5t29.5 -70.5v-700h-300z" />
<glyph unicode="&#xe186;" d="M-100 300v500q0 124 88 212t212 88h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212zM100 200h900v700h-900v-700zM200 300h300v300h-200v100h200v100h-300v-300h200v-100h-200v-100zM600 300h200v100h100v300h-100v100h-200v-500 zM700 400v300h100v-300h-100z" />
<glyph unicode="&#xe187;" d="M-100 300v500q0 124 88 212t212 88h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212zM100 200h900v700h-900v-700zM200 300h100v200h100v-200h100v500h-100v-200h-100v200h-100v-500zM600 300h200v100h100v300h-100v100h-200v-500 zM700 400v300h100v-300h-100z" />
<glyph unicode="&#xe188;" d="M-100 300v500q0 124 88 212t212 88h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212zM100 200h900v700h-900v-700zM200 300h300v100h-200v300h200v100h-300v-500zM600 300h300v100h-200v300h200v100h-300v-500z" />
<glyph unicode="&#xe189;" d="M-100 300v500q0 124 88 212t212 88h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212zM100 200h900v700h-900v-700zM200 550l300 -150v300zM600 400l300 150l-300 150v-300z" />
<glyph unicode="&#xe190;" d="M-100 300v500q0 124 88 212t212 88h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212zM100 200h900v700h-900v-700zM200 300v500h700v-500h-700zM300 400h130q41 0 68 42t27 107t-28.5 108t-66.5 43h-130v-300zM575 549 q0 -65 27 -107t68 -42h130v300h-130q-38 0 -66.5 -43t-28.5 -108z" />
<glyph unicode="&#xe191;" d="M-100 300v500q0 124 88 212t212 88h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212zM100 200h900v700h-900v-700zM200 300h300v300h-200v100h200v100h-300v-300h200v-100h-200v-100zM601 300h100v100h-100v-100zM700 700h100 v-400h100v500h-200v-100z" />
<glyph unicode="&#xe192;" d="M-100 300v500q0 124 88 212t212 88h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212zM100 200h900v700h-900v-700zM200 300h300v400h-200v100h-100v-500zM301 400v200h100v-200h-100zM601 300h100v100h-100v-100zM700 700h100 v-400h100v500h-200v-100z" />
<glyph unicode="&#xe193;" d="M-100 300v500q0 124 88 212t212 88h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212zM100 200h900v700h-900v-700zM200 700v100h300v-300h-99v-100h-100v100h99v200h-200zM201 300v100h100v-100h-100zM601 300v100h100v-100h-100z M700 700v100h200v-500h-100v400h-100z" />
<glyph unicode="&#xe194;" d="M4 600q0 162 80 299t217 217t299 80t299 -80t217 -217t80 -299t-80 -299t-217 -217t-299 -80t-299 80t-217 217t-80 299zM186 600q0 -171 121.5 -292.5t292.5 -121.5t292.5 121.5t121.5 292.5t-121.5 292.5t-292.5 121.5t-292.5 -121.5t-121.5 -292.5zM400 500v200 l100 100h300v-100h-300v-200h300v-100h-300z" />
<glyph unicode="&#xe195;" d="M0 600q0 162 80 299t217 217t299 80t299 -80t217 -217t80 -299t-80 -299t-217 -217t-299 -80t-299 80t-217 217t-80 299zM182 600q0 -171 121.5 -292.5t292.5 -121.5t292.5 121.5t121.5 292.5t-121.5 292.5t-292.5 121.5t-292.5 -121.5t-121.5 -292.5zM400 400v400h300 l100 -100v-100h-100v100h-200v-100h200v-100h-200v-100h-100zM700 400v100h100v-100h-100z" />
<glyph unicode="&#xe197;" d="M-14 494q0 -80 56.5 -137t135.5 -57h222v300h400v-300h128q120 0 205 86.5t85 207.5t-85 207t-205 86q-46 0 -90 -14q-44 97 -134.5 156.5t-200.5 59.5q-152 0 -260 -107.5t-108 -260.5q0 -25 2 -37q-66 -14 -108.5 -67.5t-42.5 -122.5zM300 200h200v300h200v-300h200 l-300 -300z" />
<glyph unicode="&#xe198;" d="M-14 494q0 -80 56.5 -137t135.5 -57h8l414 414l403 -403q94 26 154.5 104.5t60.5 178.5q0 120 -85 206.5t-205 86.5q-46 0 -90 -14q-44 97 -134.5 156.5t-200.5 59.5q-152 0 -260 -107.5t-108 -260.5q0 -25 2 -37q-66 -14 -108.5 -67.5t-42.5 -122.5zM300 200l300 300 l300 -300h-200v-300h-200v300h-200z" />
<glyph unicode="&#xe199;" d="M100 200h400v-155l-75 -45h350l-75 45v155h400l-270 300h170l-270 300h170l-300 333l-300 -333h170l-270 -300h170z" />
<glyph unicode="&#xe200;" d="M121 700q0 -53 28.5 -97t75.5 -65q-4 -16 -4 -38q0 -74 52.5 -126.5t126.5 -52.5q56 0 100 30v-306l-75 -45h350l-75 45v306q46 -30 100 -30q74 0 126.5 52.5t52.5 126.5q0 24 -9 55q50 32 79.5 83t29.5 112q0 90 -61.5 155.5t-150.5 71.5q-26 89 -99.5 145.5 t-167.5 56.5q-116 0 -197.5 -81.5t-81.5 -197.5q0 -4 1 -11.5t1 -11.5q-14 2 -23 2q-74 0 -126.5 -52.5t-52.5 -126.5z" />
</font>
</defs></svg>

After

Width:  |  Height:  |  Size: 62 KiB

View File

@ -0,0 +1,262 @@
var CKAN = {};
var isNodeModule = (typeof module !== 'undefined' && module != null && typeof require !== 'undefined');
if (isNodeModule) {
var _ = require('underscore')
, request = require('request')
;
module.exports = CKAN;
}
(function(my) {
my.Client = function(endpoint, apiKey) {
this.endpoint = _getEndpoint(endpoint);
this.apiKey = apiKey;
};
my.Client.prototype.action = function(name, data, cb) {
if (name.indexOf('dataset_' === 0)) {
name = name.replace('dataset_', 'package_');
}
var options = {
url: this.endpoint + '/3/action/' + name,
data: data,
type: 'POST'
};
return this._ajax(options, cb);
};
// make an AJAX request
my.Client.prototype._ajax = function(options, cb) {
options.headers = options.headers || {};
if (this.apiKey) {
options.headers['X-CKAN-API-KEY'] = this.apiKey;
}
var csrf_field = $('meta[name=csrf_field_name]').attr('content');
var csrf_token = $('meta[name='+ csrf_field +']').attr('content');
options.headers['X-CSRFToken'] = csrf_token;
var meth = isNodeModule ? _nodeRequest : _browserRequest;
return meth(options, cb);
}
// Like search but supports ReclineJS style query structure
//
// Primarily for use by Recline backend below
my.Client.prototype.datastoreQuery = function(queryObj, cb) {
var actualQuery = my._normalizeQuery(queryObj);
this.action('datastore_search', actualQuery, function(err, results) {
// map ckan types to our usual types ...
var fields = _.map(results.result.fields, function(field) {
field.type = field.type in my.ckan2JsonTableSchemaTypes ? my.ckan2JsonTableSchemaTypes[field.type] : field.type;
return field;
});
var out = {
total: results.result.total,
fields: fields,
hits: results.result.records,
total_was_estimated: results.result.total_was_estimated
};
cb(null, out);
});
};
my.ckan2JsonTableSchemaTypes = {
'text': 'string',
'int': 'integer',
'int4': 'integer',
'int8': 'integer',
'float8': 'float',
'timestamp': 'datetime',
'bool': 'boolean',
};
//
my.jsonTableSchema2CkanTypes = {
'string': 'text',
'number': 'float',
'integer': 'int',
'datetime': 'timestamp',
'boolean': 'bool',
'binary': 'bytea',
'object': 'json',
'array': 'text[]',
'any': 'text'
};
// list all the resources with an entry in the DataStore
my.Client.prototype.datastoreResources = function(cb) {
var data = {
resource_id: '_table_metadata'
};
return this._client.action('datastore_search', data, cb);
};
// Utilities
// =========
var _getEndpoint = function(endpoint) {
endpoint = endpoint || '/';
// strip trailing /
endpoint = endpoint.replace(/\/$/, '');
if (!endpoint.match(/\/api$/)) {
endpoint += '/api';
}
return endpoint;
};
var _nodeRequest = function(options, cb) {
var conf = {
url: options.url,
headers: options.headers || {},
method: options.type || 'GET',
json: options.data
};
// we could just call request but that's a PITA to mock plus request.get = request (if you look at the source code)
request.get(conf, function(err, res, body) {
if (!err && res && !(res.statusCode === 200 || res.statusCode === 302)) {
err = 'Bad HTTP code ' + res.statusCode;
}
cb(err, body);
});
};
var _browserRequest = function(options, cb) {
var self = this;
options.data = encodeURIComponent(JSON.stringify(options.data));
options.success = function(data) {
cb(null, data);
}
options.error = function(obj, obj2, obj3) {
var err = {
code: obj.status,
message: obj.responseText
}
cb(err);
}
if (options.headers) {
options.beforeSend = function(req) {
for (key in options.headers) {
req.setRequestHeader(key, options.headers[key]);
}
};
}
return jQuery.ajax(options);
};
// only put in the module namespace so we can access for tests!
my._normalizeQuery = function(queryObj) {
var actualQuery = {
resource_id: queryObj.resource_id,
q: queryObj.q,
filters: {},
limit: queryObj.size || 10,
offset: queryObj.from || 0,
total_estimation_threshold: 1000
};
if (queryObj.sort && queryObj.sort.length > 0) {
var _tmp = _.map(queryObj.sort, function(sortObj) {
return sortObj.field + ' ' + (sortObj.order || '');
});
actualQuery.sort = _tmp.join(',');
}
if (queryObj.filters && queryObj.filters.length > 0) {
_.each(queryObj.filters, function(filter) {
if (filter.type === "term") {
actualQuery.filters[filter.field] = filter.term;
}
});
}
return actualQuery;
};
// Parse a normal CKAN resource URL and return API endpoint etc
//
// Normal URL is something like http://demo.ckan.org/dataset/some-dataset/resource/eb23e809-ccbb-4ad1-820a-19586fc4bebd
my._parseCkanResourceUrl = function(url) {
parts = url.split('/');
var len = parts.length;
return {
resource_id: parts[len-1],
endpoint: parts.slice(0,[len-4]).join('/') + '/api'
};
};
}(CKAN));
// Recline Wrapper
//
// Wrap the DataStore to create a Backend suitable for usage in ReclineJS
//
// This provides connection to the CKAN DataStore (v2)
//
// General notes
//
// We need 2 things to make most requests:
//
// 1. CKAN API endpoint
// 2. ID of resource for which request is being made
//
// There are 2 ways to specify this information.
//
// EITHER (checked in order):
//
// * Every dataset must have an id equal to its resource id on the CKAN instance
// * The dataset has an endpoint attribute pointing to the CKAN API endpoint
//
// OR:
//
// Set the url attribute of the dataset to point to the Resource on the CKAN instance. The endpoint and id will then be automatically computed.
var recline = recline || {};
recline.Backend = recline.Backend || {};
recline.Backend.Ckan = recline.Backend.Ckan || {};
(function(my) {
my.__type__ = 'ckan';
// private - use either jQuery or Underscore Deferred depending on what is available
var Deferred = _.isUndefined(this.jQuery) ? _.Deferred : jQuery.Deferred;
// ### fetch
my.fetch = function(dataset) {
var dfd = new Deferred()
my.query({}, dataset)
.done(function(data) {
dfd.resolve({
fields: data.fields,
records: data.hits
});
})
.fail(function(err) {
dfd.reject(err);
})
;
return dfd.promise();
};
my.query = function(queryObj, dataset) {
var dfd = new Deferred()
, wrapper
;
if (dataset.endpoint) {
wrapper = new CKAN.Client(dataset.endpoint);
} else {
var out = CKAN._parseCkanResourceUrl(dataset.url);
dataset.id = out.resource_id;
wrapper = new CKAN.Client(out.endpoint);
}
queryObj.resource_id = dataset.id;
wrapper.datastoreQuery(queryObj, function(err, out) {
if (err) {
dfd.reject(err);
} else {
dfd.resolve(out);
}
});
return dfd.promise();
};
}(recline.Backend.Ckan));

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,431 @@
/* Pretty handling of time axes.
Copyright (c) 2007-2013 IOLA and Ole Laursen.
Licensed under the MIT license.
Set axis.mode to "time" to enable. See the section "Time series data" in
API.txt for details.
*/
(function($) {
var options = {
xaxis: {
timezone: null, // "browser" for local to the client or timezone for timezone-js
timeformat: null, // format string to use
twelveHourClock: false, // 12 or 24 time in time mode
monthNames: null // list of names of months
}
};
// round to nearby lower multiple of base
function floorInBase(n, base) {
return base * Math.floor(n / base);
}
// Returns a string with the date d formatted according to fmt.
// A subset of the Open Group's strftime format is supported.
function formatDate(d, fmt, monthNames, dayNames) {
if (typeof d.strftime == "function") {
return d.strftime(fmt);
}
var leftPad = function(n, pad) {
n = "" + n;
pad = "" + (pad == null ? "0" : pad);
return n.length == 1 ? pad + n : n;
};
var r = [];
var escape = false;
var hours = d.getHours();
var isAM = hours < 12;
if (monthNames == null) {
monthNames = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
}
if (dayNames == null) {
dayNames = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
}
var hours12;
if (hours > 12) {
hours12 = hours - 12;
} else if (hours == 0) {
hours12 = 12;
} else {
hours12 = hours;
}
for (var i = 0; i < fmt.length; ++i) {
var c = fmt.charAt(i);
if (escape) {
switch (c) {
case 'a': c = "" + dayNames[d.getDay()]; break;
case 'b': c = "" + monthNames[d.getMonth()]; break;
case 'd': c = leftPad(d.getDate()); break;
case 'e': c = leftPad(d.getDate(), " "); break;
case 'h': // For back-compat with 0.7; remove in 1.0
case 'H': c = leftPad(hours); break;
case 'I': c = leftPad(hours12); break;
case 'l': c = leftPad(hours12, " "); break;
case 'm': c = leftPad(d.getMonth() + 1); break;
case 'M': c = leftPad(d.getMinutes()); break;
// quarters not in Open Group's strftime specification
case 'q':
c = "" + (Math.floor(d.getMonth() / 3) + 1); break;
case 'S': c = leftPad(d.getSeconds()); break;
case 'y': c = leftPad(d.getFullYear() % 100); break;
case 'Y': c = "" + d.getFullYear(); break;
case 'p': c = (isAM) ? ("" + "am") : ("" + "pm"); break;
case 'P': c = (isAM) ? ("" + "AM") : ("" + "PM"); break;
case 'w': c = "" + d.getDay(); break;
}
r.push(c);
escape = false;
} else {
if (c == "%") {
escape = true;
} else {
r.push(c);
}
}
}
return r.join("");
}
// To have a consistent view of time-based data independent of which time
// zone the client happens to be in we need a date-like object independent
// of time zones. This is done through a wrapper that only calls the UTC
// versions of the accessor methods.
function makeUtcWrapper(d) {
function addProxyMethod(sourceObj, sourceMethod, targetObj, targetMethod) {
sourceObj[sourceMethod] = function() {
return targetObj[targetMethod].apply(targetObj, arguments);
};
};
var utc = {
date: d
};
// support strftime, if found
if (d.strftime != undefined) {
addProxyMethod(utc, "strftime", d, "strftime");
}
addProxyMethod(utc, "getTime", d, "getTime");
addProxyMethod(utc, "setTime", d, "setTime");
var props = ["Date", "Day", "FullYear", "Hours", "Milliseconds", "Minutes", "Month", "Seconds"];
for (var p = 0; p < props.length; p++) {
addProxyMethod(utc, "get" + props[p], d, "getUTC" + props[p]);
addProxyMethod(utc, "set" + props[p], d, "setUTC" + props[p]);
}
return utc;
};
// select time zone strategy. This returns a date-like object tied to the
// desired timezone
function dateGenerator(ts, opts) {
if (opts.timezone == "browser") {
return new Date(ts);
} else if (!opts.timezone || opts.timezone == "utc") {
return makeUtcWrapper(new Date(ts));
} else if (typeof timezoneJS != "undefined" && typeof timezoneJS.Date != "undefined") {
var d = new timezoneJS.Date();
// timezone-js is fickle, so be sure to set the time zone before
// setting the time.
d.setTimezone(opts.timezone);
d.setTime(ts);
return d;
} else {
return makeUtcWrapper(new Date(ts));
}
}
// map of app. size of time units in milliseconds
var timeUnitSize = {
"second": 1000,
"minute": 60 * 1000,
"hour": 60 * 60 * 1000,
"day": 24 * 60 * 60 * 1000,
"month": 30 * 24 * 60 * 60 * 1000,
"quarter": 3 * 30 * 24 * 60 * 60 * 1000,
"year": 365.2425 * 24 * 60 * 60 * 1000
};
// the allowed tick sizes, after 1 year we use
// an integer algorithm
var baseSpec = [
[1, "second"], [2, "second"], [5, "second"], [10, "second"],
[30, "second"],
[1, "minute"], [2, "minute"], [5, "minute"], [10, "minute"],
[30, "minute"],
[1, "hour"], [2, "hour"], [4, "hour"],
[8, "hour"], [12, "hour"],
[1, "day"], [2, "day"], [3, "day"],
[0.25, "month"], [0.5, "month"], [1, "month"],
[2, "month"]
];
// we don't know which variant(s) we'll need yet, but generating both is
// cheap
var specMonths = baseSpec.concat([[3, "month"], [6, "month"],
[1, "year"]]);
var specQuarters = baseSpec.concat([[1, "quarter"], [2, "quarter"],
[1, "year"]]);
function init(plot) {
plot.hooks.processOptions.push(function (plot, options) {
$.each(plot.getAxes(), function(axisName, axis) {
var opts = axis.options;
if (opts.mode == "time") {
axis.tickGenerator = function(axis) {
var ticks = [];
var d = dateGenerator(axis.min, opts);
var minSize = 0;
// make quarter use a possibility if quarters are
// mentioned in either of these options
var spec = (opts.tickSize && opts.tickSize[1] ===
"quarter") ||
(opts.minTickSize && opts.minTickSize[1] ===
"quarter") ? specQuarters : specMonths;
if (opts.minTickSize != null) {
if (typeof opts.tickSize == "number") {
minSize = opts.tickSize;
} else {
minSize = opts.minTickSize[0] * timeUnitSize[opts.minTickSize[1]];
}
}
for (var i = 0; i < spec.length - 1; ++i) {
if (axis.delta < (spec[i][0] * timeUnitSize[spec[i][1]]
+ spec[i + 1][0] * timeUnitSize[spec[i + 1][1]]) / 2
&& spec[i][0] * timeUnitSize[spec[i][1]] >= minSize) {
break;
}
}
var size = spec[i][0];
var unit = spec[i][1];
// special-case the possibility of several years
if (unit == "year") {
// if given a minTickSize in years, just use it,
// ensuring that it's an integer
if (opts.minTickSize != null && opts.minTickSize[1] == "year") {
size = Math.floor(opts.minTickSize[0]);
} else {
var magn = Math.pow(10, Math.floor(Math.log(axis.delta / timeUnitSize.year) / Math.LN10));
var norm = (axis.delta / timeUnitSize.year) / magn;
if (norm < 1.5) {
size = 1;
} else if (norm < 3) {
size = 2;
} else if (norm < 7.5) {
size = 5;
} else {
size = 10;
}
size *= magn;
}
// minimum size for years is 1
if (size < 1) {
size = 1;
}
}
axis.tickSize = opts.tickSize || [size, unit];
var tickSize = axis.tickSize[0];
unit = axis.tickSize[1];
var step = tickSize * timeUnitSize[unit];
if (unit == "second") {
d.setSeconds(floorInBase(d.getSeconds(), tickSize));
} else if (unit == "minute") {
d.setMinutes(floorInBase(d.getMinutes(), tickSize));
} else if (unit == "hour") {
d.setHours(floorInBase(d.getHours(), tickSize));
} else if (unit == "month") {
d.setMonth(floorInBase(d.getMonth(), tickSize));
} else if (unit == "quarter") {
d.setMonth(3 * floorInBase(d.getMonth() / 3,
tickSize));
} else if (unit == "year") {
d.setFullYear(floorInBase(d.getFullYear(), tickSize));
}
// reset smaller components
d.setMilliseconds(0);
if (step >= timeUnitSize.minute) {
d.setSeconds(0);
}
if (step >= timeUnitSize.hour) {
d.setMinutes(0);
}
if (step >= timeUnitSize.day) {
d.setHours(0);
}
if (step >= timeUnitSize.day * 4) {
d.setDate(1);
}
if (step >= timeUnitSize.month * 2) {
d.setMonth(floorInBase(d.getMonth(), 3));
}
if (step >= timeUnitSize.quarter * 2) {
d.setMonth(floorInBase(d.getMonth(), 6));
}
if (step >= timeUnitSize.year) {
d.setMonth(0);
}
var carry = 0;
var v = Number.NaN;
var prev;
do {
prev = v;
v = d.getTime();
ticks.push(v);
if (unit == "month" || unit == "quarter") {
if (tickSize < 1) {
// a bit complicated - we'll divide the
// month/quarter up but we need to take
// care of fractions so we don't end up in
// the middle of a day
d.setDate(1);
var start = d.getTime();
d.setMonth(d.getMonth() +
(unit == "quarter" ? 3 : 1));
var end = d.getTime();
d.setTime(v + carry * timeUnitSize.hour + (end - start) * tickSize);
carry = d.getHours();
d.setHours(0);
} else {
d.setMonth(d.getMonth() +
tickSize * (unit == "quarter" ? 3 : 1));
}
} else if (unit == "year") {
d.setFullYear(d.getFullYear() + tickSize);
} else {
d.setTime(v + step);
}
} while (v < axis.max && v != prev);
return ticks;
};
axis.tickFormatter = function (v, axis) {
var d = dateGenerator(v, axis.options);
// first check global format
if (opts.timeformat != null) {
return formatDate(d, opts.timeformat, opts.monthNames, opts.dayNames);
}
// possibly use quarters if quarters are mentioned in
// any of these places
var useQuarters = (axis.options.tickSize &&
axis.options.tickSize[1] == "quarter") ||
(axis.options.minTickSize &&
axis.options.minTickSize[1] == "quarter");
var t = axis.tickSize[0] * timeUnitSize[axis.tickSize[1]];
var span = axis.max - axis.min;
var suffix = (opts.twelveHourClock) ? " %p" : "";
var hourCode = (opts.twelveHourClock) ? "%I" : "%H";
var fmt;
if (t < timeUnitSize.minute) {
fmt = hourCode + ":%M:%S" + suffix;
} else if (t < timeUnitSize.day) {
if (span < 2 * timeUnitSize.day) {
fmt = hourCode + ":%M" + suffix;
} else {
fmt = "%b %d " + hourCode + ":%M" + suffix;
}
} else if (t < timeUnitSize.month) {
fmt = "%b %d";
} else if ((useQuarters && t < timeUnitSize.quarter) ||
(!useQuarters && t < timeUnitSize.year)) {
if (span < timeUnitSize.year) {
fmt = "%b";
} else {
fmt = "%b %Y";
}
} else if (useQuarters && t < timeUnitSize.year) {
if (span < timeUnitSize.year) {
fmt = "Q%q";
} else {
fmt = "Q%q %Y";
}
} else {
fmt = "%Y";
}
var rt = formatDate(d, fmt, opts.monthNames, opts.dayNames);
return rt;
};
}
});
});
}
$.plot.plugins.push({
init: init,
options: options,
name: 'time',
version: '1.0'
});
// Time-axis support used to be in Flot core, which exposed the
// formatDate function on the plot object. Various plugins depend
// on the function, so we need to re-expose it here.
$.plot.formatDate = formatDate;
})(jQuery);

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,489 @@
!function(name,context,definition){if(typeof module!=='undefined')module.exports=definition(name,context);else if(typeof define==='function'&&typeof define.amd==='object')define(definition);else context[name]=definition(name,context);}('bean',this,function(name,context){var win=window,old=context[name],overOut=/over|out/,namespaceRegex=/[^\.]*(?=\..*)\.|.*/,nameRegex=/\..*/,addEvent='addEventListener',attachEvent='attachEvent',removeEvent='removeEventListener',detachEvent='detachEvent',doc=document||{},root=doc.documentElement||{},W3C_MODEL=root[addEvent],eventSupport=W3C_MODEL?addEvent:attachEvent,slice=Array.prototype.slice,mouseTypeRegex=/click|mouse|menu|drag|drop/i,touchTypeRegex=/^touch|^gesture/i,ONE={one:1},nativeEvents=(function(hash,events,i){for(i=0;i<events.length;i++)
hash[events[i]]=1
return hash})({},('click dblclick mouseup mousedown contextmenu '+'mousewheel DOMMouseScroll '+'mouseover mouseout mousemove selectstart selectend '+'keydown keypress keyup '+'orientationchange '+'focus blur change reset select submit '+'load unload beforeunload resize move DOMContentLoaded readystatechange '+'error abort scroll '+
(W3C_MODEL?'show '+'input invalid '+'touchstart touchmove touchend touchcancel '+'gesturestart gesturechange gestureend '+'message readystatechange pageshow pagehide popstate '+'hashchange offline online '+'afterprint beforeprint '+'dragstart dragenter dragover dragleave drag drop dragend '+'loadstart progress suspend emptied stalled loadmetadata '+'loadeddata canplay canplaythrough playing waiting seeking '+'seeked ended durationchange timeupdate play pause ratechange '+'volumechange cuechange '+'checking noupdate downloading cached updateready obsolete '+'':'')).split(' ')),customEvents=(function(){function isDescendant(parent,node){while((node=node.parentNode)!==null){if(node===parent)return true}
return false}
function check(event){var related=event.relatedTarget
if(!related)return related===null
return(related!==this&&related.prefix!=='xul'&&!/document/.test(this.toString())&&!isDescendant(this,related))}
return{mouseenter:{base:'mouseover',condition:check},mouseleave:{base:'mouseout',condition:check},mousewheel:{base:/Firefox/.test(navigator.userAgent)?'DOMMouseScroll':'mousewheel'}}})(),fixEvent=(function(){var commonProps='altKey attrChange attrName bubbles cancelable ctrlKey currentTarget detail eventPhase getModifierState isTrusted metaKey relatedNode relatedTarget shiftKey srcElement target timeStamp type view which'.split(' '),mouseProps=commonProps.concat('button buttons clientX clientY dataTransfer fromElement offsetX offsetY pageX pageY screenX screenY toElement'.split(' ')),keyProps=commonProps.concat('char charCode key keyCode'.split(' ')),touchProps=commonProps.concat('touches targetTouches changedTouches scale rotation'.split(' ')),preventDefault='preventDefault',createPreventDefault=function(event){return function(){if(event[preventDefault])
event[preventDefault]()
else
event.returnValue=false}},stopPropagation='stopPropagation',createStopPropagation=function(event){return function(){if(event[stopPropagation])
event[stopPropagation]()
else
event.cancelBubble=true}},createStop=function(synEvent){return function(){synEvent[preventDefault]()
synEvent[stopPropagation]()
synEvent.stopped=true}},copyProps=function(event,result,props){var i,p
for(i=props.length;i--;){p=props[i]
if(!(p in result)&&p in event)result[p]=event[p]}}
return function(event,isNative){var result={originalEvent:event,isNative:isNative}
if(!event)
return result
var props,type=event.type,target=event.target||event.srcElement
result[preventDefault]=createPreventDefault(event)
result[stopPropagation]=createStopPropagation(event)
result.stop=createStop(result)
result.target=target&&target.nodeType===3?target.parentNode:target
if(isNative){if(type.indexOf('key')!==-1){props=keyProps
result.keyCode=event.which||event.keyCode}else if(mouseTypeRegex.test(type)){props=mouseProps
result.rightClick=event.which===3||event.button===2
result.pos={x:0,y:0}
if(event.pageX||event.pageY){result.clientX=event.pageX
result.clientY=event.pageY}else if(event.clientX||event.clientY){result.clientX=event.clientX+doc.body.scrollLeft+root.scrollLeft
result.clientY=event.clientY+doc.body.scrollTop+root.scrollTop}
if(overOut.test(type))
result.relatedTarget=event.relatedTarget||event[(type==='mouseover'?'from':'to')+'Element']}else if(touchTypeRegex.test(type)){props=touchProps}
copyProps(event,result,props||commonProps)}
return result}})(),targetElement=function(element,isNative){return!W3C_MODEL&&!isNative&&(element===doc||element===win)?root:element},RegEntry=(function(){function entry(element,type,handler,original,namespaces){this.element=element
this.type=type
this.handler=handler
this.original=original
this.namespaces=namespaces
this.custom=customEvents[type]
this.isNative=nativeEvents[type]&&element[eventSupport]
this.eventType=W3C_MODEL||this.isNative?type:'propertychange'
this.customType=!W3C_MODEL&&!this.isNative&&type
this.target=targetElement(element,this.isNative)
this.eventSupport=this.target[eventSupport]}
entry.prototype={inNamespaces:function(checkNamespaces){var i,j
if(!checkNamespaces)
return true
if(!this.namespaces)
return false
for(i=checkNamespaces.length;i--;){for(j=this.namespaces.length;j--;){if(checkNamespaces[i]===this.namespaces[j])
return true}}
return false},matches:function(checkElement,checkOriginal,checkHandler){return this.element===checkElement&&(!checkOriginal||this.original===checkOriginal)&&(!checkHandler||this.handler===checkHandler)}}
return entry})(),registry=(function(){var map={},forAll=function(element,type,original,handler,fn){if(!type||type==='*'){for(var t in map){if(t.charAt(0)==='$')
forAll(element,t.substr(1),original,handler,fn)}}else{var i=0,l,list=map['$'+type],all=element==='*'
if(!list)
return
for(l=list.length;i<l;i++){if(all||list[i].matches(element,original,handler))
if(!fn(list[i],list,i,type))
return}}},has=function(element,type,original){var i,list=map['$'+type]
if(list){for(i=list.length;i--;){if(list[i].matches(element,original,null))
return true}}
return false},get=function(element,type,original){var entries=[]
forAll(element,type,original,null,function(entry){return entries.push(entry)})
return entries},put=function(entry){(map['$'+entry.type]||(map['$'+entry.type]=[])).push(entry)
return entry},del=function(entry){forAll(entry.element,entry.type,null,entry.handler,function(entry,list,i){list.splice(i,1)
if(list.length===0)
delete map['$'+entry.type]
return false})},entries=function(){var t,entries=[]
for(t in map){if(t.charAt(0)==='$')
entries=entries.concat(map[t])}
return entries}
return{has:has,get:get,put:put,del:del,entries:entries}})(),listener=W3C_MODEL?function(element,type,fn,add){element[add?addEvent:removeEvent](type,fn,false)}:function(element,type,fn,add,custom){if(custom&&add&&element['_on'+custom]===null)
element['_on'+custom]=0
element[add?attachEvent:detachEvent]('on'+type,fn)},nativeHandler=function(element,fn,args){return function(event){event=fixEvent(event||((this.ownerDocument||this.document||this).parentWindow||win).event,true)
return fn.apply(element,[event].concat(args))}},customHandler=function(element,fn,type,condition,args,isNative){return function(event){if(condition?condition.apply(this,arguments):W3C_MODEL?true:event&&event.propertyName==='_on'+type||!event){if(event)
event=fixEvent(event||((this.ownerDocument||this.document||this).parentWindow||win).event,isNative)
fn.apply(element,event&&(!args||args.length===0)?arguments:slice.call(arguments,event?0:1).concat(args))}}},once=function(rm,element,type,fn,originalFn){return function(){rm(element,type,originalFn)
fn.apply(this,arguments)}},removeListener=function(element,orgType,handler,namespaces){var i,l,entry,type=(orgType&&orgType.replace(nameRegex,'')),handlers=registry.get(element,type,handler)
for(i=0,l=handlers.length;i<l;i++){if(handlers[i].inNamespaces(namespaces)){if((entry=handlers[i]).eventSupport)
listener(entry.target,entry.eventType,entry.handler,false,entry.type)
registry.del(entry)}}},addListener=function(element,orgType,fn,originalFn,args){var entry,type=orgType.replace(nameRegex,''),namespaces=orgType.replace(namespaceRegex,'').split('.')
if(registry.has(element,type,fn))
return element
if(type==='unload')
fn=once(removeListener,element,type,fn,originalFn)
if(customEvents[type]){if(customEvents[type].condition)
fn=customHandler(element,fn,type,customEvents[type].condition,true)
type=customEvents[type].base||type}
entry=registry.put(new RegEntry(element,type,fn,originalFn,namespaces[0]&&namespaces))
entry.handler=entry.isNative?nativeHandler(element,entry.handler,args):customHandler(element,entry.handler,type,false,args,false)
if(entry.eventSupport)
listener(entry.target,entry.eventType,entry.handler,true,entry.customType)},del=function(selector,fn,$){return function(e){var target,i,array=typeof selector==='string'?$(selector,this):selector
for(target=e.target;target&&target!==this;target=target.parentNode){for(i=array.length;i--;){if(array[i]===target){return fn.apply(target,arguments)}}}}},remove=function(element,typeSpec,fn){var k,m,type,namespaces,i,rm=removeListener,isString=typeSpec&&typeof typeSpec==='string'
if(isString&&typeSpec.indexOf(' ')>0){typeSpec=typeSpec.split(' ')
for(i=typeSpec.length;i--;)
remove(element,typeSpec[i],fn)
return element}
type=isString&&typeSpec.replace(nameRegex,'')
if(type&&customEvents[type])
type=customEvents[type].type
if(!typeSpec||isString){if(namespaces=isString&&typeSpec.replace(namespaceRegex,''))
namespaces=namespaces.split('.')
rm(element,type,fn,namespaces)}else if(typeof typeSpec==='function'){rm(element,null,typeSpec)}else{for(k in typeSpec){if(typeSpec.hasOwnProperty(k))
remove(element,k,typeSpec[k])}}
return element},add=function(element,events,fn,delfn,$){var type,types,i,args,originalFn=fn,isDel=fn&&typeof fn==='string'
if(events&&!fn&&typeof events==='object'){for(type in events){if(events.hasOwnProperty(type))
add.apply(this,[element,type,events[type]])}}else{args=arguments.length>3?slice.call(arguments,3):[]
types=(isDel?fn:events).split(' ')
isDel&&(fn=del(events,(originalFn=delfn),$))&&(args=slice.call(args,1))
this===ONE&&(fn=once(remove,element,events,fn,originalFn))
for(i=types.length;i--;)addListener(element,types[i],fn,originalFn,args)}
return element},one=function(){return add.apply(ONE,arguments)},fireListener=W3C_MODEL?function(isNative,type,element){var evt=doc.createEvent(isNative?'HTMLEvents':'UIEvents')
evt[isNative?'initEvent':'initUIEvent'](type,true,true,win,1)
element.dispatchEvent(evt)}:function(isNative,type,element){element=targetElement(element,isNative)
isNative?element.fireEvent('on'+type,doc.createEventObject()):element['_on'+type]++},fire=function(element,type,args){var i,j,l,names,handlers,types=type.split(' ')
for(i=types.length;i--;){type=types[i].replace(nameRegex,'')
if(names=types[i].replace(namespaceRegex,''))
names=names.split('.')
if(!names&&!args&&element[eventSupport]){fireListener(nativeEvents[type],type,element)}else{handlers=registry.get(element,type)
args=[false].concat(args)
for(j=0,l=handlers.length;j<l;j++){if(handlers[j].inNamespaces(names))
handlers[j].handler.apply(element,args)}}}
return element},clone=function(element,from,type){var i=0,handlers=registry.get(from,type),l=handlers.length
for(;i<l;i++)
handlers[i].original&&add(element,handlers[i].type,handlers[i].original)
return element},bean={add:add,one:one,remove:remove,clone:clone,fire:fire,noConflict:function(){context[name]=old
return this}}
if(win[attachEvent]){var cleanup=function(){var i,entries=registry.entries()
for(i in entries){if(entries[i].type&&entries[i].type!=='unload')
remove(entries[i].element,entries[i].type)}
win[detachEvent]('onunload',cleanup)
win.CollectGarbage&&win.CollectGarbage()}
win[attachEvent]('onunload',cleanup)}
return bean});(function(){var
global=this,previousFlotr=this.Flotr,Flotr;Flotr={_:_,bean:bean,isIphone:/iphone/i.test(navigator.userAgent),isIE:(navigator.appVersion.indexOf("MSIE")!=-1?parseFloat(navigator.appVersion.split("MSIE")[1]):false),graphTypes:{},plugins:{},addType:function(name,graphType){Flotr.graphTypes[name]=graphType;Flotr.defaultOptions[name]=graphType.options||{};Flotr.defaultOptions.defaultType=Flotr.defaultOptions.defaultType||name;},addPlugin:function(name,plugin){Flotr.plugins[name]=plugin;Flotr.defaultOptions[name]=plugin.options||{};},draw:function(el,data,options,GraphKlass){GraphKlass=GraphKlass||Flotr.Graph;return new GraphKlass(el,data,options);},merge:function(src,dest){var i,v,result=dest||{};for(i in src){v=src[i];if(v&&typeof(v)==='object'){if(v.constructor===Array){result[i]=this._.clone(v);}else if(v.constructor!==RegExp&&!this._.isElement(v)){result[i]=Flotr.merge(v,(dest?dest[i]:undefined));}else{result[i]=v;}}else{result[i]=v;}}
return result;},clone:function(object){return Flotr.merge(object,{});},getTickSize:function(noTicks,min,max,decimals){var delta=(max-min)/noTicks,magn=Flotr.getMagnitude(delta),tickSize=10,norm=delta/magn;if(norm<1.5)tickSize=1;else if(norm<2.25)tickSize=2;else if(norm<3)tickSize=((decimals===0)?2:2.5);else if(norm<7.5)tickSize=5;return tickSize*magn;},defaultTickFormatter:function(val,axisOpts){return val+'';},defaultTrackFormatter:function(obj){return'('+obj.x+', '+obj.y+')';},engineeringNotation:function(value,precision,base){var sizes=['Y','Z','E','P','T','G','M','k',''],fractionSizes=['y','z','a','f','p','n','µ','m',''],total=sizes.length;base=base||1000;precision=Math.pow(10,precision||2);if(value===0)return 0;if(value>1){while(total--&&(value>=base))value/=base;}
else{sizes=fractionSizes;total=sizes.length;while(total--&&(value<1))value*=base;}
return(Math.round(value*precision)/precision)+sizes[total];},getMagnitude:function(x){return Math.pow(10,Math.floor(Math.log(x)/Math.LN10));},toPixel:function(val){return Math.floor(val)+0.5;},toRad:function(angle){return-angle*(Math.PI/180);},floorInBase:function(n,base){return base*Math.floor(n/base);},drawText:function(ctx,text,x,y,style){if(!ctx.fillText){ctx.drawText(text,x,y,style);return;}
style=this._.extend({size:Flotr.defaultOptions.fontSize,color:'#000000',textAlign:'left',textBaseline:'bottom',weight:1,angle:0},style);ctx.save();ctx.translate(x,y);ctx.rotate(style.angle);ctx.fillStyle=style.color;ctx.font=(style.weight>1?"bold ":"")+(style.size*1.3)+"px sans-serif";ctx.textAlign=style.textAlign;ctx.textBaseline=style.textBaseline;ctx.fillText(text,0,0);ctx.restore();},getBestTextAlign:function(angle,style){style=style||{textAlign:'center',textBaseline:'middle'};angle+=Flotr.getTextAngleFromAlign(style);if(Math.abs(Math.cos(angle))>10e-3)
style.textAlign=(Math.cos(angle)>0?'right':'left');if(Math.abs(Math.sin(angle))>10e-3)
style.textBaseline=(Math.sin(angle)>0?'top':'bottom');return style;},alignTable:{'right middle':0,'right top':Math.PI/4,'center top':Math.PI/2,'left top':3*(Math.PI/4),'left middle':Math.PI,'left bottom':-3*(Math.PI/4),'center bottom':-Math.PI/2,'right bottom':-Math.PI/4,'center middle':0},getTextAngleFromAlign:function(style){return Flotr.alignTable[style.textAlign+' '+style.textBaseline]||0;},noConflict:function(){global.Flotr=previousFlotr;return this;}};global.Flotr=Flotr;})();Flotr.defaultOptions={colors:['#00A8F0','#C0D800','#CB4B4B','#4DA74D','#9440ED'],ieBackgroundColor:'#FFFFFF',title:null,subtitle:null,shadowSize:4,defaultType:null,HtmlText:true,fontColor:'#545454',fontSize:7.5,resolution:1,parseFloat:true,preventDefault:true,xaxis:{ticks:null,minorTicks:null,showLabels:true,showMinorLabels:false,labelsAngle:0,title:null,titleAngle:0,noTicks:5,minorTickFreq:null,tickFormatter:Flotr.defaultTickFormatter,tickDecimals:null,min:null,max:null,autoscale:false,autoscaleMargin:0,color:null,mode:'normal',timeFormat:null,timeMode:'UTC',timeUnit:'millisecond',scaling:'linear',base:Math.E,titleAlign:'center',margin:true},x2axis:{},yaxis:{ticks:null,minorTicks:null,showLabels:true,showMinorLabels:false,labelsAngle:0,title:null,titleAngle:90,noTicks:5,minorTickFreq:null,tickFormatter:Flotr.defaultTickFormatter,tickDecimals:null,min:null,max:null,autoscale:false,autoscaleMargin:0,color:null,scaling:'linear',base:Math.E,titleAlign:'center',margin:true},y2axis:{titleAngle:270},grid:{color:'#545454',backgroundColor:null,backgroundImage:null,watermarkAlpha:0.4,tickColor:'#DDDDDD',labelMargin:3,verticalLines:true,minorVerticalLines:null,horizontalLines:true,minorHorizontalLines:null,outlineWidth:1,outline:'nsew',circular:false},mouse:{track:false,trackAll:false,position:'se',relative:false,trackFormatter:Flotr.defaultTrackFormatter,margin:5,lineColor:'#FF3F19',trackDecimals:1,sensibility:2,trackY:true,radius:3,fillColor:null,fillOpacity:0.4}};(function(){var
_=Flotr._;function Color(r,g,b,a){this.rgba=['r','g','b','a'];var x=4;while(-1<--x){this[this.rgba[x]]=arguments[x]||((x==3)?1.0:0);}
this.normalize();}
var COLOR_NAMES={aqua:[0,255,255],azure:[240,255,255],beige:[245,245,220],black:[0,0,0],blue:[0,0,255],brown:[165,42,42],cyan:[0,255,255],darkblue:[0,0,139],darkcyan:[0,139,139],darkgrey:[169,169,169],darkgreen:[0,100,0],darkkhaki:[189,183,107],darkmagenta:[139,0,139],darkolivegreen:[85,107,47],darkorange:[255,140,0],darkorchid:[153,50,204],darkred:[139,0,0],darksalmon:[233,150,122],darkviolet:[148,0,211],fuchsia:[255,0,255],gold:[255,215,0],green:[0,128,0],indigo:[75,0,130],khaki:[240,230,140],lightblue:[173,216,230],lightcyan:[224,255,255],lightgreen:[144,238,144],lightgrey:[211,211,211],lightpink:[255,182,193],lightyellow:[255,255,224],lime:[0,255,0],magenta:[255,0,255],maroon:[128,0,0],navy:[0,0,128],olive:[128,128,0],orange:[255,165,0],pink:[255,192,203],purple:[128,0,128],violet:[128,0,128],red:[255,0,0],silver:[192,192,192],white:[255,255,255],yellow:[255,255,0]};Color.prototype={scale:function(rf,gf,bf,af){var x=4;while(-1<--x){if(!_.isUndefined(arguments[x]))this[this.rgba[x]]*=arguments[x];}
return this.normalize();},alpha:function(alpha){if(!_.isUndefined(alpha)&&!_.isNull(alpha)){this.a=alpha;}
return this.normalize();},clone:function(){return new Color(this.r,this.b,this.g,this.a);},limit:function(val,minVal,maxVal){return Math.max(Math.min(val,maxVal),minVal);},normalize:function(){var limit=this.limit;this.r=limit(parseInt(this.r,10),0,255);this.g=limit(parseInt(this.g,10),0,255);this.b=limit(parseInt(this.b,10),0,255);this.a=limit(this.a,0,1);return this;},distance:function(color){if(!color)return;color=new Color.parse(color);var dist=0,x=3;while(-1<--x){dist+=Math.abs(this[this.rgba[x]]-color[this.rgba[x]]);}
return dist;},toString:function(){return(this.a>=1.0)?'rgb('+[this.r,this.g,this.b].join(',')+')':'rgba('+[this.r,this.g,this.b,this.a].join(',')+')';},contrast:function(){var
test=1-(0.299*this.r+0.587*this.g+0.114*this.b)/255;return(test<0.5?'#000000':'#ffffff');}};_.extend(Color,{parse:function(color){if(color instanceof Color)return color;var result;if((result=/#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/.exec(color)))
return new Color(parseInt(result[1],16),parseInt(result[2],16),parseInt(result[3],16));if((result=/rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)/.exec(color)))
return new Color(parseInt(result[1],10),parseInt(result[2],10),parseInt(result[3],10));if((result=/#([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/.exec(color)))
return new Color(parseInt(result[1]+result[1],16),parseInt(result[2]+result[2],16),parseInt(result[3]+result[3],16));if((result=/rgba\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]+(?:\.[0-9]+)?)\s*\)/.exec(color)))
return new Color(parseInt(result[1],10),parseInt(result[2],10),parseInt(result[3],10),parseFloat(result[4]));if((result=/rgb\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*\)/.exec(color)))
return new Color(parseFloat(result[1])*2.55,parseFloat(result[2])*2.55,parseFloat(result[3])*2.55);if((result=/rgba\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\s*\)/.exec(color)))
return new Color(parseFloat(result[1])*2.55,parseFloat(result[2])*2.55,parseFloat(result[3])*2.55,parseFloat(result[4]));var name=(color+'').replace(/^\s*([\S\s]*?)\s*$/,'$1').toLowerCase();if(name=='transparent'){return new Color(255,255,255,0);}
return(result=COLOR_NAMES[name])?new Color(result[0],result[1],result[2]):new Color(0,0,0,0);},processColor:function(color,options){var opacity=options.opacity;if(!color)return'rgba(0, 0, 0, 0)';if(color instanceof Color)return color.alpha(opacity).toString();if(_.isString(color))return Color.parse(color).alpha(opacity).toString();var grad=color.colors?color:{colors:color};if(!options.ctx){if(!_.isArray(grad.colors))return'rgba(0, 0, 0, 0)';return Color.parse(_.isArray(grad.colors[0])?grad.colors[0][1]:grad.colors[0]).alpha(opacity).toString();}
grad=_.extend({start:'top',end:'bottom'},grad);if(/top/i.test(grad.start))options.x1=0;if(/left/i.test(grad.start))options.y1=0;if(/bottom/i.test(grad.end))options.x2=0;if(/right/i.test(grad.end))options.y2=0;var i,c,stop,gradient=options.ctx.createLinearGradient(options.x1,options.y1,options.x2,options.y2);for(i=0;i<grad.colors.length;i++){c=grad.colors[i];if(_.isArray(c)){stop=c[0];c=c[1];}
else stop=i/(grad.colors.length-1);gradient.addColorStop(stop,Color.parse(c).alpha(opacity));}
return gradient;}});Flotr.Color=Color;})();Flotr.Date={set:function(date,name,mode,value){mode=mode||'UTC';name='set'+(mode==='UTC'?'UTC':'')+name;date[name](value);},get:function(date,name,mode){mode=mode||'UTC';name='get'+(mode==='UTC'?'UTC':'')+name;return date[name]();},format:function(d,format,mode){if(!d)return;var
get=this.get,tokens={h:get(d,'Hours',mode).toString(),H:leftPad(get(d,'Hours',mode)),M:leftPad(get(d,'Minutes',mode)),S:leftPad(get(d,'Seconds',mode)),s:get(d,'Milliseconds',mode),d:get(d,'Date',mode).toString(),m:(get(d,'Month',mode)+1).toString(),y:get(d,'FullYear',mode).toString(),b:Flotr.Date.monthNames[get(d,'Month',mode)]};function leftPad(n){n+='';return n.length==1?"0"+n:n;}
var r=[],c,escape=false;for(var i=0;i<format.length;++i){c=format.charAt(i);if(escape){r.push(tokens[c]||c);escape=false;}
else if(c=="%")
escape=true;else
r.push(c);}
return r.join('');},getFormat:function(time,span){var tu=Flotr.Date.timeUnits;if(time<tu.second)return"%h:%M:%S.%s";else if(time<tu.minute)return"%h:%M:%S";else if(time<tu.day)return(span<2*tu.day)?"%h:%M":"%b %d %h:%M";else if(time<tu.month)return"%b %d";else if(time<tu.year)return(span<tu.year)?"%b":"%b %y";else return"%y";},formatter:function(v,axis){var
options=axis.options,scale=Flotr.Date.timeUnits[options.timeUnit],d=new Date(v*scale);if(axis.options.timeFormat)
return Flotr.Date.format(d,options.timeFormat,options.timeMode);var span=(axis.max-axis.min)*scale,t=axis.tickSize*Flotr.Date.timeUnits[axis.tickUnit];return Flotr.Date.format(d,Flotr.Date.getFormat(t,span),options.timeMode);},generator:function(axis){var
set=this.set,get=this.get,timeUnits=this.timeUnits,spec=this.spec,options=axis.options,mode=options.timeMode,scale=timeUnits[options.timeUnit],min=axis.min*scale,max=axis.max*scale,delta=(max-min)/options.noTicks,ticks=[],tickSize=axis.tickSize,tickUnit,formatter,i;formatter=(options.tickFormatter===Flotr.defaultTickFormatter?this.formatter:options.tickFormatter);for(i=0;i<spec.length-1;++i){var d=spec[i][0]*timeUnits[spec[i][1]];if(delta<(d+spec[i+1][0]*timeUnits[spec[i+1][1]])/2&&d>=tickSize)
break;}
tickSize=spec[i][0];tickUnit=spec[i][1];if(tickUnit=="year"){tickSize=Flotr.getTickSize(options.noTicks*timeUnits.year,min,max,0);if(tickSize==0.5){tickUnit="month";tickSize=6;}}
axis.tickUnit=tickUnit;axis.tickSize=tickSize;var step=tickSize*timeUnits[tickUnit];d=new Date(min);function setTick(name){set(d,name,mode,Flotr.floorInBase(get(d,name,mode),tickSize));}
switch(tickUnit){case"millisecond":setTick('Milliseconds');break;case"second":setTick('Seconds');break;case"minute":setTick('Minutes');break;case"hour":setTick('Hours');break;case"month":setTick('Month');break;case"year":setTick('FullYear');break;}
if(step>=timeUnits.second)set(d,'Milliseconds',mode,0);if(step>=timeUnits.minute)set(d,'Seconds',mode,0);if(step>=timeUnits.hour)set(d,'Minutes',mode,0);if(step>=timeUnits.day)set(d,'Hours',mode,0);if(step>=timeUnits.day*4)set(d,'Date',mode,1);if(step>=timeUnits.year)set(d,'Month',mode,0);var carry=0,v=NaN,prev;do{prev=v;v=d.getTime();ticks.push({v:v/scale,label:formatter(v/scale,axis)});if(tickUnit=="month"){if(tickSize<1){set(d,'Date',mode,1);var start=d.getTime();set(d,'Month',mode,get(d,'Month',mode)+1);var end=d.getTime();d.setTime(v+carry*timeUnits.hour+(end-start)*tickSize);carry=get(d,'Hours',mode);set(d,'Hours',mode,0);}
else
set(d,'Month',mode,get(d,'Month',mode)+tickSize);}
else if(tickUnit=="year"){set(d,'FullYear',mode,get(d,'FullYear',mode)+tickSize);}
else
d.setTime(v+step);}while(v<max&&v!=prev);return ticks;},timeUnits:{millisecond:1,second:1000,minute:1000*60,hour:1000*60*60,day:1000*60*60*24,month:1000*60*60*24*30,year:1000*60*60*24*365.2425},spec:[[1,"millisecond"],[20,"millisecond"],[50,"millisecond"],[100,"millisecond"],[200,"millisecond"],[500,"millisecond"],[1,"second"],[2,"second"],[5,"second"],[10,"second"],[30,"second"],[1,"minute"],[2,"minute"],[5,"minute"],[10,"minute"],[30,"minute"],[1,"hour"],[2,"hour"],[4,"hour"],[8,"hour"],[12,"hour"],[1,"day"],[2,"day"],[3,"day"],[0.25,"month"],[0.5,"month"],[1,"month"],[2,"month"],[3,"month"],[6,"month"],[1,"year"]],monthNames:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"]};(function(){var _=Flotr._;Flotr.DOM={addClass:function(element,name){var classList=(element.className?element.className:'');if(_.include(classList.split(/\s+/g),name))return;element.className=(classList?classList+' ':'')+name;},create:function(tag){return document.createElement(tag);},node:function(html){var div=Flotr.DOM.create('div'),n;div.innerHTML=html;n=div.children[0];div.innerHTML='';return n;},empty:function(element){element.innerHTML='';},hide:function(element){Flotr.DOM.setStyles(element,{display:'none'});},insert:function(element,child){if(_.isString(child))
element.innerHTML+=child;else if(_.isElement(child))
element.appendChild(child);},opacity:function(element,opacity){element.style.opacity=opacity;},position:function(element,p){if(!element.offsetParent)
return{left:(element.offsetLeft||0),top:(element.offsetTop||0)};p=this.position(element.offsetParent);p.left+=element.offsetLeft;p.top+=element.offsetTop;return p;},removeClass:function(element,name){var classList=(element.className?element.className:'');element.className=_.filter(classList.split(/\s+/g),function(c){if(c!=name)return true;}).join(' ');},setStyles:function(element,o){_.each(o,function(value,key){element.style[key]=value;});},show:function(element){Flotr.DOM.setStyles(element,{display:''});},size:function(element){return{height:element.offsetHeight,width:element.offsetWidth};}};})();(function(){var
F=Flotr,bean=F.bean;F.EventAdapter={observe:function(object,name,callback){bean.add(object,name,callback);return this;},fire:function(object,name,args){bean.fire(object,name,args);if(typeof(Prototype)!='undefined')
Event.fire(object,name,args);return this;},stopObserving:function(object,name,callback){bean.remove(object,name,callback);return this;},eventPointer:function(e){if(!F._.isUndefined(e.touches)&&e.touches.length>0){return{x:e.touches[0].pageX,y:e.touches[0].pageY};}else if(!F._.isUndefined(e.changedTouches)&&e.changedTouches.length>0){return{x:e.changedTouches[0].pageX,y:e.changedTouches[0].pageY};}else if(e.pageX||e.pageY){return{x:e.pageX,y:e.pageY};}else if(e.clientX||e.clientY){var
d=document,b=d.body,de=d.documentElement;return{x:e.clientX+b.scrollLeft+de.scrollLeft,y:e.clientY+b.scrollTop+de.scrollTop};}}};})();(function(){var
F=Flotr,D=F.DOM,_=F._,Text=function(o){this.o=o;};Text.prototype={dimensions:function(text,canvasStyle,htmlStyle,className){if(!text)return{width:0,height:0};return(this.o.html)?this.html(text,this.o.element,htmlStyle,className):this.canvas(text,canvasStyle);},canvas:function(text,style){if(!this.o.textEnabled)return;style=style||{};var
metrics=this.measureText(text,style),width=metrics.width,height=style.size||F.defaultOptions.fontSize,angle=style.angle||0,cosAngle=Math.cos(angle),sinAngle=Math.sin(angle),widthPadding=2,heightPadding=6,bounds;bounds={width:Math.abs(cosAngle*width)+Math.abs(sinAngle*height)+widthPadding,height:Math.abs(sinAngle*width)+Math.abs(cosAngle*height)+heightPadding};return bounds;},html:function(text,element,style,className){var div=D.create('div');D.setStyles(div,{'position':'absolute','top':'-10000px'});D.insert(div,'<div style="'+style+'" class="'+className+' flotr-dummy-div">'+text+'</div>');D.insert(this.o.element,div);return D.size(div);},measureText:function(text,style){var
context=this.o.ctx,metrics;if(!context.fillText||(F.isIphone&&context.measure)){return{width:context.measure(text,style)};}
style=_.extend({size:F.defaultOptions.fontSize,weight:1,angle:0},style);context.save();context.font=(style.weight>1?"bold ":"")+(style.size*1.3)+"px sans-serif";metrics=context.measureText(text);context.restore();return metrics;}};Flotr.Text=Text;})();(function(){var
D=Flotr.DOM,E=Flotr.EventAdapter,_=Flotr._,flotr=Flotr;Graph=function(el,data,options){this._setEl(el);this._initMembers();this._initPlugins();E.fire(this.el,'flotr:beforeinit',[this]);this.data=data;this.series=flotr.Series.getSeries(data);this._initOptions(options);this._initGraphTypes();this._initCanvas();this._text=new flotr.Text({element:this.el,ctx:this.ctx,html:this.options.HtmlText,textEnabled:this.textEnabled});E.fire(this.el,'flotr:afterconstruct',[this]);this._initEvents();this.findDataRanges();this.calculateSpacing();this.draw(_.bind(function(){E.fire(this.el,'flotr:afterinit',[this]);},this));};function observe(object,name,callback){E.observe.apply(this,arguments);this._handles.push(arguments);return this;}
Graph.prototype={destroy:function(){E.fire(this.el,'flotr:destroy');_.each(this._handles,function(handle){E.stopObserving.apply(this,handle);});this._handles=[];this.el.graph=null;},observe:observe,_observe:observe,processColor:function(color,options){var o={x1:0,y1:0,x2:this.plotWidth,y2:this.plotHeight,opacity:1,ctx:this.ctx};_.extend(o,options);return flotr.Color.processColor(color,o);},findDataRanges:function(){var a=this.axes,xaxis,yaxis,range;_.each(this.series,function(series){range=series.getRange();if(range){xaxis=series.xaxis;yaxis=series.yaxis;xaxis.datamin=Math.min(range.xmin,xaxis.datamin);xaxis.datamax=Math.max(range.xmax,xaxis.datamax);yaxis.datamin=Math.min(range.ymin,yaxis.datamin);yaxis.datamax=Math.max(range.ymax,yaxis.datamax);xaxis.used=(xaxis.used||range.xused);yaxis.used=(yaxis.used||range.yused);}},this);if(!a.x.used&&!a.x2.used)a.x.used=true;if(!a.y.used&&!a.y2.used)a.y.used=true;_.each(a,function(axis){axis.calculateRange();});var
types=_.keys(flotr.graphTypes),drawn=false;_.each(this.series,function(series){if(series.hide)return;_.each(types,function(type){if(series[type]&&series[type].show){this.extendRange(type,series);drawn=true;}},this);if(!drawn){this.extendRange(this.options.defaultType,series);}},this);},extendRange:function(type,series){if(this[type].extendRange)this[type].extendRange(series,series.data,series[type],this[type]);if(this[type].extendYRange)this[type].extendYRange(series.yaxis,series.data,series[type],this[type]);if(this[type].extendXRange)this[type].extendXRange(series.xaxis,series.data,series[type],this[type]);},calculateSpacing:function(){var a=this.axes,options=this.options,series=this.series,margin=options.grid.labelMargin,T=this._text,x=a.x,x2=a.x2,y=a.y,y2=a.y2,maxOutset=options.grid.outlineWidth,i,j,l,dim;_.each(a,function(axis){axis.calculateTicks();axis.calculateTextDimensions(T,options);});dim=T.dimensions(options.title,{size:options.fontSize*1.5},'font-size:1em;font-weight:bold;','flotr-title');this.titleHeight=dim.height;dim=T.dimensions(options.subtitle,{size:options.fontSize},'font-size:smaller;','flotr-subtitle');this.subtitleHeight=dim.height;for(j=0;j<options.length;++j){if(series[j].points.show){maxOutset=Math.max(maxOutset,series[j].points.radius+series[j].points.lineWidth/2);}}
var p=this.plotOffset;if(x.options.margin===false){p.bottom=0;p.top=0;}else{p.bottom+=(options.grid.circular?0:(x.used&&x.options.showLabels?(x.maxLabel.height+margin):0))+
(x.used&&x.options.title?(x.titleSize.height+margin):0)+maxOutset;p.top+=(options.grid.circular?0:(x2.used&&x2.options.showLabels?(x2.maxLabel.height+margin):0))+
(x2.used&&x2.options.title?(x2.titleSize.height+margin):0)+this.subtitleHeight+this.titleHeight+maxOutset;}
if(y.options.margin===false){p.left=0;p.right=0;}else{p.left+=(options.grid.circular?0:(y.used&&y.options.showLabels?(y.maxLabel.width+margin):0))+
(y.used&&y.options.title?(y.titleSize.width+margin):0)+maxOutset;p.right+=(options.grid.circular?0:(y2.used&&y2.options.showLabels?(y2.maxLabel.width+margin):0))+
(y2.used&&y2.options.title?(y2.titleSize.width+margin):0)+maxOutset;}
p.top=Math.floor(p.top);this.plotWidth=this.canvasWidth-p.left-p.right;this.plotHeight=this.canvasHeight-p.bottom-p.top;x.length=x2.length=this.plotWidth;y.length=y2.length=this.plotHeight;y.offset=y2.offset=this.plotHeight;x.setScale();x2.setScale();y.setScale();y2.setScale();},draw:function(after){var
context=this.ctx,i;E.fire(this.el,'flotr:beforedraw',[this.series,this]);if(this.series.length){context.save();context.translate(this.plotOffset.left,this.plotOffset.top);for(i=0;i<this.series.length;i++){if(!this.series[i].hide)this.drawSeries(this.series[i]);}
context.restore();this.clip();}
E.fire(this.el,'flotr:afterdraw',[this.series,this]);if(after)after();},drawSeries:function(series){function drawChart(series,typeKey){var options=this.getOptions(series,typeKey);this[typeKey].draw(options);}
var drawn=false;series=series||this.series;_.each(flotr.graphTypes,function(type,typeKey){if(series[typeKey]&&series[typeKey].show&&this[typeKey]){drawn=true;drawChart.call(this,series,typeKey);}},this);if(!drawn)drawChart.call(this,series,this.options.defaultType);},getOptions:function(series,typeKey){var
type=series[typeKey],graphType=this[typeKey],xaxis=series.xaxis,yaxis=series.yaxis,options={context:this.ctx,width:this.plotWidth,height:this.plotHeight,fontSize:this.options.fontSize,fontColor:this.options.fontColor,textEnabled:this.textEnabled,htmlText:this.options.HtmlText,text:this._text,element:this.el,data:series.data,color:series.color,shadowSize:series.shadowSize,xScale:xaxis.d2p,yScale:yaxis.d2p,xInverse:xaxis.p2d,yInverse:yaxis.p2d};options=flotr.merge(type,options);options.fillStyle=this.processColor(type.fillColor||series.color,{opacity:type.fillOpacity});return options;},getEventPosition:function(e){var
d=document,b=d.body,de=d.documentElement,axes=this.axes,plotOffset=this.plotOffset,lastMousePos=this.lastMousePos,pointer=E.eventPointer(e),dx=pointer.x-lastMousePos.pageX,dy=pointer.y-lastMousePos.pageY,r,rx,ry;if('ontouchstart'in this.el){r=D.position(this.overlay);rx=pointer.x-r.left-plotOffset.left;ry=pointer.y-r.top-plotOffset.top;}else{r=this.overlay.getBoundingClientRect();rx=e.clientX-r.left-plotOffset.left-b.scrollLeft-de.scrollLeft;ry=e.clientY-r.top-plotOffset.top-b.scrollTop-de.scrollTop;}
return{x:axes.x.p2d(rx),x2:axes.x2.p2d(rx),y:axes.y.p2d(ry),y2:axes.y2.p2d(ry),relX:rx,relY:ry,dX:dx,dY:dy,absX:pointer.x,absY:pointer.y,pageX:pointer.x,pageY:pointer.y};},clickHandler:function(event){if(this.ignoreClick){this.ignoreClick=false;return this.ignoreClick;}
E.fire(this.el,'flotr:click',[this.getEventPosition(event),this]);},mouseMoveHandler:function(event){if(this.mouseDownMoveHandler)return;var pos=this.getEventPosition(event);E.fire(this.el,'flotr:mousemove',[event,pos,this]);this.lastMousePos=pos;},mouseDownHandler:function(event){if(this.mouseUpHandler)return;this.mouseUpHandler=_.bind(function(e){E.stopObserving(document,'mouseup',this.mouseUpHandler);E.stopObserving(document,'mousemove',this.mouseDownMoveHandler);this.mouseDownMoveHandler=null;this.mouseUpHandler=null;E.fire(this.el,'flotr:mouseup',[e,this]);},this);this.mouseDownMoveHandler=_.bind(function(e){var pos=this.getEventPosition(e);E.fire(this.el,'flotr:mousemove',[event,pos,this]);this.lastMousePos=pos;},this);E.observe(document,'mouseup',this.mouseUpHandler);E.observe(document,'mousemove',this.mouseDownMoveHandler);E.fire(this.el,'flotr:mousedown',[event,this]);this.ignoreClick=false;},drawTooltip:function(content,x,y,options){var mt=this.getMouseTrack(),style='opacity:0.7;background-color:#000;color:#fff;display:none;position:absolute;padding:2px 8px;-moz-border-radius:4px;border-radius:4px;white-space:nowrap;',p=options.position,m=options.margin,plotOffset=this.plotOffset;if(x!==null&&y!==null){if(!options.relative){if(p.charAt(0)=='n')style+='top:'+(m+plotOffset.top)+'px;bottom:auto;';else if(p.charAt(0)=='s')style+='bottom:'+(m+plotOffset.bottom)+'px;top:auto;';if(p.charAt(1)=='e')style+='right:'+(m+plotOffset.right)+'px;left:auto;';else if(p.charAt(1)=='w')style+='left:'+(m+plotOffset.left)+'px;right:auto;';}
else{if(p.charAt(0)=='n')style+='bottom:'+(m-plotOffset.top-y+this.canvasHeight)+'px;top:auto;';else if(p.charAt(0)=='s')style+='top:'+(m+plotOffset.top+y)+'px;bottom:auto;';if(p.charAt(1)=='e')style+='left:'+(m+plotOffset.left+x)+'px;right:auto;';else if(p.charAt(1)=='w')style+='right:'+(m-plotOffset.left-x+this.canvasWidth)+'px;left:auto;';}
mt.style.cssText=style;D.empty(mt);D.insert(mt,content);D.show(mt);}
else{D.hide(mt);}},clip:function(ctx){var
o=this.plotOffset,w=this.canvasWidth,h=this.canvasHeight;ctx=ctx||this.ctx;if(flotr.isIE&&flotr.isIE<9){ctx.save();ctx.fillStyle=this.processColor(this.options.ieBackgroundColor);ctx.fillRect(0,0,w,o.top);ctx.fillRect(0,0,o.left,h);ctx.fillRect(0,h-o.bottom,w,o.bottom);ctx.fillRect(w-o.right,0,o.right,h);ctx.restore();}else{ctx.clearRect(0,0,w,o.top);ctx.clearRect(0,0,o.left,h);ctx.clearRect(0,h-o.bottom,w,o.bottom);ctx.clearRect(w-o.right,0,o.right,h);}},_initMembers:function(){this._handles=[];this.lastMousePos={pageX:null,pageY:null};this.plotOffset={left:0,right:0,top:0,bottom:0};this.ignoreClick=true;this.prevHit=null;},_initGraphTypes:function(){_.each(flotr.graphTypes,function(handler,graphType){this[graphType]=flotr.clone(handler);},this);},_initEvents:function(){var
el=this.el,touchendHandler,movement,touchend;if('ontouchstart'in el){touchendHandler=_.bind(function(e){touchend=true;E.stopObserving(document,'touchend',touchendHandler);E.fire(el,'flotr:mouseup',[event,this]);this.multitouches=null;if(!movement){this.clickHandler(e);}},this);this.observe(this.overlay,'touchstart',_.bind(function(e){movement=false;touchend=false;this.ignoreClick=false;if(e.touches&&e.touches.length>1){this.multitouches=e.touches;}
E.fire(el,'flotr:mousedown',[event,this]);this.observe(document,'touchend',touchendHandler);},this));this.observe(this.overlay,'touchmove',_.bind(function(e){var pos=this.getEventPosition(e);if(this.options.preventDefault){e.preventDefault();}
movement=true;if(this.multitouches||(e.touches&&e.touches.length>1)){this.multitouches=e.touches;}else{if(!touchend){E.fire(el,'flotr:mousemove',[event,pos,this]);}}
this.lastMousePos=pos;},this));}else{this.observe(this.overlay,'mousedown',_.bind(this.mouseDownHandler,this)).observe(el,'mousemove',_.bind(this.mouseMoveHandler,this)).observe(this.overlay,'click',_.bind(this.clickHandler,this)).observe(el,'mouseout',function(){E.fire(el,'flotr:mouseout');});}},_initCanvas:function(){var el=this.el,o=this.options,children=el.children,removedChildren=[],child,i,size,style;for(i=children.length;i--;){child=children[i];if(!this.canvas&&child.className==='flotr-canvas'){this.canvas=child;}else if(!this.overlay&&child.className==='flotr-overlay'){this.overlay=child;}else{removedChildren.push(child);}}
for(i=removedChildren.length;i--;){el.removeChild(removedChildren[i]);}
D.setStyles(el,{position:'relative'});size={};size.width=el.clientWidth;size.height=el.clientHeight;if(size.width<=0||size.height<=0||o.resolution<=0){throw'Invalid dimensions for plot, width = '+size.width+', height = '+size.height+', resolution = '+o.resolution;}
this.canvas=getCanvas(this.canvas,'canvas');this.overlay=getCanvas(this.overlay,'overlay');this.ctx=getContext(this.canvas);this.ctx.clearRect(0,0,this.canvas.width,this.canvas.height);this.octx=getContext(this.overlay);this.octx.clearRect(0,0,this.overlay.width,this.overlay.height);this.canvasHeight=size.height;this.canvasWidth=size.width;this.textEnabled=!!this.ctx.drawText||!!this.ctx.fillText;function getCanvas(canvas,name){if(!canvas){canvas=D.create('canvas');if(typeof FlashCanvas!="undefined"&&typeof canvas.getContext==='function'){FlashCanvas.initElement(canvas);}
canvas.className='flotr-'+name;canvas.style.cssText='position:absolute;left:0px;top:0px;';D.insert(el,canvas);}
_.each(size,function(size,attribute){D.show(canvas);if(name=='canvas'&&canvas.getAttribute(attribute)===size){return;}
canvas.setAttribute(attribute,size*o.resolution);canvas.style[attribute]=size+'px';});canvas.context_=null;return canvas;}
function getContext(canvas){if(window.G_vmlCanvasManager)window.G_vmlCanvasManager.initElement(canvas);var context=canvas.getContext('2d');if(!window.G_vmlCanvasManager)context.scale(o.resolution,o.resolution);return context;}},_initPlugins:function(){_.each(flotr.plugins,function(plugin,name){_.each(plugin.callbacks,function(fn,c){this.observe(this.el,c,_.bind(fn,this));},this);this[name]=flotr.clone(plugin);_.each(this[name],function(fn,p){if(_.isFunction(fn))
this[name][p]=_.bind(fn,this);},this);},this);},_initOptions:function(opts){var options=flotr.clone(flotr.defaultOptions);options.x2axis=_.extend(_.clone(options.xaxis),options.x2axis);options.y2axis=_.extend(_.clone(options.yaxis),options.y2axis);this.options=flotr.merge(opts||{},options);if(this.options.grid.minorVerticalLines===null&&this.options.xaxis.scaling==='logarithmic'){this.options.grid.minorVerticalLines=true;}
if(this.options.grid.minorHorizontalLines===null&&this.options.yaxis.scaling==='logarithmic'){this.options.grid.minorHorizontalLines=true;}
E.fire(this.el,'flotr:afterinitoptions',[this]);this.axes=flotr.Axis.getAxes(this.options);var assignedColors=[],colors=[],ln=this.series.length,neededColors=this.series.length,oc=this.options.colors,usedColors=[],variation=0,c,i,j,s;for(i=neededColors-1;i>-1;--i){c=this.series[i].color;if(c){--neededColors;if(_.isNumber(c))assignedColors.push(c);else usedColors.push(flotr.Color.parse(c));}}
for(i=assignedColors.length-1;i>-1;--i)
neededColors=Math.max(neededColors,assignedColors[i]+1);for(i=0;colors.length<neededColors;){c=(oc.length==i)?new flotr.Color(100,100,100):flotr.Color.parse(oc[i]);var sign=variation%2==1?-1:1,factor=1+sign*Math.ceil(variation/2)*0.2;c.scale(factor,factor,factor);colors.push(c);if(++i>=oc.length){i=0;++variation;}}
for(i=0,j=0;i<ln;++i){s=this.series[i];if(!s.color){s.color=colors[j++].toString();}else if(_.isNumber(s.color)){s.color=colors[s.color].toString();}
if(!s.xaxis)s.xaxis=this.axes.x;if(s.xaxis==1)s.xaxis=this.axes.x;else if(s.xaxis==2)s.xaxis=this.axes.x2;if(!s.yaxis)s.yaxis=this.axes.y;if(s.yaxis==1)s.yaxis=this.axes.y;else if(s.yaxis==2)s.yaxis=this.axes.y2;for(var t in flotr.graphTypes){s[t]=_.extend(_.clone(this.options[t]),s[t]);}
s.mouse=_.extend(_.clone(this.options.mouse),s.mouse);if(_.isUndefined(s.shadowSize))s.shadowSize=this.options.shadowSize;}},_setEl:function(el){if(!el)throw'The target container doesn\'t exist';else if(el.graph instanceof Graph)el.graph.destroy();else if(!el.clientWidth)throw'The target container must be visible';el.graph=this;this.el=el;}};Flotr.Graph=Graph;})();(function(){var
_=Flotr._,LOGARITHMIC='logarithmic';function Axis(o){this.orientation=1;this.offset=0;this.datamin=Number.MAX_VALUE;this.datamax=-Number.MAX_VALUE;_.extend(this,o);}
Axis.prototype={setScale:function(){var
length=this.length,max=this.max,min=this.min,offset=this.offset,orientation=this.orientation,options=this.options,logarithmic=options.scaling===LOGARITHMIC,scale;if(logarithmic){scale=length/(log(max,options.base)-log(min,options.base));}else{scale=length/(max-min);}
this.scale=scale;if(logarithmic){this.d2p=function(dataValue){return offset+orientation*(log(dataValue,options.base)-log(min,options.base))*scale;}
this.p2d=function(pointValue){return exp((offset+orientation*pointValue)/scale+log(min,options.base),options.base);}}else{this.d2p=function(dataValue){return offset+orientation*(dataValue-min)*scale;}
this.p2d=function(pointValue){return(offset+orientation*pointValue)/scale+min;}}},calculateTicks:function(){var options=this.options;this.ticks=[];this.minorTicks=[];if(options.ticks){this._cleanUserTicks(options.ticks,this.ticks);this._cleanUserTicks(options.minorTicks||[],this.minorTicks);}
else{if(options.mode=='time'){this._calculateTimeTicks();}else if(options.scaling==='logarithmic'){this._calculateLogTicks();}else{this._calculateTicks();}}
_.each(this.ticks,function(tick){tick.label+='';});_.each(this.minorTicks,function(tick){tick.label+='';});},calculateRange:function(){if(!this.used)return;var axis=this,o=axis.options,min=o.min!==null?o.min:axis.datamin,max=o.max!==null?o.max:axis.datamax,margin=o.autoscaleMargin;if(o.scaling=='logarithmic'){if(min<=0)min=axis.datamin;if(max<=0)max=min;}
if(max==min){var widen=max?0.01:1.00;if(o.min===null)min-=widen;if(o.max===null)max+=widen;}
if(o.scaling==='logarithmic'){if(min<0)min=max/o.base;var maxexp=Math.log(max);if(o.base!=Math.E)maxexp/=Math.log(o.base);maxexp=Math.ceil(maxexp);var minexp=Math.log(min);if(o.base!=Math.E)minexp/=Math.log(o.base);minexp=Math.ceil(minexp);axis.tickSize=Flotr.getTickSize(o.noTicks,minexp,maxexp,o.tickDecimals===null?0:o.tickDecimals);if(o.minorTickFreq===null){if(maxexp-minexp>10)
o.minorTickFreq=0;else if(maxexp-minexp>5)
o.minorTickFreq=2;else
o.minorTickFreq=5;}}else{axis.tickSize=Flotr.getTickSize(o.noTicks,min,max,o.tickDecimals);}
axis.min=min;axis.max=max;if(o.min===null&&o.autoscale){axis.min-=axis.tickSize*margin;if(axis.min<0&&axis.datamin>=0)axis.min=0;axis.min=axis.tickSize*Math.floor(axis.min/axis.tickSize);}
if(o.max===null&&o.autoscale){axis.max+=axis.tickSize*margin;if(axis.max>0&&axis.datamax<=0&&axis.datamax!=axis.datamin)axis.max=0;axis.max=axis.tickSize*Math.ceil(axis.max/axis.tickSize);}
if(axis.min==axis.max)axis.max=axis.min+1;},calculateTextDimensions:function(T,options){var maxLabel='',length,i;if(this.options.showLabels){for(i=0;i<this.ticks.length;++i){length=this.ticks[i].label.length;if(length>maxLabel.length){maxLabel=this.ticks[i].label;}}}
this.maxLabel=T.dimensions(maxLabel,{size:options.fontSize,angle:Flotr.toRad(this.options.labelsAngle)},'font-size:smaller;','flotr-grid-label');this.titleSize=T.dimensions(this.options.title,{size:options.fontSize*1.2,angle:Flotr.toRad(this.options.titleAngle)},'font-weight:bold;','flotr-axis-title');},_cleanUserTicks:function(ticks,axisTicks){var axis=this,options=this.options,v,i,label,tick;if(_.isFunction(ticks))ticks=ticks({min:axis.min,max:axis.max});for(i=0;i<ticks.length;++i){tick=ticks[i];if(typeof(tick)==='object'){v=tick[0];label=(tick.length>1)?tick[1]:options.tickFormatter(v,{min:axis.min,max:axis.max});}else{v=tick;label=options.tickFormatter(v,{min:this.min,max:this.max});}
axisTicks[i]={v:v,label:label};}},_calculateTimeTicks:function(){this.ticks=Flotr.Date.generator(this);},_calculateLogTicks:function(){var axis=this,o=axis.options,v,decadeStart;var max=Math.log(axis.max);if(o.base!=Math.E)max/=Math.log(o.base);max=Math.ceil(max);var min=Math.log(axis.min);if(o.base!=Math.E)min/=Math.log(o.base);min=Math.ceil(min);for(i=min;i<max;i+=axis.tickSize){decadeStart=(o.base==Math.E)?Math.exp(i):Math.pow(o.base,i);var decadeEnd=decadeStart*((o.base==Math.E)?Math.exp(axis.tickSize):Math.pow(o.base,axis.tickSize));var stepSize=(decadeEnd-decadeStart)/o.minorTickFreq;axis.ticks.push({v:decadeStart,label:o.tickFormatter(decadeStart,{min:axis.min,max:axis.max})});for(v=decadeStart+stepSize;v<decadeEnd;v+=stepSize)
axis.minorTicks.push({v:v,label:o.tickFormatter(v,{min:axis.min,max:axis.max})});}
decadeStart=(o.base==Math.E)?Math.exp(i):Math.pow(o.base,i);axis.ticks.push({v:decadeStart,label:o.tickFormatter(decadeStart,{min:axis.min,max:axis.max})});},_calculateTicks:function(){var axis=this,o=axis.options,tickSize=axis.tickSize,min=axis.min,max=axis.max,start=tickSize*Math.ceil(min/tickSize),decimals,minorTickSize,v,v2,i,j;if(o.minorTickFreq)
minorTickSize=tickSize/o.minorTickFreq;for(i=0;(v=v2=start+i*tickSize)<=max;++i){decimals=o.tickDecimals;if(decimals===null)decimals=1-Math.floor(Math.log(tickSize)/Math.LN10);if(decimals<0)decimals=0;v=v.toFixed(decimals);axis.ticks.push({v:v,label:o.tickFormatter(v,{min:axis.min,max:axis.max})});if(o.minorTickFreq){for(j=0;j<o.minorTickFreq&&(i*tickSize+j*minorTickSize)<max;++j){v=v2+j*minorTickSize;axis.minorTicks.push({v:v,label:o.tickFormatter(v,{min:axis.min,max:axis.max})});}}}}};_.extend(Axis,{getAxes:function(options){return{x:new Axis({options:options.xaxis,n:1,length:this.plotWidth}),x2:new Axis({options:options.x2axis,n:2,length:this.plotWidth}),y:new Axis({options:options.yaxis,n:1,length:this.plotHeight,offset:this.plotHeight,orientation:-1}),y2:new Axis({options:options.y2axis,n:2,length:this.plotHeight,offset:this.plotHeight,orientation:-1})};}});function log(value,base){value=Math.log(Math.max(value,Number.MIN_VALUE));if(base!==Math.E)
value/=Math.log(base);return value;}
function exp(value,base){return(base===Math.E)?Math.exp(value):Math.pow(base,value);}
Flotr.Axis=Axis;})();(function(){var
_=Flotr._;function Series(o){_.extend(this,o);}
Series.prototype={getRange:function(){var
data=this.data,length=data.length,xmin=Number.MAX_VALUE,ymin=Number.MAX_VALUE,xmax=-Number.MAX_VALUE,ymax=-Number.MAX_VALUE,xused=false,yused=false,x,y,i;if(length<0||this.hide)return false;for(i=0;i<length;i++){x=data[i][0];y=data[i][1];if(x!==null){if(x<xmin){xmin=x;xused=true;}
if(x>xmax){xmax=x;xused=true;}}
if(y!==null){if(y<ymin){ymin=y;yused=true;}
if(y>ymax){ymax=y;yused=true;}}}
return{xmin:xmin,xmax:xmax,ymin:ymin,ymax:ymax,xused:xused,yused:yused};}};_.extend(Series,{getSeries:function(data){return _.map(data,function(s){var series;if(s.data){series=new Series();_.extend(series,s);}else{series=new Series({data:s});}
return series;});}});Flotr.Series=Series;})();Flotr.addType('lines',{options:{show:false,lineWidth:2,fill:false,fillBorder:false,fillColor:null,fillOpacity:0.4,steps:false,stacked:false},stack:{values:[]},draw:function(options){var
context=options.context,lineWidth=options.lineWidth,shadowSize=options.shadowSize,offset;context.save();context.lineJoin='round';if(shadowSize){context.lineWidth=shadowSize/2;offset=lineWidth/2+context.lineWidth/2;context.strokeStyle="rgba(0,0,0,0.1)";this.plot(options,offset+shadowSize/2,false);context.strokeStyle="rgba(0,0,0,0.2)";this.plot(options,offset,false);}
context.lineWidth=lineWidth;context.strokeStyle=options.color;this.plot(options,0,true);context.restore();},plot:function(options,shadowOffset,incStack){var
context=options.context,width=options.width,height=options.height,xScale=options.xScale,yScale=options.yScale,data=options.data,stack=options.stacked?this.stack:false,length=data.length-1,prevx=null,prevy=null,zero=yScale(0),start=null,x1,x2,y1,y2,stack1,stack2,i;if(length<1)return;context.beginPath();for(i=0;i<length;++i){if(data[i][1]===null||data[i+1][1]===null){if(options.fill){if(i>0&&data[i][1]){context.stroke();fill();start=null;context.closePath();context.beginPath();}}
continue;}
x1=xScale(data[i][0]);x2=xScale(data[i+1][0]);if(start===null)start=data[i];if(stack){stack1=stack.values[data[i][0]]||0;stack2=stack.values[data[i+1][0]]||stack.values[data[i][0]]||0;y1=yScale(data[i][1]+stack1);y2=yScale(data[i+1][1]+stack2);if(incStack){stack.values[data[i][0]]=data[i][1]+stack1;if(i==length-1)
stack.values[data[i+1][0]]=data[i+1][1]+stack2;}}
else{y1=yScale(data[i][1]);y2=yScale(data[i+1][1]);}
if((y1>height&&y2>height)||(y1<0&&y2<0)||(x1<0&&x2<0)||(x1>width&&x2>width))continue;if((prevx!=x1)||(prevy!=y1+shadowOffset))
context.moveTo(x1,y1+shadowOffset);prevx=x2;prevy=y2+shadowOffset;if(options.steps){context.lineTo(prevx+shadowOffset/2,y1+shadowOffset);context.lineTo(prevx+shadowOffset/2,prevy);}else{context.lineTo(prevx,prevy);}}
if(!options.fill||options.fill&&!options.fillBorder)context.stroke();fill();function fill(){if(!shadowOffset&&options.fill&&start){x1=xScale(start[0]);context.fillStyle=options.fillStyle;context.lineTo(x2,zero);context.lineTo(x1,zero);context.lineTo(x1,yScale(start[1]));context.fill();if(options.fillBorder){context.stroke();}}}
context.closePath();},extendYRange:function(axis,data,options,lines){var o=axis.options;if(options.stacked&&((!o.max&&o.max!==0)||(!o.min&&o.min!==0))){var
newmax=axis.max,newmin=axis.min,positiveSums=lines.positiveSums||{},negativeSums=lines.negativeSums||{},x,j;for(j=0;j<data.length;j++){x=data[j][0]+'';if(data[j][1]>0){positiveSums[x]=(positiveSums[x]||0)+data[j][1];newmax=Math.max(newmax,positiveSums[x]);}
else{negativeSums[x]=(negativeSums[x]||0)+data[j][1];newmin=Math.min(newmin,negativeSums[x]);}}
lines.negativeSums=negativeSums;lines.positiveSums=positiveSums;axis.max=newmax;axis.min=newmin;}
if(options.steps){this.hit=function(options){var
data=options.data,args=options.args,yScale=options.yScale,mouse=args[0],length=data.length,n=args[1],x=options.xInverse(mouse.relX),relY=mouse.relY,i;for(i=0;i<length-1;i++){if(x>=data[i][0]&&x<=data[i+1][0]){if(Math.abs(yScale(data[i][1])-relY)<8){n.x=data[i][0];n.y=data[i][1];n.index=i;n.seriesIndex=options.index;}
break;}}};this.drawHit=function(options){var
context=options.context,args=options.args,data=options.data,xScale=options.xScale,index=args.index,x=xScale(args.x),y=options.yScale(args.y),x2;if(data.length-1>index){x2=options.xScale(data[index+1][0]);context.save();context.strokeStyle=options.color;context.lineWidth=options.lineWidth;context.beginPath();context.moveTo(x,y);context.lineTo(x2,y);context.stroke();context.closePath();context.restore();}};this.clearHit=function(options){var
context=options.context,args=options.args,data=options.data,xScale=options.xScale,width=options.lineWidth,index=args.index,x=xScale(args.x),y=options.yScale(args.y),x2;if(data.length-1>index){x2=options.xScale(data[index+1][0]);context.clearRect(x-width,y-width,x2-x+2*width,2*width);}};}}});Flotr.addType('bars',{options:{show:false,lineWidth:2,barWidth:1,fill:true,fillColor:null,fillOpacity:0.4,horizontal:false,stacked:false,centered:true,topPadding:0.1,grouped:false},stack:{positive:[],negative:[],_positive:[],_negative:[]},draw:function(options){var
context=options.context;this.current+=1;context.save();context.lineJoin='miter';context.lineWidth=options.lineWidth;context.strokeStyle=options.color;if(options.fill)context.fillStyle=options.fillStyle;this.plot(options);context.restore();},plot:function(options){var
data=options.data,context=options.context,shadowSize=options.shadowSize,i,geometry,left,top,width,height;if(data.length<1)return;this.translate(context,options.horizontal);for(i=0;i<data.length;i++){geometry=this.getBarGeometry(data[i][0],data[i][1],options);if(geometry===null)continue;left=geometry.left;top=geometry.top;width=geometry.width;height=geometry.height;if(options.fill)context.fillRect(left,top,width,height);if(shadowSize){context.save();context.fillStyle='rgba(0,0,0,0.05)';context.fillRect(left+shadowSize,top+shadowSize,width,height);context.restore();}
if(options.lineWidth){context.strokeRect(left,top,width,height);}}},translate:function(context,horizontal){if(horizontal){context.rotate(-Math.PI/2);context.scale(-1,1);}},getBarGeometry:function(x,y,options){var
horizontal=options.horizontal,barWidth=options.barWidth,centered=options.centered,stack=options.stacked?this.stack:false,lineWidth=options.lineWidth,bisection=centered?barWidth/2:0,xScale=horizontal?options.yScale:options.xScale,yScale=horizontal?options.xScale:options.yScale,xValue=horizontal?y:x,yValue=horizontal?x:y,stackOffset=0,stackValue,left,right,top,bottom;if(options.grouped){this.current/this.groups;xValue=xValue-bisection;barWidth=barWidth/this.groups;bisection=barWidth/2;xValue=xValue+barWidth*this.current-bisection;}
if(stack){stackValue=yValue>0?stack.positive:stack.negative;stackOffset=stackValue[xValue]||stackOffset;stackValue[xValue]=stackOffset+yValue;}
left=xScale(xValue-bisection);right=xScale(xValue+barWidth-bisection);top=yScale(yValue+stackOffset);bottom=yScale(stackOffset);if(bottom<0)bottom=0;return(x===null||y===null)?null:{x:xValue,y:yValue,xScale:xScale,yScale:yScale,top:top,left:Math.min(left,right)-lineWidth/2,width:Math.abs(right-left)-lineWidth,height:bottom-top};},hit:function(options){var
data=options.data,args=options.args,mouse=args[0],n=args[1],x=options.xInverse(mouse.relX),y=options.yInverse(mouse.relY),hitGeometry=this.getBarGeometry(x,y,options),width=hitGeometry.width/2,left=hitGeometry.left,height=hitGeometry.y,geometry,i;for(i=data.length;i--;){geometry=this.getBarGeometry(data[i][0],data[i][1],options);if(((height>0&&height<geometry.y)||(height<0&&height>geometry.y))&&(Math.abs(left-geometry.left)<width)){n.x=data[i][0];n.y=data[i][1];n.index=i;n.seriesIndex=options.index;}}},drawHit:function(options){var
context=options.context,args=options.args,geometry=this.getBarGeometry(args.x,args.y,options),left=geometry.left,top=geometry.top,width=geometry.width,height=geometry.height;context.save();context.strokeStyle=options.color;context.lineWidth=options.lineWidth;this.translate(context,options.horizontal);context.beginPath();context.moveTo(left,top+height);context.lineTo(left,top);context.lineTo(left+width,top);context.lineTo(left+width,top+height);if(options.fill){context.fillStyle=options.fillStyle;context.fill();}
context.stroke();context.closePath();context.restore();},clearHit:function(options){var
context=options.context,args=options.args,geometry=this.getBarGeometry(args.x,args.y,options),left=geometry.left,width=geometry.width,top=geometry.top,height=geometry.height,lineWidth=2*options.lineWidth;context.save();this.translate(context,options.horizontal);context.clearRect(left-lineWidth,Math.min(top,top+height)-lineWidth,width+2*lineWidth,Math.abs(height)+2*lineWidth);context.restore();},extendXRange:function(axis,data,options,bars){this._extendRange(axis,data,options,bars);this.groups=(this.groups+1)||1;this.current=0;},extendYRange:function(axis,data,options,bars){this._extendRange(axis,data,options,bars);},_extendRange:function(axis,data,options,bars){var
max=axis.options.max;if(_.isNumber(max)||_.isString(max))return;var
newmin=axis.min,newmax=axis.max,horizontal=options.horizontal,orientation=axis.orientation,positiveSums=this.positiveSums||{},negativeSums=this.negativeSums||{},value,datum,index,j;if((orientation==1&&!horizontal)||(orientation==-1&&horizontal)){if(options.centered){newmax=Math.max(axis.datamax+options.barWidth,newmax);newmin=Math.min(axis.datamin-options.barWidth,newmin);}}
if(options.stacked&&((orientation==1&&horizontal)||(orientation==-1&&!horizontal))){for(j=data.length;j--;){value=data[j][(orientation==1?1:0)]+'';datum=data[j][(orientation==1?0:1)];if(datum>0){positiveSums[value]=(positiveSums[value]||0)+datum;newmax=Math.max(newmax,positiveSums[value]);}
else{negativeSums[value]=(negativeSums[value]||0)+datum;newmin=Math.min(newmin,negativeSums[value]);}}}
if((orientation==1&&horizontal)||(orientation==-1&&!horizontal)){if(options.topPadding&&(axis.max===axis.datamax||(options.stacked&&this.stackMax!==newmax))){newmax+=options.topPadding*(newmax-newmin);}}
this.stackMin=newmin;this.stackMax=newmax;this.negativeSums=negativeSums;this.positiveSums=positiveSums;axis.max=newmax;axis.min=newmin;}});Flotr.addType('bubbles',{options:{show:false,lineWidth:2,fill:true,fillOpacity:0.4,baseRadius:2},draw:function(options){var
context=options.context,shadowSize=options.shadowSize;context.save();context.lineWidth=options.lineWidth;context.fillStyle='rgba(0,0,0,0.05)';context.strokeStyle='rgba(0,0,0,0.05)';this.plot(options,shadowSize/2);context.strokeStyle='rgba(0,0,0,0.1)';this.plot(options,shadowSize/4);context.strokeStyle=options.color;context.fillStyle=options.fillStyle;this.plot(options);context.restore();},plot:function(options,offset){var
data=options.data,context=options.context,geometry,i,x,y,z;offset=offset||0;for(i=0;i<data.length;++i){geometry=this.getGeometry(data[i],options);context.beginPath();context.arc(geometry.x+offset,geometry.y+offset,geometry.z,0,2*Math.PI,true);context.stroke();if(options.fill)context.fill();context.closePath();}},getGeometry:function(point,options){return{x:options.xScale(point[0]),y:options.yScale(point[1]),z:point[2]*options.baseRadius};},hit:function(options){var
data=options.data,args=options.args,mouse=args[0],n=args[1],relX=mouse.relX,relY=mouse.relY,distance,geometry,dx,dy;n.best=n.best||Number.MAX_VALUE;for(i=data.length;i--;){geometry=this.getGeometry(data[i],options);dx=geometry.x-relX;dy=geometry.y-relY;distance=Math.sqrt(dx*dx+dy*dy);if(distance<geometry.z&&geometry.z<n.best){n.x=data[i][0];n.y=data[i][1];n.index=i;n.seriesIndex=options.index;n.best=geometry.z;}}},drawHit:function(options){var
context=options.context,geometry=this.getGeometry(options.data[options.args.index],options);context.save();context.lineWidth=options.lineWidth;context.fillStyle=options.fillStyle;context.strokeStyle=options.color;context.beginPath();context.arc(geometry.x,geometry.y,geometry.z,0,2*Math.PI,true);context.fill();context.stroke();context.closePath();context.restore();},clearHit:function(options){var
context=options.context,geometry=this.getGeometry(options.data[options.args.index],options),offset=geometry.z+options.lineWidth;context.save();context.clearRect(geometry.x-offset,geometry.y-offset,2*offset,2*offset);context.restore();}});Flotr.addType('candles',{options:{show:false,lineWidth:1,wickLineWidth:1,candleWidth:0.6,fill:true,upFillColor:'#00A8F0',downFillColor:'#CB4B4B',fillOpacity:0.5,barcharts:false},draw:function(options){var
context=options.context;context.save();context.lineJoin='miter';context.lineCap='butt';context.lineWidth=options.wickLineWidth||options.lineWidth;this.plot(options);context.restore();},plot:function(options){var
data=options.data,context=options.context,xScale=options.xScale,yScale=options.yScale,width=options.candleWidth/2,shadowSize=options.shadowSize,lineWidth=options.lineWidth,wickLineWidth=options.wickLineWidth,pixelOffset=(wickLineWidth%2)/2,color,datum,x,y,open,high,low,close,left,right,bottom,top,bottom2,top2,i;if(data.length<1)return;for(i=0;i<data.length;i++){datum=data[i];x=datum[0];open=datum[1];high=datum[2];low=datum[3];close=datum[4];left=xScale(x-width);right=xScale(x+width);bottom=yScale(low);top=yScale(high);bottom2=yScale(Math.min(open,close));top2=yScale(Math.max(open,close));color=options[open>close?'downFillColor':'upFillColor'];if(options.fill&&!options.barcharts){context.fillStyle='rgba(0,0,0,0.05)';context.fillRect(left+shadowSize,top2+shadowSize,right-left,bottom2-top2);context.save();context.globalAlpha=options.fillOpacity;context.fillStyle=color;context.fillRect(left,top2+lineWidth,right-left,bottom2-top2);context.restore();}
if(lineWidth||wickLineWidth){x=Math.floor((left+right)/2)+pixelOffset;context.strokeStyle=color;context.beginPath();if(options.barcharts){context.moveTo(x,Math.floor(top+width));context.lineTo(x,Math.floor(bottom+width));y=Math.floor(open+width)+0.5;context.moveTo(Math.floor(left)+pixelOffset,y);context.lineTo(x,y);y=Math.floor(close+width)+0.5;context.moveTo(Math.floor(right)+pixelOffset,y);context.lineTo(x,y);}else{context.strokeRect(left,top2+lineWidth,right-left,bottom2-top2);context.moveTo(x,Math.floor(top2+lineWidth));context.lineTo(x,Math.floor(top+lineWidth));context.moveTo(x,Math.floor(bottom2+lineWidth));context.lineTo(x,Math.floor(bottom+lineWidth));}
context.closePath();context.stroke();}}},extendXRange:function(axis,data,options){if(axis.options.max===null){axis.max=Math.max(axis.datamax+0.5,axis.max);axis.min=Math.min(axis.datamin-0.5,axis.min);}}});Flotr.addType('gantt',{options:{show:false,lineWidth:2,barWidth:1,fill:true,fillColor:null,fillOpacity:0.4,centered:true},draw:function(series){var ctx=this.ctx,bw=series.gantt.barWidth,lw=Math.min(series.gantt.lineWidth,bw);ctx.save();ctx.translate(this.plotOffset.left,this.plotOffset.top);ctx.lineJoin='miter';ctx.lineWidth=lw;ctx.strokeStyle=series.color;ctx.save();this.gantt.plotShadows(series,bw,0,series.gantt.fill);ctx.restore();if(series.gantt.fill){var color=series.gantt.fillColor||series.color;ctx.fillStyle=this.processColor(color,{opacity:series.gantt.fillOpacity});}
this.gantt.plot(series,bw,0,series.gantt.fill);ctx.restore();},plot:function(series,barWidth,offset,fill){var data=series.data;if(data.length<1)return;var xa=series.xaxis,ya=series.yaxis,ctx=this.ctx,i;for(i=0;i<data.length;i++){var y=data[i][0],s=data[i][1],d=data[i][2],drawLeft=true,drawTop=true,drawRight=true;if(s===null||d===null)continue;var left=s,right=s+d,bottom=y-(series.gantt.centered?barWidth/2:0),top=y+barWidth-(series.gantt.centered?barWidth/2:0);if(right<xa.min||left>xa.max||top<ya.min||bottom>ya.max)
continue;if(left<xa.min){left=xa.min;drawLeft=false;}
if(right>xa.max){right=xa.max;if(xa.lastSerie!=series)
drawTop=false;}
if(bottom<ya.min)
bottom=ya.min;if(top>ya.max){top=ya.max;if(ya.lastSerie!=series)
drawTop=false;}
if(fill){ctx.beginPath();ctx.moveTo(xa.d2p(left),ya.d2p(bottom)+offset);ctx.lineTo(xa.d2p(left),ya.d2p(top)+offset);ctx.lineTo(xa.d2p(right),ya.d2p(top)+offset);ctx.lineTo(xa.d2p(right),ya.d2p(bottom)+offset);ctx.fill();ctx.closePath();}
if(series.gantt.lineWidth&&(drawLeft||drawRight||drawTop)){ctx.beginPath();ctx.moveTo(xa.d2p(left),ya.d2p(bottom)+offset);ctx[drawLeft?'lineTo':'moveTo'](xa.d2p(left),ya.d2p(top)+offset);ctx[drawTop?'lineTo':'moveTo'](xa.d2p(right),ya.d2p(top)+offset);ctx[drawRight?'lineTo':'moveTo'](xa.d2p(right),ya.d2p(bottom)+offset);ctx.stroke();ctx.closePath();}}},plotShadows:function(series,barWidth,offset){var data=series.data;if(data.length<1)return;var i,y,s,d,xa=series.xaxis,ya=series.yaxis,ctx=this.ctx,sw=this.options.shadowSize;for(i=0;i<data.length;i++){y=data[i][0];s=data[i][1];d=data[i][2];if(s===null||d===null)continue;var left=s,right=s+d,bottom=y-(series.gantt.centered?barWidth/2:0),top=y+barWidth-(series.gantt.centered?barWidth/2:0);if(right<xa.min||left>xa.max||top<ya.min||bottom>ya.max)
continue;if(left<xa.min)left=xa.min;if(right>xa.max)right=xa.max;if(bottom<ya.min)bottom=ya.min;if(top>ya.max)top=ya.max;var width=xa.d2p(right)-xa.d2p(left)-((xa.d2p(right)+sw<=this.plotWidth)?0:sw);var height=ya.d2p(bottom)-ya.d2p(top)-((ya.d2p(bottom)+sw<=this.plotHeight)?0:sw);ctx.fillStyle='rgba(0,0,0,0.05)';ctx.fillRect(Math.min(xa.d2p(left)+sw,this.plotWidth),Math.min(ya.d2p(top)+sw,this.plotHeight),width,height);}},extendXRange:function(axis){if(axis.options.max===null){var newmin=axis.min,newmax=axis.max,i,j,x,s,g,stackedSumsPos={},stackedSumsNeg={},lastSerie=null;for(i=0;i<this.series.length;++i){s=this.series[i];g=s.gantt;if(g.show&&s.xaxis==axis){for(j=0;j<s.data.length;j++){if(g.show){y=s.data[j][0]+'';stackedSumsPos[y]=Math.max((stackedSumsPos[y]||0),s.data[j][1]+s.data[j][2]);lastSerie=s;}}
for(j in stackedSumsPos){newmax=Math.max(stackedSumsPos[j],newmax);}}}
axis.lastSerie=lastSerie;axis.max=newmax;axis.min=newmin;}},extendYRange:function(axis){if(axis.options.max===null){var newmax=Number.MIN_VALUE,newmin=Number.MAX_VALUE,i,j,s,g,stackedSumsPos={},stackedSumsNeg={},lastSerie=null;for(i=0;i<this.series.length;++i){s=this.series[i];g=s.gantt;if(g.show&&!s.hide&&s.yaxis==axis){var datamax=Number.MIN_VALUE,datamin=Number.MAX_VALUE;for(j=0;j<s.data.length;j++){datamax=Math.max(datamax,s.data[j][0]);datamin=Math.min(datamin,s.data[j][0]);}
if(g.centered){newmax=Math.max(datamax+0.5,newmax);newmin=Math.min(datamin-0.5,newmin);}
else{newmax=Math.max(datamax+1,newmax);newmin=Math.min(datamin,newmin);}
if(g.barWidth+datamax>newmax){newmax=axis.max+g.barWidth;}}}
axis.lastSerie=lastSerie;axis.max=newmax;axis.min=newmin;axis.tickSize=Flotr.getTickSize(axis.options.noTicks,newmin,newmax,axis.options.tickDecimals);}}});(function(){Flotr.defaultMarkerFormatter=function(obj){return(Math.round(obj.y*100)/100)+'';};Flotr.addType('markers',{options:{show:false,lineWidth:1,color:'#000000',fill:false,fillColor:"#FFFFFF",fillOpacity:0.4,stroke:false,position:'ct',verticalMargin:0,labelFormatter:Flotr.defaultMarkerFormatter,fontSize:Flotr.defaultOptions.fontSize,stacked:false,stackingType:'b',horizontal:false},stack:{positive:[],negative:[],values:[]},draw:function(options){var
data=options.data,context=options.context,stack=options.stacked?options.stack:false,stackType=options.stackingType,stackOffsetNeg,stackOffsetPos,stackOffset,i,x,y,label;context.save();context.lineJoin='round';context.lineWidth=options.lineWidth;context.strokeStyle='rgba(0,0,0,0.5)';context.fillStyle=options.fillStyle;function stackPos(a,b){stackOffsetPos=stack.negative[a]||0;stackOffsetNeg=stack.positive[a]||0;if(b>0){stack.positive[a]=stackOffsetPos+b;return stackOffsetPos+b;}else{stack.negative[a]=stackOffsetNeg+b;return stackOffsetNeg+b;}}
for(i=0;i<data.length;++i){x=data[i][0];y=data[i][1];if(stack){if(stackType=='b'){if(options.horizontal)y=stackPos(y,x);else x=stackPos(x,y);}else if(stackType=='a'){stackOffset=stack.values[x]||0;stack.values[x]=stackOffset+y;y=stackOffset+y;}}
label=options.labelFormatter({x:x,y:y,index:i,data:data});this.plot(options.xScale(x),options.yScale(y),label,options);}
context.restore();},plot:function(x,y,label,options){var context=options.context;if(isImage(label)&&!label.complete){throw'Marker image not loaded.';}else{this._plot(x,y,label,options);}},_plot:function(x,y,label,options){var context=options.context,margin=2,left=x,top=y,dim;if(isImage(label))
dim={height:label.height,width:label.width};else
dim=options.text.canvas(label);dim.width=Math.floor(dim.width+margin*2);dim.height=Math.floor(dim.height+margin*2);if(options.position.indexOf('c')!=-1)left-=dim.width/2+margin;else if(options.position.indexOf('l')!=-1)left-=dim.width;if(options.position.indexOf('m')!=-1)top-=dim.height/2+margin;else if(options.position.indexOf('t')!=-1)top-=dim.height+options.verticalMargin;else top+=options.verticalMargin;left=Math.floor(left)+0.5;top=Math.floor(top)+0.5;if(options.fill)
context.fillRect(left,top,dim.width,dim.height);if(options.stroke)
context.strokeRect(left,top,dim.width,dim.height);if(isImage(label))
context.drawImage(label,left+margin,top+margin);else
Flotr.drawText(context,label,left+margin,top+margin,{textBaseline:'top',textAlign:'left',size:options.fontSize,color:options.color});}});function isImage(i){return typeof i==='object'&&i.constructor&&(Image?true:i.constructor===Image);}})();(function(){var
_=Flotr._;Flotr.defaultPieLabelFormatter=function(total,value){return(100*value/total).toFixed(2)+'%';};Flotr.addType('pie',{options:{show:false,lineWidth:1,fill:true,fillColor:null,fillOpacity:0.6,explode:6,sizeRatio:0.6,startAngle:Math.PI/4,labelFormatter:Flotr.defaultPieLabelFormatter,pie3D:false,pie3DviewAngle:(Math.PI/2*0.8),pie3DspliceThickness:20,epsilon:0.1},draw:function(options){var
data=options.data,context=options.context,canvas=context.canvas,lineWidth=options.lineWidth,shadowSize=options.shadowSize,sizeRatio=options.sizeRatio,height=options.height,width=options.width,explode=options.explode,color=options.color,fill=options.fill,fillStyle=options.fillStyle,radius=Math.min(canvas.width,canvas.height)*sizeRatio/2,value=data[0][1],html=[],vScale=1,measure=Math.PI*2*value/this.total,startAngle=this.startAngle||(2*Math.PI*options.startAngle),endAngle=startAngle+measure,bisection=startAngle+measure/2,label=options.labelFormatter(this.total,value),explodeCoeff=explode+radius+4,distX=Math.cos(bisection)*explodeCoeff,distY=Math.sin(bisection)*explodeCoeff,textAlign=distX<0?'right':'left',textBaseline=distY>0?'top':'bottom',style,x,y;context.save();context.translate(width/2,height/2);context.scale(1,vScale);x=Math.cos(bisection)*explode;y=Math.sin(bisection)*explode;if(shadowSize>0){this.plotSlice(x+shadowSize,y+shadowSize,radius,startAngle,endAngle,context);if(fill){context.fillStyle='rgba(0,0,0,0.1)';context.fill();}}
this.plotSlice(x,y,radius,startAngle,endAngle,context);if(fill){context.fillStyle=fillStyle;context.fill();}
context.lineWidth=lineWidth;context.strokeStyle=color;context.stroke();style={size:options.fontSize*1.2,color:options.fontColor,weight:1.5};if(label){if(options.htmlText||!options.textEnabled){divStyle='position:absolute;'+textBaseline+':'+(height/2+(textBaseline==='top'?distY:-distY))+'px;';divStyle+=textAlign+':'+(width/2+(textAlign==='right'?-distX:distX))+'px;';html.push('<div style="',divStyle,'" class="flotr-grid-label">',label,'</div>');}
else{style.textAlign=textAlign;style.textBaseline=textBaseline;Flotr.drawText(context,label,distX,distY,style);}}
if(options.htmlText||!options.textEnabled){var div=Flotr.DOM.node('<div style="color:'+options.fontColor+'" class="flotr-labels"></div>');Flotr.DOM.insert(div,html.join(''));Flotr.DOM.insert(options.element,div);}
context.restore();this.startAngle=endAngle;this.slices=this.slices||[];this.slices.push({radius:Math.min(canvas.width,canvas.height)*sizeRatio/2,x:x,y:y,explode:explode,start:startAngle,end:endAngle});},plotSlice:function(x,y,radius,startAngle,endAngle,context){context.beginPath();context.moveTo(x,y);context.arc(x,y,radius,startAngle,endAngle,false);context.lineTo(x,y);context.closePath();},hit:function(options){var
data=options.data[0],args=options.args,index=options.index,mouse=args[0],n=args[1],slice=this.slices[index],x=mouse.relX-options.width/2,y=mouse.relY-options.height/2,r=Math.sqrt(x*x+y*y),theta=Math.atan(y/x),circle=Math.PI*2,explode=slice.explode||options.explode,start=slice.start%circle,end=slice.end%circle,epsilon=options.epsilon;if(x<0){theta+=Math.PI;}else if(x>0&&y<0){theta+=circle;}
if(r<slice.radius+explode&&r>explode){if((theta>start&&theta<end)||(start>end&&(theta<end||theta>start))||(start===end&&((slice.start===slice.end&&Math.abs(theta-start)<epsilon)||(slice.start!==slice.end&&Math.abs(theta-start)>epsilon)))){n.x=data[0];n.y=data[1];n.sAngle=start;n.eAngle=end;n.index=0;n.seriesIndex=index;n.fraction=data[1]/this.total;}}},drawHit:function(options){var
context=options.context,slice=this.slices[options.args.seriesIndex];context.save();context.translate(options.width/2,options.height/2);this.plotSlice(slice.x,slice.y,slice.radius,slice.start,slice.end,context);context.stroke();context.restore();},clearHit:function(options){var
context=options.context,slice=this.slices[options.args.seriesIndex],padding=2*options.lineWidth,radius=slice.radius+padding;context.save();context.translate(options.width/2,options.height/2);context.clearRect(slice.x-radius,slice.y-radius,2*radius+padding,2*radius+padding);context.restore();},extendYRange:function(axis,data){this.total=(this.total||0)+data[0][1];}});})();Flotr.addType('points',{options:{show:false,radius:3,lineWidth:2,fill:true,fillColor:'#FFFFFF',fillOpacity:1,hitRadius:null},draw:function(options){var
context=options.context,lineWidth=options.lineWidth,shadowSize=options.shadowSize;context.save();if(shadowSize>0){context.lineWidth=shadowSize/2;context.strokeStyle='rgba(0,0,0,0.1)';this.plot(options,shadowSize/2+context.lineWidth/2);context.strokeStyle='rgba(0,0,0,0.2)';this.plot(options,context.lineWidth/2);}
context.lineWidth=options.lineWidth;context.strokeStyle=options.color;if(options.fill)context.fillStyle=options.fillStyle;this.plot(options);context.restore();},plot:function(options,offset){var
data=options.data,context=options.context,xScale=options.xScale,yScale=options.yScale,i,x,y;for(i=data.length-1;i>-1;--i){y=data[i][1];if(y===null)continue;x=xScale(data[i][0]);y=yScale(y);if(x<0||x>options.width||y<0||y>options.height)continue;context.beginPath();if(offset){context.arc(x,y+offset,options.radius,0,Math.PI,false);}else{context.arc(x,y,options.radius,0,2*Math.PI,true);if(options.fill)context.fill();}
context.stroke();context.closePath();}}});Flotr.addType('radar',{options:{show:false,lineWidth:2,fill:true,fillOpacity:0.4,radiusRatio:0.90},draw:function(options){var
context=options.context,shadowSize=options.shadowSize;context.save();context.translate(options.width/2,options.height/2);context.lineWidth=options.lineWidth;context.fillStyle='rgba(0,0,0,0.05)';context.strokeStyle='rgba(0,0,0,0.05)';this.plot(options,shadowSize/2);context.strokeStyle='rgba(0,0,0,0.1)';this.plot(options,shadowSize/4);context.strokeStyle=options.color;context.fillStyle=options.fillStyle;this.plot(options);context.restore();},plot:function(options,offset){var
data=options.data,context=options.context,radius=Math.min(options.height,options.width)*options.radiusRatio/2,step=2*Math.PI/data.length,angle=-Math.PI/2,i,ratio;offset=offset||0;context.beginPath();for(i=0;i<data.length;++i){ratio=data[i][1]/this.max;context[i===0?'moveTo':'lineTo'](Math.cos(i*step+angle)*radius*ratio+offset,Math.sin(i*step+angle)*radius*ratio+offset);}
context.closePath();if(options.fill)context.fill();context.stroke();},extendYRange:function(axis,data){this.max=Math.max(axis.max,this.max||-Number.MAX_VALUE);}});Flotr.addType('timeline',{options:{show:false,lineWidth:1,barWidth:0.2,fill:true,fillColor:null,fillOpacity:0.4,centered:true},draw:function(options){var
context=options.context;context.save();context.lineJoin='miter';context.lineWidth=options.lineWidth;context.strokeStyle=options.color;context.fillStyle=options.fillStyle;this.plot(options);context.restore();},plot:function(options){var
data=options.data,context=options.context,xScale=options.xScale,yScale=options.yScale,barWidth=options.barWidth,lineWidth=options.lineWidth,i;Flotr._.each(data,function(timeline){var
x=timeline[0],y=timeline[1],w=timeline[2],h=barWidth,xt=Math.ceil(xScale(x)),wt=Math.ceil(xScale(x+w))-xt,yt=Math.round(yScale(y)),ht=Math.round(yScale(y-h))-yt,x0=xt-lineWidth/2,y0=Math.round(yt-ht/2)-lineWidth/2;context.strokeRect(x0,y0,wt,ht);context.fillRect(x0,y0,wt,ht);});},extendRange:function(series){var
data=series.data,xa=series.xaxis,ya=series.yaxis,w=series.timeline.barWidth;if(xa.options.min===null)
xa.min=xa.datamin-w/2;if(xa.options.max===null){var
max=xa.max;Flotr._.each(data,function(timeline){max=Math.max(max,timeline[0]+timeline[2]);},this);xa.max=max+w/2;}
if(ya.options.min===null)
ya.min=ya.datamin-w;if(ya.options.min===null)
ya.max=ya.datamax+w;}});(function(){var D=Flotr.DOM;Flotr.addPlugin('crosshair',{options:{mode:null,color:'#FF0000',hideCursor:true},callbacks:{'flotr:mousemove':function(e,pos){if(this.options.crosshair.mode){this.crosshair.clearCrosshair();this.crosshair.drawCrosshair(pos);}}},drawCrosshair:function(pos){var octx=this.octx,options=this.options.crosshair,plotOffset=this.plotOffset,x=plotOffset.left+Math.round(pos.relX)+.5,y=plotOffset.top+Math.round(pos.relY)+.5;if(pos.relX<0||pos.relY<0||pos.relX>this.plotWidth||pos.relY>this.plotHeight){this.el.style.cursor=null;D.removeClass(this.el,'flotr-crosshair');return;}
if(options.hideCursor){this.el.style.cursor='none';D.addClass(this.el,'flotr-crosshair');}
octx.save();octx.strokeStyle=options.color;octx.lineWidth=1;octx.beginPath();if(options.mode.indexOf('x')!=-1){octx.moveTo(x,plotOffset.top);octx.lineTo(x,plotOffset.top+this.plotHeight);}
if(options.mode.indexOf('y')!=-1){octx.moveTo(plotOffset.left,y);octx.lineTo(plotOffset.left+this.plotWidth,y);}
octx.stroke();octx.restore();},clearCrosshair:function(){var
plotOffset=this.plotOffset,position=this.lastMousePos,context=this.octx;if(position){context.clearRect(Math.round(position.relX)+plotOffset.left,plotOffset.top,1,this.plotHeight+1);context.clearRect(plotOffset.left,Math.round(position.relY)+plotOffset.top,this.plotWidth+1,1);}}});})();(function(){var
D=Flotr.DOM,_=Flotr._;function getImage(type,canvas,width,height){var
mime='image/'+type,data=canvas.toDataURL(mime),image=new Image();image.src=data;return image;}
Flotr.addPlugin('download',{saveImage:function(type,width,height,replaceCanvas){var image=null;if(Flotr.isIE&&Flotr.isIE<9){image='<html><body>'+this.canvas.firstChild.innerHTML+'</body></html>';return window.open().document.write(image);}
if(type!=='jpeg'&&type!=='png')return;image=getImage(type,this.canvas,width,height);if(_.isElement(image)&&replaceCanvas){this.download.restoreCanvas();D.hide(this.canvas);D.hide(this.overlay);D.setStyles({position:'absolute'});D.insert(this.el,image);this.saveImageElement=image;}else{return window.open(image.src);}},restoreCanvas:function(){D.show(this.canvas);D.show(this.overlay);if(this.saveImageElement)this.el.removeChild(this.saveImageElement);this.saveImageElement=null;}});})();(function(){var E=Flotr.EventAdapter,_=Flotr._;Flotr.addPlugin('graphGrid',{callbacks:{'flotr:beforedraw':function(){this.graphGrid.drawGrid();},'flotr:afterdraw':function(){this.graphGrid.drawOutline();}},drawGrid:function(){var
ctx=this.ctx,options=this.options,grid=options.grid,verticalLines=grid.verticalLines,horizontalLines=grid.horizontalLines,minorVerticalLines=grid.minorVerticalLines,minorHorizontalLines=grid.minorHorizontalLines,plotHeight=this.plotHeight,plotWidth=this.plotWidth,a,v,i,j;if(verticalLines||minorVerticalLines||horizontalLines||minorHorizontalLines){E.fire(this.el,'flotr:beforegrid',[this.axes.x,this.axes.y,options,this]);}
ctx.save();ctx.lineWidth=1;ctx.strokeStyle=grid.tickColor;function circularHorizontalTicks(ticks){for(i=0;i<ticks.length;++i){var ratio=ticks[i].v/a.max;for(j=0;j<=sides;++j){ctx[j===0?'moveTo':'lineTo'](Math.cos(j*coeff+angle)*radius*ratio,Math.sin(j*coeff+angle)*radius*ratio);}}}
function drawGridLines(ticks,callback){_.each(_.pluck(ticks,'v'),function(v){if((v<=a.min||v>=a.max)||(v==a.min||v==a.max)&&grid.outlineWidth)
return;callback(Math.floor(a.d2p(v))+ctx.lineWidth/2);});}
function drawVerticalLines(x){ctx.moveTo(x,0);ctx.lineTo(x,plotHeight);}
function drawHorizontalLines(y){ctx.moveTo(0,y);ctx.lineTo(plotWidth,y);}
if(grid.circular){ctx.translate(this.plotOffset.left+plotWidth/2,this.plotOffset.top+plotHeight/2);var radius=Math.min(plotHeight,plotWidth)*options.radar.radiusRatio/2,sides=this.axes.x.ticks.length,coeff=2*(Math.PI/sides),angle=-Math.PI/2;ctx.beginPath();a=this.axes.y;if(horizontalLines){circularHorizontalTicks(a.ticks);}
if(minorHorizontalLines){circularHorizontalTicks(a.minorTicks);}
if(verticalLines){_.times(sides,function(i){ctx.moveTo(0,0);ctx.lineTo(Math.cos(i*coeff+angle)*radius,Math.sin(i*coeff+angle)*radius);});}
ctx.stroke();}
else{ctx.translate(this.plotOffset.left,this.plotOffset.top);if(grid.backgroundColor){ctx.fillStyle=this.processColor(grid.backgroundColor,{x1:0,y1:0,x2:plotWidth,y2:plotHeight});ctx.fillRect(0,0,plotWidth,plotHeight);}
ctx.beginPath();a=this.axes.x;if(verticalLines)drawGridLines(a.ticks,drawVerticalLines);if(minorVerticalLines)drawGridLines(a.minorTicks,drawVerticalLines);a=this.axes.y;if(horizontalLines)drawGridLines(a.ticks,drawHorizontalLines);if(minorHorizontalLines)drawGridLines(a.minorTicks,drawHorizontalLines);ctx.stroke();}
ctx.restore();if(verticalLines||minorVerticalLines||horizontalLines||minorHorizontalLines){E.fire(this.el,'flotr:aftergrid',[this.axes.x,this.axes.y,options,this]);}},drawOutline:function(){var
that=this,options=that.options,grid=options.grid,outline=grid.outline,ctx=that.ctx,backgroundImage=grid.backgroundImage,plotOffset=that.plotOffset,leftOffset=plotOffset.left,topOffset=plotOffset.top,plotWidth=that.plotWidth,plotHeight=that.plotHeight,v,img,src,left,top,globalAlpha;if(!grid.outlineWidth)return;ctx.save();if(grid.circular){ctx.translate(leftOffset+plotWidth/2,topOffset+plotHeight/2);var radius=Math.min(plotHeight,plotWidth)*options.radar.radiusRatio/2,sides=this.axes.x.ticks.length,coeff=2*(Math.PI/sides),angle=-Math.PI/2;ctx.beginPath();ctx.lineWidth=grid.outlineWidth;ctx.strokeStyle=grid.color;ctx.lineJoin='round';for(i=0;i<=sides;++i){ctx[i===0?'moveTo':'lineTo'](Math.cos(i*coeff+angle)*radius,Math.sin(i*coeff+angle)*radius);}
ctx.stroke();}
else{ctx.translate(leftOffset,topOffset);var lw=grid.outlineWidth,orig=0.5-lw+((lw+1)%2/2),lineTo='lineTo',moveTo='moveTo';ctx.lineWidth=lw;ctx.strokeStyle=grid.color;ctx.lineJoin='miter';ctx.beginPath();ctx.moveTo(orig,orig);plotWidth=plotWidth-(lw/2)%1;plotHeight=plotHeight+lw/2;ctx[outline.indexOf('n')!==-1?lineTo:moveTo](plotWidth,orig);ctx[outline.indexOf('e')!==-1?lineTo:moveTo](plotWidth,plotHeight);ctx[outline.indexOf('s')!==-1?lineTo:moveTo](orig,plotHeight);ctx[outline.indexOf('w')!==-1?lineTo:moveTo](orig,orig);ctx.stroke();ctx.closePath();}
ctx.restore();if(backgroundImage){src=backgroundImage.src||backgroundImage;left=(parseInt(backgroundImage.left,10)||0)+plotOffset.left;top=(parseInt(backgroundImage.top,10)||0)+plotOffset.top;img=new Image();img.onload=function(){ctx.save();if(backgroundImage.alpha)ctx.globalAlpha=backgroundImage.alpha;ctx.globalCompositeOperation='destination-over';ctx.drawImage(img,0,0,img.width,img.height,left,top,plotWidth,plotHeight);ctx.restore();};img.src=src;}}});})();(function(){var
D=Flotr.DOM,_=Flotr._,flotr=Flotr,S_MOUSETRACK='opacity:0.7;background-color:#000;color:#fff;display:none;position:absolute;padding:2px 8px;-moz-border-radius:4px;border-radius:4px;white-space:nowrap;';Flotr.addPlugin('hit',{callbacks:{'flotr:mousemove':function(e,pos){this.hit.track(pos);},'flotr:click':function(pos){var
hit=this.hit.track(pos);_.defaults(pos,hit);},'flotr:mouseout':function(){this.hit.clearHit();},'flotr:destroy':function(){this.mouseTrack=null;}},track:function(pos){if(this.options.mouse.track||_.any(this.series,function(s){return s.mouse&&s.mouse.track;})){return this.hit.hit(pos);}},executeOnType:function(s,method,args){var
success=false,options;if(!_.isArray(s))s=[s];function e(s,index){_.each(_.keys(flotr.graphTypes),function(type){if(s[type]&&s[type].show&&this[type][method]){options=this.getOptions(s,type);options.fill=!!s.mouse.fillColor;options.fillStyle=this.processColor(s.mouse.fillColor||'#ffffff',{opacity:s.mouse.fillOpacity});options.color=s.mouse.lineColor;options.context=this.octx;options.index=index;if(args)options.args=args;this[type][method].call(this[type],options);success=true;}},this);}
_.each(s,e,this);return success;},drawHit:function(n){var octx=this.octx,s=n.series;if(s.mouse.lineColor){octx.save();octx.lineWidth=(s.points?s.points.lineWidth:1);octx.strokeStyle=s.mouse.lineColor;octx.fillStyle=this.processColor(s.mouse.fillColor||'#ffffff',{opacity:s.mouse.fillOpacity});octx.translate(this.plotOffset.left,this.plotOffset.top);if(!this.hit.executeOnType(s,'drawHit',n)){var
xa=n.xaxis,ya=n.yaxis;octx.beginPath();octx.arc(xa.d2p(n.x),ya.d2p(n.y),s.points.hitRadius||s.points.radius||s.mouse.radius,0,2*Math.PI,true);octx.fill();octx.stroke();octx.closePath();}
octx.restore();this.clip(octx);}
this.prevHit=n;},clearHit:function(){var prev=this.prevHit,octx=this.octx,plotOffset=this.plotOffset;octx.save();octx.translate(plotOffset.left,plotOffset.top);if(prev){if(!this.hit.executeOnType(prev.series,'clearHit',this.prevHit)){var
s=prev.series,lw=(s.points?s.points.lineWidth:1);offset=(s.points.hitRadius||s.points.radius||s.mouse.radius)+lw;octx.clearRect(prev.xaxis.d2p(prev.x)-offset,prev.yaxis.d2p(prev.y)-offset,offset*2,offset*2);}
D.hide(this.mouseTrack);this.prevHit=null;}
octx.restore();},hit:function(mouse){var
options=this.options,prevHit=this.prevHit,closest,sensibility,dataIndex,seriesIndex,series,value,xaxis,yaxis,n;if(this.series.length===0)return;n={relX:mouse.relX,relY:mouse.relY,absX:mouse.absX,absY:mouse.absY};if(options.mouse.trackY&&!options.mouse.trackAll&&this.hit.executeOnType(this.series,'hit',[mouse,n])&&!_.isUndefined(n.seriesIndex))
{series=this.series[n.seriesIndex];n.series=series;n.mouse=series.mouse;n.xaxis=series.xaxis;n.yaxis=series.yaxis;}else{closest=this.hit.closest(mouse);if(closest){closest=options.mouse.trackY?closest.point:closest.x;seriesIndex=closest.seriesIndex;series=this.series[seriesIndex];xaxis=series.xaxis;yaxis=series.yaxis;sensibility=2*series.mouse.sensibility;if
(options.mouse.trackAll||(closest.distanceX<sensibility/xaxis.scale&&(!options.mouse.trackY||closest.distanceY<sensibility/yaxis.scale)))
{n.series=series;n.xaxis=series.xaxis;n.yaxis=series.yaxis;n.mouse=series.mouse;n.x=closest.x;n.y=closest.y;n.dist=closest.distance;n.index=closest.dataIndex;n.seriesIndex=seriesIndex;}}}
if(!prevHit||(prevHit.index!==n.index||prevHit.seriesIndex!==n.seriesIndex)){this.hit.clearHit();if(n.series&&n.mouse&&n.mouse.track){this.hit.drawMouseTrack(n);this.hit.drawHit(n);Flotr.EventAdapter.fire(this.el,'flotr:hit',[n,this]);}}
return n;},closest:function(mouse){var
series=this.series,options=this.options,relX=mouse.relX,relY=mouse.relY,compare=Number.MAX_VALUE,compareX=Number.MAX_VALUE,closest={},closestX={},check=false,serie,data,distance,distanceX,distanceY,mouseX,mouseY,x,y,i,j;function setClosest(o){o.distance=distance;o.distanceX=distanceX;o.distanceY=distanceY;o.seriesIndex=i;o.dataIndex=j;o.x=x;o.y=y;check=true;}
for(i=0;i<series.length;i++){serie=series[i];data=serie.data;mouseX=serie.xaxis.p2d(relX);mouseY=serie.yaxis.p2d(relY);for(j=data.length;j--;){x=data[j][0];y=data[j][1];if(x===null||y===null)continue;if(x<serie.xaxis.min||x>serie.xaxis.max)continue;distanceX=Math.abs(x-mouseX);distanceY=Math.abs(y-mouseY);distance=distanceX*distanceX+distanceY*distanceY;if(distance<compare){compare=distance;setClosest(closest);}
if(distanceX<compareX){compareX=distanceX;setClosest(closestX);}}}
return check?{point:closest,x:closestX}:false;},drawMouseTrack:function(n){var
pos='',s=n.series,p=n.mouse.position,m=n.mouse.margin,x=n.x,y=n.y,elStyle=S_MOUSETRACK,mouseTrack=this.mouseTrack,plotOffset=this.plotOffset,left=plotOffset.left,right=plotOffset.right,bottom=plotOffset.bottom,top=plotOffset.top,decimals=n.mouse.trackDecimals,options=this.options;if(!mouseTrack){mouseTrack=D.node('<div class="flotr-mouse-value"></div>');this.mouseTrack=mouseTrack;D.insert(this.el,mouseTrack);}
if(!n.mouse.relative){if(p.charAt(0)=='n')pos+='top:'+(m+top)+'px;bottom:auto;';else if(p.charAt(0)=='s')pos+='bottom:'+(m+bottom)+'px;top:auto;';if(p.charAt(1)=='e')pos+='right:'+(m+right)+'px;left:auto;';else if(p.charAt(1)=='w')pos+='left:'+(m+left)+'px;right:auto;';}else if(s.pie&&s.pie.show){var center={x:(this.plotWidth)/2,y:(this.plotHeight)/2},radius=(Math.min(this.canvasWidth,this.canvasHeight)*s.pie.sizeRatio)/2,bisection=n.sAngle<n.eAngle?(n.sAngle+n.eAngle)/2:(n.sAngle+n.eAngle+2*Math.PI)/2;pos+='bottom:'+(m-top-center.y-Math.sin(bisection)*radius/2+this.canvasHeight)+'px;top:auto;';pos+='left:'+(m+left+center.x+Math.cos(bisection)*radius/2)+'px;right:auto;';}else{if(/n/.test(p))pos+='bottom:'+(m-top-n.yaxis.d2p(n.y)+this.canvasHeight)+'px;top:auto;';else pos+='top:'+(m+top+n.yaxis.d2p(n.y))+'px;bottom:auto;';if(/w/.test(p))pos+='right:'+(m-left-n.xaxis.d2p(n.x)+this.canvasWidth)+'px;left:auto;';else pos+='left:'+(m+left+n.xaxis.d2p(n.x))+'px;right:auto;';}
elStyle+=pos;mouseTrack.style.cssText=elStyle;if(!decimals||decimals<0)decimals=0;if(x&&x.toFixed)x=x.toFixed(decimals);if(y&&y.toFixed)y=y.toFixed(decimals);mouseTrack.innerHTML=n.mouse.trackFormatter({x:x,y:y,series:n.series,index:n.index,nearest:n,fraction:n.fraction});D.show(mouseTrack);if(n.mouse.relative){if(!/[ew]/.test(p)){mouseTrack.style.left=(left+n.xaxis.d2p(n.x)-D.size(mouseTrack).width/2)+'px';}else
if(!/[ns]/.test(p)){mouseTrack.style.top=(top+n.yaxis.d2p(n.y)-D.size(mouseTrack).height/2)+'px';}}}});})();(function(){function isLeftClick(e,type){return(e.which?(e.which===1):(e.button===0||e.button===1));}
function boundX(x,graph){return Math.min(Math.max(0,x),graph.plotWidth-1);}
function boundY(y,graph){return Math.min(Math.max(0,y),graph.plotHeight);}
var
D=Flotr.DOM,E=Flotr.EventAdapter,_=Flotr._;Flotr.addPlugin('selection',{options:{pinchOnly:null,mode:null,color:'#B6D9FF',fps:20},callbacks:{'flotr:mouseup':function(event){var
options=this.options.selection,selection=this.selection,pointer=this.getEventPosition(event);if(!options||!options.mode)return;if(selection.interval)clearInterval(selection.interval);if(this.multitouches){selection.updateSelection();}else
if(!options.pinchOnly){selection.setSelectionPos(selection.selection.second,pointer);}
selection.clearSelection();if(selection.selecting&&selection.selectionIsSane()){selection.drawSelection();selection.fireSelectEvent();this.ignoreClick=true;}},'flotr:mousedown':function(event){var
options=this.options.selection,selection=this.selection,pointer=this.getEventPosition(event);if(!options||!options.mode)return;if(!options.mode||(!isLeftClick(event)&&_.isUndefined(event.touches)))return;if(!options.pinchOnly)selection.setSelectionPos(selection.selection.first,pointer);if(selection.interval)clearInterval(selection.interval);this.lastMousePos.pageX=null;selection.selecting=false;selection.interval=setInterval(_.bind(selection.updateSelection,this),1000/options.fps);},'flotr:destroy':function(event){clearInterval(this.selection.interval);}},getArea:function(){var
s=this.selection.selection,a=this.axes,first=s.first,second=s.second,x1,x2,y1,y2;x1=a.x.p2d(s.first.x);x2=a.x.p2d(s.second.x);y1=a.y.p2d(s.first.y);y2=a.y.p2d(s.second.y);return{x1:Math.min(x1,x2),y1:Math.min(y1,y2),x2:Math.max(x1,x2),y2:Math.max(y1,y2),xfirst:x1,xsecond:x2,yfirst:y1,ysecond:y2};},selection:{first:{x:-1,y:-1},second:{x:-1,y:-1}},prevSelection:null,interval:null,fireSelectEvent:function(name){var
area=this.selection.getArea();name=name||'select';area.selection=this.selection.selection;E.fire(this.el,'flotr:'+name,[area,this]);},setSelection:function(area,preventEvent){var options=this.options,xa=this.axes.x,ya=this.axes.y,vertScale=ya.scale,hozScale=xa.scale,selX=options.selection.mode.indexOf('x')!=-1,selY=options.selection.mode.indexOf('y')!=-1,s=this.selection.selection;this.selection.clearSelection();s.first.y=boundY((selX&&!selY)?0:(ya.max-area.y1)*vertScale,this);s.second.y=boundY((selX&&!selY)?this.plotHeight-1:(ya.max-area.y2)*vertScale,this);s.first.x=boundX((selY&&!selX)?0:(area.x1-xa.min)*hozScale,this);s.second.x=boundX((selY&&!selX)?this.plotWidth:(area.x2-xa.min)*hozScale,this);this.selection.drawSelection();if(!preventEvent)
this.selection.fireSelectEvent();},setSelectionPos:function(pos,pointer){var mode=this.options.selection.mode,selection=this.selection.selection;if(mode.indexOf('x')==-1){pos.x=(pos==selection.first)?0:this.plotWidth;}else{pos.x=boundX(pointer.relX,this);}
if(mode.indexOf('y')==-1){pos.y=(pos==selection.first)?0:this.plotHeight-1;}else{pos.y=boundY(pointer.relY,this);}},drawSelection:function(){this.selection.fireSelectEvent('selecting');var s=this.selection.selection,octx=this.octx,options=this.options,plotOffset=this.plotOffset,prevSelection=this.selection.prevSelection;if(prevSelection&&s.first.x==prevSelection.first.x&&s.first.y==prevSelection.first.y&&s.second.x==prevSelection.second.x&&s.second.y==prevSelection.second.y){return;}
octx.save();octx.strokeStyle=this.processColor(options.selection.color,{opacity:0.8});octx.lineWidth=1;octx.lineJoin='miter';octx.fillStyle=this.processColor(options.selection.color,{opacity:0.4});this.selection.prevSelection={first:{x:s.first.x,y:s.first.y},second:{x:s.second.x,y:s.second.y}};var x=Math.min(s.first.x,s.second.x),y=Math.min(s.first.y,s.second.y),w=Math.abs(s.second.x-s.first.x),h=Math.abs(s.second.y-s.first.y);octx.fillRect(x+plotOffset.left+0.5,y+plotOffset.top+0.5,w,h);octx.strokeRect(x+plotOffset.left+0.5,y+plotOffset.top+0.5,w,h);octx.restore();},updateSelection:function(){if(!this.lastMousePos.pageX)return;this.selection.selecting=true;if(this.multitouches){this.selection.setSelectionPos(this.selection.selection.first,this.getEventPosition(this.multitouches[0]));this.selection.setSelectionPos(this.selection.selection.second,this.getEventPosition(this.multitouches[1]));}else
if(this.options.selection.pinchOnly){return;}else{this.selection.setSelectionPos(this.selection.selection.second,this.lastMousePos);}
this.selection.clearSelection();if(this.selection.selectionIsSane()){this.selection.drawSelection();}},clearSelection:function(){if(!this.selection.prevSelection)return;var prevSelection=this.selection.prevSelection,lw=1,plotOffset=this.plotOffset,x=Math.min(prevSelection.first.x,prevSelection.second.x),y=Math.min(prevSelection.first.y,prevSelection.second.y),w=Math.abs(prevSelection.second.x-prevSelection.first.x),h=Math.abs(prevSelection.second.y-prevSelection.first.y);this.octx.clearRect(x+plotOffset.left-lw+0.5,y+plotOffset.top-lw,w+2*lw+0.5,h+2*lw+0.5);this.selection.prevSelection=null;},selectionIsSane:function(){var s=this.selection.selection;return Math.abs(s.second.x-s.first.x)>=5||Math.abs(s.second.y-s.first.y)>=5;}});})();(function(){var D=Flotr.DOM;Flotr.addPlugin('labels',{callbacks:{'flotr:afterdraw':function(){this.labels.draw();}},draw:function(){var
axis,tick,left,top,xBoxWidth,radius,sides,coeff,angle,div,i,html='',noLabels=0,options=this.options,ctx=this.ctx,a=this.axes,style={size:options.fontSize};for(i=0;i<a.x.ticks.length;++i){if(a.x.ticks[i].label){++noLabels;}}
xBoxWidth=this.plotWidth/noLabels;if(options.grid.circular){ctx.save();ctx.translate(this.plotOffset.left+this.plotWidth/2,this.plotOffset.top+this.plotHeight/2);radius=this.plotHeight*options.radar.radiusRatio/2+options.fontSize;sides=this.axes.x.ticks.length;coeff=2*(Math.PI/sides);angle=-Math.PI/2;drawLabelCircular(this,a.x,false);drawLabelCircular(this,a.x,true);drawLabelCircular(this,a.y,false);drawLabelCircular(this,a.y,true);ctx.restore();}
if(!options.HtmlText&&this.textEnabled){drawLabelNoHtmlText(this,a.x,'center','top');drawLabelNoHtmlText(this,a.x2,'center','bottom');drawLabelNoHtmlText(this,a.y,'right','middle');drawLabelNoHtmlText(this,a.y2,'left','middle');}else if((a.x.options.showLabels||a.x2.options.showLabels||a.y.options.showLabels||a.y2.options.showLabels)&&!options.grid.circular){html='';drawLabelHtml(this,a.x);drawLabelHtml(this,a.x2);drawLabelHtml(this,a.y);drawLabelHtml(this,a.y2);ctx.stroke();ctx.restore();div=D.create('div');D.setStyles(div,{fontSize:'smaller',color:options.grid.color});div.className='flotr-labels';D.insert(this.el,div);D.insert(div,html);}
function drawLabelCircular(graph,axis,minorTicks){var
ticks=minorTicks?axis.minorTicks:axis.ticks,isX=axis.orientation===1,isFirst=axis.n===1,style,offset;style={color:axis.options.color||options.grid.color,angle:Flotr.toRad(axis.options.labelsAngle),textBaseline:'middle'};for(i=0;i<ticks.length&&(minorTicks?axis.options.showMinorLabels:axis.options.showLabels);++i){tick=ticks[i];tick.label+='';if(!tick.label||!tick.label.length){continue;}
x=Math.cos(i*coeff+angle)*radius;y=Math.sin(i*coeff+angle)*radius;style.textAlign=isX?(Math.abs(x)<0.1?'center':(x<0?'right':'left')):'left';Flotr.drawText(ctx,tick.label,isX?x:3,isX?y:-(axis.ticks[i].v/axis.max)*(radius-options.fontSize),style);}}
function drawLabelNoHtmlText(graph,axis,textAlign,textBaseline){var
isX=axis.orientation===1,isFirst=axis.n===1,style,offset;style={color:axis.options.color||options.grid.color,textAlign:textAlign,textBaseline:textBaseline,angle:Flotr.toRad(axis.options.labelsAngle)};style=Flotr.getBestTextAlign(style.angle,style);for(i=0;i<axis.ticks.length&&continueShowingLabels(axis);++i){tick=axis.ticks[i];if(!tick.label||!tick.label.length){continue;}
offset=axis.d2p(tick.v);if(offset<0||offset>(isX?graph.plotWidth:graph.plotHeight)){continue;}
Flotr.drawText(ctx,tick.label,leftOffset(graph,isX,isFirst,offset),topOffset(graph,isX,isFirst,offset),style);if(!isX&&!isFirst){ctx.save();ctx.strokeStyle=style.color;ctx.beginPath();ctx.moveTo(graph.plotOffset.left+graph.plotWidth-8,graph.plotOffset.top+axis.d2p(tick.v));ctx.lineTo(graph.plotOffset.left+graph.plotWidth,graph.plotOffset.top+axis.d2p(tick.v));ctx.stroke();ctx.restore();}}
function continueShowingLabels(axis){return axis.options.showLabels&&axis.used;}
function leftOffset(graph,isX,isFirst,offset){return graph.plotOffset.left+
(isX?offset:(isFirst?-options.grid.labelMargin:options.grid.labelMargin+graph.plotWidth));}
function topOffset(graph,isX,isFirst,offset){return graph.plotOffset.top+
(isX?options.grid.labelMargin:offset)+
((isX&&isFirst)?graph.plotHeight:0);}}
function drawLabelHtml(graph,axis){var
isX=axis.orientation===1,isFirst=axis.n===1,name='',left,style,top,offset=graph.plotOffset;if(!isX&&!isFirst){ctx.save();ctx.strokeStyle=axis.options.color||options.grid.color;ctx.beginPath();}
if(axis.options.showLabels&&(isFirst?true:axis.used)){for(i=0;i<axis.ticks.length;++i){tick=axis.ticks[i];if(!tick.label||!tick.label.length||((isX?offset.left:offset.top)+axis.d2p(tick.v)<0)||((isX?offset.left:offset.top)+axis.d2p(tick.v)>(isX?graph.canvasWidth:graph.canvasHeight))){continue;}
top=offset.top+
(isX?((isFirst?1:-1)*(graph.plotHeight+options.grid.labelMargin)):axis.d2p(tick.v)-axis.maxLabel.height/2);left=isX?(offset.left+axis.d2p(tick.v)-xBoxWidth/2):0;name='';if(i===0){name=' first';}else if(i===axis.ticks.length-1){name=' last';}
name+=isX?' flotr-grid-label-x':' flotr-grid-label-y';html+=['<div style="position:absolute; text-align:'+(isX?'center':'right')+'; ','top:'+top+'px; ',((!isX&&!isFirst)?'right:':'left:')+left+'px; ','width:'+(isX?xBoxWidth:((isFirst?offset.left:offset.right)-options.grid.labelMargin))+'px; ',axis.options.color?('color:'+axis.options.color+'; '):' ','" class="flotr-grid-label'+name+'">'+tick.label+'</div>'].join(' ');if(!isX&&!isFirst){ctx.moveTo(offset.left+graph.plotWidth-8,offset.top+axis.d2p(tick.v));ctx.lineTo(offset.left+graph.plotWidth,offset.top+axis.d2p(tick.v));}}}}}});})();(function(){var
D=Flotr.DOM,_=Flotr._;Flotr.addPlugin('legend',{options:{show:true,noColumns:1,labelFormatter:function(v){return v;},labelBoxBorderColor:'#CCCCCC',labelBoxWidth:14,labelBoxHeight:10,labelBoxMargin:5,container:null,position:'nw',margin:5,backgroundColor:'#F0F0F0',backgroundOpacity:0.85},callbacks:{'flotr:afterinit':function(){this.legend.insertLegend();}},insertLegend:function(){if(!this.options.legend.show)
return;var series=this.series,plotOffset=this.plotOffset,options=this.options,legend=options.legend,fragments=[],rowStarted=false,ctx=this.ctx,itemCount=_.filter(series,function(s){return(s.label&&!s.hide);}).length,p=legend.position,m=legend.margin,opacity=legend.backgroundOpacity,i,label,color;if(itemCount){var lbw=legend.labelBoxWidth,lbh=legend.labelBoxHeight,lbm=legend.labelBoxMargin,offsetX=plotOffset.left+m,offsetY=plotOffset.top+m,labelMaxWidth=0,style={size:options.fontSize*1.1,color:options.grid.color};for(i=series.length-1;i>-1;--i){if(!series[i].label||series[i].hide)continue;label=legend.labelFormatter(series[i].label);labelMaxWidth=Math.max(labelMaxWidth,this._text.measureText(label,style).width);}
var legendWidth=Math.round(lbw+lbm*3+labelMaxWidth),legendHeight=Math.round(itemCount*(lbm+lbh)+lbm);if(!opacity&&!opacity===0){opacity=0.1;}
if(!options.HtmlText&&this.textEnabled&&!legend.container){if(p.charAt(0)=='s')offsetY=plotOffset.top+this.plotHeight-(m+legendHeight);if(p.charAt(0)=='c')offsetY=plotOffset.top+(this.plotHeight/2)-(m+(legendHeight/2));if(p.charAt(1)=='e')offsetX=plotOffset.left+this.plotWidth-(m+legendWidth);color=this.processColor(legend.backgroundColor,{opacity:opacity});ctx.fillStyle=color;ctx.fillRect(offsetX,offsetY,legendWidth,legendHeight);ctx.strokeStyle=legend.labelBoxBorderColor;ctx.strokeRect(Flotr.toPixel(offsetX),Flotr.toPixel(offsetY),legendWidth,legendHeight);var x=offsetX+lbm;var y=offsetY+lbm;for(i=0;i<series.length;i++){if(!series[i].label||series[i].hide)continue;label=legend.labelFormatter(series[i].label);ctx.fillStyle=series[i].color;ctx.fillRect(x,y,lbw-1,lbh-1);ctx.strokeStyle=legend.labelBoxBorderColor;ctx.lineWidth=1;ctx.strokeRect(Math.ceil(x)-1.5,Math.ceil(y)-1.5,lbw+2,lbh+2);Flotr.drawText(ctx,label,x+lbw+lbm,y+lbh,style);y+=lbh+lbm;}}
else{for(i=0;i<series.length;++i){if(!series[i].label||series[i].hide)continue;if(i%legend.noColumns===0){fragments.push(rowStarted?'</tr><tr>':'<tr>');rowStarted=true;}
var s=series[i],boxWidth=legend.labelBoxWidth,boxHeight=legend.labelBoxHeight;label=legend.labelFormatter(s.label);color='background-color:'+((s.bars&&s.bars.show&&s.bars.fillColor&&s.bars.fill)?s.bars.fillColor:s.color)+';';fragments.push('<td class="flotr-legend-color-box">','<div style="border:1px solid ',legend.labelBoxBorderColor,';padding:1px">','<div style="width:',(boxWidth-1),'px;height:',(boxHeight-1),'px;border:1px solid ',series[i].color,'">','<div style="width:',boxWidth,'px;height:',boxHeight,'px;',color,'"></div>','</div>','</div>','</td>','<td class="flotr-legend-label">',label,'</td>');}
if(rowStarted)fragments.push('</tr>');if(fragments.length>0){var table='<table style="font-size:smaller;color:'+options.grid.color+'">'+fragments.join('')+'</table>';if(legend.container){D.empty(legend.container);D.insert(legend.container,table);}
else{var styles={position:'absolute','zIndex':'2','border':'1px solid '+legend.labelBoxBorderColor};if(p.charAt(0)=='n'){styles.top=(m+plotOffset.top)+'px';styles.bottom='auto';}
else if(p.charAt(0)=='c'){styles.top=(m+(this.plotHeight-legendHeight)/2)+'px';styles.bottom='auto';}
else if(p.charAt(0)=='s'){styles.bottom=(m+plotOffset.bottom)+'px';styles.top='auto';}
if(p.charAt(1)=='e'){styles.right=(m+plotOffset.right)+'px';styles.left='auto';}
else if(p.charAt(1)=='w'){styles.left=(m+plotOffset.left)+'px';styles.right='auto';}
var div=D.create('div'),size;div.className='flotr-legend';D.setStyles(div,styles);D.insert(div,table);D.insert(this.el,div);if(!opacity)return;var c=legend.backgroundColor||options.grid.backgroundColor||'#ffffff';_.extend(styles,D.size(div),{'backgroundColor':c,'zIndex':'','border':''});styles.width+='px';styles.height+='px';div=D.create('div');div.className='flotr-legend-bg';D.setStyles(div,styles);D.opacity(div,opacity);D.insert(div,' ');D.insert(this.el,div);}}}}}});})();(function(){function getRowLabel(value){if(this.options.spreadsheet.tickFormatter){return this.options.spreadsheet.tickFormatter(value);}
else{var t=_.find(this.axes.x.ticks,function(t){return t.v==value;});if(t){return t.label;}
return value;}}
var
D=Flotr.DOM,_=Flotr._;Flotr.addPlugin('spreadsheet',{options:{show:false,tabGraphLabel:'Graph',tabDataLabel:'Data',toolbarDownload:'Download CSV',toolbarSelectAll:'Select all',csvFileSeparator:',',decimalSeparator:'.',tickFormatter:null,initialTab:'graph'},callbacks:{'flotr:afterconstruct':function(){if(!this.options.spreadsheet.show)return;var ss=this.spreadsheet,container=D.node('<div class="flotr-tabs-group" style="position:absolute;left:0px;width:'+this.canvasWidth+'px"></div>'),graph=D.node('<div style="float:left" class="flotr-tab selected">'+this.options.spreadsheet.tabGraphLabel+'</div>'),data=D.node('<div style="float:left" class="flotr-tab">'+this.options.spreadsheet.tabDataLabel+'</div>'),offset;ss.tabsContainer=container;ss.tabs={graph:graph,data:data};D.insert(container,graph);D.insert(container,data);D.insert(this.el,container);offset=D.size(data).height+2;this.plotOffset.bottom+=offset;D.setStyles(container,{top:this.canvasHeight-offset+'px'});this.observe(graph,'click',function(){ss.showTab('graph');}).observe(data,'click',function(){ss.showTab('data');});if(this.options.spreadsheet.initialTab!=='graph'){ss.showTab(this.options.spreadsheet.initialTab);}}},loadDataGrid:function(){if(this.seriesData)return this.seriesData;var s=this.series,rows={};_.each(s,function(serie,i){_.each(serie.data,function(v){var x=v[0],y=v[1],r=rows[x];if(r){r[i+1]=y;}else{var newRow=[];newRow[0]=x;newRow[i+1]=y;rows[x]=newRow;}});});this.seriesData=_.sortBy(rows,function(row,x){return parseInt(x,10);});return this.seriesData;},constructDataGrid:function(){if(this.spreadsheet.datagrid)return this.spreadsheet.datagrid;var s=this.series,datagrid=this.spreadsheet.loadDataGrid(),colgroup=['<colgroup><col />'],buttonDownload,buttonSelect,t;var html=['<table class="flotr-datagrid"><tr class="first-row">'];html.push('<th>&nbsp;</th>');_.each(s,function(serie,i){html.push('<th scope="col">'+(serie.label||String.fromCharCode(65+i))+'</th>');colgroup.push('<col />');});html.push('</tr>');_.each(datagrid,function(row){html.push('<tr>');_.times(s.length+1,function(i){var tag='td',value=row[i],content=(!_.isUndefined(value)?Math.round(value*100000)/100000:'');if(i===0){tag='th';var label=getRowLabel.call(this,content);if(label)content=label;}
html.push('<'+tag+(tag=='th'?' scope="row"':'')+'>'+content+'</'+tag+'>');},this);html.push('</tr>');},this);colgroup.push('</colgroup>');t=D.node(html.join(''));buttonDownload=D.node('<button type="button" class="flotr-datagrid-toolbar-button">'+
this.options.spreadsheet.toolbarDownload+'</button>');buttonSelect=D.node('<button type="button" class="flotr-datagrid-toolbar-button">'+
this.options.spreadsheet.toolbarSelectAll+'</button>');this.observe(buttonDownload,'click',_.bind(this.spreadsheet.downloadCSV,this)).observe(buttonSelect,'click',_.bind(this.spreadsheet.selectAllData,this));var toolbar=D.node('<div class="flotr-datagrid-toolbar"></div>');D.insert(toolbar,buttonDownload);D.insert(toolbar,buttonSelect);var containerHeight=this.canvasHeight-D.size(this.spreadsheet.tabsContainer).height-2,container=D.node('<div class="flotr-datagrid-container" style="position:absolute;left:0px;top:0px;width:'+
this.canvasWidth+'px;height:'+containerHeight+'px;overflow:auto;z-index:10"></div>');D.insert(container,toolbar);D.insert(container,t);D.insert(this.el,container);this.spreadsheet.datagrid=t;this.spreadsheet.container=container;return t;},showTab:function(tabName){if(this.spreadsheet.activeTab===tabName){return;}
switch(tabName){case'graph':D.hide(this.spreadsheet.container);D.removeClass(this.spreadsheet.tabs.data,'selected');D.addClass(this.spreadsheet.tabs.graph,'selected');break;case'data':if(!this.spreadsheet.datagrid)
this.spreadsheet.constructDataGrid();D.show(this.spreadsheet.container);D.addClass(this.spreadsheet.tabs.data,'selected');D.removeClass(this.spreadsheet.tabs.graph,'selected');break;default:throw'Illegal tab name: '+tabName;}
this.spreadsheet.activeTab=tabName;},selectAllData:function(){if(this.spreadsheet.tabs){var selection,range,doc,win,node=this.spreadsheet.constructDataGrid();this.spreadsheet.showTab('data');setTimeout(function(){if((doc=node.ownerDocument)&&(win=doc.defaultView)&&win.getSelection&&doc.createRange&&(selection=window.getSelection())&&selection.removeAllRanges){range=doc.createRange();range.selectNode(node);selection.removeAllRanges();selection.addRange(range);}
else if(document.body&&document.body.createTextRange&&(range=document.body.createTextRange())){range.moveToElementText(node);range.select();}},0);return true;}
else return false;},downloadCSV:function(){var csv='',series=this.series,options=this.options,dg=this.spreadsheet.loadDataGrid(),separator=encodeURIComponent(options.spreadsheet.csvFileSeparator);if(options.spreadsheet.decimalSeparator===options.spreadsheet.csvFileSeparator){throw"The decimal separator is the same as the column separator ("+options.spreadsheet.decimalSeparator+")";}
_.each(series,function(serie,i){csv+=separator+'"'+(serie.label||String.fromCharCode(65+i)).replace(/\"/g,'\\"')+'"';});csv+="%0D%0A";csv+=_.reduce(dg,function(memo,row){var rowLabel=getRowLabel.call(this,row[0])||'';rowLabel='"'+(rowLabel+'').replace(/\"/g,'\\"')+'"';var numbers=row.slice(1).join(separator);if(options.spreadsheet.decimalSeparator!=='.'){numbers=numbers.replace(/\./g,options.spreadsheet.decimalSeparator);}
return memo+rowLabel+separator+numbers+"%0D%0A";},'',this);if(Flotr.isIE&&Flotr.isIE<9){csv=csv.replace(new RegExp(separator,'g'),decodeURIComponent(separator)).replace(/%0A/g,'\n').replace(/%0D/g,'\r');window.open().document.write(csv);}
else window.open('data:text/csv,'+csv);}});})();(function(){var D=Flotr.DOM;Flotr.addPlugin('titles',{callbacks:{'flotr:afterdraw':function(){this.titles.drawTitles();}},drawTitles:function(){var html,options=this.options,margin=options.grid.labelMargin,ctx=this.ctx,a=this.axes;if(!options.HtmlText&&this.textEnabled){var style={size:options.fontSize,color:options.grid.color,textAlign:'center'};if(options.subtitle){Flotr.drawText(ctx,options.subtitle,this.plotOffset.left+this.plotWidth/2,this.titleHeight+this.subtitleHeight-2,style);}
style.weight=1.5;style.size*=1.5;if(options.title){Flotr.drawText(ctx,options.title,this.plotOffset.left+this.plotWidth/2,this.titleHeight-2,style);}
style.weight=1.8;style.size*=0.8;if(a.x.options.title&&a.x.used){style.textAlign=a.x.options.titleAlign||'center';style.textBaseline='top';style.angle=Flotr.toRad(a.x.options.titleAngle);style=Flotr.getBestTextAlign(style.angle,style);Flotr.drawText(ctx,a.x.options.title,this.plotOffset.left+this.plotWidth/2,this.plotOffset.top+a.x.maxLabel.height+this.plotHeight+2*margin,style);}
if(a.x2.options.title&&a.x2.used){style.textAlign=a.x2.options.titleAlign||'center';style.textBaseline='bottom';style.angle=Flotr.toRad(a.x2.options.titleAngle);style=Flotr.getBestTextAlign(style.angle,style);Flotr.drawText(ctx,a.x2.options.title,this.plotOffset.left+this.plotWidth/2,this.plotOffset.top-a.x2.maxLabel.height-2*margin,style);}
if(a.y.options.title&&a.y.used){style.textAlign=a.y.options.titleAlign||'right';style.textBaseline='middle';style.angle=Flotr.toRad(a.y.options.titleAngle);style=Flotr.getBestTextAlign(style.angle,style);Flotr.drawText(ctx,a.y.options.title,this.plotOffset.left-a.y.maxLabel.width-2*margin,this.plotOffset.top+this.plotHeight/2,style);}
if(a.y2.options.title&&a.y2.used){style.textAlign=a.y2.options.titleAlign||'left';style.textBaseline='middle';style.angle=Flotr.toRad(a.y2.options.titleAngle);style=Flotr.getBestTextAlign(style.angle,style);Flotr.drawText(ctx,a.y2.options.title,this.plotOffset.left+this.plotWidth+a.y2.maxLabel.width+2*margin,this.plotOffset.top+this.plotHeight/2,style);}}
else{html=[];if(options.title)
html.push('<div style="position:absolute;top:0;left:',this.plotOffset.left,'px;font-size:1em;font-weight:bold;text-align:center;width:',this.plotWidth,'px;" class="flotr-title">',options.title,'</div>');if(options.subtitle)
html.push('<div style="position:absolute;top:',this.titleHeight,'px;left:',this.plotOffset.left,'px;font-size:smaller;text-align:center;width:',this.plotWidth,'px;" class="flotr-subtitle">',options.subtitle,'</div>');html.push('</div>');html.push('<div class="flotr-axis-title" style="font-weight:bold;">');if(a.x.options.title&&a.x.used)
html.push('<div style="position:absolute;top:',(this.plotOffset.top+this.plotHeight+options.grid.labelMargin+a.x.titleSize.height),'px;left:',this.plotOffset.left,'px;width:',this.plotWidth,'px;text-align:',a.x.options.titleAlign,';" class="flotr-axis-title flotr-axis-title-x1">',a.x.options.title,'</div>');if(a.x2.options.title&&a.x2.used)
html.push('<div style="position:absolute;top:0;left:',this.plotOffset.left,'px;width:',this.plotWidth,'px;text-align:',a.x2.options.titleAlign,';" class="flotr-axis-title flotr-axis-title-x2">',a.x2.options.title,'</div>');if(a.y.options.title&&a.y.used)
html.push('<div style="position:absolute;top:',(this.plotOffset.top+this.plotHeight/2-a.y.titleSize.height/2),'px;left:0;text-align:',a.y.options.titleAlign,';" class="flotr-axis-title flotr-axis-title-y1">',a.y.options.title,'</div>');if(a.y2.options.title&&a.y2.used)
html.push('<div style="position:absolute;top:',(this.plotOffset.top+this.plotHeight/2-a.y.titleSize.height/2),'px;right:0;text-align:',a.y2.options.titleAlign,';" class="flotr-axis-title flotr-axis-title-y2">',a.y2.options.title,'</div>');html=html.join('');var div=D.create('div');D.setStyles({color:options.grid.color});div.className='flotr-titles';D.insert(this.el,div);D.insert(div,html);}}});})();

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,486 @@
/*
json2.js
2012-10-08
Public Domain.
NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
See http://www.JSON.org/js.html
This code should be minified before deployment.
See http://javascript.crockford.com/jsmin.html
USE YOUR OWN COPY. IT IS EXTREMELY UNWISE TO LOAD CODE FROM SERVERS YOU DO
NOT CONTROL.
This file creates a global JSON object containing two methods: stringify
and parse.
JSON.stringify(value, replacer, space)
value any JavaScript value, usually an object or array.
replacer an optional parameter that determines how object
values are stringified for objects. It can be a
function or an array of strings.
space an optional parameter that specifies the indentation
of nested structures. If it is omitted, the text will
be packed without extra whitespace. If it is a number,
it will specify the number of spaces to indent at each
level. If it is a string (such as '\t' or '&nbsp;'),
it contains the characters used to indent at each level.
This method produces a JSON text from a JavaScript value.
When an object value is found, if the object contains a toJSON
method, its toJSON method will be called and the result will be
stringified. A toJSON method does not serialize: it returns the
value represented by the name/value pair that should be serialized,
or undefined if nothing should be serialized. The toJSON method
will be passed the key associated with the value, and this will be
bound to the value
For example, this would serialize Dates as ISO strings.
Date.prototype.toJSON = function (key) {
function f(n) {
// Format integers to have at least two digits.
return n < 10 ? '0' + n : n;
}
return this.getUTCFullYear() + '-' +
f(this.getUTCMonth() + 1) + '-' +
f(this.getUTCDate()) + 'T' +
f(this.getUTCHours()) + ':' +
f(this.getUTCMinutes()) + ':' +
f(this.getUTCSeconds()) + 'Z';
};
You can provide an optional replacer method. It will be passed the
key and value of each member, with this bound to the containing
object. The value that is returned from your method will be
serialized. If your method returns undefined, then the member will
be excluded from the serialization.
If the replacer parameter is an array of strings, then it will be
used to select the members to be serialized. It filters the results
such that only members with keys listed in the replacer array are
stringified.
Values that do not have JSON representations, such as undefined or
functions, will not be serialized. Such values in objects will be
dropped; in arrays they will be replaced with null. You can use
a replacer function to replace those with JSON values.
JSON.stringify(undefined) returns undefined.
The optional space parameter produces a stringification of the
value that is filled with line breaks and indentation to make it
easier to read.
If the space parameter is a non-empty string, then that string will
be used for indentation. If the space parameter is a number, then
the indentation will be that many spaces.
Example:
text = JSON.stringify(['e', {pluribus: 'unum'}]);
// text is '["e",{"pluribus":"unum"}]'
text = JSON.stringify(['e', {pluribus: 'unum'}], null, '\t');
// text is '[\n\t"e",\n\t{\n\t\t"pluribus": "unum"\n\t}\n]'
text = JSON.stringify([new Date()], function (key, value) {
return this[key] instanceof Date ?
'Date(' + this[key] + ')' : value;
});
// text is '["Date(---current time---)"]'
JSON.parse(text, reviver)
This method parses a JSON text to produce an object or array.
It can throw a SyntaxError exception.
The optional reviver parameter is a function that can filter and
transform the results. It receives each of the keys and values,
and its return value is used instead of the original value.
If it returns what it received, then the structure is not modified.
If it returns undefined then the member is deleted.
Example:
// Parse the text. Values that look like ISO date strings will
// be converted to Date objects.
myData = JSON.parse(text, function (key, value) {
var a;
if (typeof value === 'string') {
a =
/^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}(?:\.\d*)?)Z$/.exec(value);
if (a) {
return new Date(Date.UTC(+a[1], +a[2] - 1, +a[3], +a[4],
+a[5], +a[6]));
}
}
return value;
});
myData = JSON.parse('["Date(09/09/2001)"]', function (key, value) {
var d;
if (typeof value === 'string' &&
value.slice(0, 5) === 'Date(' &&
value.slice(-1) === ')') {
d = new Date(value.slice(5, -1));
if (d) {
return d;
}
}
return value;
});
This is a reference implementation. You are free to copy, modify, or
redistribute.
*/
/*jslint evil: true, regexp: true */
/*members "", "\b", "\t", "\n", "\f", "\r", "\"", JSON, "\\", apply,
call, charCodeAt, getUTCDate, getUTCFullYear, getUTCHours,
getUTCMinutes, getUTCMonth, getUTCSeconds, hasOwnProperty, join,
lastIndex, length, parse, prototype, push, replace, slice, stringify,
test, toJSON, toString, valueOf
*/
// Create a JSON object only if one does not already exist. We create the
// methods in a closure to avoid creating global variables.
if (typeof JSON !== 'object') {
JSON = {};
}
(function () {
'use strict';
function f(n) {
// Format integers to have at least two digits.
return n < 10 ? '0' + n : n;
}
if (typeof Date.prototype.toJSON !== 'function') {
Date.prototype.toJSON = function (key) {
return isFinite(this.valueOf())
? this.getUTCFullYear() + '-' +
f(this.getUTCMonth() + 1) + '-' +
f(this.getUTCDate()) + 'T' +
f(this.getUTCHours()) + ':' +
f(this.getUTCMinutes()) + ':' +
f(this.getUTCSeconds()) + 'Z'
: null;
};
String.prototype.toJSON =
Number.prototype.toJSON =
Boolean.prototype.toJSON = function (key) {
return this.valueOf();
};
}
var cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
escapable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
gap,
indent,
meta = { // table of character substitutions
'\b': '\\b',
'\t': '\\t',
'\n': '\\n',
'\f': '\\f',
'\r': '\\r',
'"' : '\\"',
'\\': '\\\\'
},
rep;
function quote(string) {
// If the string contains no control characters, no quote characters, and no
// backslash characters, then we can safely slap some quotes around it.
// Otherwise we must also replace the offending characters with safe escape
// sequences.
escapable.lastIndex = 0;
return escapable.test(string) ? '"' + string.replace(escapable, function (a) {
var c = meta[a];
return typeof c === 'string'
? c
: '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
}) + '"' : '"' + string + '"';
}
function str(key, holder) {
// Produce a string from holder[key].
var i, // The loop counter.
k, // The member key.
v, // The member value.
length,
mind = gap,
partial,
value = holder[key];
// If the value has a toJSON method, call it to obtain a replacement value.
if (value && typeof value === 'object' &&
typeof value.toJSON === 'function') {
value = value.toJSON(key);
}
// If we were called with a replacer function, then call the replacer to
// obtain a replacement value.
if (typeof rep === 'function') {
value = rep.call(holder, key, value);
}
// What happens next depends on the value's type.
switch (typeof value) {
case 'string':
return quote(value);
case 'number':
// JSON numbers must be finite. Encode non-finite numbers as null.
return isFinite(value) ? String(value) : 'null';
case 'boolean':
case 'null':
// If the value is a boolean or null, convert it to a string. Note:
// typeof null does not produce 'null'. The case is included here in
// the remote chance that this gets fixed someday.
return String(value);
// If the type is 'object', we might be dealing with an object or an array or
// null.
case 'object':
// Due to a specification blunder in ECMAScript, typeof null is 'object',
// so watch out for that case.
if (!value) {
return 'null';
}
// Make an array to hold the partial results of stringifying this object value.
gap += indent;
partial = [];
// Is the value an array?
if (Object.prototype.toString.apply(value) === '[object Array]') {
// The value is an array. Stringify every element. Use null as a placeholder
// for non-JSON values.
length = value.length;
for (i = 0; i < length; i += 1) {
partial[i] = str(i, value) || 'null';
}
// Join all of the elements together, separated with commas, and wrap them in
// brackets.
v = partial.length === 0
? '[]'
: gap
? '[\n' + gap + partial.join(',\n' + gap) + '\n' + mind + ']'
: '[' + partial.join(',') + ']';
gap = mind;
return v;
}
// If the replacer is an array, use it to select the members to be stringified.
if (rep && typeof rep === 'object') {
length = rep.length;
for (i = 0; i < length; i += 1) {
if (typeof rep[i] === 'string') {
k = rep[i];
v = str(k, value);
if (v) {
partial.push(quote(k) + (gap ? ': ' : ':') + v);
}
}
}
} else {
// Otherwise, iterate through all of the keys in the object.
for (k in value) {
if (Object.prototype.hasOwnProperty.call(value, k)) {
v = str(k, value);
if (v) {
partial.push(quote(k) + (gap ? ': ' : ':') + v);
}
}
}
}
// Join all of the member texts together, separated with commas,
// and wrap them in braces.
v = partial.length === 0
? '{}'
: gap
? '{\n' + gap + partial.join(',\n' + gap) + '\n' + mind + '}'
: '{' + partial.join(',') + '}';
gap = mind;
return v;
}
}
// If the JSON object does not yet have a stringify method, give it one.
if (typeof JSON.stringify !== 'function') {
JSON.stringify = function (value, replacer, space) {
// The stringify method takes a value and an optional replacer, and an optional
// space parameter, and returns a JSON text. The replacer can be a function
// that can replace values, or an array of strings that will select the keys.
// A default replacer method can be provided. Use of the space parameter can
// produce text that is more easily readable.
var i;
gap = '';
indent = '';
// If the space parameter is a number, make an indent string containing that
// many spaces.
if (typeof space === 'number') {
for (i = 0; i < space; i += 1) {
indent += ' ';
}
// If the space parameter is a string, it will be used as the indent string.
} else if (typeof space === 'string') {
indent = space;
}
// If there is a replacer, it must be a function or an array.
// Otherwise, throw an error.
rep = replacer;
if (replacer && typeof replacer !== 'function' &&
(typeof replacer !== 'object' ||
typeof replacer.length !== 'number')) {
throw new Error('JSON.stringify');
}
// Make a fake root object containing our value under the key of ''.
// Return the result of stringifying the value.
return str('', {'': value});
};
}
// If the JSON object does not yet have a parse method, give it one.
if (typeof JSON.parse !== 'function') {
JSON.parse = function (text, reviver) {
// The parse method takes a text and an optional reviver function, and returns
// a JavaScript value if the text is a valid JSON text.
var j;
function walk(holder, key) {
// The walk method is used to recursively walk the resulting structure so
// that modifications can be made.
var k, v, value = holder[key];
if (value && typeof value === 'object') {
for (k in value) {
if (Object.prototype.hasOwnProperty.call(value, k)) {
v = walk(value, k);
if (v !== undefined) {
value[k] = v;
} else {
delete value[k];
}
}
}
}
return reviver.call(holder, key, value);
}
// Parsing happens in four stages. In the first stage, we replace certain
// Unicode characters with escape sequences. JavaScript handles many characters
// incorrectly, either silently deleting them, or treating them as line endings.
text = String(text);
cx.lastIndex = 0;
if (cx.test(text)) {
text = text.replace(cx, function (a) {
return '\\u' +
('0000' + a.charCodeAt(0).toString(16)).slice(-4);
});
}
// In the second stage, we run the text against regular expressions that look
// for non-JSON patterns. We are especially concerned with '()' and 'new'
// because they can cause invocation, and '=' because it can cause mutation.
// But just to be safe, we want to reject all unexpected forms.
// We split the second stage into 4 regexp operations in order to work around
// crippling inefficiencies in IE's and Safari's regexp engines. First we
// replace the JSON backslash pairs with '@' (a non-JSON character). Second, we
// replace all simple value tokens with ']' characters. Third, we delete all
// open brackets that follow a colon or comma or that begin the text. Finally,
// we look to see that the remaining characters are only whitespace or ']' or
// ',' or ':' or '{' or '}'. If that is so, then the text is safe for eval.
if (/^[\],:{}\s]*$/
.test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@')
.replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']')
.replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) {
// In the third stage we use the eval function to compile the text into a
// JavaScript structure. The '{' operator is subject to a syntactic ambiguity
// in JavaScript: it can begin a block or an object literal. We wrap the text
// in parens to eliminate the ambiguity.
j = eval('(' + text + ')');
// In the optional fourth stage, we recursively walk the new structure, passing
// each name/value pair to a reviver function for possible transformation.
return typeof reviver === 'function'
? walk({'': j}, '')
: j;
}
// If the text is not JSON parseable, then a SyntaxError is thrown.
throw new SyntaxError('JSON.parse');
};
}
}());

View File

@ -0,0 +1,25 @@
if(typeof JSON!=='object'){JSON={};}
(function(){'use strict';function f(n){return n<10?'0'+n:n;}
if(typeof Date.prototype.toJSON!=='function'){Date.prototype.toJSON=function(key){return isFinite(this.valueOf())?this.getUTCFullYear()+'-'+
f(this.getUTCMonth()+1)+'-'+
f(this.getUTCDate())+'T'+
f(this.getUTCHours())+':'+
f(this.getUTCMinutes())+':'+
f(this.getUTCSeconds())+'Z':null;};String.prototype.toJSON=Number.prototype.toJSON=Boolean.prototype.toJSON=function(key){return this.valueOf();};}
var cx=/[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,escapable=/[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,gap,indent,meta={'\b':'\\b','\t':'\\t','\n':'\\n','\f':'\\f','\r':'\\r','"':'\\"','\\':'\\\\'},rep;function quote(string){escapable.lastIndex=0;return escapable.test(string)?'"'+string.replace(escapable,function(a){var c=meta[a];return typeof c==='string'?c:'\\u'+('0000'+a.charCodeAt(0).toString(16)).slice(-4);})+'"':'"'+string+'"';}
function str(key,holder){var i,k,v,length,mind=gap,partial,value=holder[key];if(value&&typeof value==='object'&&typeof value.toJSON==='function'){value=value.toJSON(key);}
if(typeof rep==='function'){value=rep.call(holder,key,value);}
switch(typeof value){case'string':return quote(value);case'number':return isFinite(value)?String(value):'null';case'boolean':case'null':return String(value);case'object':if(!value){return'null';}
gap+=indent;partial=[];if(Object.prototype.toString.apply(value)==='[object Array]'){length=value.length;for(i=0;i<length;i+=1){partial[i]=str(i,value)||'null';}
v=partial.length===0?'[]':gap?'[\n'+gap+partial.join(',\n'+gap)+'\n'+mind+']':'['+partial.join(',')+']';gap=mind;return v;}
if(rep&&typeof rep==='object'){length=rep.length;for(i=0;i<length;i+=1){if(typeof rep[i]==='string'){k=rep[i];v=str(k,value);if(v){partial.push(quote(k)+(gap?': ':':')+v);}}}}else{for(k in value){if(Object.prototype.hasOwnProperty.call(value,k)){v=str(k,value);if(v){partial.push(quote(k)+(gap?': ':':')+v);}}}}
v=partial.length===0?'{}':gap?'{\n'+gap+partial.join(',\n'+gap)+'\n'+mind+'}':'{'+partial.join(',')+'}';gap=mind;return v;}}
if(typeof JSON.stringify!=='function'){JSON.stringify=function(value,replacer,space){var i;gap='';indent='';if(typeof space==='number'){for(i=0;i<space;i+=1){indent+=' ';}}else if(typeof space==='string'){indent=space;}
rep=replacer;if(replacer&&typeof replacer!=='function'&&(typeof replacer!=='object'||typeof replacer.length!=='number')){throw new Error('JSON.stringify');}
return str('',{'':value});};}
if(typeof JSON.parse!=='function'){JSON.parse=function(text,reviver){var j;function walk(holder,key){var k,v,value=holder[key];if(value&&typeof value==='object'){for(k in value){if(Object.prototype.hasOwnProperty.call(value,k)){v=walk(value,k);if(v!==undefined){value[k]=v;}else{delete value[k];}}}}
return reviver.call(holder,key,value);}
text=String(text);cx.lastIndex=0;if(cx.test(text)){text=text.replace(cx,function(a){return'\\u'+
('0000'+a.charCodeAt(0).toString(16)).slice(-4);});}
if(/^[\],:{}\s]*$/.test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,'@').replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,']').replace(/(?:^|:|,)(?:\s*\[)+/g,''))){j=eval('('+text+')');return typeof reviver==='function'?walk({'':j},''):j;}
throw new SyntaxError('JSON.parse');};}}());

View File

@ -0,0 +1,60 @@
.marker-cluster-small {
background-color: rgba(181, 226, 140, 0.6);
}
.marker-cluster-small div {
background-color: rgba(110, 204, 57, 0.6);
}
.marker-cluster-medium {
background-color: rgba(241, 211, 87, 0.6);
}
.marker-cluster-medium div {
background-color: rgba(240, 194, 12, 0.6);
}
.marker-cluster-large {
background-color: rgba(253, 156, 115, 0.6);
}
.marker-cluster-large div {
background-color: rgba(241, 128, 23, 0.6);
}
/* IE 6-8 fallback colors */
.leaflet-oldie .marker-cluster-small {
background-color: rgb(181, 226, 140);
}
.leaflet-oldie .marker-cluster-small div {
background-color: rgb(110, 204, 57);
}
.leaflet-oldie .marker-cluster-medium {
background-color: rgb(241, 211, 87);
}
.leaflet-oldie .marker-cluster-medium div {
background-color: rgb(240, 194, 12);
}
.leaflet-oldie .marker-cluster-large {
background-color: rgb(253, 156, 115);
}
.leaflet-oldie .marker-cluster-large div {
background-color: rgb(241, 128, 23);
}
.marker-cluster {
background-clip: padding-box;
border-radius: 20px;
}
.marker-cluster div {
width: 30px;
height: 30px;
margin-left: 5px;
margin-top: 5px;
text-align: center;
border-radius: 15px;
font: 12px "Helvetica Neue", Arial, Helvetica, sans-serif;
}
.marker-cluster span {
line-height: 30px;
}

View File

@ -0,0 +1,6 @@
.leaflet-cluster-anim .leaflet-marker-icon, .leaflet-cluster-anim .leaflet-marker-shadow {
-webkit-transition: -webkit-transform 0.3s ease-out, opacity 0.3s ease-in;
-moz-transition: -moz-transform 0.3s ease-out, opacity 0.3s ease-in;
-o-transition: -o-transform 0.3s ease-out, opacity 0.3s ease-in;
transition: transform 0.3s ease-out, opacity 0.3s ease-in;
}

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 913 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 681 B

View File

@ -0,0 +1,479 @@
/* required styles */
.leaflet-map-pane,
.leaflet-tile,
.leaflet-marker-icon,
.leaflet-marker-shadow,
.leaflet-tile-pane,
.leaflet-tile-container,
.leaflet-overlay-pane,
.leaflet-shadow-pane,
.leaflet-marker-pane,
.leaflet-popup-pane,
.leaflet-overlay-pane svg,
.leaflet-zoom-box,
.leaflet-image-layer,
.leaflet-layer {
position: absolute;
left: 0;
top: 0;
}
.leaflet-container {
overflow: hidden;
-ms-touch-action: none;
touch-action: none;
}
.leaflet-tile,
.leaflet-marker-icon,
.leaflet-marker-shadow {
-webkit-user-select: none;
-moz-user-select: none;
user-select: none;
-webkit-user-drag: none;
}
.leaflet-marker-icon,
.leaflet-marker-shadow {
display: block;
}
/* map is broken in FF if you have max-width: 100% on tiles */
.leaflet-container img {
max-width: none !important;
}
/* stupid Android 2 doesn't understand "max-width: none" properly */
.leaflet-container img.leaflet-image-layer {
max-width: 15000px !important;
}
.leaflet-tile {
filter: inherit;
visibility: hidden;
}
.leaflet-tile-loaded {
visibility: inherit;
}
.leaflet-zoom-box {
width: 0;
height: 0;
}
/* workaround for https://bugzilla.mozilla.org/show_bug.cgi?id=888319 */
.leaflet-overlay-pane svg {
-moz-user-select: none;
}
.leaflet-tile-pane { z-index: 2; }
.leaflet-objects-pane { z-index: 3; }
.leaflet-overlay-pane { z-index: 4; }
.leaflet-shadow-pane { z-index: 5; }
.leaflet-marker-pane { z-index: 6; }
.leaflet-popup-pane { z-index: 7; }
.leaflet-vml-shape {
width: 1px;
height: 1px;
}
.lvml {
behavior: url(#default#VML);
display: inline-block;
position: absolute;
}
/* control positioning */
.leaflet-control {
position: relative;
z-index: 7;
pointer-events: auto;
}
.leaflet-top,
.leaflet-bottom {
position: absolute;
z-index: 1000;
pointer-events: none;
}
.leaflet-top {
top: 0;
}
.leaflet-right {
right: 0;
}
.leaflet-bottom {
bottom: 0;
}
.leaflet-left {
left: 0;
}
.leaflet-control {
float: left;
clear: both;
}
.leaflet-right .leaflet-control {
float: right;
}
.leaflet-top .leaflet-control {
margin-top: 10px;
}
.leaflet-bottom .leaflet-control {
margin-bottom: 10px;
}
.leaflet-left .leaflet-control {
margin-left: 10px;
}
.leaflet-right .leaflet-control {
margin-right: 10px;
}
/* zoom and fade animations */
.leaflet-fade-anim .leaflet-tile,
.leaflet-fade-anim .leaflet-popup {
opacity: 0;
-webkit-transition: opacity 0.2s linear;
-moz-transition: opacity 0.2s linear;
-o-transition: opacity 0.2s linear;
transition: opacity 0.2s linear;
}
.leaflet-fade-anim .leaflet-tile-loaded,
.leaflet-fade-anim .leaflet-map-pane .leaflet-popup {
opacity: 1;
}
.leaflet-zoom-anim .leaflet-zoom-animated {
-webkit-transition: -webkit-transform 0.25s cubic-bezier(0,0,0.25,1);
-moz-transition: -moz-transform 0.25s cubic-bezier(0,0,0.25,1);
-o-transition: -o-transform 0.25s cubic-bezier(0,0,0.25,1);
transition: transform 0.25s cubic-bezier(0,0,0.25,1);
}
.leaflet-zoom-anim .leaflet-tile,
.leaflet-pan-anim .leaflet-tile,
.leaflet-touching .leaflet-zoom-animated {
-webkit-transition: none;
-moz-transition: none;
-o-transition: none;
transition: none;
}
.leaflet-zoom-anim .leaflet-zoom-hide {
visibility: hidden;
}
/* cursors */
.leaflet-clickable {
cursor: pointer;
}
.leaflet-container {
cursor: -webkit-grab;
cursor: -moz-grab;
}
.leaflet-popup-pane,
.leaflet-control {
cursor: auto;
}
.leaflet-dragging .leaflet-container,
.leaflet-dragging .leaflet-clickable {
cursor: move;
cursor: -webkit-grabbing;
cursor: -moz-grabbing;
}
/* visual tweaks */
.leaflet-container {
background: #ddd;
outline: 0;
}
.leaflet-container a {
color: #0078A8;
}
.leaflet-container a.leaflet-active {
outline: 2px solid orange;
}
.leaflet-zoom-box {
border: 2px dotted #38f;
background: rgba(255,255,255,0.5);
}
/* general typography */
.leaflet-container {
font: 12px/1.5 "Helvetica Neue", Arial, Helvetica, sans-serif;
}
/* general toolbar styles */
.leaflet-bar {
box-shadow: 0 1px 5px rgba(0,0,0,0.65);
border-radius: 4px;
}
.leaflet-bar a,
.leaflet-bar a:hover {
background-color: #fff;
border-bottom: 1px solid #ccc;
width: 26px;
height: 26px;
line-height: 26px;
display: block;
text-align: center;
text-decoration: none;
color: black;
}
.leaflet-bar a,
.leaflet-control-layers-toggle {
background-position: 50% 50%;
background-repeat: no-repeat;
display: block;
}
.leaflet-bar a:hover {
background-color: #f4f4f4;
}
.leaflet-bar a:first-child {
border-top-left-radius: 4px;
border-top-right-radius: 4px;
}
.leaflet-bar a:last-child {
border-bottom-left-radius: 4px;
border-bottom-right-radius: 4px;
border-bottom: none;
}
.leaflet-bar a.leaflet-disabled {
cursor: default;
background-color: #f4f4f4;
color: #bbb;
}
.leaflet-touch .leaflet-bar a {
width: 30px;
height: 30px;
line-height: 30px;
}
/* zoom control */
.leaflet-control-zoom-in,
.leaflet-control-zoom-out {
font: bold 18px 'Lucida Console', Monaco, monospace;
text-indent: 1px;
}
.leaflet-control-zoom-out {
font-size: 20px;
}
.leaflet-touch .leaflet-control-zoom-in {
font-size: 22px;
}
.leaflet-touch .leaflet-control-zoom-out {
font-size: 24px;
}
/* layers control */
.leaflet-control-layers {
box-shadow: 0 1px 5px rgba(0,0,0,0.4);
background: #fff;
border-radius: 5px;
}
.leaflet-control-layers-toggle {
background-image: url(images/layers.png);
width: 36px;
height: 36px;
}
.leaflet-retina .leaflet-control-layers-toggle {
background-image: url(images/layers-2x.png);
background-size: 26px 26px;
}
.leaflet-touch .leaflet-control-layers-toggle {
width: 44px;
height: 44px;
}
.leaflet-control-layers .leaflet-control-layers-list,
.leaflet-control-layers-expanded .leaflet-control-layers-toggle {
display: none;
}
.leaflet-control-layers-expanded .leaflet-control-layers-list {
display: block;
position: relative;
}
.leaflet-control-layers-expanded {
padding: 6px 10px 6px 6px;
color: #333;
background: #fff;
}
.leaflet-control-layers-selector {
margin-top: 2px;
position: relative;
top: 1px;
}
.leaflet-control-layers label {
display: block;
}
.leaflet-control-layers-separator {
height: 0;
border-top: 1px solid #ddd;
margin: 5px -10px 5px -6px;
}
/* attribution and scale controls */
.leaflet-container .leaflet-control-attribution {
background: #fff;
background: rgba(255, 255, 255, 0.7);
margin: 0;
}
.leaflet-control-attribution,
.leaflet-control-scale-line {
padding: 0 5px;
color: #333;
}
.leaflet-control-attribution a {
text-decoration: none;
}
.leaflet-control-attribution a:hover {
text-decoration: underline;
}
.leaflet-container .leaflet-control-attribution,
.leaflet-container .leaflet-control-scale {
font-size: 11px;
}
.leaflet-left .leaflet-control-scale {
margin-left: 5px;
}
.leaflet-bottom .leaflet-control-scale {
margin-bottom: 5px;
}
.leaflet-control-scale-line {
border: 2px solid #777;
border-top: none;
line-height: 1.1;
padding: 2px 5px 1px;
font-size: 11px;
white-space: nowrap;
overflow: hidden;
-moz-box-sizing: content-box;
box-sizing: content-box;
background: #fff;
background: rgba(255, 255, 255, 0.5);
}
.leaflet-control-scale-line:not(:first-child) {
border-top: 2px solid #777;
border-bottom: none;
margin-top: -2px;
}
.leaflet-control-scale-line:not(:first-child):not(:last-child) {
border-bottom: 2px solid #777;
}
.leaflet-touch .leaflet-control-attribution,
.leaflet-touch .leaflet-control-layers,
.leaflet-touch .leaflet-bar {
box-shadow: none;
}
.leaflet-touch .leaflet-control-layers,
.leaflet-touch .leaflet-bar {
border: 2px solid rgba(0,0,0,0.2);
background-clip: padding-box;
}
/* popup */
.leaflet-popup {
position: absolute;
text-align: center;
}
.leaflet-popup-content-wrapper {
padding: 1px;
text-align: left;
border-radius: 12px;
}
.leaflet-popup-content {
margin: 13px 19px;
line-height: 1.4;
}
.leaflet-popup-content p {
margin: 18px 0;
}
.leaflet-popup-tip-container {
margin: 0 auto;
width: 40px;
height: 20px;
position: relative;
overflow: hidden;
}
.leaflet-popup-tip {
width: 17px;
height: 17px;
padding: 1px;
margin: -10px auto 0;
-webkit-transform: rotate(45deg);
-moz-transform: rotate(45deg);
-ms-transform: rotate(45deg);
-o-transform: rotate(45deg);
transform: rotate(45deg);
}
.leaflet-popup-content-wrapper,
.leaflet-popup-tip {
background: white;
box-shadow: 0 3px 14px rgba(0,0,0,0.4);
}
.leaflet-container a.leaflet-popup-close-button {
position: absolute;
top: 0;
right: 0;
padding: 4px 4px 0 0;
text-align: center;
width: 18px;
height: 14px;
font: 16px/14px Tahoma, Verdana, sans-serif;
color: #c3c3c3;
text-decoration: none;
font-weight: bold;
background: transparent;
}
.leaflet-container a.leaflet-popup-close-button:hover {
color: #999;
}
.leaflet-popup-scrolled {
overflow: auto;
border-bottom: 1px solid #ddd;
border-top: 1px solid #ddd;
}
.leaflet-oldie .leaflet-popup-content-wrapper {
zoom: 1;
}
.leaflet-oldie .leaflet-popup-tip {
width: 24px;
margin: 0 auto;
-ms-filter: "progid:DXImageTransform.Microsoft.Matrix(M11=0.70710678, M12=0.70710678, M21=-0.70710678, M22=0.70710678)";
filter: progid:DXImageTransform.Microsoft.Matrix(M11=0.70710678, M12=0.70710678, M21=-0.70710678, M22=0.70710678);
}
.leaflet-oldie .leaflet-popup-tip-container {
margin-top: -1px;
}
.leaflet-oldie .leaflet-control-zoom,
.leaflet-oldie .leaflet-control-layers,
.leaflet-oldie .leaflet-popup-content-wrapper,
.leaflet-oldie .leaflet-popup-tip {
border: 1px solid #999;
}
/* div icon */
.leaflet-div-icon {
background: #fff;
border: 1px solid #666;
}

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,536 @@
/*!
* mustache.js - Logic-less {{mustache}} templates with JavaScript
* http://github.com/janl/mustache.js
*/
var Mustache = (typeof module !== "undefined" && module.exports) || {};
(function (exports) {
exports.name = "mustache.js";
exports.version = "0.5.0-dev";
exports.tags = ["{{", "}}"];
exports.parse = parse;
exports.compile = compile;
exports.render = render;
exports.clearCache = clearCache;
// This is here for backwards compatibility with 0.4.x.
exports.to_html = function (template, view, partials, send) {
var result = render(template, view, partials);
if (typeof send === "function") {
send(result);
} else {
return result;
}
};
var _toString = Object.prototype.toString;
var _isArray = Array.isArray;
var _forEach = Array.prototype.forEach;
var _trim = String.prototype.trim;
var isArray;
if (_isArray) {
isArray = _isArray;
} else {
isArray = function (obj) {
return _toString.call(obj) === "[object Array]";
};
}
var forEach;
if (_forEach) {
forEach = function (obj, callback, scope) {
return _forEach.call(obj, callback, scope);
};
} else {
forEach = function (obj, callback, scope) {
for (var i = 0, len = obj.length; i < len; ++i) {
callback.call(scope, obj[i], i, obj);
}
};
}
var spaceRe = /^\s*$/;
function isWhitespace(string) {
return spaceRe.test(string);
}
var trim;
if (_trim) {
trim = function (string) {
return string == null ? "" : _trim.call(string);
};
} else {
var trimLeft, trimRight;
if (isWhitespace("\xA0")) {
trimLeft = /^\s+/;
trimRight = /\s+$/;
} else {
// IE doesn't match non-breaking spaces with \s, thanks jQuery.
trimLeft = /^[\s\xA0]+/;
trimRight = /[\s\xA0]+$/;
}
trim = function (string) {
return string == null ? "" :
String(string).replace(trimLeft, "").replace(trimRight, "");
};
}
var escapeMap = {
"&": "&amp;",
"<": "&lt;",
">": "&gt;",
'"': '&quot;',
"'": '&#39;'
};
function escapeHTML(string) {
return String(string).replace(/&(?!\w+;)|[<>"']/g, function (s) {
return escapeMap[s] || s;
});
}
/**
* Adds the `template`, `line`, and `file` properties to the given error
* object and alters the message to provide more useful debugging information.
*/
function debug(e, template, line, file) {
file = file || "<template>";
var lines = template.split("\n"),
start = Math.max(line - 3, 0),
end = Math.min(lines.length, line + 3),
context = lines.slice(start, end);
var c;
for (var i = 0, len = context.length; i < len; ++i) {
c = i + start + 1;
context[i] = (c === line ? " >> " : " ") + context[i];
}
e.template = template;
e.line = line;
e.file = file;
e.message = [file + ":" + line, context.join("\n"), "", e.message].join("\n");
return e;
}
/**
* Looks up the value of the given `name` in the given context `stack`.
*/
function lookup(name, stack, defaultValue) {
if (name === ".") {
return stack[stack.length - 1];
}
var names = name.split(".");
var lastIndex = names.length - 1;
var target = names[lastIndex];
var value, context, i = stack.length, j, localStack;
while (i) {
localStack = stack.slice(0);
context = stack[--i];
j = 0;
while (j < lastIndex) {
context = context[names[j++]];
if (context == null) {
break;
}
localStack.push(context);
}
if (context && typeof context === "object" && target in context) {
value = context[target];
break;
}
}
// If the value is a function, call it in the current context.
if (typeof value === "function") {
value = value.call(localStack[localStack.length - 1]);
}
if (value == null) {
return defaultValue;
}
return value;
}
function renderSection(name, stack, callback, inverted) {
var buffer = "";
var value = lookup(name, stack);
if (inverted) {
// From the spec: inverted sections may render text once based on the
// inverse value of the key. That is, they will be rendered if the key
// doesn't exist, is false, or is an empty list.
if (value == null || value === false || (isArray(value) && value.length === 0)) {
buffer += callback();
}
} else if (isArray(value)) {
forEach(value, function (value) {
stack.push(value);
buffer += callback();
stack.pop();
});
} else if (typeof value === "object") {
stack.push(value);
buffer += callback();
stack.pop();
} else if (typeof value === "function") {
var scope = stack[stack.length - 1];
var scopedRender = function (template) {
return render(template, scope);
};
buffer += value.call(scope, callback(), scopedRender) || "";
} else if (value) {
buffer += callback();
}
return buffer;
}
/**
* Parses the given `template` and returns the source of a function that,
* with the proper arguments, will render the template. Recognized options
* include the following:
*
* - file The name of the file the template comes from (displayed in
* error messages)
* - tags An array of open and close tags the `template` uses. Defaults
* to the value of Mustache.tags
* - debug Set `true` to log the body of the generated function to the
* console
* - space Set `true` to preserve whitespace from lines that otherwise
* contain only a {{tag}}. Defaults to `false`
*/
function parse(template, options) {
options = options || {};
var tags = options.tags || exports.tags,
openTag = tags[0],
closeTag = tags[tags.length - 1];
var code = [
'var buffer = "";', // output buffer
"\nvar line = 1;", // keep track of source line number
"\ntry {",
'\nbuffer += "'
];
var spaces = [], // indices of whitespace in code on the current line
hasTag = false, // is there a {{tag}} on the current line?
nonSpace = false; // is there a non-space char on the current line?
// Strips all space characters from the code array for the current line
// if there was a {{tag}} on it and otherwise only spaces.
var stripSpace = function () {
if (hasTag && !nonSpace && !options.space) {
while (spaces.length) {
code.splice(spaces.pop(), 1);
}
} else {
spaces = [];
}
hasTag = false;
nonSpace = false;
};
var sectionStack = [], updateLine, nextOpenTag, nextCloseTag;
var setTags = function (source) {
tags = trim(source).split(/\s+/);
nextOpenTag = tags[0];
nextCloseTag = tags[tags.length - 1];
};
var includePartial = function (source) {
code.push(
'";',
updateLine,
'\nvar partial = partials["' + trim(source) + '"];',
'\nif (partial) {',
'\n buffer += render(partial,stack[stack.length - 1],partials);',
'\n}',
'\nbuffer += "'
);
};
var openSection = function (source, inverted) {
var name = trim(source);
if (name === "") {
throw debug(new Error("Section name may not be empty"), template, line, options.file);
}
sectionStack.push({name: name, inverted: inverted});
code.push(
'";',
updateLine,
'\nvar name = "' + name + '";',
'\nvar callback = (function () {',
'\n return function () {',
'\n var buffer = "";',
'\nbuffer += "'
);
};
var openInvertedSection = function (source) {
openSection(source, true);
};
var closeSection = function (source) {
var name = trim(source);
var openName = sectionStack.length != 0 && sectionStack[sectionStack.length - 1].name;
if (!openName || name != openName) {
throw debug(new Error('Section named "' + name + '" was never opened'), template, line, options.file);
}
var section = sectionStack.pop();
code.push(
'";',
'\n return buffer;',
'\n };',
'\n})();'
);
if (section.inverted) {
code.push("\nbuffer += renderSection(name,stack,callback,true);");
} else {
code.push("\nbuffer += renderSection(name,stack,callback);");
}
code.push('\nbuffer += "');
};
var sendPlain = function (source) {
code.push(
'";',
updateLine,
'\nbuffer += lookup("' + trim(source) + '",stack,"");',
'\nbuffer += "'
);
};
var sendEscaped = function (source) {
code.push(
'";',
updateLine,
'\nbuffer += escapeHTML(lookup("' + trim(source) + '",stack,""));',
'\nbuffer += "'
);
};
var line = 1, c, callback;
for (var i = 0, len = template.length; i < len; ++i) {
if (template.slice(i, i + openTag.length) === openTag) {
i += openTag.length;
c = template.substr(i, 1);
updateLine = '\nline = ' + line + ';';
nextOpenTag = openTag;
nextCloseTag = closeTag;
hasTag = true;
switch (c) {
case "!": // comment
i++;
callback = null;
break;
case "=": // change open/close tags, e.g. {{=<% %>=}}
i++;
closeTag = "=" + closeTag;
callback = setTags;
break;
case ">": // include partial
i++;
callback = includePartial;
break;
case "#": // start section
i++;
callback = openSection;
break;
case "^": // start inverted section
i++;
callback = openInvertedSection;
break;
case "/": // end section
i++;
callback = closeSection;
break;
case "{": // plain variable
closeTag = "}" + closeTag;
// fall through
case "&": // plain variable
i++;
nonSpace = true;
callback = sendPlain;
break;
default: // escaped variable
nonSpace = true;
callback = sendEscaped;
}
var end = template.indexOf(closeTag, i);
if (end === -1) {
throw debug(new Error('Tag "' + openTag + '" was not closed properly'), template, line, options.file);
}
var source = template.substring(i, end);
if (callback) {
callback(source);
}
// Maintain line count for \n in source.
var n = 0;
while (~(n = source.indexOf("\n", n))) {
line++;
n++;
}
i = end + closeTag.length - 1;
openTag = nextOpenTag;
closeTag = nextCloseTag;
} else {
c = template.substr(i, 1);
switch (c) {
case '"':
case "\\":
nonSpace = true;
code.push("\\" + c);
break;
case "\r":
// Ignore carriage returns.
break;
case "\n":
spaces.push(code.length);
code.push("\\n");
stripSpace(); // Check for whitespace on the current line.
line++;
break;
default:
if (isWhitespace(c)) {
spaces.push(code.length);
} else {
nonSpace = true;
}
code.push(c);
}
}
}
if (sectionStack.length != 0) {
throw debug(new Error('Section "' + sectionStack[sectionStack.length - 1].name + '" was not closed properly'), template, line, options.file);
}
// Clean up any whitespace from a closing {{tag}} that was at the end
// of the template without a trailing \n.
stripSpace();
code.push(
'";',
"\nreturn buffer;",
"\n} catch (e) { throw {error: e, line: line}; }"
);
// Ignore `buffer += "";` statements.
var body = code.join("").replace(/buffer \+= "";\n/g, "");
if (options.debug) {
if (typeof console != "undefined" && console.log) {
console.log(body);
} else if (typeof print === "function") {
print(body);
}
}
return body;
}
/**
* Used by `compile` to generate a reusable function for the given `template`.
*/
function _compile(template, options) {
var args = "view,partials,stack,lookup,escapeHTML,renderSection,render";
var body = parse(template, options);
var fn = new Function(args, body);
// This anonymous function wraps the generated function so we can do
// argument coercion, setup some variables, and handle any errors
// encountered while executing it.
return function (view, partials) {
partials = partials || {};
var stack = [view]; // context stack
try {
return fn(view, partials, stack, lookup, escapeHTML, renderSection, render);
} catch (e) {
throw debug(e.error, template, e.line, options.file);
}
};
}
// Cache of pre-compiled templates.
var _cache = {};
/**
* Clear the cache of compiled templates.
*/
function clearCache() {
_cache = {};
}
/**
* Compiles the given `template` into a reusable function using the given
* `options`. In addition to the options accepted by Mustache.parse,
* recognized options include the following:
*
* - cache Set `false` to bypass any pre-compiled version of the given
* template. Otherwise, a given `template` string will be cached
* the first time it is parsed
*/
function compile(template, options) {
options = options || {};
// Use a pre-compiled version from the cache if we have one.
if (options.cache !== false) {
if (!_cache[template]) {
_cache[template] = _compile(template, options);
}
return _cache[template];
}
return _compile(template, options);
}
/**
* High-level function that renders the given `template` using the given
* `view` and `partials`. If you need to use any of the template options (see
* `compile` above), you must compile in a separate step, and then call that
* compiled function.
*/
function render(template, view, partials) {
return compile(template)(view, partials);
}
})(Mustache);

View File

@ -0,0 +1,36 @@
var Mustache=(typeof module!=="undefined"&&module.exports)||{};(function(exports){exports.name="mustache.js";exports.version="0.5.0-dev";exports.tags=["{{","}}"];exports.parse=parse;exports.compile=compile;exports.render=render;exports.clearCache=clearCache;exports.to_html=function(template,view,partials,send){var result=render(template,view,partials);if(typeof send==="function"){send(result);}else{return result;}};var _toString=Object.prototype.toString;var _isArray=Array.isArray;var _forEach=Array.prototype.forEach;var _trim=String.prototype.trim;var isArray;if(_isArray){isArray=_isArray;}else{isArray=function(obj){return _toString.call(obj)==="[object Array]";};}
var forEach;if(_forEach){forEach=function(obj,callback,scope){return _forEach.call(obj,callback,scope);};}else{forEach=function(obj,callback,scope){for(var i=0,len=obj.length;i<len;++i){callback.call(scope,obj[i],i,obj);}};}
var spaceRe=/^\s*$/;function isWhitespace(string){return spaceRe.test(string);}
var trim;if(_trim){trim=function(string){return string==null?"":_trim.call(string);};}else{var trimLeft,trimRight;if(isWhitespace("\xA0")){trimLeft=/^\s+/;trimRight=/\s+$/;}else{trimLeft=/^[\s\xA0]+/;trimRight=/[\s\xA0]+$/;}
trim=function(string){return string==null?"":String(string).replace(trimLeft,"").replace(trimRight,"");};}
var escapeMap={"&":"&amp;","<":"&lt;",">":"&gt;",'"':'&quot;',"'":'&#39;'};function escapeHTML(string){return String(string).replace(/&(?!\w+;)|[<>"']/g,function(s){return escapeMap[s]||s;});}
function debug(e,template,line,file){file=file||"<template>";var lines=template.split("\n"),start=Math.max(line-3,0),end=Math.min(lines.length,line+3),context=lines.slice(start,end);var c;for(var i=0,len=context.length;i<len;++i){c=i+start+1;context[i]=(c===line?" >> ":" ")+context[i];}
e.template=template;e.line=line;e.file=file;e.message=[file+":"+line,context.join("\n"),"",e.message].join("\n");return e;}
function lookup(name,stack,defaultValue){if(name==="."){return stack[stack.length-1];}
var names=name.split(".");var lastIndex=names.length-1;var target=names[lastIndex];var value,context,i=stack.length,j,localStack;while(i){localStack=stack.slice(0);context=stack[--i];j=0;while(j<lastIndex){context=context[names[j++]];if(context==null){break;}
localStack.push(context);}
if(context&&typeof context==="object"&&target in context){value=context[target];break;}}
if(typeof value==="function"){value=value.call(localStack[localStack.length-1]);}
if(value==null){return defaultValue;}
return value;}
function renderSection(name,stack,callback,inverted){var buffer="";var value=lookup(name,stack);if(inverted){if(value==null||value===false||(isArray(value)&&value.length===0)){buffer+=callback();}}else if(isArray(value)){forEach(value,function(value){stack.push(value);buffer+=callback();stack.pop();});}else if(typeof value==="object"){stack.push(value);buffer+=callback();stack.pop();}else if(typeof value==="function"){var scope=stack[stack.length-1];var scopedRender=function(template){return render(template,scope);};buffer+=value.call(scope,callback(),scopedRender)||"";}else if(value){buffer+=callback();}
return buffer;}
function parse(template,options){options=options||{};var tags=options.tags||exports.tags,openTag=tags[0],closeTag=tags[tags.length-1];var code=['var buffer = "";',"\nvar line = 1;","\ntry {",'\nbuffer += "'];var spaces=[],hasTag=false,nonSpace=false;var stripSpace=function(){if(hasTag&&!nonSpace&&!options.space){while(spaces.length){code.splice(spaces.pop(),1);}}else{spaces=[];}
hasTag=false;nonSpace=false;};var sectionStack=[],updateLine,nextOpenTag,nextCloseTag;var setTags=function(source){tags=trim(source).split(/\s+/);nextOpenTag=tags[0];nextCloseTag=tags[tags.length-1];};var includePartial=function(source){code.push('";',updateLine,'\nvar partial = partials["'+trim(source)+'"];','\nif (partial) {','\n buffer += render(partial,stack[stack.length - 1],partials);','\n}','\nbuffer += "');};var openSection=function(source,inverted){var name=trim(source);if(name===""){throw debug(new Error("Section name may not be empty"),template,line,options.file);}
sectionStack.push({name:name,inverted:inverted});code.push('";',updateLine,'\nvar name = "'+name+'";','\nvar callback = (function () {','\n return function () {','\n var buffer = "";','\nbuffer += "');};var openInvertedSection=function(source){openSection(source,true);};var closeSection=function(source){var name=trim(source);var openName=sectionStack.length!=0&&sectionStack[sectionStack.length-1].name;if(!openName||name!=openName){throw debug(new Error('Section named "'+name+'" was never opened'),template,line,options.file);}
var section=sectionStack.pop();code.push('";','\n return buffer;','\n };','\n})();');if(section.inverted){code.push("\nbuffer += renderSection(name,stack,callback,true);");}else{code.push("\nbuffer += renderSection(name,stack,callback);");}
code.push('\nbuffer += "');};var sendPlain=function(source){code.push('";',updateLine,'\nbuffer += lookup("'+trim(source)+'",stack,"");','\nbuffer += "');};var sendEscaped=function(source){code.push('";',updateLine,'\nbuffer += escapeHTML(lookup("'+trim(source)+'",stack,""));','\nbuffer += "');};var line=1,c,callback;for(var i=0,len=template.length;i<len;++i){if(template.slice(i,i+openTag.length)===openTag){i+=openTag.length;c=template.substr(i,1);updateLine='\nline = '+line+';';nextOpenTag=openTag;nextCloseTag=closeTag;hasTag=true;switch(c){case"!":i++;callback=null;break;case"=":i++;closeTag="="+closeTag;callback=setTags;break;case">":i++;callback=includePartial;break;case"#":i++;callback=openSection;break;case"^":i++;callback=openInvertedSection;break;case"/":i++;callback=closeSection;break;case"{":closeTag="}"+closeTag;case"&":i++;nonSpace=true;callback=sendPlain;break;default:nonSpace=true;callback=sendEscaped;}
var end=template.indexOf(closeTag,i);if(end===-1){throw debug(new Error('Tag "'+openTag+'" was not closed properly'),template,line,options.file);}
var source=template.substring(i,end);if(callback){callback(source);}
var n=0;while(~(n=source.indexOf("\n",n))){line++;n++;}
i=end+closeTag.length-1;openTag=nextOpenTag;closeTag=nextCloseTag;}else{c=template.substr(i,1);switch(c){case'"':case"\\":nonSpace=true;code.push("\\"+c);break;case"\r":break;case"\n":spaces.push(code.length);code.push("\\n");stripSpace();line++;break;default:if(isWhitespace(c)){spaces.push(code.length);}else{nonSpace=true;}
code.push(c);}}}
if(sectionStack.length!=0){throw debug(new Error('Section "'+sectionStack[sectionStack.length-1].name+'" was not closed properly'),template,line,options.file);}
stripSpace();code.push('";',"\nreturn buffer;","\n} catch (e) { throw {error: e, line: line}; }");var body=code.join("").replace(/buffer \+= "";\n/g,"");if(options.debug){if(typeof console!="undefined"&&console.log){console.log(body);}else if(typeof print==="function"){print(body);}}
return body;}
function _compile(template,options){var args="view,partials,stack,lookup,escapeHTML,renderSection,render";var body=parse(template,options);var fn=new Function(args,body);return function(view,partials){partials=partials||{};var stack=[view];try{return fn(view,partials,stack,lookup,escapeHTML,renderSection,render);}catch(e){throw debug(e.error,template,e.line,options.file);}};}
var _cache={};function clearCache(){_cache={};}
function compile(template,options){options=options||{};if(options.cache!==false){if(!_cache[template]){_cache[template]=_compile(template,options);}
return _cache[template];}
return _compile(template,options);}
function render(template,view,partials){return compile(template)(view,partials);}})(Mustache);

View File

@ -0,0 +1,26 @@
.recline-flot .graph {
height: 500px;
overflow: hidden;
}
.recline-flot .legend table {
width: auto;
margin-bottom: 0;
}
.recline-flot .legend td {
padding: 5px;
line-height: 13px;
}
.recline-flot .graph .alert {
width: 450px;
}
#recline-flot-tooltip {
position: absolute;
background-color: #FEE;
color: #000000;
opacity: 0.8;
border: 1px solid #fdd;
}

View File

@ -0,0 +1,28 @@
.recline-map .map {
height: 500px;
}
/**********************************************************
* Editor
*********************************************************/
.recline-map .editor {
float: right;
width: 200px;
padding-left: 0px;
margin-left: 10px;
}
.recline-map .editor form {
padding-left: 4px;
}
.recline-map .editor select {
width: 100%;
}
.recline-map .editor .editor-options {
margin-top: 10px;
border-top: 1px solid gray;
padding: 5px 0;
}

View File

@ -0,0 +1,644 @@
.recline-flot .graph {
height: 500px;
overflow: hidden;
}
.recline-flot .legend table {
width: auto;
margin-bottom: 0;
}
.recline-flot .legend td {
padding: 5px;
line-height: 13px;
}
.recline-flot .graph .alert {
width: 450px;
}
#recline-flot-tooltip {
position: absolute;
background-color: #FEE;
color: #000000;
opacity: 0.8;
border: 1px solid #fdd;
}
/**********************************************************
* (Data) Grid
*********************************************************/
table.recline-grid {
table-layout: fixed;
width: 100%;
}
.recline-grid .btn-group .dropdown-toggle {
padding: 1px 3px;
line-height: auto;
}
.recline-grid td, .recline-grid th {
border-left: 1px solid #ccc;
padding: 3px 4px;
text-align: left;
word-wrap: break-word;
white-space: normal;
}
.recline-grid tbody tr {
vertical-align: top;
border-bottom: solid 1px #ccc;
}
.recline-grid tbody tr:last-child {
border-bottom: 1px solid #ccc;
}
.recline-grid tbody td:last-child {
border-right: 1px solid #ccc;
}
/* direct borrowing from twitter buttons */
.recline-grid th {
background-color: #e6e6e6;
background-repeat: no-repeat;
background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), color-stop(25%, #ffffff), to(#e6e6e6));
background-image: -webkit-linear-gradient(#ffffff, #ffffff 25%, #e6e6e6);
background-image: -moz-linear-gradient(top, #ffffff, #ffffff 25%, #e6e6e6);
background-image: -ms-linear-gradient(#ffffff, #ffffff 25%, #e6e6e6);
background-image: -o-linear-gradient(#ffffff, #ffffff 25%, #e6e6e6);
background-image: linear-gradient(#ffffff, #ffffff 25%, #e6e6e6);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#e6e6e6', GradientType=0);
text-shadow: 0 1px 1px rgba(255, 255, 255, 0.75);
color: #333;
border: 1px solid #ccc;
border-bottom-color: #bbb;
-webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);
-moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);
-webkit-transition: 0.1s linear all;
-moz-transition: 0.1s linear all;
-ms-transition: 0.1s linear all;
-o-transition: 0.1s linear all;
transition: 0.1s linear all;
}
/**********************************************************
* Fixed Header - http://www.imaputz.com/cssStuff/bigFourVersion.html
*********************************************************/
div.table-container {
overflow: auto;
}
/* Reset overflow value to hidden for all non-IE browsers. */
html>body div.table-container {
overflow: hidden;
}
thead.fixed-header tr {
overflow-x: hidden;
}
/* set table header to a fixed position. WinIE 6.x only */
/* In WinIE 6.x, any element with a position property set to relative and is a child of */
/* an element that has an overflow property set, the relative value translates into fixed. */
/* Ex: parent element DIV with a class of table-container has an overflow property set to auto */
thead.fixed-header tr {
position: relative
}
/* set THEAD element to have block level attributes. All other non-IE browsers */
/* this enables overflow to work on TBODY element. All other non-IE, non-Mozilla browsers */
html>body thead.fixed-header tr {
display: block
}
/* define the table content to be scrollable */
/* set TBODY element to have block level attributes. All other non-IE browsers */
/* this enables overflow to work on TBODY element. All other non-IE, non-Mozilla browsers */
/* induced side effect is that child TDs no longer accept width: auto */
tbody.scroll-content {
display: block;
max-height: 500px;
overflow: auto;
}
/**********************************************************
* Data Table Menus
*********************************************************/
.column-header-menu, a.root-header-menu {
float: right;
}
div.data-table-cell-content {
line-height: 1.2;
color: #222;
position: relative;
}
div.data-table-cell-content-numeric {
text-align: right;
}
a.data-table-cell-edit {
position: absolute;
top: 0;
right: 0;
display: block;
width: 25px;
height: 16px;
text-decoration: none;
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAQCAYAAABUWyyMAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMC1jMDYwIDYxLjEzNDc3NywgMjAxMC8wMi8xMi0xNzozMjowMCAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNSBNYWNpbnRvc2giIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6OTNEODNFMjVEMDA5MTFERjk5NzhEQzZDRDUwRkEzMUEiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6OTNEODNFMjZEMDA5MTFERjk5NzhEQzZDRDUwRkEzMUEiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDo5M0Q4M0UyM0QwMDkxMURGOTk3OERDNkNENTBGQTMxQSIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDo5M0Q4M0UyNEQwMDkxMURGOTk3OERDNkNENTBGQTMxQSIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PpApVmcAAAKVSURBVHjaYvz//z/DcAAsIGLaxjf2QKoLiM2oaPYpIC7L8hc5COI4F9+hmR17e1UOskAFVgCxBJUDyQxqriQ97GCCCpBkATCUGQxVOTHY7KyMDFoKHMhKJXCwCQJgKDNEOAlisHk5mRh8LPgw7GChNEg2HfvI8OnbPzDbwYAH6BkmhmsPflA12EtnPmN4/vY3mF0YKgb2zJYTn5CV/EfxiKgAC4O7CS8DHzczw5PXvxl2nv7E8PP3fxTx87e/o1hipMrFcOfZT6BmVgYZUTawmKUWN8Pxa1+xOkpNhp2hLk6CQVKYleHcrW8MTYteMHz+/g9FfMW+9yh6Ih0FGA5e/MLAAIx5IzUusFiqtzDD7K1vYUpcmZA1+FnxM7z++AccyqBkAgphmMPY2ZiAHvsMFkcGMkAPgMQ+ff3L8PPXPzD++O0vztDtypBmuPXkJziUebiYwSEMcxiID/IYiEYJLKDjQWLP3v1h+AI0G4RhMQQF5UzoDvr5CxIDoJhQlmKHy527/Y3hLjDkD4BCBgsAxSAoiYEwrqQFchAoWcBiAOQge30euBwoJkAh37/6FVb9oBgEeQCE0ZKWC8488vj1LzCmJTgLTKZn0ZIquYAJOURBsQDKB68//GHgYEWkOlBMgPICKIYcoCGIC4BiFRSDuEIUFBtSQizg5AWKHRgAxQSoZALFECy54QKgZAbLKxgegZVAfFxM4LyiLMUGTPeQ0ujAhS9gz7mb8sI9iisWQclSG7UIRgFlM56CM3R3uhTY0bC0DkpOtx//AGd4mEdxxSIoWaIVwQyMoCYKsGanWTsFWM8wQmt2mtkBqmdgMfKCRna8wMGmth2MMI/EAfEdKltwB2ouAz3sYBwurV8mhmECAAIMAEe3EkMWh/DvAAAAAElFTkSuQmCC);
background-repeat: no-repeat;
visibility: hidden;
}
a.data-table-cell-edit:hover {
background-position: -25px 0px;
}
.recline-grid td:hover .data-table-cell-edit {
visibility: visible;
}
div.data-table-cell-content-numeric > a.data-table-cell-edit {
left: 0px;
right: auto;
}
.data-table-value-nonstring {
color: #282;
}
.data-table-error {
color: red;
}
.data-table-cell-editor-editor {
overflow: hidden;
display: block;
width: 98%;
height: 3em;
font-family: monospace;
margin: 3px 0;
}
.data-table-cell-copypaste-editor {
overflow: hidden;
display: block;
width: 98%;
height: 10em;
font-family: monospace;
margin: 3px 0;
}
.data-table-cell-editor-action {
float: left;
vertical-align: bottom;
text-align: center;
}
.data-table-cell-editor-key {
font-size: 0.8em;
color: #999;
}
/**********************************************************
* Read-only mode
*********************************************************/
.recline-read-only .recline-grid .write-op,
.recline-read-only .recline-grid a.data-table-cell-edit
{
display: none;
}
.recline-read-only a.row-header-menu {
display: none;
}
.recline-map .map {
height: 500px;
}
/**********************************************************
* Editor
*********************************************************/
.recline-map .editor {
float: right;
width: 200px;
padding-left: 0px;
margin-left: 10px;
}
.recline-map .editor form {
padding-left: 4px;
}
.recline-map .editor select {
width: 100%;
}
.recline-map .editor .editor-options {
margin-top: 10px;
border-top: 1px solid gray;
padding: 5px 0;
}
.recline-data-explorer .data-view-container {
display: block;
}
.recline-data-explorer .data-view-sidebar {
float: right;
margin-left: 8px;
width: 220px;
}
.recline-data-explorer .header .navigation {
margin-bottom: 8px;
}
.recline-data-explorer .header .navigation,
.recline-data-explorer .header .pagination,
.recline-data-explorer .header .pagination form
{
display: inline;
}
.recline-data-explorer .header .navigation {
float: left;
}
.recline-data-explorer .header .menu-right {
float: right;
margin-left: 5px;
padding-left: 5px;
border-left: solid 2px #ddd;
}
.header .recline-results-info {
line-height: 28px;
margin-left: 20px;
float: left;
}
/**********************************************************
* Query Editor
*********************************************************/
.header .recline-query-editor {
float: right;
height: 30px;
}
.header .input-prepend {
margin-bottom: auto;
}
.header .add-on {
float: left;
}
/* needed for Chrome but not FF */
.header .add-on {
margin-left: -27px;
}
/* needed for FF but not chrome */
.header .input-prepend {
vertical-align: top;
}
.header .recline-query-editor form button {
vertical-align: top;
}
.header .recline-query-editor label {
display:none;
}
/**********************************************************
* Pager
*********************************************************/
.header .recline-pager {
float: left;
margin: auto;
display: block;
margin-left: 20px;
}
.header .recline-pager .pagination label {
display:none;
}
.header .recline-pager .pagination input {
width: 30px;
height: 18px;
padding: 2px 4px;
margin: 0;
margin-top: -4px;
}
.header .recline-pager .pagination a {
line-height: 26px;
padding: 0 6px;
}
/**********************************************************
* Filter Editor
*********************************************************/
.recline-filter-editor {
padding: 8px;
display: none;
}
.recline-filter-editor .filter-term a {
font-size: 18px;
}
.recline-filter-editor input,
.recline-filter-editor select
{
width: 175px;
}
.recline-filter-editor input {
margin-top: 0.5em;
}
.recline-filter-editor .add-filter {
margin-top: 1em;
margin-bottom: 2em;
}
.recline-filter-editor .update-filter {
margin-top: 1em;
}
/**********************************************************
* Fields Widget
*********************************************************/
.recline-fields-view {
display: none;
}
.recline-fields-view .fields-list {
padding: 0;
}
.recline-fields-view .fields-list .accordion-heading,
.recline-fields-view .fields-list h3
{
margin: 3px 0 3px 5px;
}
.recline-fields-view .fields-list .accordion-heading a,
.recline-fields-view .fields-list .accordion-heading h4 {
display: inline;
}
.recline-fields-view .fields-list .accordion-heading a {
padding: 0;
}
.recline-fields-view .fields-list .accordion-heading h4 {
word-wrap: break-word
}
.recline-fields-view .clear {
clear: both;
}
.recline-fields-view .facet-items {
list-style-type: none;
margin-left: 0;
}
.recline-fields-view .facet-item .term {
font-weight: bold;
}
.recline-fields-view .facet-item .count {
}
/**********************************************************
* Notifications
*********************************************************/
.recline-data-explorer .notification-loader {
width: 18px;
margin-left: 5px;
background-image: url(data:image/gif;base64,R0lGODlhEAAQAPQAAP///wAAAPDw8IqKiuDg4EZGRnp6egAAAFhYWCQkJKysrL6+vhQUFJycnAQEBDY2NmhoaAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH/C05FVFNDQVBFMi4wAwEAAAAh/hpDcmVhdGVkIHdpdGggYWpheGxvYWQuaW5mbwAh+QQJCgAAACwAAAAAEAAQAAAFdyAgAgIJIeWoAkRCCMdBkKtIHIngyMKsErPBYbADpkSCwhDmQCBethRB6Vj4kFCkQPG4IlWDgrNRIwnO4UKBXDufzQvDMaoSDBgFb886MiQadgNABAokfCwzBA8LCg0Egl8jAggGAA1kBIA1BAYzlyILczULC2UhACH5BAkKAAAALAAAAAAQABAAAAV2ICACAmlAZTmOREEIyUEQjLKKxPHADhEvqxlgcGgkGI1DYSVAIAWMx+lwSKkICJ0QsHi9RgKBwnVTiRQQgwF4I4UFDQQEwi6/3YSGWRRmjhEETAJfIgMFCnAKM0KDV4EEEAQLiF18TAYNXDaSe3x6mjidN1s3IQAh+QQJCgAAACwAAAAAEAAQAAAFeCAgAgLZDGU5jgRECEUiCI+yioSDwDJyLKsXoHFQxBSHAoAAFBhqtMJg8DgQBgfrEsJAEAg4YhZIEiwgKtHiMBgtpg3wbUZXGO7kOb1MUKRFMysCChAoggJCIg0GC2aNe4gqQldfL4l/Ag1AXySJgn5LcoE3QXI3IQAh+QQJCgAAACwAAAAAEAAQAAAFdiAgAgLZNGU5joQhCEjxIssqEo8bC9BRjy9Ag7GILQ4QEoE0gBAEBcOpcBA0DoxSK/e8LRIHn+i1cK0IyKdg0VAoljYIg+GgnRrwVS/8IAkICyosBIQpBAMoKy9dImxPhS+GKkFrkX+TigtLlIyKXUF+NjagNiEAIfkECQoAAAAsAAAAABAAEAAABWwgIAICaRhlOY4EIgjH8R7LKhKHGwsMvb4AAy3WODBIBBKCsYA9TjuhDNDKEVSERezQEL0WrhXucRUQGuik7bFlngzqVW9LMl9XWvLdjFaJtDFqZ1cEZUB0dUgvL3dgP4WJZn4jkomWNpSTIyEAIfkECQoAAAAsAAAAABAAEAAABX4gIAICuSxlOY6CIgiD8RrEKgqGOwxwUrMlAoSwIzAGpJpgoSDAGifDY5kopBYDlEpAQBwevxfBtRIUGi8xwWkDNBCIwmC9Vq0aiQQDQuK+VgQPDXV9hCJjBwcFYU5pLwwHXQcMKSmNLQcIAExlbH8JBwttaX0ABAcNbWVbKyEAIfkECQoAAAAsAAAAABAAEAAABXkgIAICSRBlOY7CIghN8zbEKsKoIjdFzZaEgUBHKChMJtRwcWpAWoWnifm6ESAMhO8lQK0EEAV3rFopIBCEcGwDKAqPh4HUrY4ICHH1dSoTFgcHUiZjBhAJB2AHDykpKAwHAwdzf19KkASIPl9cDgcnDkdtNwiMJCshACH5BAkKAAAALAAAAAAQABAAAAV3ICACAkkQZTmOAiosiyAoxCq+KPxCNVsSMRgBsiClWrLTSWFoIQZHl6pleBh6suxKMIhlvzbAwkBWfFWrBQTxNLq2RG2yhSUkDs2b63AYDAoJXAcFRwADeAkJDX0AQCsEfAQMDAIPBz0rCgcxky0JRWE1AmwpKyEAIfkECQoAAAAsAAAAABAAEAAABXkgIAICKZzkqJ4nQZxLqZKv4NqNLKK2/Q4Ek4lFXChsg5ypJjs1II3gEDUSRInEGYAw6B6zM4JhrDAtEosVkLUtHA7RHaHAGJQEjsODcEg0FBAFVgkQJQ1pAwcDDw8KcFtSInwJAowCCA6RIwqZAgkPNgVpWndjdyohACH5BAkKAAAALAAAAAAQABAAAAV5ICACAimc5KieLEuUKvm2xAKLqDCfC2GaO9eL0LABWTiBYmA06W6kHgvCqEJiAIJiu3gcvgUsscHUERm+kaCxyxa+zRPk0SgJEgfIvbAdIAQLCAYlCj4DBw0IBQsMCjIqBAcPAooCBg9pKgsJLwUFOhCZKyQDA3YqIQAh+QQJCgAAACwAAAAAEAAQAAAFdSAgAgIpnOSonmxbqiThCrJKEHFbo8JxDDOZYFFb+A41E4H4OhkOipXwBElYITDAckFEOBgMQ3arkMkUBdxIUGZpEb7kaQBRlASPg0FQQHAbEEMGDSVEAA1QBhAED1E0NgwFAooCDWljaQIQCE5qMHcNhCkjIQAh+QQJCgAAACwAAAAAEAAQAAAFeSAgAgIpnOSoLgxxvqgKLEcCC65KEAByKK8cSpA4DAiHQ/DkKhGKh4ZCtCyZGo6F6iYYPAqFgYy02xkSaLEMV34tELyRYNEsCQyHlvWkGCzsPgMCEAY7Cg04Uk48LAsDhRA8MVQPEF0GAgqYYwSRlycNcWskCkApIyEAOwAAAAAAAAAAAA%3D%3D);
display: inline-block;
}
.recline-data-explorer .alert-loader {
position: absolute;
width: 200px;
left: 50%;
margin-left: -100px;
z-index: 10000;
padding: 40px 0px 40px 0px;
margin-top: -10px;
text-align: center;
font-size: 16px;
font-weight: bold;
-webkit-border-radius: 0px;
-moz-border-radius: 0px;
border-radius: 0px;
border-top: none;
}
/*
IMPORTANT:
In order to preserve the uniform grid appearance, all cell styles need to have padding, margin and border sizes.
No built-in (selected, editable, highlight, flashing, invalid, loading, :focus) or user-specified CSS
classes should alter those!
*/
.recline-slickgrid .slick-header-columns .slick-header-column {
background-color: #e6e6e6;
background-repeat: no-repeat;
background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), color-stop(25%, #ffffff), to(#e6e6e6));
background-image: -webkit-linear-gradient(#ffffff, #ffffff 25%, #e6e6e6);
background-image: -moz-linear-gradient(top, #ffffff, #ffffff 25%, #e6e6e6);
background-image: -ms-linear-gradient(#ffffff, #ffffff 25%, #e6e6e6);
background-image: -o-linear-gradient(#ffffff, #ffffff 25%, #e6e6e6);
background-image: linear-gradient(#ffffff, #ffffff 25%, #e6e6e6);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#e6e6e6', GradientType=0);
text-shadow: 0 1px 1px rgba(255, 255, 255, 0.75);
color: #333;
font-weight: bold;
border-right: 1px solid #ccc;
border-top: 1px solid #ccc;
border-bottom: 1px solid #bbb;
-webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);
-moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);
}
.recline-slickgrid .slick-header-column:hover, .slick-header-column-active {
}
.recline-slickgrid .slick-headerrow {
background: #fafafa;
}
.recline-slickgrid .slick-headerrow-column {
background: #fafafa;
border-bottom: 0;
height: 100%;
}
.recline-slickgrid .slick-row.ui-state-active {
background: #F5F7D7;
}
.recline-slickgrid .slick-row {
position: absolute;
background: white;
border: 0px;
line-height: 20px;
}
.recline-slickgrid .slick-row.selected {
z-index: 10;
background: #DFE8F6;
}
.recline-slickgrid .slick-cell {
padding-left: 4px;
padding-right: 4px;
}
.recline-slickgrid .slick-group {
border-bottom: 2px solid silver;
}
.recline-slickgrid .slick-group-toggle {
width: 9px;
height: 9px;
margin-right: 5px;
}
.recline-slickgrid .slick-group-toggle.expanded {
background: url(../images/collapse.gif) no-repeat center center;
}
.recline-slickgrid .slick-group-toggle.collapsed {
background: url(../images/expand.gif) no-repeat center center;
}
.recline-slickgrid .slick-group-totals {
color: gray;
background: white;
}
.recline-slickgrid .slick-cell.selected {
background-color: beige;
}
.recline-slickgrid .slick-cell.active {
border-color: gray;
border-style: solid;
}
.recline-slickgrid .slick-sortable-placeholder {
background: silver !important;
}
.recline-slickgrid .slick-row[row$="1"], .slick-row[row$="3"], .slick-row[row$="5"], .slick-row[row$="7"], .slick-row[row$="9"] {
background: #fafafa;
}
.recline-slickgrid .slick-row.ui-state-active {
background: #F5F7D7;
}
.recline-slickgrid .slick-row.loading {
opacity: 0.5;
filter: alpha(opacity = 50);
}
.recline-slickgrid .slick-cell.invalid {
border-color: red;
}
.recline-slickgrid .slick-row .slick-cell:first-child,
.recline-slickgrid .slick-header {
border-left: 1px solid #ccc;
}
/* add one pixel extra as added one pixel to left border of header */
.recline-slickgrid .slick-row .slick-cell {
margin-right: -1px;
}
/* Slick grid context menu (not part of the recline-slickgrid div) */
.slick-contextmenu {
border-radius: 5px
}
.slick-contextmenu li {
clear: both;
height: 24px;
cursor: pointer;
}
.slick-contextmenu .divider {
cursor: default;
}
.slick-contextmenu > li:hover {
background-color: #0088cc;
}
.slick-contextmenu .divider:hover {
background-color: #E5E5E5;
}
.slick-contextmenu li:hover > label {
color: white;
}
.slick-contextmenu input {
float: left;
margin-left: 15px;
margin-top: 5px;
}
.slick-contextmenu label {
float: left;
margin-right: 15px;
margin-left: 5px;
margin-top: 3px;
color: #555;
cursor: pointer;
}
.recline-slickgrid .recline-row-delete {
font-size: 12px;
padding: 2px;
width: 22px;
height: 14px;
line-height: 13px;
}
.recline-cell-reorder {
font-size: 12px;
padding: 2px;
width: 22px;
height: 14px;
line-height: 13px;
cursor: move;
background: url("../images/drag-handle.png") no-repeat center center;
}
.recline-timeline {
position: relative;
}

View File

@ -0,0 +1,896 @@
// # Recline Backbone Models
this.recline = this.recline || {};
this.recline.Model = this.recline.Model || {};
(function(my) {
"use strict";
// use either jQuery or Underscore Deferred depending on what is available
var Deferred = (typeof jQuery !== "undefined" && jQuery.Deferred) || _.Deferred;
// ## <a id="dataset">Dataset</a>
my.Dataset = Backbone.Model.extend({
constructor: function Dataset() {
Backbone.Model.prototype.constructor.apply(this, arguments);
},
// ### initialize
initialize: function() {
var self = this;
_.bindAll(this, 'query');
this.backend = null;
if (this.get('backend')) {
this.backend = this._backendFromString(this.get('backend'));
} else { // try to guess backend ...
if (this.get('records')) {
this.backend = recline.Backend.Memory;
}
}
this.fields = new my.FieldList();
this.records = new my.RecordList();
this._changes = {
deletes: [],
updates: [],
creates: []
};
this.facets = new my.FacetList();
this.recordCount = null;
this.queryState = new my.Query();
this.queryState.bind('change facet:add', function () {
self.query(); // We want to call query() without any arguments.
});
// store is what we query and save against
// store will either be the backend or be a memory store if Backend fetch
// tells us to use memory store
this._store = this.backend;
// if backend has a handleQueryResultFunction, use that
this._handleResult = (this.backend != null && _.has(this.backend, 'handleQueryResult')) ?
this.backend.handleQueryResult : this._handleQueryResult;
if (this.backend == recline.Backend.Memory) {
this.fetch();
}
},
sync: function(method, model, options) {
return this.backend.sync(method, model, options);
},
// ### fetch
//
// Retrieve dataset and (some) records from the backend.
fetch: function() {
var self = this;
var dfd = new Deferred();
if (this.backend !== recline.Backend.Memory) {
this.backend.fetch(this.toJSON())
.done(handleResults)
.fail(function(args) {
dfd.reject(args);
});
} else {
// special case where we have been given data directly
handleResults({
records: this.get('records'),
fields: this.get('fields'),
useMemoryStore: true
});
}
function handleResults(results) {
// if explicitly given the fields
// (e.g. var dataset = new Dataset({fields: fields, ...})
// use that field info over anything we get back by parsing the data
// (results.fields)
var fields = self.get('fields') || results.fields;
var out = self._normalizeRecordsAndFields(results.records, fields);
if (results.useMemoryStore) {
self._store = new recline.Backend.Memory.Store(out.records, out.fields);
}
self.set(results.metadata);
self.fields.reset(out.fields);
self.query()
.done(function() {
dfd.resolve(self);
})
.fail(function(args) {
dfd.reject(args);
});
}
return dfd.promise();
},
// ### _normalizeRecordsAndFields
//
// Get a proper set of fields and records from incoming set of fields and records either of which may be null or arrays or objects
//
// e.g. fields = ['a', 'b', 'c'] and records = [ [1,2,3] ] =>
// fields = [ {id: a}, {id: b}, {id: c}], records = [ {a: 1}, {b: 2}, {c: 3}]
_normalizeRecordsAndFields: function(records, fields) {
// if no fields get them from records
if (!fields && records && records.length > 0) {
// records is array then fields is first row of records ...
if (records[0] instanceof Array) {
fields = records[0];
records = records.slice(1);
} else {
fields = _.map(_.keys(records[0]), function(key) {
return {id: key};
});
}
}
// fields is an array of strings (i.e. list of field headings/ids)
if (fields && fields.length > 0 && (fields[0] === null || typeof(fields[0]) != 'object')) {
// Rename duplicate fieldIds as each field name needs to be
// unique.
var seen = {};
fields = _.map(fields, function(field, index) {
if (field === null) {
field = '';
} else {
field = field.toString();
}
// cannot use trim as not supported by IE7
var fieldId = field.replace(/^\s+|\s+$/g, '');
if (fieldId === '') {
fieldId = '_noname_';
field = fieldId;
}
while (fieldId in seen) {
seen[field] += 1;
fieldId = field + seen[field];
}
if (!(field in seen)) {
seen[field] = 0;
}
// TODO: decide whether to keep original name as label ...
// return { id: fieldId, label: field || fieldId }
return { id: fieldId };
});
}
// records is provided as arrays so need to zip together with fields
// NB: this requires you to have fields to match arrays
if (records && records.length > 0 && records[0] instanceof Array) {
records = _.map(records, function(doc) {
var tmp = {};
_.each(fields, function(field, idx) {
tmp[field.id] = doc[idx];
});
return tmp;
});
}
return {
fields: fields,
records: records
};
},
save: function() {
var self = this;
// TODO: need to reset the changes ...
return this._store.save(this._changes, this.toJSON());
},
// ### query
//
// AJAX method with promise API to get records from the backend.
//
// It will query based on current query state (given by this.queryState)
// updated by queryObj (if provided).
//
// Resulting RecordList are used to reset this.records and are
// also returned.
query: function(queryObj) {
var self = this;
var dfd = new Deferred();
this.trigger('query:start');
if (queryObj) {
var attributes = queryObj;
if (queryObj instanceof my.Query) {
attributes = queryObj.toJSON();
}
this.queryState.set(attributes, {silent: true});
}
var actualQuery = this.queryState.toJSON();
this._store.query(actualQuery, this.toJSON())
.done(function(queryResult) {
self._handleResult(queryResult);
self.trigger('query:done');
dfd.resolve(self.records);
})
.fail(function(args) {
self.trigger('query:fail', args);
dfd.reject(args);
});
return dfd.promise();
},
_handleQueryResult: function(queryResult) {
var self = this;
self.recordCount = queryResult.total;
var docs = _.map(queryResult.hits, function(hit) {
var _doc = new my.Record(hit);
_doc.fields = self.fields;
_doc.bind('change', function(doc) {
self._changes.updates.push(doc.toJSON());
});
_doc.bind('destroy', function(doc) {
self._changes.deletes.push(doc.toJSON());
});
return _doc;
});
self.records.reset(docs);
if (queryResult.facets) {
var facets = _.map(queryResult.facets, function(facetResult, facetId) {
facetResult.id = facetId;
return new my.Facet(facetResult);
});
self.facets.reset(facets);
}
},
toTemplateJSON: function() {
var data = this.toJSON();
data.recordCount = this.recordCount;
data.fields = this.fields.toJSON();
return data;
},
// ### getFieldsSummary
//
// Get a summary for each field in the form of a `Facet`.
//
// @return null as this is async function. Provides deferred/promise interface.
getFieldsSummary: function() {
var self = this;
var query = new my.Query();
query.set({size: 0});
this.fields.each(function(field) {
query.addFacet(field.id);
});
var dfd = new Deferred();
this._store.query(query.toJSON(), this.toJSON()).done(function(queryResult) {
if (queryResult.facets) {
_.each(queryResult.facets, function(facetResult, facetId) {
facetResult.id = facetId;
var facet = new my.Facet(facetResult);
// TODO: probably want replace rather than reset (i.e. just replace the facet with this id)
self.fields.get(facetId).facets.reset(facet);
});
}
dfd.resolve(queryResult);
});
return dfd.promise();
},
// Deprecated (as of v0.5) - use record.summary()
recordSummary: function(record) {
return record.summary();
},
// ### _backendFromString(backendString)
//
// Look up a backend module from a backend string (look in recline.Backend)
_backendFromString: function(backendString) {
var backend = null;
if (recline && recline.Backend) {
_.each(_.keys(recline.Backend), function(name) {
if (name.toLowerCase() === backendString.toLowerCase()) {
backend = recline.Backend[name];
}
});
}
return backend;
}
});
// ## <a id="record">A Record</a>
//
// A single record (or row) in the dataset
my.Record = Backbone.Model.extend({
constructor: function Record() {
Backbone.Model.prototype.constructor.apply(this, arguments);
},
// ### initialize
//
// Create a Record
//
// You usually will not do this directly but will have records created by
// Dataset e.g. in query method
//
// Certain methods require presence of a fields attribute (identical to that on Dataset)
initialize: function() {
_.bindAll(this, 'getFieldValue');
},
// ### getFieldValue
//
// For the provided Field get the corresponding rendered computed data value
// for this record.
//
// NB: if field is undefined a default '' value will be returned
getFieldValue: function(field) {
var val = this.getFieldValueUnrendered(field);
if (field && !_.isUndefined(field.renderer)) {
val = field.renderer(val, field, this.toJSON());
}
return val;
},
// ### getFieldValueUnrendered
//
// For the provided Field get the corresponding computed data value
// for this record.
//
// NB: if field is undefined a default '' value will be returned
getFieldValueUnrendered: function(field) {
if (!field) {
return '';
}
var val = this.get(field.id);
if (field.deriver) {
val = field.deriver(val, field, this);
}
return val;
},
// ### summary
//
// Get a simple html summary of this record in form of key/value list
summary: function(record) {
var self = this;
var html = '<div class="recline-record-summary">';
this.fields.each(function(field) {
if (field.id != 'id') {
html += '<div class="' + field.id + '"><strong>' + field.get('label') + '</strong>: ' + self.getFieldValue(field) + '</div>';
}
});
html += '</div>';
return html;
},
// Override Backbone save, fetch and destroy so they do nothing
// Instead, Dataset object that created this Record should take care of
// handling these changes (discovery will occur via event notifications)
// WARNING: these will not persist *unless* you call save on Dataset
fetch: function() {},
save: function() {},
destroy: function() { this.trigger('destroy', this); }
});
// ## A Backbone collection of Records
my.RecordList = Backbone.Collection.extend({
constructor: function RecordList() {
Backbone.Collection.prototype.constructor.apply(this, arguments);
},
model: my.Record
});
// ## <a id="field">A Field (aka Column) on a Dataset</a>
my.Field = Backbone.Model.extend({
constructor: function Field() {
Backbone.Model.prototype.constructor.apply(this, arguments);
},
// ### defaults - define default values
defaults: {
label: null,
type: 'string',
format: null,
is_derived: false
},
// ### initialize
//
// @param {Object} data: standard Backbone model attributes
//
// @param {Object} options: renderer and/or deriver functions.
initialize: function(data, options) {
// if a hash not passed in the first argument throw error
if ('0' in data) {
throw new Error('Looks like you did not pass a proper hash with id to Field constructor');
}
if (this.attributes.label === null) {
this.set({label: this.id});
}
if (this.attributes.type.toLowerCase() in this._typeMap) {
this.attributes.type = this._typeMap[this.attributes.type.toLowerCase()];
}
if (options) {
this.renderer = options.renderer;
this.deriver = options.deriver;
}
if (!this.renderer) {
this.renderer = this.defaultRenderers[this.get('type')];
}
this.facets = new my.FacetList();
},
_typeMap: {
'text': 'string',
'double': 'number',
'float': 'number',
'numeric': 'number',
'int': 'integer',
'datetime': 'date-time',
'bool': 'boolean',
'timestamp': 'date-time',
'json': 'object'
},
defaultRenderers: {
object: function(val, field, doc) {
return JSON.stringify(val);
},
geo_point: function(val, field, doc) {
return JSON.stringify(val);
},
'number': function(val, field, doc) {
var format = field.get('format');
if (format === 'percentage') {
return val + '%';
}
return val;
},
'string': function(val, field, doc) {
var format = field.get('format');
if (format === 'markdown') {
if (typeof Showdown !== 'undefined') {
var showdown = new Showdown.converter();
out = showdown.makeHtml(val);
return out;
} else {
return val;
}
} else if (format == 'plain') {
return val;
} else {
// as this is the default and default type is string may get things
// here that are not actually strings
if (val && typeof val === 'string') {
val = val.replace(/(https?:\/\/[^ ]+)/g, '<a href="$1">$1</a>');
}
return val;
}
}
}
});
my.FieldList = Backbone.Collection.extend({
constructor: function FieldList() {
Backbone.Collection.prototype.constructor.apply(this, arguments);
},
model: my.Field
});
// ## <a id="query">Query</a>
my.Query = Backbone.Model.extend({
constructor: function Query() {
Backbone.Model.prototype.constructor.apply(this, arguments);
},
defaults: function() {
return {
size: 100,
from: 0,
q: '',
facets: {},
filters: []
};
},
_filterTemplates: {
term: {
type: 'term',
// TODO do we need this attribute here?
field: '',
term: ''
},
range: {
type: 'range',
from: '',
to: ''
},
geo_distance: {
type: 'geo_distance',
distance: 10,
unit: 'km',
point: {
lon: 0,
lat: 0
}
}
},
// ### addFilter(filter)
//
// Add a new filter specified by the filter hash and append to the list of filters
//
// @param filter an object specifying the filter - see _filterTemplates for examples. If only type is provided will generate a filter by cloning _filterTemplates
addFilter: function(filter) {
// crude deep copy
var ourfilter = JSON.parse(JSON.stringify(filter));
// not fully specified so use template and over-write
if (_.keys(filter).length <= 3) {
ourfilter = _.defaults(ourfilter, this._filterTemplates[filter.type]);
}
var filters = this.get('filters');
filters.push(ourfilter);
this.trigger('change:filters:new-blank');
},
replaceFilter: function(filter) {
// delete filter on the same field, then add
var filters = this.get('filters');
var idx = -1;
_.each(this.get('filters'), function(f, key, list) {
if (filter.field == f.field) {
idx = key;
}
});
// trigger just one event (change:filters:new-blank) instead of one for remove and
// one for add
if (idx >= 0) {
filters.splice(idx, 1);
this.set({filters: filters});
}
this.addFilter(filter);
},
updateFilter: function(index, value) {
},
// ### removeFilter
//
// Remove a filter from filters at index filterIndex
removeFilter: function(filterIndex) {
var filters = this.get('filters');
filters.splice(filterIndex, 1);
this.set({filters: filters});
this.trigger('change');
},
// ### addFacet
//
// Add a Facet to this query
//
// See <http://www.elasticsearch.org/guide/reference/api/search/facets/>
addFacet: function(fieldId, size, silent) {
var facets = this.get('facets');
// Assume id and fieldId should be the same (TODO: this need not be true if we want to add two different type of facets on same field)
if (_.contains(_.keys(facets), fieldId)) {
return;
}
facets[fieldId] = {
terms: { field: fieldId }
};
if (!_.isUndefined(size)) {
facets[fieldId].terms.size = size;
}
this.set({facets: facets}, {silent: true});
if (!silent) {
this.trigger('facet:add', this);
}
},
addHistogramFacet: function(fieldId) {
var facets = this.get('facets');
facets[fieldId] = {
date_histogram: {
field: fieldId,
interval: 'day'
}
};
this.set({facets: facets}, {silent: true});
this.trigger('facet:add', this);
},
removeFacet: function(fieldId) {
var facets = this.get('facets');
// Assume id and fieldId should be the same (TODO: this need not be true if we want to add two different type of facets on same field)
if (!_.contains(_.keys(facets), fieldId)) {
return;
}
delete facets[fieldId];
this.set({facets: facets}, {silent: true});
this.trigger('facet:remove', this);
},
clearFacets: function() {
var facets = this.get('facets');
_.each(_.keys(facets), function(fieldId) {
delete facets[fieldId];
});
this.trigger('facet:remove', this);
},
// trigger a facet add; use this to trigger a single event after adding
// multiple facets
refreshFacets: function() {
this.trigger('facet:add', this);
}
});
// ## <a id="facet">A Facet (Result)</a>
my.Facet = Backbone.Model.extend({
constructor: function Facet() {
Backbone.Model.prototype.constructor.apply(this, arguments);
},
defaults: function() {
return {
_type: 'terms',
total: 0,
other: 0,
missing: 0,
terms: []
};
}
});
// ## A Collection/List of Facets
my.FacetList = Backbone.Collection.extend({
constructor: function FacetList() {
Backbone.Collection.prototype.constructor.apply(this, arguments);
},
model: my.Facet
});
// ## Object State
//
// Convenience Backbone model for storing (configuration) state of objects like Views.
my.ObjectState = Backbone.Model.extend({
});
// ## Backbone.sync
//
// Override Backbone.sync to hand off to sync function in relevant backend
// Backbone.sync = function(method, model, options) {
// return model.backend.sync(method, model, options);
// };
}(this.recline.Model));
this.recline = this.recline || {};
this.recline.Backend = this.recline.Backend || {};
this.recline.Backend.Memory = this.recline.Backend.Memory || {};
(function(my) {
"use strict";
my.__type__ = 'memory';
// private data - use either jQuery or Underscore Deferred depending on what is available
var Deferred = (typeof jQuery !== "undefined" && jQuery.Deferred) || _.Deferred;
// ## Data Wrapper
//
// Turn a simple array of JS objects into a mini data-store with
// functionality like querying, faceting, updating (by ID) and deleting (by
// ID).
//
// @param records list of hashes for each record/row in the data ({key:
// value, key: value})
// @param fields (optional) list of field hashes (each hash defining a field
// as per recline.Model.Field). If fields not specified they will be taken
// from the data.
my.Store = function(records, fields) {
var self = this;
this.records = records;
// backwards compatability (in v0.5 records was named data)
this.data = this.records;
if (fields) {
this.fields = fields;
} else {
if (records) {
this.fields = _.map(records[0], function(value, key) {
return {id: key, type: 'string'};
});
}
}
this.update = function(doc) {
_.each(self.records, function(internalDoc, idx) {
if(doc.id === internalDoc.id) {
self.records[idx] = doc;
}
});
};
this.remove = function(doc) {
var newdocs = _.reject(self.records, function(internalDoc) {
return (doc.id === internalDoc.id);
});
this.records = newdocs;
};
this.save = function(changes, dataset) {
var self = this;
var dfd = new Deferred();
// TODO _.each(changes.creates) { ... }
_.each(changes.updates, function(record) {
self.update(record);
});
_.each(changes.deletes, function(record) {
self.remove(record);
});
dfd.resolve();
return dfd.promise();
},
this.query = function(queryObj) {
var dfd = new Deferred();
var numRows = queryObj.size || this.records.length;
var start = queryObj.from || 0;
var results = this.records;
results = this._applyFilters(results, queryObj);
results = this._applyFreeTextQuery(results, queryObj);
// TODO: this is not complete sorting!
// What's wrong is we sort on the *last* entry in the sort list if there are multiple sort criteria
_.each(queryObj.sort, function(sortObj) {
var fieldName = sortObj.field;
results = _.sortBy(results, function(doc) {
var _out = doc[fieldName];
return _out;
});
if (sortObj.order == 'desc') {
results.reverse();
}
});
var facets = this.computeFacets(results, queryObj);
var out = {
total: results.length,
hits: results.slice(start, start+numRows),
facets: facets
};
dfd.resolve(out);
return dfd.promise();
};
// in place filtering
this._applyFilters = function(results, queryObj) {
var filters = queryObj.filters;
// register filters
var filterFunctions = {
term : term,
terms : terms,
range : range,
geo_distance : geo_distance
};
var dataParsers = {
integer: function (e) { return parseFloat(e, 10); },
'float': function (e) { return parseFloat(e, 10); },
number: function (e) { return parseFloat(e, 10); },
string : function (e) { return e.toString(); },
date : function (e) { return moment(e).valueOf(); },
datetime : function (e) { return new Date(e).valueOf(); }
};
var keyedFields = {};
_.each(self.fields, function(field) {
keyedFields[field.id] = field;
});
function getDataParser(filter) {
var fieldType = keyedFields[filter.field].type || 'string';
return dataParsers[fieldType];
}
// filter records
return _.filter(results, function (record) {
var passes = _.map(filters, function (filter) {
return filterFunctions[filter.type](record, filter);
});
// return only these records that pass all filters
return _.all(passes, _.identity);
});
// filters definitions
function term(record, filter) {
var parse = getDataParser(filter);
var value = parse(record[filter.field]);
var term = parse(filter.term);
return (value === term);
}
function terms(record, filter) {
var parse = getDataParser(filter);
var value = parse(record[filter.field]);
var terms = parse(filter.terms).split(",");
return (_.indexOf(terms, value) >= 0);
}
function range(record, filter) {
var fromnull = (_.isUndefined(filter.from) || filter.from === null || filter.from === '');
var tonull = (_.isUndefined(filter.to) || filter.to === null || filter.to === '');
var parse = getDataParser(filter);
var value = parse(record[filter.field]);
var from = parse(fromnull ? '' : filter.from);
var to = parse(tonull ? '' : filter.to);
// if at least one end of range is set do not allow '' to get through
// note that for strings '' <= {any-character} e.g. '' <= 'a'
if ((!fromnull || !tonull) && value === '') {
return false;
}
return ((fromnull || value >= from) && (tonull || value <= to));
}
function geo_distance() {
// TODO code here
}
};
// we OR across fields but AND across terms in query string
this._applyFreeTextQuery = function(results, queryObj) {
if (queryObj.q) {
var terms = queryObj.q.split(' ');
var patterns=_.map(terms, function(term) {
return new RegExp(term.toLowerCase());
});
results = _.filter(results, function(rawdoc) {
var matches = true;
_.each(patterns, function(pattern) {
var foundmatch = false;
_.each(self.fields, function(field) {
var value = rawdoc[field.id];
if ((value !== null) && (value !== undefined)) {
value = value.toString();
} else {
// value can be null (apparently in some cases)
value = '';
}
// TODO regexes?
foundmatch = foundmatch || (pattern.test(value.toLowerCase()));
// TODO: early out (once we are true should break to spare unnecessary testing)
// if (foundmatch) return true;
});
matches = matches && foundmatch;
// TODO: early out (once false should break to spare unnecessary testing)
// if (!matches) return false;
});
return matches;
});
}
return results;
};
this.computeFacets = function(records, queryObj) {
var facetResults = {};
if (!queryObj.facets) {
return facetResults;
}
_.each(queryObj.facets, function(query, facetId) {
// TODO: remove dependency on recline.Model
facetResults[facetId] = new recline.Model.Facet({id: facetId}).toJSON();
facetResults[facetId].termsall = {};
});
// faceting
_.each(records, function(doc) {
_.each(queryObj.facets, function(query, facetId) {
var fieldId = query.terms.field;
var val = doc[fieldId];
var tmp = facetResults[facetId];
if (val) {
tmp.termsall[val] = tmp.termsall[val] ? tmp.termsall[val] + 1 : 1;
} else {
tmp.missing = tmp.missing + 1;
}
});
});
_.each(queryObj.facets, function(query, facetId) {
var tmp = facetResults[facetId];
var terms = _.map(tmp.termsall, function(count, term) {
return { term: term, count: count };
});
tmp.terms = _.sortBy(terms, function(item) {
// want descending order
return -item.count;
});
tmp.terms = tmp.terms.slice(0, 10);
});
return facetResults;
};
};
}(this.recline.Backend.Memory));

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,188 @@
/*
IMPORTANT:
In order to preserve the uniform grid appearance, all cell styles need to have padding, margin and border sizes.
No built-in (selected, editable, highlight, flashing, invalid, loading, :focus) or user-specified CSS
classes should alter those!
*/
.recline-slickgrid .slick-header-columns .slick-header-column {
background-color: #e6e6e6;
background-repeat: no-repeat;
background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), color-stop(25%, #ffffff), to(#e6e6e6));
background-image: -webkit-linear-gradient(#ffffff, #ffffff 25%, #e6e6e6);
background-image: -moz-linear-gradient(top, #ffffff, #ffffff 25%, #e6e6e6);
background-image: -ms-linear-gradient(#ffffff, #ffffff 25%, #e6e6e6);
background-image: -o-linear-gradient(#ffffff, #ffffff 25%, #e6e6e6);
background-image: linear-gradient(#ffffff, #ffffff 25%, #e6e6e6);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#e6e6e6', GradientType=0);
text-shadow: 0 1px 1px rgba(255, 255, 255, 0.75);
color: #333;
font-weight: bold;
border-right: 1px solid #ccc;
border-top: 1px solid #ccc;
border-bottom: 1px solid #bbb;
-webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);
-moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);
}
.recline-slickgrid .slick-header-column:hover, .slick-header-column-active {
}
.recline-slickgrid .slick-header-column.ui-state-default {
height: 26px;
}
.recline-slickgrid .slick-headerrow {
background: #fafafa;
}
.recline-slickgrid .slick-headerrow-column {
background: #fafafa;
border-bottom: 0;
height: 100%;
}
.recline-slickgrid .slick-row.ui-state-active {
background: #F5F7D7;
}
.recline-slickgrid .slick-row {
position: absolute;
background: white;
border: 0px;
line-height: 20px;
}
.recline-slickgrid .slick-row.selected {
z-index: 10;
background: #DFE8F6;
}
.recline-slickgrid .slick-cell {
padding-left: 4px;
padding-right: 4px;
}
.recline-slickgrid .slick-group {
border-bottom: 2px solid silver;
}
.recline-slickgrid .slick-group-toggle {
width: 9px;
height: 9px;
margin-right: 5px;
}
.recline-slickgrid .slick-group-toggle.expanded {
background: url(../images/collapse.gif) no-repeat center center;
}
.recline-slickgrid .slick-group-toggle.collapsed {
background: url(../images/expand.gif) no-repeat center center;
}
.recline-slickgrid .slick-group-totals {
color: gray;
background: white;
}
.recline-slickgrid .slick-cell.selected {
background-color: beige;
}
.recline-slickgrid .slick-cell.active {
border-color: gray;
border-style: solid;
}
.recline-slickgrid .slick-sortable-placeholder {
background: silver !important;
}
.recline-slickgrid .slick-row[row$="1"], .slick-row[row$="3"], .slick-row[row$="5"], .slick-row[row$="7"], .slick-row[row$="9"] {
background: #fafafa;
}
.recline-slickgrid .slick-row.ui-state-active {
background: #F5F7D7;
}
.recline-slickgrid .slick-row.loading {
opacity: 0.5;
filter: alpha(opacity = 50);
}
.recline-slickgrid .slick-cell.invalid {
border-color: red;
}
.recline-slickgrid .slick-row .slick-cell:first-child,
.recline-slickgrid .slick-header {
border-left: 1px solid #ccc;
}
/* add one pixel extra as added one pixel to left border of header */
.recline-slickgrid .slick-row .slick-cell {
margin-right: -1px;
}
/* Slick grid context menu (not part of the recline-slickgrid div) */
.slick-contextmenu {
border-radius: 5px
}
.slick-contextmenu li {
clear: both;
height: 24px;
cursor: pointer;
}
.slick-contextmenu .divider {
cursor: default;
}
.slick-contextmenu > li:hover {
background-color: #0088cc;
}
.slick-contextmenu .divider:hover {
background-color: #E5E5E5;
}
.slick-contextmenu li:hover > label {
color: white;
}
.slick-contextmenu input {
float: left;
margin-left: 15px;
margin-top: 5px;
}
.slick-contextmenu label {
float: left;
margin-right: 15px;
margin-left: 5px;
margin-top: 3px;
color: #555;
cursor: pointer;
}
.recline-slickgrid .recline-row-delete {
font-size: 12px;
padding: 3px;
width: 29px;
height: 18px;
line-height: 13px;
}
.recline-cell-reorder {
font-size: 12px;
padding: 1px;
width: 31px;
height: 14px;
line-height: 13px;
cursor: move;
background: url("../images/drag-handle.png") no-repeat center center;
}

View File

@ -0,0 +1,48 @@
var Showdown={};Showdown.converter=function(){var g_urls;var g_titles;var g_html_blocks;var g_list_level=0;this.makeHtml=function(text){g_urls=new Array();g_titles=new Array();g_html_blocks=new Array();text=text.replace(/~/g,"~T");text=text.replace(/\$/g,"~D");text=text.replace(/\r\n/g,"\n");text=text.replace(/\r/g,"\n");text="\n\n"+text+"\n\n";text=_Detab(text);text=text.replace(/^[ \t]+$/mg,"");text=_DoGithubCodeBlocks(text);text=_HashHTMLBlocks(text);text=_StripLinkDefinitions(text);text=_RunBlockGamut(text);text=_UnescapeSpecialChars(text);text=text.replace(/~D/g,"$$");text=text.replace(/~T/g,"~");return text;};var _StripLinkDefinitions=function(text){var text=text.replace(/^[ ]{0,3}\[(.+)\]:[ \t]*\n?[ \t]*<?(\S+?)>?[ \t]*\n?[ \t]*(?:(\n*)["(](.+?)[")][ \t]*)?(?:\n+|\Z)/gm,function(wholeMatch,m1,m2,m3,m4){m1=m1.toLowerCase();g_urls[m1]=_EncodeAmpsAndAngles(m2);if(m3){return m3+m4;}else if(m4){g_titles[m1]=m4.replace(/"/g,"&quot;");}
return"";});return text;}
var _HashHTMLBlocks=function(text){text=text.replace(/\n/g,"\n\n");var block_tags_a="p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|script|noscript|form|fieldset|iframe|math|ins|del|style|section|header|footer|nav|article|aside";var block_tags_b="p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|script|noscript|form|fieldset|iframe|math|style|section|header|footer|nav|article|aside";text=text.replace(/^(<(p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|script|noscript|form|fieldset|iframe|math|ins|del)\b[^\r]*?\n<\/\2>[ \t]*(?=\n+))/gm,hashElement);text=text.replace(/^(<(p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|script|noscript|form|fieldset|iframe|math|style|section|header|footer|nav|article|aside)\b[^\r]*?.*<\/\2>[ \t]*(?=\n+)\n)/gm,hashElement);text=text.replace(/(\n[ ]{0,3}(<(hr)\b([^<>])*?\/?>)[ \t]*(?=\n{2,}))/g,hashElement);text=text.replace(/(\n\n[ ]{0,3}<!(--[^\r]*?--\s*)+>[ \t]*(?=\n{2,}))/g,hashElement);text=text.replace(/(?:\n\n)([ ]{0,3}(?:<([?%])[^\r]*?\2>)[ \t]*(?=\n{2,}))/g,hashElement);text=text.replace(/\n\n/g,"\n");return text;}
var hashElement=function(wholeMatch,m1){var blockText=m1;blockText=blockText.replace(/\n\n/g,"\n");blockText=blockText.replace(/^\n/,"");blockText=blockText.replace(/\n+$/g,"");blockText="\n\n~K"+(g_html_blocks.push(blockText)-1)+"K\n\n";return blockText;};var _RunBlockGamut=function(text){text=_DoHeaders(text);var key=hashBlock("<hr />");text=text.replace(/^[ ]{0,2}([ ]?\*[ ]?){3,}[ \t]*$/gm,key);text=text.replace(/^[ ]{0,2}([ ]?\-[ ]?){3,}[ \t]*$/gm,key);text=text.replace(/^[ ]{0,2}([ ]?\_[ ]?){3,}[ \t]*$/gm,key);text=_DoLists(text);text=_DoCodeBlocks(text);text=_DoBlockQuotes(text);text=_HashHTMLBlocks(text);text=_FormParagraphs(text);return text;};var _RunSpanGamut=function(text){text=_DoCodeSpans(text);text=_EscapeSpecialCharsWithinTagAttributes(text);text=_EncodeBackslashEscapes(text);text=_DoImages(text);text=_DoAnchors(text);text=_DoAutoLinks(text);text=_EncodeAmpsAndAngles(text);text=_DoItalicsAndBold(text);text=text.replace(/ +\n/g," <br />\n");return text;}
var _EscapeSpecialCharsWithinTagAttributes=function(text){var regex=/(<[a-z\/!$]("[^"]*"|'[^']*'|[^'">])*>|<!(--.*?--\s*)+>)/gi;text=text.replace(regex,function(wholeMatch){var tag=wholeMatch.replace(/(.)<\/?code>(?=.)/g,"$1`");tag=escapeCharacters(tag,"\\`*_");return tag;});return text;}
var _DoAnchors=function(text){text=text.replace(/(\[((?:\[[^\]]*\]|[^\[\]])*)\][ ]?(?:\n[ ]*)?\[(.*?)\])()()()()/g,writeAnchorTag);text=text.replace(/(\[((?:\[[^\]]*\]|[^\[\]])*)\]\([ \t]*()<?(.*?)>?[ \t]*((['"])(.*?)\6[ \t]*)?\))/g,writeAnchorTag);text=text.replace(/(\[([^\[\]]+)\])()()()()()/g,writeAnchorTag);return text;}
var writeAnchorTag=function(wholeMatch,m1,m2,m3,m4,m5,m6,m7){if(m7==undefined)m7="";var whole_match=m1;var link_text=m2;var link_id=m3.toLowerCase();var url=m4;var title=m7;if(url==""){if(link_id==""){link_id=link_text.toLowerCase().replace(/ ?\n/g," ");}
url="#"+link_id;if(g_urls[link_id]!=undefined){url=g_urls[link_id];if(g_titles[link_id]!=undefined){title=g_titles[link_id];}}
else{if(whole_match.search(/\(\s*\)$/m)>-1){url="";}else{return whole_match;}}}
url=escapeCharacters(url,"*_");var result="<a href=\""+url+"\"";if(title!=""){title=title.replace(/"/g,"&quot;");title=escapeCharacters(title,"*_");result+=" title=\""+title+"\"";}
result+=">"+link_text+"</a>";return result;}
var _DoImages=function(text){text=text.replace(/(!\[(.*?)\][ ]?(?:\n[ ]*)?\[(.*?)\])()()()()/g,writeImageTag);text=text.replace(/(!\[(.*?)\]\s?\([ \t]*()<?(\S+?)>?[ \t]*((['"])(.*?)\6[ \t]*)?\))/g,writeImageTag);return text;}
var writeImageTag=function(wholeMatch,m1,m2,m3,m4,m5,m6,m7){var whole_match=m1;var alt_text=m2;var link_id=m3.toLowerCase();var url=m4;var title=m7;if(!title)title="";if(url==""){if(link_id==""){link_id=alt_text.toLowerCase().replace(/ ?\n/g," ");}
url="#"+link_id;if(g_urls[link_id]!=undefined){url=g_urls[link_id];if(g_titles[link_id]!=undefined){title=g_titles[link_id];}}
else{return whole_match;}}
alt_text=alt_text.replace(/"/g,"&quot;");url=escapeCharacters(url,"*_");var result="<img src=\""+url+"\" alt=\""+alt_text+"\"";title=title.replace(/"/g,"&quot;");title=escapeCharacters(title,"*_");result+=" title=\""+title+"\"";result+=" />";return result;}
var _DoHeaders=function(text){text=text.replace(/^(.+)[ \t]*\n=+[ \t]*\n+/gm,function(wholeMatch,m1){return hashBlock('<h1 id="'+headerId(m1)+'">'+_RunSpanGamut(m1)+"</h1>");});text=text.replace(/^(.+)[ \t]*\n-+[ \t]*\n+/gm,function(matchFound,m1){return hashBlock('<h2 id="'+headerId(m1)+'">'+_RunSpanGamut(m1)+"</h2>");});text=text.replace(/^(\#{1,6})[ \t]*(.+?)[ \t]*\#*\n+/gm,function(wholeMatch,m1,m2){var h_level=m1.length;return hashBlock("<h"+h_level+' id="'+headerId(m2)+'">'+_RunSpanGamut(m2)+"</h"+h_level+">");});function headerId(m){return m.replace(/[^\w]/g,'').toLowerCase();}
return text;}
var _ProcessListItems;var _DoLists=function(text){text+="~0";var whole_list=/^(([ ]{0,3}([*+-]|\d+[.])[ \t]+)[^\r]+?(~0|\n{2,}(?=\S)(?![ \t]*(?:[*+-]|\d+[.])[ \t]+)))/gm;if(g_list_level){text=text.replace(whole_list,function(wholeMatch,m1,m2){var list=m1;var list_type=(m2.search(/[*+-]/g)>-1)?"ul":"ol";list=list.replace(/\n{2,}/g,"\n\n\n");;var result=_ProcessListItems(list);result=result.replace(/\s+$/,"");result="<"+list_type+">"+result+"</"+list_type+">\n";return result;});}else{whole_list=/(\n\n|^\n?)(([ ]{0,3}([*+-]|\d+[.])[ \t]+)[^\r]+?(~0|\n{2,}(?=\S)(?![ \t]*(?:[*+-]|\d+[.])[ \t]+)))/g;text=text.replace(whole_list,function(wholeMatch,m1,m2,m3){var runup=m1;var list=m2;var list_type=(m3.search(/[*+-]/g)>-1)?"ul":"ol";var list=list.replace(/\n{2,}/g,"\n\n\n");;var result=_ProcessListItems(list);result=runup+"<"+list_type+">\n"+result+"</"+list_type+">\n";return result;});}
text=text.replace(/~0/,"");return text;}
_ProcessListItems=function(list_str){g_list_level++;list_str=list_str.replace(/\n{2,}$/,"\n");list_str+="~0";list_str=list_str.replace(/(\n)?(^[ \t]*)([*+-]|\d+[.])[ \t]+([^\r]+?(\n{1,2}))(?=\n*(~0|\2([*+-]|\d+[.])[ \t]+))/gm,function(wholeMatch,m1,m2,m3,m4){var item=m4;var leading_line=m1;var leading_space=m2;if(leading_line||(item.search(/\n{2,}/)>-1)){item=_RunBlockGamut(_Outdent(item));}
else{item=_DoLists(_Outdent(item));item=item.replace(/\n$/,"");item=_RunSpanGamut(item);}
return"<li>"+item+"</li>\n";});list_str=list_str.replace(/~0/g,"");g_list_level--;return list_str;}
var _DoCodeBlocks=function(text){text+="~0";text=text.replace(/(?:\n\n|^)((?:(?:[ ]{4}|\t).*\n+)+)(\n*[ ]{0,3}[^ \t\n]|(?=~0))/g,function(wholeMatch,m1,m2){var codeblock=m1;var nextChar=m2;codeblock=_EncodeCode(_Outdent(codeblock));codeblock=_Detab(codeblock);codeblock=codeblock.replace(/^\n+/g,"");codeblock=codeblock.replace(/\n+$/g,"");codeblock="<pre><code>"+codeblock+"\n</code></pre>";return hashBlock(codeblock)+nextChar;});text=text.replace(/~0/,"");return text;};var _DoGithubCodeBlocks=function(text){text+="~0";text=text.replace(/(?:^|\n)```(.*)\n([\s\S]*?)\n```/g,function(wholeMatch,m1,m2){var language=m1;var codeblock=m2;codeblock=_EncodeCode(codeblock);codeblock=_Detab(codeblock);codeblock=codeblock.replace(/^\n+/g,"");codeblock=codeblock.replace(/\n+$/g,"");codeblock="<pre><code"+(language?" class=\""+language+'"':"")+">"+codeblock+"\n</code></pre>";return hashBlock(codeblock);});text=text.replace(/~0/,"");return text;}
var hashBlock=function(text){text=text.replace(/(^\n+|\n+$)/g,"");return"\n\n~K"+(g_html_blocks.push(text)-1)+"K\n\n";}
var _DoCodeSpans=function(text){text=text.replace(/(^|[^\\])(`+)([^\r]*?[^`])\2(?!`)/gm,function(wholeMatch,m1,m2,m3,m4){var c=m3;c=c.replace(/^([ \t]*)/g,"");c=c.replace(/[ \t]*$/g,"");c=_EncodeCode(c);return m1+"<code>"+c+"</code>";});return text;}
var _EncodeCode=function(text){text=text.replace(/&/g,"&amp;");text=text.replace(/</g,"&lt;");text=text.replace(/>/g,"&gt;");text=escapeCharacters(text,"\*_{}[]\\",false);return text;}
var _DoItalicsAndBold=function(text){text=text.replace(/(\*\*|__)(?=\S)([^\r]*?\S[*_]*)\1/g,"<strong>$2</strong>");text=text.replace(/(\*|_)(?=\S)([^\r]*?\S)\1/g,"<em>$2</em>");return text;}
var _DoBlockQuotes=function(text){text=text.replace(/((^[ \t]*>[ \t]?.+\n(.+\n)*\n*)+)/gm,function(wholeMatch,m1){var bq=m1;bq=bq.replace(/^[ \t]*>[ \t]?/gm,"~0");bq=bq.replace(/~0/g,"");bq=bq.replace(/^[ \t]+$/gm,"");bq=_RunBlockGamut(bq);bq=bq.replace(/(^|\n)/g,"$1 ");bq=bq.replace(/(\s*<pre>[^\r]+?<\/pre>)/gm,function(wholeMatch,m1){var pre=m1;pre=pre.replace(/^ /mg,"~0");pre=pre.replace(/~0/g,"");return pre;});return hashBlock("<blockquote>\n"+bq+"\n</blockquote>");});return text;}
var _FormParagraphs=function(text){text=text.replace(/^\n+/g,"");text=text.replace(/\n+$/g,"");var grafs=text.split(/\n{2,}/g);var grafsOut=new Array();var end=grafs.length;for(var i=0;i<end;i++){var str=grafs[i];if(str.search(/~K(\d+)K/g)>=0){grafsOut.push(str);}
else if(str.search(/\S/)>=0){str=_RunSpanGamut(str);str=str.replace(/^([ \t]*)/g,"<p>");str+="</p>"
grafsOut.push(str);}}
end=grafsOut.length;for(var i=0;i<end;i++){while(grafsOut[i].search(/~K(\d+)K/)>=0){var blockText=g_html_blocks[RegExp.$1];blockText=blockText.replace(/\$/g,"$$$$");grafsOut[i]=grafsOut[i].replace(/~K\d+K/,blockText);}}
return grafsOut.join("\n\n");}
var _EncodeAmpsAndAngles=function(text){text=text.replace(/&(?!#?[xX]?(?:[0-9a-fA-F]+|\w+);)/g,"&amp;");text=text.replace(/<(?![a-z\/?\$!])/gi,"&lt;");return text;}
var _EncodeBackslashEscapes=function(text){text=text.replace(/\\(\\)/g,escapeCharacters_callback);text=text.replace(/\\([`*_{}\[\]()>#+-.!])/g,escapeCharacters_callback);return text;}
var _DoAutoLinks=function(text){text=text.replace(/<((https?|ftp|dict):[^'">\s]+)>/gi,"<a href=\"$1\">$1</a>");text=text.replace(/<(?:mailto:)?([-.\w]+\@[-a-z0-9]+(\.[-a-z0-9]+)*\.[a-z]+)>/gi,function(wholeMatch,m1){return _EncodeEmailAddress(_UnescapeSpecialChars(m1));});return text;}
var _EncodeEmailAddress=function(addr){function char2hex(ch){var hexDigits='0123456789ABCDEF';var dec=ch.charCodeAt(0);return(hexDigits.charAt(dec>>4)+hexDigits.charAt(dec&15));}
var encode=[function(ch){return"&#"+ch.charCodeAt(0)+";";},function(ch){return"&#x"+char2hex(ch)+";";},function(ch){return ch;}];addr="mailto:"+addr;addr=addr.replace(/./g,function(ch){if(ch=="@"){ch=encode[Math.floor(Math.random()*2)](ch);}else if(ch!=":"){var r=Math.random();ch=(r>.9?encode[2](ch):r>.45?encode[1](ch):encode[0](ch));}
return ch;});addr="<a href=\""+addr+"\">"+addr+"</a>";addr=addr.replace(/">.+:/g,"\">");return addr;}
var _UnescapeSpecialChars=function(text){text=text.replace(/~E(\d+)E/g,function(wholeMatch,m1){var charCodeToReplace=parseInt(m1);return String.fromCharCode(charCodeToReplace);});return text;}
var _Outdent=function(text){text=text.replace(/^(\t|[ ]{1,4})/gm,"~0");text=text.replace(/~0/g,"")
return text;}
var _Detab=function(text){text=text.replace(/\t(?=\t)/g," ");text=text.replace(/\t/g,"~A~B");text=text.replace(/~B(.+?)~A/g,function(wholeMatch,m1,m2){var leadingText=m1;var numSpaces=4-leadingText.length%4;for(var i=0;i<numSpaces;i++)leadingText+=" ";return leadingText;});text=text.replace(/~A/g," ");text=text.replace(/~B/g,"");return text;}
var escapeCharacters=function(text,charsToEscape,afterBackslash){var regexString="(["+charsToEscape.replace(/([\[\]\\])/g,"\\$1")+"])";if(afterBackslash){regexString="\\\\"+regexString;}
var regex=new RegExp(regexString,"g");text=text.replace(regex,escapeCharacters_callback);return text;}
var escapeCharacters_callback=function(wholeMatch,m1){var charCodeToEscape=m1.charCodeAt(0);return"~E"+charCodeToEscape+"E";}}
if(typeof module!=='undefined')module.exports=Showdown;

View File

@ -0,0 +1,20 @@
Copyright (c) 2010 Michael Leibman, http://github.com/mleibman/slickgrid
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

View File

@ -0,0 +1,25 @@
# Welcome to SlickGrid
Find documentation and examples in [the wiki](https://github.com/mleibman/SlickGrid/wiki).
**UPDATE: March 5th, 2014 - I have too many things going on in my life right now to really give SlickGrid support and development the time and attention it deserves. I am not stopping it, but I will most likely be unresponsive for some time. Sorry.**
## SlickGrid is an advanced JavaScript grid/spreadsheet component
Some highlights:
* Adaptive virtual scrolling (handle hundreds of thousands of rows with extreme responsiveness)
* Extremely fast rendering speed
* Supports jQuery UI Themes
* Background post-rendering for richer cells
* Configurable & customizable
* Full keyboard navigation
* Column resize/reorder/show/hide
* Column autosizing & force-fit
* Pluggable cell formatters & editors
* Support for editing and creating new rows.
* Grouping, filtering, custom aggregators, and more!
* Advanced detached & multi-field editors with undo/redo support.
* “GlobalEditorLock” to manage concurrent edits in cases where multiple Views on a page can edit the same data.
* Support for [millions of rows](http://stackoverflow.com/a/2569488/1269037)

View File

@ -0,0 +1,31 @@
.slick-columnpicker {
border: 1px solid #718BB7;
background: #f0f0f0;
padding: 6px;
-moz-box-shadow: 2px 2px 2px silver;
-webkit-box-shadow: 2px 2px 2px silver;
box-shadow: 2px 2px 2px silver;
min-width: 100px;
cursor: default;
}
.slick-columnpicker li {
list-style: none;
margin: 0;
padding: 0;
background: none;
}
.slick-columnpicker input {
margin: 4px;
}
.slick-columnpicker li a {
display: block;
padding: 4px;
font-weight: bold;
}
.slick-columnpicker li a:hover {
background: white;
}

View File

@ -0,0 +1,152 @@
(function ($) {
function SlickColumnPicker(columns, grid, options) {
var $menu;
var columnCheckboxes;
var defaults = {
fadeSpeed:250
};
function init() {
grid.onHeaderContextMenu.subscribe(handleHeaderContextMenu);
grid.onColumnsReordered.subscribe(updateColumnOrder);
options = $.extend({}, defaults, options);
$menu = $("<span class='slick-columnpicker' style='display:none;position:absolute;z-index:20;' />").appendTo(document.body);
$menu.bind("mouseleave", function (e) {
$(this).fadeOut(options.fadeSpeed)
});
$menu.bind("click", updateColumn);
}
function destroy() {
grid.onHeaderContextMenu.unsubscribe(handleHeaderContextMenu);
grid.onColumnsReordered.unsubscribe(updateColumnOrder);
$menu.remove();
}
function handleHeaderContextMenu(e, args) {
e.preventDefault();
$menu.empty();
updateColumnOrder();
columnCheckboxes = [];
var $li, $input;
for (var i = 0; i < columns.length; i++) {
$li = $("<li />").appendTo($menu);
$input = $("<input type='checkbox' />").data("column-id", columns[i].id);
columnCheckboxes.push($input);
if (grid.getColumnIndex(columns[i].id) != null) {
$input.attr("checked", "checked");
}
$("<label />")
.text(columns[i].name)
.prepend($input)
.appendTo($li);
}
$("<hr/>").appendTo($menu);
$li = $("<li />").appendTo($menu);
$input = $("<input type='checkbox' />").data("option", "autoresize");
$("<label />")
.text("Force fit columns")
.prepend($input)
.appendTo($li);
if (grid.getOptions().forceFitColumns) {
$input.attr("checked", "checked");
}
$li = $("<li />").appendTo($menu);
$input = $("<input type='checkbox' />").data("option", "syncresize");
$("<label />")
.text("Synchronous resize")
.prepend($input)
.appendTo($li);
if (grid.getOptions().syncColumnCellResize) {
$input.attr("checked", "checked");
}
$menu
.css("top", e.pageY - 10)
.css("left", e.pageX - 10)
.fadeIn(options.fadeSpeed);
}
function updateColumnOrder() {
// Because columns can be reordered, we have to update the `columns`
// to reflect the new order, however we can't just take `grid.getColumns()`,
// as it does not include columns currently hidden by the picker.
// We create a new `columns` structure by leaving currently-hidden
// columns in their original ordinal position and interleaving the results
// of the current column sort.
var current = grid.getColumns().slice(0);
var ordered = new Array(columns.length);
for (var i = 0; i < ordered.length; i++) {
if ( grid.getColumnIndex(columns[i].id) === undefined ) {
// If the column doesn't return a value from getColumnIndex,
// it is hidden. Leave it in this position.
ordered[i] = columns[i];
} else {
// Otherwise, grab the next visible column.
ordered[i] = current.shift();
}
}
columns = ordered;
}
function updateColumn(e) {
if ($(e.target).data("option") == "autoresize") {
if (e.target.checked) {
grid.setOptions({forceFitColumns:true});
grid.autosizeColumns();
} else {
grid.setOptions({forceFitColumns:false});
}
return;
}
if ($(e.target).data("option") == "syncresize") {
if (e.target.checked) {
grid.setOptions({syncColumnCellResize:true});
} else {
grid.setOptions({syncColumnCellResize:false});
}
return;
}
if ($(e.target).is(":checkbox")) {
var visibleColumns = [];
$.each(columnCheckboxes, function (i, e) {
if ($(this).is(":checked")) {
visibleColumns.push(columns[i]);
}
});
if (!visibleColumns.length) {
$(e.target).attr("checked", "checked");
return;
}
grid.setColumns(visibleColumns);
}
}
function getAllColumns() {
return columns;
}
init();
return {
"getAllColumns": getAllColumns,
"destroy": destroy
};
}
// Slick.Controls.ColumnPicker
$.extend(true, window, { Slick:{ Controls:{ ColumnPicker:SlickColumnPicker }}});
})(jQuery);

View File

@ -0,0 +1,41 @@
.slick-pager {
width: 100%;
height: 26px;
border: 1px solid gray;
border-top: 0;
background: url('../images/header-columns-bg.gif') repeat-x center bottom;
vertical-align: middle;
}
.slick-pager .slick-pager-status {
display: inline-block;
padding: 6px;
}
.slick-pager .ui-icon-container {
display: inline-block;
margin: 2px;
border-color: gray;
}
.slick-pager .slick-pager-nav {
display: inline-block;
float: left;
padding: 2px;
}
.slick-pager .slick-pager-settings {
display: block;
float: right;
padding: 2px;
}
.slick-pager .slick-pager-settings * {
vertical-align: middle;
}
.slick-pager .slick-pager-settings a {
padding: 2px;
text-decoration: underline;
cursor: pointer;
}

View File

@ -0,0 +1,154 @@
(function ($) {
function SlickGridPager(dataView, grid, $container) {
var $status;
function init() {
dataView.onPagingInfoChanged.subscribe(function (e, pagingInfo) {
updatePager(pagingInfo);
});
constructPagerUI();
updatePager(dataView.getPagingInfo());
}
function getNavState() {
var cannotLeaveEditMode = !Slick.GlobalEditorLock.commitCurrentEdit();
var pagingInfo = dataView.getPagingInfo();
var lastPage = pagingInfo.totalPages - 1;
return {
canGotoFirst: !cannotLeaveEditMode && pagingInfo.pageSize != 0 && pagingInfo.pageNum > 0,
canGotoLast: !cannotLeaveEditMode && pagingInfo.pageSize != 0 && pagingInfo.pageNum != lastPage,
canGotoPrev: !cannotLeaveEditMode && pagingInfo.pageSize != 0 && pagingInfo.pageNum > 0,
canGotoNext: !cannotLeaveEditMode && pagingInfo.pageSize != 0 && pagingInfo.pageNum < lastPage,
pagingInfo: pagingInfo
}
}
function setPageSize(n) {
dataView.setRefreshHints({
isFilterUnchanged: true
});
dataView.setPagingOptions({pageSize: n});
}
function gotoFirst() {
if (getNavState().canGotoFirst) {
dataView.setPagingOptions({pageNum: 0});
}
}
function gotoLast() {
var state = getNavState();
if (state.canGotoLast) {
dataView.setPagingOptions({pageNum: state.pagingInfo.totalPages - 1});
}
}
function gotoPrev() {
var state = getNavState();
if (state.canGotoPrev) {
dataView.setPagingOptions({pageNum: state.pagingInfo.pageNum - 1});
}
}
function gotoNext() {
var state = getNavState();
if (state.canGotoNext) {
dataView.setPagingOptions({pageNum: state.pagingInfo.pageNum + 1});
}
}
function constructPagerUI() {
$container.empty();
var $nav = $("<span class='slick-pager-nav' />").appendTo($container);
var $settings = $("<span class='slick-pager-settings' />").appendTo($container);
$status = $("<span class='slick-pager-status' />").appendTo($container);
$settings
.append("<span class='slick-pager-settings-expanded' style='display:none'>Show: <a data=0>All</a><a data='-1'>Auto</a><a data=25>25</a><a data=50>50</a><a data=100>100</a></span>");
$settings.find("a[data]").click(function (e) {
var pagesize = $(e.target).attr("data");
if (pagesize != undefined) {
if (pagesize == -1) {
var vp = grid.getViewport();
setPageSize(vp.bottom - vp.top);
} else {
setPageSize(parseInt(pagesize));
}
}
});
var icon_prefix = "<span class='ui-state-default ui-corner-all ui-icon-container'><span class='ui-icon ";
var icon_suffix = "' /></span>";
$(icon_prefix + "ui-icon-lightbulb" + icon_suffix)
.click(function () {
$(".slick-pager-settings-expanded").toggle()
})
.appendTo($settings);
$(icon_prefix + "ui-icon-seek-first" + icon_suffix)
.click(gotoFirst)
.appendTo($nav);
$(icon_prefix + "ui-icon-seek-prev" + icon_suffix)
.click(gotoPrev)
.appendTo($nav);
$(icon_prefix + "ui-icon-seek-next" + icon_suffix)
.click(gotoNext)
.appendTo($nav);
$(icon_prefix + "ui-icon-seek-end" + icon_suffix)
.click(gotoLast)
.appendTo($nav);
$container.find(".ui-icon-container")
.hover(function () {
$(this).toggleClass("ui-state-hover");
});
$container.children().wrapAll("<div class='slick-pager' />");
}
function updatePager(pagingInfo) {
var state = getNavState();
$container.find(".slick-pager-nav span").removeClass("ui-state-disabled");
if (!state.canGotoFirst) {
$container.find(".ui-icon-seek-first").addClass("ui-state-disabled");
}
if (!state.canGotoLast) {
$container.find(".ui-icon-seek-end").addClass("ui-state-disabled");
}
if (!state.canGotoNext) {
$container.find(".ui-icon-seek-next").addClass("ui-state-disabled");
}
if (!state.canGotoPrev) {
$container.find(".ui-icon-seek-prev").addClass("ui-state-disabled");
}
if (pagingInfo.pageSize == 0) {
var totalRowsCount = dataView.getItems().length;
var visibleRowsCount = pagingInfo.totalRows;
if (visibleRowsCount < totalRowsCount) {
$status.text("Showing " + visibleRowsCount + " of " + totalRowsCount + " rows");
} else {
$status.text("Showing all " + totalRowsCount + " rows");
}
$status.text("Showing all " + pagingInfo.totalRows + " rows");
} else {
$status.text("Showing page " + (pagingInfo.pageNum + 1) + " of " + pagingInfo.totalPages);
}
}
init();
}
// Slick.Controls.Pager
$.extend(true, window, { Slick:{ Controls:{ Pager:SlickGridPager }}});
})(jQuery);

Some files were not shown because too many files have changed in this diff Show More