diff --git a/alembic/versions/34c4a3c687b_additional_metadata_on_perspectives_and_.py b/alembic/versions/34c4a3c687b_additional_metadata_on_perspectives_and_.py new file mode 100644 index 000000000..532a53d34 --- /dev/null +++ b/alembic/versions/34c4a3c687b_additional_metadata_on_perspectives_and_.py @@ -0,0 +1,28 @@ +"""additional metadata on perspectives and dictionaries + +Revision ID: 34c4a3c687b +Revises: 28894fa7718 +Create Date: 2015-11-13 13:53:15.258799 + +""" + +# revision identifiers, used by Alembic. +revision = '34c4a3c687b' +down_revision = '28894fa7718' +branch_labels = None +depends_on = None + +from alembic import op +import sqlalchemy as sa + + +def upgrade(): + op.add_column('dictionaryperspective', sa.Column('additional_metadata', sa.UnicodeText(), nullable=True)) + op.add_column('dictionary', sa.Column('additional_metadata', sa.UnicodeText(), nullable=True)) + pass + + +def downgrade(): + op.drop_column('dictionary', 'additional_metadata') + op.drop_column('dictionaryperspective', 'additional_metadata') + pass diff --git a/alembic/versions/479841e119f_added_indexes.py b/alembic/versions/479841e119f_added_indexes.py new file mode 100644 index 000000000..a8e98b126 --- /dev/null +++ b/alembic/versions/479841e119f_added_indexes.py @@ -0,0 +1,42 @@ +"""Added indexes + +Revision ID: 479841e119f +Revises: 34c4a3c687b +Create Date: 2015-12-01 16:21:32.634476 + +""" + +# revision identifiers, used by Alembic. +revision = '479841e119f' +down_revision = '34c4a3c687b' +branch_labels = None +depends_on = None + +from alembic import op +import sqlalchemy as sa + + +def upgrade(): + ### commands auto generated by Alembic - please adjust! ### + op.create_index('pl1e_parent_idx', 'publishleveloneentity', ['parent_client_id', 'parent_object_id'], unique=False) + op.create_index('pl1e_entity_type_idx', 'publishleveloneentity', ['entity_type'], unique=False) + op.create_index('pl1e_entity_idx', 'publishleveloneentity', ['entity_client_id', 'entity_object_id'], unique=False) + op.create_index('pl1e_deleted_idx', 'publishleveloneentity', ['marked_for_deletion'], unique=False) + op.create_index('l1e_parent_idx', 'leveloneentity', ['parent_client_id', 'parent_object_id'], unique=False) + op.create_index('l1e_entity_type_idx', 'leveloneentity', ['entity_type'], unique=False) + op.create_index('l1e_deleted_idx', 'leveloneentity', ['marked_for_deletion'], unique=False) + op.create_index('l1e_content_idx', 'leveloneentity', ['content'], unique=False) + ### end Alembic commands ### + + +def downgrade(): + ### commands auto generated by Alembic - please adjust! ### + op.drop_index('l1e_content_idx', table_name='leveloneentity') + op.drop_index('l1e_deleted_idx', table_name='leveloneentity') + op.drop_index('l1e_entity_type_idx', table_name='leveloneentity') + op.drop_index('l1e_parent_idx', table_name='leveloneentity') + op.drop_index('pl1e_deleted_idx', table_name='publishleveloneentity') + op.drop_index('pl1e_entity_idx', table_name='publishleveloneentity') + op.drop_index('pl1e_entity_type_idx', table_name='publishleveloneentity') + op.drop_index('pl1e_parent_idx', table_name='publishleveloneentity') + ### end Alembic commands ### diff --git a/alembic/versions/4eaaa494e36_added_more_indexes.py b/alembic/versions/4eaaa494e36_added_more_indexes.py new file mode 100644 index 000000000..2bae17af2 --- /dev/null +++ b/alembic/versions/4eaaa494e36_added_more_indexes.py @@ -0,0 +1,56 @@ +"""Added more indexes + +Revision ID: 4eaaa494e36 +Revises: 479841e119f +Create Date: 2015-12-01 16:53:27.562361 + +""" + +# revision identifiers, used by Alembic. +revision = '4eaaa494e36' +down_revision = '479841e119f' +branch_labels = None +depends_on = None + +from alembic import op +import sqlalchemy as sa + + +def upgrade(): + op.create_index('pl2e_parent_idx', 'publishleveltwoentity', ['parent_client_id', 'parent_object_id'], unique=False) + op.create_index('pl2e_entity_type_idx', 'publishleveltwoentity', ['entity_type'], unique=False) + op.create_index('pl2e_entity_idx', 'publishleveltwoentity', ['entity_client_id', 'entity_object_id'], unique=False) + op.create_index('pl2e_deleted_idx', 'publishleveltwoentity', ['marked_for_deletion'], unique=False) + op.create_index('l2e_parent_idx', 'leveltwoentity', ['parent_client_id', 'parent_object_id'], unique=False) + op.create_index('l2e_entity_type_idx', 'leveltwoentity', ['entity_type'], unique=False) + op.create_index('l2e_deleted_idx', 'leveltwoentity', ['marked_for_deletion'], unique=False) + op.create_index('l2e_content_idx', 'leveltwoentity', ['content'], unique=False) + op.create_index('pge_parent_idx', 'publishgroupingentity', ['parent_client_id', 'parent_object_id'], unique=False) + op.create_index('pge_entity_type_idx', 'publishgroupingentity', ['entity_type'], unique=False) + op.create_index('pge_entity_idx', 'publishgroupingentity', ['entity_client_id', 'entity_object_id'], unique=False) + op.create_index('pge_deleted_idx', 'publishgroupingentity', ['marked_for_deletion'], unique=False) + op.create_index('ge_parent_idx', 'groupingentity', ['parent_client_id', 'parent_object_id'], unique=False) + op.create_index('ge_entity_type_idx', 'groupingentity', ['entity_type'], unique=False) + op.create_index('ge_deleted_idx', 'groupingentity', ['marked_for_deletion'], unique=False) + op.create_index('ge_content_idx', 'groupingentity', ['content'], unique=False) + pass + + +def downgrade(): + op.drop_index('l2e_content_idx', table_name='leveltwoentity') + op.drop_index('l2e_deleted_idx', table_name='leveltwoentity') + op.drop_index('l2e_entity_type_idx', table_name='leveltwoentity') + op.drop_index('l2e_parent_idx', table_name='leveltwoentity') + op.drop_index('pl2e_deleted_idx', table_name='publishleveltwoentity') + op.drop_index('pl2e_entity_idx', table_name='publishleveltwoentity') + op.drop_index('pl2e_entity_type_idx', table_name='publishleveltwoentity') + op.drop_index('pl2e_parent_idx', table_name='publishleveltwoentity') + op.drop_index('ge_content_idx', table_name='groupingentity') + op.drop_index('ge_deleted_idx', table_name='groupingentity') + op.drop_index('ge_entity_type_idx', table_name='groupingentity') + op.drop_index('ge_parent_idx', table_name='groupingentity') + op.drop_index('pge_deleted_idx', table_name='publishgroupingentity') + op.drop_index('pge_entity_idx', table_name='publishgroupingentity') + op.drop_index('pge_entity_type_idx', table_name='publishgroupingentity') + op.drop_index('pge_parent_idx', table_name='publishgroupingentity') + pass diff --git a/lingvodoc/__init__.py b/lingvodoc/__init__.py index f2e8797e8..c7b7d13fd 100755 --- a/lingvodoc/__init__.py +++ b/lingvodoc/__init__.py @@ -56,11 +56,22 @@ def configure_routes(config): # web-view #GET config.add_route(name='languages', pattern='/languages/map') + # web-view #GET + config.add_route(name='maps', pattern='/dashboard/maps') + # API #GET && PUT && DELETE # Gets/puts info about language config.add_route(name='language', pattern='/language/{client_id}/{object_id}', factory='lingvodoc.models.LanguageAcl') # 100% ready + # API #POST + # Convert blob + config.add_route(name='convert', pattern='/convert/blob') # 100% ready + + # API #POST + # Convert markup + config.add_route(name='convert_markup', pattern='/convert/markup') # 100% ready + # API #POST # Create language config.add_route(name='create_language', pattern='/language', @@ -106,6 +117,8 @@ def configure_routes(config): # Gets/puts info about dictionary (name/additional authors/etc) config.add_route(name='dictionary', pattern='/dictionary/{client_id}/{object_id}', factory='lingvodoc.models.DictionaryAcl') # 100% ready + config.add_route(name='dictionary_copy', pattern='/dictionary/{client_id}/{object_id}/copy', + factory='lingvodoc.models.DictionaryAcl') config.add_route(name='dictionary_info', @@ -159,6 +172,31 @@ def configure_routes(config): config.add_route(name='perspective_outside', pattern='perspective/{perspective_client_id}/{perspective_id}', factory='lingvodoc.models.PerspectiveAcl') + # API #POST + # creates hash in metadata on objects + config.add_route(name='perspective_hash', + pattern='/dictionary/{dictionary_client_id}/{dictionary_object_id}/' + 'perspective/{perspective_client_id}/{perspective_id}/hash', + factory='lingvodoc.models.PerspectiveAcl') + + config.add_route(name='dangerous_perspectives_hash', + pattern='/perspectives/hash', + factory='lingvodoc.models.AdminAcl') + # API #GET && PUT && DELETE + # {:{"type"", "content":},} + # for geo: {"location":{"type":"location", "content":{"lat":, "lng":}}} + # for info:{"info":{"type":"list", + # "content":[{"info":{"type":"blob", + # "content":{"client_id":, "object_id":} + # } + # }, + # ] + # } + # } + config.add_route(name='perspective_meta', + pattern='/dictionary/{dictionary_client_id}/{dictionary_object_id}/' + 'perspective/{perspective_client_id}/{perspective_id}/meta', + factory='lingvodoc.models.PerspectiveAcl') config.add_route(name='perspective_tree', pattern='/dictionary/{dictionary_client_id}/{dictionary_object_id}/' @@ -236,14 +274,15 @@ def configure_routes(config): pattern="/blob") # seems to be redundant + # not anymore # API #GET # no params, returns file - #config.add_route(name="get_user_blob", - # pattern="/blobs/{client_id}/{object_id}") + config.add_route(name="get_user_blob", + pattern="/blobs/{client_id}/{object_id}") # API #GET # no params, lists only own blobs config.add_route(name="list_user_blobs", - pattern="/blobs/") + pattern="/blobs") # TODO: LOCALES! # API #GET && DELETE @@ -302,8 +341,25 @@ def configure_routes(config): # API #GET # like + # perspective_client_id + # perspective_object_id config.add_route(name='basic_search', pattern='/basic_search') + # API #POST + # {"searchstrings":[{"searchstring":, "entity_type":, "search_by_or":true/false}, + # ], + # "perspectives":[{"client_id":,"object_id":}, + # ] + # "adopted":True/False, + # "adopted_type":, + # "count":True/False, + # "with_etimology":True/False} + config.add_route(name='advanced_search', pattern='/advanced_search') + + # API #GET + # like + config.add_route(name='entity_metadata_search', pattern='/meta_search') + # API #GET # like config.add_route(name='basic_search_old', pattern='/basic_search_old') @@ -506,6 +562,10 @@ def configure_routes(config): # client_id = # Response example: # {"id": , "login": , "name": , "intl_name": , "userpic": } + # #PUT + # {"client_id": OR "user_id":, + # "new_password": , "old_password":, + # "name":, "birthday":, "email":, "about":} config.add_route(name='get_user_info', pattern='/user') # ready, not tested # API #GET # Returns translations for a list of words for current or default or fallback locale @@ -520,6 +580,7 @@ def configure_routes(config): # params: # {"blob_client_id": , "blob_object_id": , "parent_client_id": , "parent_object_id": } config.add_route(name='convert_dictionary', pattern='/convert') + config.add_route(name='convert_dictionary_check', pattern='/convert_check') def main(global_config, **settings): diff --git a/lingvodoc/models.py b/lingvodoc/models.py index ee7188f92..36e575660 100755 --- a/lingvodoc/models.py +++ b/lingvodoc/models.py @@ -270,11 +270,12 @@ def find_by_translation_string(locale_id, translation_string): def add_translation_to_translation_string(locale_id, translation, translation_string, client_id): - if not translation: - translation = translation_string + client = DBSession.query(Client).filter_by(id=client_id).first() uets = DBSession.query(UserEntitiesTranslationString).filter_by(locale_id=locale_id, translation_string=translation_string).first() + if not translation: + translation = translation_string if not uets: uets = UserEntitiesTranslationString(object_id=DBSession.query(UserEntitiesTranslationString).filter_by(client_id=client.id).count()+1, client_id=client.id, @@ -306,7 +307,7 @@ def set_translation(cls, request): else: req = request.json_body - translation = req.get('translation_string') + translation = None if 'translation' in req: translation = req['translation'] translation_string = req.get('translation_string') @@ -320,7 +321,7 @@ def set_translation(cls, request): return -class Language(Base, TableNameMixin, TranslationStringMixin): +class Language(Base, TableNameMixin): """ This is grouping entity that isn't related with dictionaries directly. Locale can have pointer to language. """ @@ -334,6 +335,52 @@ class Language(Base, TableNameMixin, TranslationStringMixin): marked_for_deletion = Column(Boolean, default=False) parent = relationship('Language', remote_side=[client_id, object_id], backref=backref('language')) + def get_translation(cls, request): + return find_by_translation_string(find_locale_id(request), cls.translation_string) + + def set_translation(self, request): + if type(request.json_body) == str: + req = json.loads(request.json_body) + else: + req = request.json_body + + translation = None + if 'translation' in req: + translation = req['translation'] + translation_string = req.get('translation_string') + if not translation_string: + if self.translation_string: + translation_string = self.translation_string + else: + return + client_id = request.authenticated_userid + locale_id = find_locale_id(request) + client = DBSession.query(Client).filter_by(id=client_id).first() + search_translation_string = self.translation_string + if not search_translation_string: + search_translation_string = translation_string + print('SHEEEET', search_translation_string) + uets = DBSession.query(UserEntitiesTranslationString).filter_by(locale_id=locale_id, + translation_string=search_translation_string).first() + if not translation: + translation = translation_string + if not uets: + uets = UserEntitiesTranslationString(object_id=DBSession.query(UserEntitiesTranslationString).filter_by(client_id=client.id).count()+1, + client_id=client.id, + locale_id=locale_id, + translation_string=translation_string, + translation=translation) + self.translation_string = translation_string + DBSession.add(uets) + DBSession.flush() + print('HEY, LISTEN! WTF') + else: + uets.translation_string = translation_string + self.translation_string = translation_string + uets.translation = translation + print('HEY, LISTEN!') + return + class Locale(Base, TableNameMixin, IdMixin, RelationshipMixin): """ @@ -384,6 +431,7 @@ class Dictionary(Base, TableNameMixin, CompositeIdMixin, RelationshipMixin, Tran authors = Column(UnicodeText) translation_string = Column(UnicodeText) marked_for_deletion = Column(Boolean, default=False) + additional_metadata = Column(UnicodeText) # about = Column(UnicodeText) @@ -407,6 +455,7 @@ class DictionaryPerspective(Base, TableNameMixin, CompositeIdMixin, Relationship is_template = Column(Boolean, default=False) import_source = Column(UnicodeText) import_hash = Column(UnicodeText) + additional_metadata = Column(UnicodeText) # about = Column(UnicodeText) @@ -558,6 +607,8 @@ def track(self, publish): 'marked_for_deletion': self.marked_for_deletion, 'locale_id': self.locale_id } + if self.additional_metadata: + dictionary['additional_metadata'] = self.additional_metadata children = recursive_content(self, publish) if children: dictionary['contains'] = children @@ -799,6 +850,7 @@ def acl_by_groups(object_id, client_id, subject): base_group = group.parent if group.subject_override: group_name = base_group.action + ":" + base_group.subject + ":" + str(group.subject_override) + group_name = base_group.action + ":" + base_group.subject + ":" + str(group.subject_override) else: group_name = base_group.action + ":" + base_group.subject \ + ":" + str(group.subject_client_id) + ":" + str(group.subject_object_id) diff --git a/lingvodoc/scripts/convert_rules.py b/lingvodoc/scripts/convert_rules.py new file mode 100644 index 000000000..0b368f271 --- /dev/null +++ b/lingvodoc/scripts/convert_rules.py @@ -0,0 +1,60 @@ +import os +import tgt + + +class ConvertRule: + def __init__(self, in_type, out_type, in_extensions, out_extensions, convert_method, converter_config=None, max_out_size = 1, max_in_size = 1): + self.in_type = in_type + self.out_type = out_type + self.max_out_size = max_out_size # in MB + self.max_in_size = max_in_size # in MB + self.in_extensions = in_extensions + self.out_extensions = out_extensions + self.converter_config = converter_config + self.convert = convert_method + + +def _export_to_elan(textGrid_file): + if os.stat(textGrid_file).st_size == 0: + return 'error' + try: + textgrid = tgt.io.read_textgrid(textGrid_file, encoding='utf-8') + elan = tgt.io.export_to_elan(textgrid) + except Exception as e: + try: + print(e) + textgrid = tgt.io.read_textgrid(textGrid_file, encoding='utf-16') + elan = tgt.io.export_to_elan(textgrid) + except Exception as e: + print(e) + return 'error' + return elan + + +def _import_from_elan(elan_file): + if os.stat(elan_file).st_size == 0: + return 'error' + try: + textgrid = tgt.io.read_eaf(elan_file) + content = tgt.io.export_to_long_textgrid(textgrid) + except Exception as e: + print(e) + return 'error' + return content + + +# def _is_empty(tier): +# """ Checks whether all intervals are marked as "" +# """ +# for int in tier: +# if int.text != "": +# return False +# return True + + +def praat_to_elan(filename, user_config=None, converter_config=None): + content = _export_to_elan(filename) + return content + + +rules = [ConvertRule('Praat','Elan', ['TextGrid'], ['eaf'], praat_to_elan)] \ No newline at end of file diff --git a/lingvodoc/scripts/lingvodoc_converter.py b/lingvodoc/scripts/lingvodoc_converter.py index 27e10156a..94e7a2902 100644 --- a/lingvodoc/scripts/lingvodoc_converter.py +++ b/lingvodoc/scripts/lingvodoc_converter.py @@ -38,16 +38,39 @@ def upload_audio(upload_url, audio_sequence, markup_sequence, session): log.debug(status.text) -def upload_audio_simple(session, ids_mapping, sound_and_markup_cursor, upload_url, audio_hashes, entity_types, client_id, is_a_regular_form, - locale_id=1): +def upload_markup(upload_url, search_url, markup_sequence, session): + log = logging.getLogger(__name__) + for entry in markup_sequence: + audio_hash = entry[0] + markup_element = entry[1] + entity_metadata_search = search_url + '&searchstring=%s&searchtype=ound'% audio_hash # TODO: change ound to sound, when found how to do lowercase like + status = session.get(entity_metadata_search) + ents = json.loads(status.text) + if ents: + existing_entity = ents[0] + if existing_entity: + parent_client_id = existing_entity['client_id'] + parent_object_id = existing_entity['object_id'] + markup_element["parent_client_id"] = parent_client_id + markup_element["parent_object_id"] = parent_object_id + new_markup_sequence = [o[1] for o in markup_sequence if o[1].get("parent_client_id")] + result = [o for o in markup_sequence if o[1].get("parent_client_id") is None] + status = session.post(upload_url, json=new_markup_sequence) + log.debug(status.text) + return result + + +def upload_audio_simple(session, ids_mapping, sound_and_markup_cursor, upload_url, audio_hashes, entity_types, + client_id, is_a_regular_form, locale_id=1): audio_sequence = [] for cursor in sound_and_markup_cursor: blob_id = cursor[0] audio = cursor[1] filename = cursor[2] word_id = cursor[3] - - if hashlib.sha224(audio).hexdigest() not in audio_hashes: + audio_hash = hashlib.sha224(audio).hexdigest() + if audio_hash not in audio_hashes: + audio_hashes.add(audio_hash) audio_element = {"locale_id": locale_id, "level": "leveloneentity", @@ -58,7 +81,11 @@ def upload_audio_simple(session, ids_mapping, sound_and_markup_cursor, upload_ur "parent_object_id": ids_mapping[int(word_id)][1], "content": base64.urlsafe_b64encode(audio).decode()} if not is_a_regular_form: - audio_element['additional_metadata'] = '{"client_id": %s, "row_id": %s}' % (client_id, cursor[4]) + audio_element['additional_metadata'] = json.dumps({"hash": audio_hash, + "client_id": client_id, + "row_id": cursor[4]}) + else: + audio_element['additional_metadata'] = json.dumps({"hash": audio_hash }) audio_sequence.append(audio_element) if len(audio_sequence) > 50: upload_audio(upload_url, audio_sequence, None, session) @@ -68,10 +95,11 @@ def upload_audio_simple(session, ids_mapping, sound_and_markup_cursor, upload_ur audio_sequence = [] -def upload_audio_with_markup(session, ids_mapping, sound_and_markup_cursor, upload_url, audio_hashes, entity_types, client_id, is_a_regular_form, - locale_id=1): +def upload_audio_with_markup(session, ids_mapping, sound_and_markup_cursor, upload_url, search_url, audio_hashes, markup_hashes, + entity_types, client_id, is_a_regular_form, locale_id=1): audio_sequence = [] markup_sequence = [] + markup__without_audio_sequence = [] for cursor in sound_and_markup_cursor: blob_id = cursor[0] audio = cursor[1] @@ -80,80 +108,116 @@ def upload_audio_with_markup(session, ids_mapping, sound_and_markup_cursor, uplo word_id = cursor[4] if not audio or not markup: continue - audio_hashes.add(hashlib.sha224(audio).hexdigest()) - - audio_element = {"locale_id": locale_id, - "level": "leveloneentity", - "data_type": "sound", - "filename": common_name + ".wav", - "entity_type": entity_types[0], - "parent_client_id": ids_mapping[int(word_id)][0], - "parent_object_id": ids_mapping[int(word_id)][1], - "content": base64.urlsafe_b64encode(audio).decode()} - if not is_a_regular_form: - audio_element['additional_metadata'] = '{"client_id": %s, "row_id": %s}' % (client_id, cursor[5]) - audio_sequence.append(audio_element) - - markup_element = { - "locale_id": locale_id, - "level": "leveltwoentity", - "data_type": "markup", - "filename": common_name + ".TextGrid", - "entity_type": entity_types[1], - # need to set after push "parent_client_id": ids_mapping[int(word_id)][0], - # need to set after push "parent_object_id": ids_mapping[int(word_id)][1], - "content": base64.urlsafe_b64encode(markup).decode()} - if not is_a_regular_form: - audio_element['additional_metadata'] = '{"client_id": %s, "row_id": %s}' % (client_id, cursor[5]) - markup_sequence.append(markup_element) + audio_hash = hashlib.sha224(audio).hexdigest() + markup_hash = hashlib.sha224(markup).hexdigest() + if audio_hash not in audio_hashes: + audio_hashes.add(audio_hash) + audio_element = {"locale_id": locale_id, + "level": "leveloneentity", + "data_type": "sound", + "filename": common_name + ".wav", + "entity_type": entity_types[0], + "parent_client_id": ids_mapping[int(word_id)][0], + "parent_object_id": ids_mapping[int(word_id)][1], + "content": base64.urlsafe_b64encode(audio).decode()} + if not is_a_regular_form: + audio_element['additional_metadata'] = json.dumps({"hash": audio_hash, + "client_id": client_id, + "row_id": cursor[5]}) + else: + audio_element['additional_metadata'] = json.dumps({"hash": audio_hash }) + audio_sequence.append(audio_element) + + + markup_hashes.add(markup_hash) + markup_element = { + "locale_id": locale_id, + "level": "leveltwoentity", + "data_type": "markup", + "filename": common_name + ".TextGrid", + "entity_type": entity_types[1], + # need to set after push "parent_client_id": ids_mapping[int(word_id)][0], + # need to set after push "parent_object_id": ids_mapping[int(word_id)][1], + "content": base64.urlsafe_b64encode(markup).decode(), + "additional_metadata": json.dumps({"hash": markup_hash})} + markup_sequence.append(markup_element) + else: + if markup_hash not in markup_hashes: + + markup_hashes.add(markup_hash) + markup_element = { + "locale_id": locale_id, + "level": "leveltwoentity", + "data_type": "markup", + "filename": common_name + ".TextGrid", + "entity_type": entity_types[1], + "content": base64.urlsafe_b64encode(markup).decode(), + "additional_metadata": json.dumps({"hash": markup_hash})} + markup__without_audio_sequence.append((audio_hash, markup_element)) + if len(markup__without_audio_sequence) > 50: + markup__without_audio_sequence = upload_markup(upload_url, search_url, + markup__without_audio_sequence, session) if len(audio_sequence) > 50: upload_audio(upload_url, audio_sequence, markup_sequence, session) audio_sequence = [] markup_sequence = [] + if len(markup__without_audio_sequence) > 50: + markup__without_audio_sequence = upload_markup(upload_url, search_url, + markup__without_audio_sequence, session) if len(audio_sequence) != 0: upload_audio(upload_url, audio_sequence, markup_sequence, session) audio_sequence = [] markup_sequence = [] + if len(markup__without_audio_sequence) != 0: + markup__without_audio_sequence = upload_markup(upload_url, search_url, markup__without_audio_sequence, session) + def change_dict_status(session, converting_status_url, status): session.put(converting_status_url, json={'status': status}) -def convert_db_new(sqconn, session, language_client_id, language_object_id, server_url, locale_id=1): +def convert_db_new(sqconn, session, language_client_id, language_object_id, server_url, + dictionary_client_id, dictionary_object_id, perspective_client_id, perspective_object_id, locale_id=1): log = logging.getLogger(__name__) dict_attributes = get_dict_attributes(sqconn) - create_dictionary_request = {"parent_client_id": language_client_id, - "parent_object_id": language_object_id, - "translation": dict_attributes['dictionary_name'], - "translation_string": dict_attributes['dictionary_name']} - status = session.post(server_url + 'dictionary', json=create_dictionary_request) - dictionary = json.loads(status.text) + if not dictionary_client_id or not dictionary_object_id: + create_dictionary_request = {"parent_client_id": language_client_id, + "parent_object_id": language_object_id, + "translation": dict_attributes['dictionary_name'], + "translation_string": dict_attributes['dictionary_name']} + status = session.post(server_url + 'dictionary', json=create_dictionary_request) + dictionary = json.loads(status.text) + else: + dictionary = {'client_id': dictionary_client_id, 'object_id': dictionary_object_id} client_id = dictionary['client_id'] converting_status_url = server_url + 'dictionary/%s/%s/state' % (dictionary['client_id'], dictionary['object_id']) change_dict_status(session, converting_status_url, 'Converting 5%') - perspective_create_url = server_url + 'dictionary/%s/%s/perspective' % ( dictionary['client_id'], dictionary['object_id']) - create_perspective_request = {"translation": "Этимологический словарь из Lingvodoc 0.98", - "translation_string": "Lingvodoc 0.98 etymology dictionary", - "import_source": "Lingvodoc-0.98", - "import_hash": dict_attributes['dialeqt_id']} - status = session.post(perspective_create_url, json=create_perspective_request) - perspective = json.loads(status.text) + if not perspective_client_id or not perspective_object_id: + create_perspective_request = {"translation": "Этимологический словарь из Lingvodoc 0.98", + "translation_string": "Lingvodoc 0.98 etymology dictionary", + "import_source": "Lingvodoc-0.98", + "import_hash": dict_attributes['dialeqt_id']} + status = session.post(perspective_create_url, json=create_perspective_request) + perspective = json.loads(status.text) + else: + perspective = {'client_id': perspective_client_id, 'object_id': perspective_object_id} converting_perspective_status_url = server_url + 'dictionary/%s/%s/perspective/%s/%s/state' % \ (dictionary['client_id'], dictionary['object_id'], perspective['client_id'], perspective['object_id']) change_dict_status(session, converting_perspective_status_url, 'Converting') create_perspective_fields_request = session.get(server_url + 'dictionary/1/1/perspective/1/1/fields') - perspective_fields_create_url = perspective_create_url + '/%s/%s/fields' % (perspective['client_id'], perspective['object_id']) + perspective_fields_create_url = perspective_create_url + '/%s/%s/fields' % (perspective['client_id'], + perspective['object_id']) status = session.post(perspective_fields_create_url, json=create_perspective_fields_request.text) get_all_ids = sqconn.cursor() @@ -199,7 +263,7 @@ def create_entity_list(mapping, cursor, level, data_type, entity_type, is_a_regu "parent_object_id": parent_object_id, "content": content} if not is_a_regular_form: - element['additional_metadata'] = '{"client_id": %s, "row_id": %s}' % (client_id, ld_cursor[2]) + element['additional_metadata'] = json.dumps({"client_id": client_id, "row_id": ld_cursor[2]}) push_list.append(element) return push_list @@ -239,9 +303,39 @@ def prepare_and_upload_text_entities(id_column, is_a_regular_form, text_column, and dictionary.is_a_regular_form=1;""") audio_hashes = set() + markup_hashes = set() + + + perspective_search = server_url + 'dictionary/%s/%s/perspective/%s/%s/all' % (dictionary['client_id'], + dictionary['object_id'], + perspective['client_id'], + perspective['object_id']) + search_url = server_url + 'meta_search' \ + '?perspective_client_id=%d&perspective_object_id=%d' % (perspective['client_id'], + perspective['object_id']) + status = session.get(perspective_search) + lexes = json.loads(status.text)['lexical_entries'] + sound_types = ['Sound', 'Paradigm sound'] + markup_types = ['Praat markup', "Paradigm Praat markup"] + for lex in lexes: + for entry in lex['contains']: + meta = entry.get('additional_metadata') + if meta: + hsh = meta.get('hash') + if hsh: + if entry['entity_type'] in sound_types: + audio_hashes.add(hsh) + if entry.get('contains'): + for ent in entry['contains']: + meta = entry.get('additional_metadata') + if meta: + hsh = meta.get('hash') + if hsh: + if ent['entity_type'] in markup_types: + markup_hashes.add(hsh) entity_types = ['Sound', 'Praat markup'] - upload_audio_with_markup(session, ids_mapping, sound_and_markup_word_cursor, create_entities_url, audio_hashes, - entity_types, client_id, True, locale_id) + upload_audio_with_markup(session, ids_mapping, sound_and_markup_word_cursor, create_entities_url, search_url, + audio_hashes, markup_hashes, entity_types, client_id, True, locale_id) log.debug(audio_hashes) change_dict_status(session, converting_status_url, 'Converting 45%') @@ -260,8 +354,8 @@ def prepare_and_upload_text_entities(id_column, is_a_regular_form, text_column, and dictionary.is_a_regular_form=0;""") entity_types = ['Paradigm sound', "Paradigm Praat markup"] - upload_audio_with_markup(session, ids_mapping, paradigm_sound_and_markup_cursor, create_entities_url, audio_hashes, - entity_types, client_id, False, locale_id) + upload_audio_with_markup(session, ids_mapping, paradigm_sound_and_markup_cursor, create_entities_url, search_url, + audio_hashes, markup_hashes, entity_types, client_id, False, locale_id) log.debug(audio_hashes) change_dict_status(session, converting_status_url, 'Converting 60%') @@ -294,8 +388,8 @@ def prepare_and_upload_text_entities(id_column, is_a_regular_form, text_column, and dict_blobs_description.type=1 and dictionary.is_a_regular_form=0;""") entity_types = ['Paradigm sound'] - upload_audio_simple(session, ids_mapping, simple_paradigm_sound_cursor, create_entities_url, audio_hashes, entity_types, - client_id, False, locale_id) + upload_audio_simple(session, ids_mapping, simple_paradigm_sound_cursor, create_entities_url, audio_hashes, + entity_types, client_id, False, locale_id) change_dict_status(session, converting_status_url, 'Converting 80%') @@ -316,15 +410,36 @@ def prepare_and_upload_text_entities(id_column, is_a_regular_form, text_column, "connections": [{"client_id": client_id, "object_id": object_id}]} status = session.post(connect_url, json=item) log.debug(status.text) + suggestions_url = server_url + 'merge/suggestions' + + suggestions_params = {'threshold': 1.0, + 'levenstein': 0, + 'client_id': perspective['client_id'], + 'object_id': perspective['object_id']} + status = session.post(suggestions_url, json=suggestions_params) + for entry in json.loads(status.text): + if entry['confidence'] >= 1.0: + first_entry = entry['suggestion'][0] + second_entry = entry['suggestion'][1] + lex_move_url = server_url + 'lexical_entry/%d/%d/move' % (second_entry['lexical_entry_client_id'], + second_entry['lexical_entry_object_id']) + move_params = {'client_id': first_entry['lexical_entry_client_id'], + 'object_id': first_entry['lexical_entry_object_id'], + 'real_delete': True} + status = session.patch(lex_move_url, json=move_params) + + else: + break change_dict_status(session, converting_status_url, 'Converted 100%') change_dict_status(session, converting_status_url, 'Published') change_dict_status(session, converting_perspective_status_url, 'Published') - return dictionary + def convert_one(filename, login, password_hash, language_client_id, language_object_id, + dictionary_client_id, dictionary_object_id, perspective_client_id, perspective_object_id, server_url="http://localhost:6543/"): log = logging.getLogger(__name__) log.debug("Starting convert_one") @@ -344,7 +459,8 @@ def convert_one(filename, login, password_hash, language_client_id, language_obj sqconn = sqlite3.connect(filename) log.debug("Connected to sqlite3 database") try: - status = convert_db_new(sqconn, session, language_client_id, language_object_id, server_url) + status = convert_db_new(sqconn, session, language_client_id, language_object_id, server_url, + dictionary_client_id, dictionary_object_id, perspective_client_id, perspective_object_id) except Exception as e: log.error("Converting failed") log.error(e.__traceback__) diff --git a/lingvodoc/scripts/lingvodoc_converter_old.py b/lingvodoc/scripts/lingvodoc_converter_old.py new file mode 100644 index 000000000..27e10156a --- /dev/null +++ b/lingvodoc/scripts/lingvodoc_converter_old.py @@ -0,0 +1,363 @@ +import sqlite3 +import base64 +import requests +import json +import hashlib +import logging + + +def get_dict_attributes(sqconn): + dict_trav = sqconn.cursor() + dict_trav.execute("""SELECT + dict_name, + dict_identificator, + dict_description + FROM + dict_attributes + WHERE + id = 1;""") + req = dict() + for dictionary in dict_trav: + req['dictionary_name'] = dictionary[0] + req['dialeqt_id'] = dictionary[1] + return req + + +def upload_audio(upload_url, audio_sequence, markup_sequence, session): + log = logging.getLogger(__name__) + status = session.post(upload_url, json=audio_sequence) + log.debug(status.text) + audio_ids_list = json.loads(status.text) + if markup_sequence: + for k in range(0, len(audio_ids_list)): + parent_client_id = audio_ids_list[k]['client_id'] + parent_object_id = audio_ids_list[k]['object_id'] + markup_sequence[k]["parent_client_id"] = parent_client_id + markup_sequence[k]["parent_object_id"] = parent_object_id + status = session.post(upload_url, json=markup_sequence) + log.debug(status.text) + + +def upload_audio_simple(session, ids_mapping, sound_and_markup_cursor, upload_url, audio_hashes, entity_types, client_id, is_a_regular_form, + locale_id=1): + audio_sequence = [] + for cursor in sound_and_markup_cursor: + blob_id = cursor[0] + audio = cursor[1] + filename = cursor[2] + word_id = cursor[3] + + if hashlib.sha224(audio).hexdigest() not in audio_hashes: + + audio_element = {"locale_id": locale_id, + "level": "leveloneentity", + "data_type": "sound", + "filename": filename, + "entity_type": entity_types[0], + "parent_client_id": ids_mapping[int(word_id)][0], + "parent_object_id": ids_mapping[int(word_id)][1], + "content": base64.urlsafe_b64encode(audio).decode()} + if not is_a_regular_form: + audio_element['additional_metadata'] = '{"client_id": %s, "row_id": %s}' % (client_id, cursor[4]) + audio_sequence.append(audio_element) + if len(audio_sequence) > 50: + upload_audio(upload_url, audio_sequence, None, session) + audio_sequence = [] + if len(audio_sequence) != 0: + upload_audio(upload_url, audio_sequence, None, session) + audio_sequence = [] + + +def upload_audio_with_markup(session, ids_mapping, sound_and_markup_cursor, upload_url, audio_hashes, entity_types, client_id, is_a_regular_form, + locale_id=1): + audio_sequence = [] + markup_sequence = [] + for cursor in sound_and_markup_cursor: + blob_id = cursor[0] + audio = cursor[1] + markup = cursor[2] + common_name = cursor[3] + word_id = cursor[4] + if not audio or not markup: + continue + audio_hashes.add(hashlib.sha224(audio).hexdigest()) + + audio_element = {"locale_id": locale_id, + "level": "leveloneentity", + "data_type": "sound", + "filename": common_name + ".wav", + "entity_type": entity_types[0], + "parent_client_id": ids_mapping[int(word_id)][0], + "parent_object_id": ids_mapping[int(word_id)][1], + "content": base64.urlsafe_b64encode(audio).decode()} + if not is_a_regular_form: + audio_element['additional_metadata'] = '{"client_id": %s, "row_id": %s}' % (client_id, cursor[5]) + audio_sequence.append(audio_element) + + markup_element = { + "locale_id": locale_id, + "level": "leveltwoentity", + "data_type": "markup", + "filename": common_name + ".TextGrid", + "entity_type": entity_types[1], + # need to set after push "parent_client_id": ids_mapping[int(word_id)][0], + # need to set after push "parent_object_id": ids_mapping[int(word_id)][1], + "content": base64.urlsafe_b64encode(markup).decode()} + if not is_a_regular_form: + audio_element['additional_metadata'] = '{"client_id": %s, "row_id": %s}' % (client_id, cursor[5]) + markup_sequence.append(markup_element) + + if len(audio_sequence) > 50: + upload_audio(upload_url, audio_sequence, markup_sequence, session) + audio_sequence = [] + markup_sequence = [] + + if len(audio_sequence) != 0: + upload_audio(upload_url, audio_sequence, markup_sequence, session) + audio_sequence = [] + markup_sequence = [] + + +def change_dict_status(session, converting_status_url, status): + session.put(converting_status_url, json={'status': status}) + + +def convert_db_new(sqconn, session, language_client_id, language_object_id, server_url, locale_id=1): + log = logging.getLogger(__name__) + dict_attributes = get_dict_attributes(sqconn) + create_dictionary_request = {"parent_client_id": language_client_id, + "parent_object_id": language_object_id, + "translation": dict_attributes['dictionary_name'], + "translation_string": dict_attributes['dictionary_name']} + status = session.post(server_url + 'dictionary', json=create_dictionary_request) + dictionary = json.loads(status.text) + client_id = dictionary['client_id'] + + converting_status_url = server_url + 'dictionary/%s/%s/state' % (dictionary['client_id'], dictionary['object_id']) + + change_dict_status(session, converting_status_url, 'Converting 5%') + + perspective_create_url = server_url + 'dictionary/%s/%s/perspective' % ( + dictionary['client_id'], dictionary['object_id']) + create_perspective_request = {"translation": "Этимологический словарь из Lingvodoc 0.98", + "translation_string": "Lingvodoc 0.98 etymology dictionary", + "import_source": "Lingvodoc-0.98", + "import_hash": dict_attributes['dialeqt_id']} + + status = session.post(perspective_create_url, json=create_perspective_request) + perspective = json.loads(status.text) + + converting_perspective_status_url = server_url + 'dictionary/%s/%s/perspective/%s/%s/state' % \ + (dictionary['client_id'], dictionary['object_id'], + perspective['client_id'], perspective['object_id']) + change_dict_status(session, converting_perspective_status_url, 'Converting') + + create_perspective_fields_request = session.get(server_url + 'dictionary/1/1/perspective/1/1/fields') + perspective_fields_create_url = perspective_create_url + '/%s/%s/fields' % (perspective['client_id'], perspective['object_id']) + status = session.post(perspective_fields_create_url, json=create_perspective_fields_request.text) + + get_all_ids = sqconn.cursor() + get_all_ids.execute("select id from dictionary where is_a_regular_form=1") + + create_lexical_entries_url = perspective_create_url + '/%s/%s/lexical_entries' % ( + perspective['client_id'], perspective['object_id']) + count_cursor = sqconn.cursor() + count_cursor.execute("select count(*) from dictionary where is_a_regular_form=1") + words_count = count_cursor.fetchone()[0] + lexical_entries_create_request = {"count": words_count} + status = session.post(create_lexical_entries_url, json=lexical_entries_create_request) + ids_dict = json.loads(status.text) + + ids_mapping = dict() + i = 0 + for id_cursor in get_all_ids: + id = id_cursor[0] + client_id = ids_dict[i]['client_id'] + object_id = ids_dict[i]['object_id'] + ids_mapping[id] = (client_id, object_id) + i += 1 + + create_entities_url = server_url + 'dictionary/%s/%s/perspective/%s/%s/entities' % (dictionary['client_id'], + dictionary['object_id'], + perspective['client_id'], + perspective['object_id']) + + change_dict_status(session, converting_status_url, 'Converting 15%') + + def create_entity_list(mapping, cursor, level, data_type, entity_type, is_a_regular_form, locale_id=1): + push_list = [] + for ld_cursor in cursor: + ld_id = int(ld_cursor[0]) + content = ld_cursor[1] + parent_client_id = mapping[ld_id][0] + parent_object_id = mapping[ld_id][1] + element = {"locale_id": locale_id, + "level": level, + "data_type": data_type, + "entity_type": entity_type, + "parent_client_id": parent_client_id, + "parent_object_id": parent_object_id, + "content": content} + if not is_a_regular_form: + element['additional_metadata'] = '{"client_id": %s, "row_id": %s}' % (client_id, ld_cursor[2]) + push_list.append(element) + return push_list + + def prepare_and_upload_text_entities(id_column, is_a_regular_form, text_column, entity_type): + sqcursor = sqconn.cursor() + if is_a_regular_form: + sqcursor.execute("select %s,%s from dictionary where is_a_regular_form=1" % (id_column, text_column)) + else: + sqcursor.execute("select %s,%s,id from dictionary where is_a_regular_form=0" % (id_column, text_column)) + push_list = create_entity_list(ids_mapping, sqcursor, "leveloneentity", 'text', entity_type, is_a_regular_form) + return session.post(create_entities_url, json=push_list) + + for column_and_type in [("word", "Word"), + ("transcription", "Transcription"), + ("translation", "Translation")]: + status = prepare_and_upload_text_entities("id", True, column_and_type[0], column_and_type[1]) + log.debug(status.text) + + for column_and_type in [("word", "Paradigm word"), + ("transcription", "Paradigm transcription"), + ("translation", "Paradigm translation")]: + status = prepare_and_upload_text_entities("regular_form", False, column_and_type[0], column_and_type[1]) + log.debug(status.text) + + change_dict_status(session, converting_status_url, 'Converting 35%') + + sound_and_markup_word_cursor = sqconn.cursor() + sound_and_markup_word_cursor.execute("""select blobs.id, + blobs.secblob, + blobs.mainblob, + dict_blobs_description.name, + dictionary.id + from blobs, dict_blobs_description, dictionary + where dict_blobs_description.blobid=blobs.id + and dict_blobs_description.wordid=dictionary.id + and dict_blobs_description.type=2 + and dictionary.is_a_regular_form=1;""") + + audio_hashes = set() + entity_types = ['Sound', 'Praat markup'] + upload_audio_with_markup(session, ids_mapping, sound_and_markup_word_cursor, create_entities_url, audio_hashes, + entity_types, client_id, True, locale_id) + log.debug(audio_hashes) + + change_dict_status(session, converting_status_url, 'Converting 45%') + + paradigm_sound_and_markup_cursor = sqconn.cursor() + paradigm_sound_and_markup_cursor.execute("""select blobs.id, + blobs.secblob, + blobs.mainblob, + dict_blobs_description.name, + dictionary.regular_form, + dictionary.id + from blobs, dict_blobs_description, dictionary + where dict_blobs_description.blobid=blobs.id + and dict_blobs_description.wordid=dictionary.id + and dict_blobs_description.type=2 + and dictionary.is_a_regular_form=0;""") + + entity_types = ['Paradigm sound', "Paradigm Praat markup"] + upload_audio_with_markup(session, ids_mapping, paradigm_sound_and_markup_cursor, create_entities_url, audio_hashes, + entity_types, client_id, False, locale_id) + log.debug(audio_hashes) + + change_dict_status(session, converting_status_url, 'Converting 60%') + + simple_word_sound_cursor = sqconn.cursor() + simple_word_sound_cursor.execute("""select blobs.id, + blobs.mainblob, + dict_blobs_description.name, + dictionary.id + from blobs, dict_blobs_description, dictionary + where dict_blobs_description.blobid=blobs.id + and dict_blobs_description.wordid=dictionary.id + and dict_blobs_description.type=1 + and dictionary.is_a_regular_form=1;""") + entity_types = ['Sound'] + upload_audio_simple(session, ids_mapping, simple_word_sound_cursor, create_entities_url, audio_hashes, entity_types, + client_id, True, locale_id) + + change_dict_status(session, converting_status_url, 'Converting 70%') + + simple_paradigm_sound_cursor = sqconn.cursor() + simple_paradigm_sound_cursor.execute("""select blobs.id, + blobs.mainblob, + dict_blobs_description.name, + dictionary.regular_form, + dictionary.id + from blobs, dict_blobs_description, dictionary + where dict_blobs_description.blobid=blobs.id + and dict_blobs_description.wordid=dictionary.id + and dict_blobs_description.type=1 + and dictionary.is_a_regular_form=0;""") + entity_types = ['Paradigm sound'] + upload_audio_simple(session, ids_mapping, simple_paradigm_sound_cursor, create_entities_url, audio_hashes, entity_types, + client_id, False, locale_id) + + change_dict_status(session, converting_status_url, 'Converting 80%') + + connect_url = server_url + 'dictionary/%s/%s/perspective/%s/%s/lexical_entry/connect' % (dictionary['client_id'], + dictionary['object_id'], + perspective['client_id'], + perspective['object_id']) + etymology_cursor = sqconn.cursor() + etymology_cursor.execute("""select id, etimology_tag + FROM dictionary + WHERE etimology_tag NOT NULL + and dictionary.is_a_regular_form=1; """) + for cursor in etymology_cursor: + id = int(cursor[0]) + client_id = ids_mapping[id][0] + object_id = ids_mapping[id][1] + item = {"entity_type": "Etymology", "tag": cursor[1], + "connections": [{"client_id": client_id, "object_id": object_id}]} + status = session.post(connect_url, json=item) + log.debug(status.text) + + change_dict_status(session, converting_status_url, 'Converted 100%') + + change_dict_status(session, converting_status_url, 'Published') + change_dict_status(session, converting_perspective_status_url, 'Published') + + return dictionary + +def convert_one(filename, login, password_hash, language_client_id, language_object_id, + server_url="http://localhost:6543/"): + log = logging.getLogger(__name__) + log.debug("Starting convert_one") + log.debug("Creating session") + session = requests.Session() + session.headers.update({'Connection': 'Keep-Alive'}) + adapter = requests.adapters.HTTPAdapter(pool_connections=1, pool_maxsize=1, max_retries=3) + session.mount('http://', adapter) + log.debug("Going to login") + login_data = {"login": login, "passwordhash": password_hash} + log.debug("Login data: " + login_data['login'] + login_data['passwordhash']) + cookie_set = session.post(server_url + 'cheatlogin', json=login_data) + log.debug("Login status:" + str(cookie_set.status_code)) + if cookie_set.status_code != 200: + log.error("Cheat login for conversion was unsuccessful") + exit(-1) + sqconn = sqlite3.connect(filename) + log.debug("Connected to sqlite3 database") + try: + status = convert_db_new(sqconn, session, language_client_id, language_object_id, server_url) + except Exception as e: + log.error("Converting failed") + log.error(e.__traceback__) + raise + log.debug(status) + return status + + +if __name__ == "__main__": + log = logging.getLogger(__name__) + log.setLevel(logging.DEBUG) + logging.basicConfig(format='%(asctime)s\t%(levelname)s\t[%(name)s]\t%(message)s') + log.debug("!!!!!!!!!! YOU SHOULD NOT SEE IT !!!!!!!!") + convert_one(filename="/Users/al/Movies/dicts-current/nenets_kaninski.sqlite", login="", + password_hash="", + language_client_id=33, language_object_id=24, server_url="http://lingvodoc.ispras.ru/") diff --git a/lingvodoc/static/js/create-dictionary.js b/lingvodoc/static/js/create-dictionary.js index 7ed780ae1..0a8a14539 100644 --- a/lingvodoc/static/js/create-dictionary.js +++ b/lingvodoc/static/js/create-dictionary.js @@ -5377,6 +5377,3947 @@ return jQuery; }); +(function() { + var undefined; + var VERSION = "3.10.1"; + var BIND_FLAG = 1, BIND_KEY_FLAG = 2, CURRY_BOUND_FLAG = 4, CURRY_FLAG = 8, CURRY_RIGHT_FLAG = 16, PARTIAL_FLAG = 32, PARTIAL_RIGHT_FLAG = 64, ARY_FLAG = 128, REARG_FLAG = 256; + var DEFAULT_TRUNC_LENGTH = 30, DEFAULT_TRUNC_OMISSION = "..."; + var HOT_COUNT = 150, HOT_SPAN = 16; + var LARGE_ARRAY_SIZE = 200; + var LAZY_FILTER_FLAG = 1, LAZY_MAP_FLAG = 2; + var FUNC_ERROR_TEXT = "Expected a function"; + var PLACEHOLDER = "__lodash_placeholder__"; + var argsTag = "[object Arguments]", arrayTag = "[object Array]", boolTag = "[object Boolean]", dateTag = "[object Date]", errorTag = "[object Error]", funcTag = "[object Function]", mapTag = "[object Map]", numberTag = "[object Number]", objectTag = "[object Object]", regexpTag = "[object RegExp]", setTag = "[object Set]", stringTag = "[object String]", weakMapTag = "[object WeakMap]"; + var arrayBufferTag = "[object ArrayBuffer]", float32Tag = "[object Float32Array]", float64Tag = "[object Float64Array]", int8Tag = "[object Int8Array]", int16Tag = "[object Int16Array]", int32Tag = "[object Int32Array]", uint8Tag = "[object Uint8Array]", uint8ClampedTag = "[object Uint8ClampedArray]", uint16Tag = "[object Uint16Array]", uint32Tag = "[object Uint32Array]"; + var reEmptyStringLeading = /\b__p \+= '';/g, reEmptyStringMiddle = /\b(__p \+=) '' \+/g, reEmptyStringTrailing = /(__e\(.*?\)|\b__t\)) \+\n'';/g; + var reEscapedHtml = /&(?:amp|lt|gt|quot|#39|#96);/g, reUnescapedHtml = /[&<>"'`]/g, reHasEscapedHtml = RegExp(reEscapedHtml.source), reHasUnescapedHtml = RegExp(reUnescapedHtml.source); + var reEscape = /<%-([\s\S]+?)%>/g, reEvaluate = /<%([\s\S]+?)%>/g, reInterpolate = /<%=([\s\S]+?)%>/g; + var reIsDeepProp = /\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\n\\]|\\.)*?\1)\]/, reIsPlainProp = /^\w*$/, rePropName = /[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\n\\]|\\.)*?)\2)\]/g; + var reRegExpChars = /^[:!,]|[\\^$.*+?()[\]{}|\/]|(^[0-9a-fA-Fnrtuvx])|([\n\r\u2028\u2029])/g, reHasRegExpChars = RegExp(reRegExpChars.source); + var reComboMark = /[\u0300-\u036f\ufe20-\ufe23]/g; + var reEscapeChar = /\\(\\)?/g; + var reEsTemplate = /\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g; + var reFlags = /\w*$/; + var reHasHexPrefix = /^0[xX]/; + var reIsHostCtor = /^\[object .+?Constructor\]$/; + var reIsUint = /^\d+$/; + var reLatin1 = /[\xc0-\xd6\xd8-\xde\xdf-\xf6\xf8-\xff]/g; + var reNoMatch = /($^)/; + var reUnescapedString = /['\n\r\u2028\u2029\\]/g; + var reWords = function() { + var upper = "[A-Z\\xc0-\\xd6\\xd8-\\xde]", lower = "[a-z\\xdf-\\xf6\\xf8-\\xff]+"; + return RegExp(upper + "+(?=" + upper + lower + ")|" + upper + "?" + lower + "|" + upper + "+|[0-9]+", "g"); + }(); + var contextProps = [ "Array", "ArrayBuffer", "Date", "Error", "Float32Array", "Float64Array", "Function", "Int8Array", "Int16Array", "Int32Array", "Math", "Number", "Object", "RegExp", "Set", "String", "_", "clearTimeout", "isFinite", "parseFloat", "parseInt", "setTimeout", "TypeError", "Uint8Array", "Uint8ClampedArray", "Uint16Array", "Uint32Array", "WeakMap" ]; + var templateCounter = -1; + var typedArrayTags = {}; + typedArrayTags[float32Tag] = typedArrayTags[float64Tag] = typedArrayTags[int8Tag] = typedArrayTags[int16Tag] = typedArrayTags[int32Tag] = typedArrayTags[uint8Tag] = typedArrayTags[uint8ClampedTag] = typedArrayTags[uint16Tag] = typedArrayTags[uint32Tag] = true; + typedArrayTags[argsTag] = typedArrayTags[arrayTag] = typedArrayTags[arrayBufferTag] = typedArrayTags[boolTag] = typedArrayTags[dateTag] = typedArrayTags[errorTag] = typedArrayTags[funcTag] = typedArrayTags[mapTag] = typedArrayTags[numberTag] = typedArrayTags[objectTag] = typedArrayTags[regexpTag] = typedArrayTags[setTag] = typedArrayTags[stringTag] = typedArrayTags[weakMapTag] = false; + var cloneableTags = {}; + cloneableTags[argsTag] = cloneableTags[arrayTag] = cloneableTags[arrayBufferTag] = cloneableTags[boolTag] = cloneableTags[dateTag] = cloneableTags[float32Tag] = cloneableTags[float64Tag] = cloneableTags[int8Tag] = cloneableTags[int16Tag] = cloneableTags[int32Tag] = cloneableTags[numberTag] = cloneableTags[objectTag] = cloneableTags[regexpTag] = cloneableTags[stringTag] = cloneableTags[uint8Tag] = cloneableTags[uint8ClampedTag] = cloneableTags[uint16Tag] = cloneableTags[uint32Tag] = true; + cloneableTags[errorTag] = cloneableTags[funcTag] = cloneableTags[mapTag] = cloneableTags[setTag] = cloneableTags[weakMapTag] = false; + var deburredLetters = { + "À": "A", + "Á": "A", + "Â": "A", + "Ã": "A", + "Ä": "A", + "Å": "A", + "à": "a", + "á": "a", + "â": "a", + "ã": "a", + "ä": "a", + "å": "a", + "Ç": "C", + "ç": "c", + "Ð": "D", + "ð": "d", + "È": "E", + "É": "E", + "Ê": "E", + "Ë": "E", + "è": "e", + "é": "e", + "ê": "e", + "ë": "e", + "Ì": "I", + "Í": "I", + "Î": "I", + "Ï": "I", + "ì": "i", + "í": "i", + "î": "i", + "ï": "i", + "Ñ": "N", + "ñ": "n", + "Ò": "O", + "Ó": "O", + "Ô": "O", + "Õ": "O", + "Ö": "O", + "Ø": "O", + "ò": "o", + "ó": "o", + "ô": "o", + "õ": "o", + "ö": "o", + "ø": "o", + "Ù": "U", + "Ú": "U", + "Û": "U", + "Ü": "U", + "ù": "u", + "ú": "u", + "û": "u", + "ü": "u", + "Ý": "Y", + "ý": "y", + "ÿ": "y", + "Æ": "Ae", + "æ": "ae", + "Þ": "Th", + "þ": "th", + "ß": "ss" + }; + var htmlEscapes = { + "&": "&", + "<": "<", + ">": ">", + '"': """, + "'": "'", + "`": "`" + }; + var htmlUnescapes = { + "&": "&", + "<": "<", + ">": ">", + """: '"', + "'": "'", + "`": "`" + }; + var objectTypes = { + "function": true, + object: true + }; + var regexpEscapes = { + "0": "x30", + "1": "x31", + "2": "x32", + "3": "x33", + "4": "x34", + "5": "x35", + "6": "x36", + "7": "x37", + "8": "x38", + "9": "x39", + A: "x41", + B: "x42", + C: "x43", + D: "x44", + E: "x45", + F: "x46", + a: "x61", + b: "x62", + c: "x63", + d: "x64", + e: "x65", + f: "x66", + n: "x6e", + r: "x72", + t: "x74", + u: "x75", + v: "x76", + x: "x78" + }; + var stringEscapes = { + "\\": "\\", + "'": "'", + "\n": "n", + "\r": "r", + "\u2028": "u2028", + "\u2029": "u2029" + }; + var freeExports = objectTypes[typeof exports] && exports && !exports.nodeType && exports; + var freeModule = objectTypes[typeof module] && module && !module.nodeType && module; + var freeGlobal = freeExports && freeModule && typeof global == "object" && global && global.Object && global; + var freeSelf = objectTypes[typeof self] && self && self.Object && self; + var freeWindow = objectTypes[typeof window] && window && window.Object && window; + var moduleExports = freeModule && freeModule.exports === freeExports && freeExports; + var root = freeGlobal || freeWindow !== (this && this.window) && freeWindow || freeSelf || this; + function baseCompareAscending(value, other) { + if (value !== other) { + var valIsNull = value === null, valIsUndef = value === undefined, valIsReflexive = value === value; + var othIsNull = other === null, othIsUndef = other === undefined, othIsReflexive = other === other; + if (value > other && !othIsNull || !valIsReflexive || valIsNull && !othIsUndef && othIsReflexive || valIsUndef && othIsReflexive) { + return 1; + } + if (value < other && !valIsNull || !othIsReflexive || othIsNull && !valIsUndef && valIsReflexive || othIsUndef && valIsReflexive) { + return -1; + } + } + return 0; + } + function baseFindIndex(array, predicate, fromRight) { + var length = array.length, index = fromRight ? length : -1; + while (fromRight ? index-- : ++index < length) { + if (predicate(array[index], index, array)) { + return index; + } + } + return -1; + } + function baseIndexOf(array, value, fromIndex) { + if (value !== value) { + return indexOfNaN(array, fromIndex); + } + var index = fromIndex - 1, length = array.length; + while (++index < length) { + if (array[index] === value) { + return index; + } + } + return -1; + } + function baseIsFunction(value) { + return typeof value == "function" || false; + } + function baseToString(value) { + return value == null ? "" : value + ""; + } + function charsLeftIndex(string, chars) { + var index = -1, length = string.length; + while (++index < length && chars.indexOf(string.charAt(index)) > -1) {} + return index; + } + function charsRightIndex(string, chars) { + var index = string.length; + while (index-- && chars.indexOf(string.charAt(index)) > -1) {} + return index; + } + function compareAscending(object, other) { + return baseCompareAscending(object.criteria, other.criteria) || object.index - other.index; + } + function compareMultiple(object, other, orders) { + var index = -1, objCriteria = object.criteria, othCriteria = other.criteria, length = objCriteria.length, ordersLength = orders.length; + while (++index < length) { + var result = baseCompareAscending(objCriteria[index], othCriteria[index]); + if (result) { + if (index >= ordersLength) { + return result; + } + var order = orders[index]; + return result * (order === "asc" || order === true ? 1 : -1); + } + } + return object.index - other.index; + } + function deburrLetter(letter) { + return deburredLetters[letter]; + } + function escapeHtmlChar(chr) { + return htmlEscapes[chr]; + } + function escapeRegExpChar(chr, leadingChar, whitespaceChar) { + if (leadingChar) { + chr = regexpEscapes[chr]; + } else if (whitespaceChar) { + chr = stringEscapes[chr]; + } + return "\\" + chr; + } + function escapeStringChar(chr) { + return "\\" + stringEscapes[chr]; + } + function indexOfNaN(array, fromIndex, fromRight) { + var length = array.length, index = fromIndex + (fromRight ? 0 : -1); + while (fromRight ? index-- : ++index < length) { + var other = array[index]; + if (other !== other) { + return index; + } + } + return -1; + } + function isObjectLike(value) { + return !!value && typeof value == "object"; + } + function isSpace(charCode) { + return charCode <= 160 && (charCode >= 9 && charCode <= 13) || charCode == 32 || charCode == 160 || charCode == 5760 || charCode == 6158 || charCode >= 8192 && (charCode <= 8202 || charCode == 8232 || charCode == 8233 || charCode == 8239 || charCode == 8287 || charCode == 12288 || charCode == 65279); + } + function replaceHolders(array, placeholder) { + var index = -1, length = array.length, resIndex = -1, result = []; + while (++index < length) { + if (array[index] === placeholder) { + array[index] = PLACEHOLDER; + result[++resIndex] = index; + } + } + return result; + } + function sortedUniq(array, iteratee) { + var seen, index = -1, length = array.length, resIndex = -1, result = []; + while (++index < length) { + var value = array[index], computed = iteratee ? iteratee(value, index, array) : value; + if (!index || seen !== computed) { + seen = computed; + result[++resIndex] = value; + } + } + return result; + } + function trimmedLeftIndex(string) { + var index = -1, length = string.length; + while (++index < length && isSpace(string.charCodeAt(index))) {} + return index; + } + function trimmedRightIndex(string) { + var index = string.length; + while (index-- && isSpace(string.charCodeAt(index))) {} + return index; + } + function unescapeHtmlChar(chr) { + return htmlUnescapes[chr]; + } + function runInContext(context) { + context = context ? _.defaults(root.Object(), context, _.pick(root, contextProps)) : root; + var Array = context.Array, Date = context.Date, Error = context.Error, Function = context.Function, Math = context.Math, Number = context.Number, Object = context.Object, RegExp = context.RegExp, String = context.String, TypeError = context.TypeError; + var arrayProto = Array.prototype, objectProto = Object.prototype, stringProto = String.prototype; + var fnToString = Function.prototype.toString; + var hasOwnProperty = objectProto.hasOwnProperty; + var idCounter = 0; + var objToString = objectProto.toString; + var oldDash = root._; + var reIsNative = RegExp("^" + fnToString.call(hasOwnProperty).replace(/[\\^$.*+?()[\]{}|]/g, "\\$&").replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g, "$1.*?") + "$"); + var ArrayBuffer = context.ArrayBuffer, clearTimeout = context.clearTimeout, parseFloat = context.parseFloat, pow = Math.pow, propertyIsEnumerable = objectProto.propertyIsEnumerable, Set = getNative(context, "Set"), setTimeout = context.setTimeout, splice = arrayProto.splice, Uint8Array = context.Uint8Array, WeakMap = getNative(context, "WeakMap"); + var nativeCeil = Math.ceil, nativeCreate = getNative(Object, "create"), nativeFloor = Math.floor, nativeIsArray = getNative(Array, "isArray"), nativeIsFinite = context.isFinite, nativeKeys = getNative(Object, "keys"), nativeMax = Math.max, nativeMin = Math.min, nativeNow = getNative(Date, "now"), nativeParseInt = context.parseInt, nativeRandom = Math.random; + var NEGATIVE_INFINITY = Number.NEGATIVE_INFINITY, POSITIVE_INFINITY = Number.POSITIVE_INFINITY; + var MAX_ARRAY_LENGTH = 4294967295, MAX_ARRAY_INDEX = MAX_ARRAY_LENGTH - 1, HALF_MAX_ARRAY_LENGTH = MAX_ARRAY_LENGTH >>> 1; + var MAX_SAFE_INTEGER = 9007199254740991; + var metaMap = WeakMap && new WeakMap(); + var realNames = {}; + function lodash(value) { + if (isObjectLike(value) && !isArray(value) && !(value instanceof LazyWrapper)) { + if (value instanceof LodashWrapper) { + return value; + } + if (hasOwnProperty.call(value, "__chain__") && hasOwnProperty.call(value, "__wrapped__")) { + return wrapperClone(value); + } + } + return new LodashWrapper(value); + } + function baseLodash() {} + function LodashWrapper(value, chainAll, actions) { + this.__wrapped__ = value; + this.__actions__ = actions || []; + this.__chain__ = !!chainAll; + } + var support = lodash.support = {}; + lodash.templateSettings = { + escape: reEscape, + evaluate: reEvaluate, + interpolate: reInterpolate, + variable: "", + imports: { + _: lodash + } + }; + function LazyWrapper(value) { + this.__wrapped__ = value; + this.__actions__ = []; + this.__dir__ = 1; + this.__filtered__ = false; + this.__iteratees__ = []; + this.__takeCount__ = POSITIVE_INFINITY; + this.__views__ = []; + } + function lazyClone() { + var result = new LazyWrapper(this.__wrapped__); + result.__actions__ = arrayCopy(this.__actions__); + result.__dir__ = this.__dir__; + result.__filtered__ = this.__filtered__; + result.__iteratees__ = arrayCopy(this.__iteratees__); + result.__takeCount__ = this.__takeCount__; + result.__views__ = arrayCopy(this.__views__); + return result; + } + function lazyReverse() { + if (this.__filtered__) { + var result = new LazyWrapper(this); + result.__dir__ = -1; + result.__filtered__ = true; + } else { + result = this.clone(); + result.__dir__ *= -1; + } + return result; + } + function lazyValue() { + var array = this.__wrapped__.value(), dir = this.__dir__, isArr = isArray(array), isRight = dir < 0, arrLength = isArr ? array.length : 0, view = getView(0, arrLength, this.__views__), start = view.start, end = view.end, length = end - start, index = isRight ? end : start - 1, iteratees = this.__iteratees__, iterLength = iteratees.length, resIndex = 0, takeCount = nativeMin(length, this.__takeCount__); + if (!isArr || arrLength < LARGE_ARRAY_SIZE || arrLength == length && takeCount == length) { + return baseWrapperValue(array, this.__actions__); + } + var result = []; + outer: while (length-- && resIndex < takeCount) { + index += dir; + var iterIndex = -1, value = array[index]; + while (++iterIndex < iterLength) { + var data = iteratees[iterIndex], iteratee = data.iteratee, type = data.type, computed = iteratee(value); + if (type == LAZY_MAP_FLAG) { + value = computed; + } else if (!computed) { + if (type == LAZY_FILTER_FLAG) { + continue outer; + } else { + break outer; + } + } + } + result[resIndex++] = value; + } + return result; + } + function MapCache() { + this.__data__ = {}; + } + function mapDelete(key) { + return this.has(key) && delete this.__data__[key]; + } + function mapGet(key) { + return key == "__proto__" ? undefined : this.__data__[key]; + } + function mapHas(key) { + return key != "__proto__" && hasOwnProperty.call(this.__data__, key); + } + function mapSet(key, value) { + if (key != "__proto__") { + this.__data__[key] = value; + } + return this; + } + function SetCache(values) { + var length = values ? values.length : 0; + this.data = { + hash: nativeCreate(null), + set: new Set() + }; + while (length--) { + this.push(values[length]); + } + } + function cacheIndexOf(cache, value) { + var data = cache.data, result = typeof value == "string" || isObject(value) ? data.set.has(value) : data.hash[value]; + return result ? 0 : -1; + } + function cachePush(value) { + var data = this.data; + if (typeof value == "string" || isObject(value)) { + data.set.add(value); + } else { + data.hash[value] = true; + } + } + function arrayConcat(array, other) { + var index = -1, length = array.length, othIndex = -1, othLength = other.length, result = Array(length + othLength); + while (++index < length) { + result[index] = array[index]; + } + while (++othIndex < othLength) { + result[index++] = other[othIndex]; + } + return result; + } + function arrayCopy(source, array) { + var index = -1, length = source.length; + array || (array = Array(length)); + while (++index < length) { + array[index] = source[index]; + } + return array; + } + function arrayEach(array, iteratee) { + var index = -1, length = array.length; + while (++index < length) { + if (iteratee(array[index], index, array) === false) { + break; + } + } + return array; + } + function arrayEachRight(array, iteratee) { + var length = array.length; + while (length--) { + if (iteratee(array[length], length, array) === false) { + break; + } + } + return array; + } + function arrayEvery(array, predicate) { + var index = -1, length = array.length; + while (++index < length) { + if (!predicate(array[index], index, array)) { + return false; + } + } + return true; + } + function arrayExtremum(array, iteratee, comparator, exValue) { + var index = -1, length = array.length, computed = exValue, result = computed; + while (++index < length) { + var value = array[index], current = +iteratee(value); + if (comparator(current, computed)) { + computed = current; + result = value; + } + } + return result; + } + function arrayFilter(array, predicate) { + var index = -1, length = array.length, resIndex = -1, result = []; + while (++index < length) { + var value = array[index]; + if (predicate(value, index, array)) { + result[++resIndex] = value; + } + } + return result; + } + function arrayMap(array, iteratee) { + var index = -1, length = array.length, result = Array(length); + while (++index < length) { + result[index] = iteratee(array[index], index, array); + } + return result; + } + function arrayPush(array, values) { + var index = -1, length = values.length, offset = array.length; + while (++index < length) { + array[offset + index] = values[index]; + } + return array; + } + function arrayReduce(array, iteratee, accumulator, initFromArray) { + var index = -1, length = array.length; + if (initFromArray && length) { + accumulator = array[++index]; + } + while (++index < length) { + accumulator = iteratee(accumulator, array[index], index, array); + } + return accumulator; + } + function arrayReduceRight(array, iteratee, accumulator, initFromArray) { + var length = array.length; + if (initFromArray && length) { + accumulator = array[--length]; + } + while (length--) { + accumulator = iteratee(accumulator, array[length], length, array); + } + return accumulator; + } + function arraySome(array, predicate) { + var index = -1, length = array.length; + while (++index < length) { + if (predicate(array[index], index, array)) { + return true; + } + } + return false; + } + function arraySum(array, iteratee) { + var length = array.length, result = 0; + while (length--) { + result += +iteratee(array[length]) || 0; + } + return result; + } + function assignDefaults(objectValue, sourceValue) { + return objectValue === undefined ? sourceValue : objectValue; + } + function assignOwnDefaults(objectValue, sourceValue, key, object) { + return objectValue === undefined || !hasOwnProperty.call(object, key) ? sourceValue : objectValue; + } + function assignWith(object, source, customizer) { + var index = -1, props = keys(source), length = props.length; + while (++index < length) { + var key = props[index], value = object[key], result = customizer(value, source[key], key, object, source); + if ((result === result ? result !== value : value === value) || value === undefined && !(key in object)) { + object[key] = result; + } + } + return object; + } + function baseAssign(object, source) { + return source == null ? object : baseCopy(source, keys(source), object); + } + function baseAt(collection, props) { + var index = -1, isNil = collection == null, isArr = !isNil && isArrayLike(collection), length = isArr ? collection.length : 0, propsLength = props.length, result = Array(propsLength); + while (++index < propsLength) { + var key = props[index]; + if (isArr) { + result[index] = isIndex(key, length) ? collection[key] : undefined; + } else { + result[index] = isNil ? undefined : collection[key]; + } + } + return result; + } + function baseCopy(source, props, object) { + object || (object = {}); + var index = -1, length = props.length; + while (++index < length) { + var key = props[index]; + object[key] = source[key]; + } + return object; + } + function baseCallback(func, thisArg, argCount) { + var type = typeof func; + if (type == "function") { + return thisArg === undefined ? func : bindCallback(func, thisArg, argCount); + } + if (func == null) { + return identity; + } + if (type == "object") { + return baseMatches(func); + } + return thisArg === undefined ? property(func) : baseMatchesProperty(func, thisArg); + } + function baseClone(value, isDeep, customizer, key, object, stackA, stackB) { + var result; + if (customizer) { + result = object ? customizer(value, key, object) : customizer(value); + } + if (result !== undefined) { + return result; + } + if (!isObject(value)) { + return value; + } + var isArr = isArray(value); + if (isArr) { + result = initCloneArray(value); + if (!isDeep) { + return arrayCopy(value, result); + } + } else { + var tag = objToString.call(value), isFunc = tag == funcTag; + if (tag == objectTag || tag == argsTag || isFunc && !object) { + result = initCloneObject(isFunc ? {} : value); + if (!isDeep) { + return baseAssign(result, value); + } + } else { + return cloneableTags[tag] ? initCloneByTag(value, tag, isDeep) : object ? value : {}; + } + } + stackA || (stackA = []); + stackB || (stackB = []); + var length = stackA.length; + while (length--) { + if (stackA[length] == value) { + return stackB[length]; + } + } + stackA.push(value); + stackB.push(result); + (isArr ? arrayEach : baseForOwn)(value, function(subValue, key) { + result[key] = baseClone(subValue, isDeep, customizer, key, value, stackA, stackB); + }); + return result; + } + var baseCreate = function() { + function object() {} + return function(prototype) { + if (isObject(prototype)) { + object.prototype = prototype; + var result = new object(); + object.prototype = undefined; + } + return result || {}; + }; + }(); + function baseDelay(func, wait, args) { + if (typeof func != "function") { + throw new TypeError(FUNC_ERROR_TEXT); + } + return setTimeout(function() { + func.apply(undefined, args); + }, wait); + } + function baseDifference(array, values) { + var length = array ? array.length : 0, result = []; + if (!length) { + return result; + } + var index = -1, indexOf = getIndexOf(), isCommon = indexOf === baseIndexOf, cache = isCommon && values.length >= LARGE_ARRAY_SIZE ? createCache(values) : null, valuesLength = values.length; + if (cache) { + indexOf = cacheIndexOf; + isCommon = false; + values = cache; + } + outer: while (++index < length) { + var value = array[index]; + if (isCommon && value === value) { + var valuesIndex = valuesLength; + while (valuesIndex--) { + if (values[valuesIndex] === value) { + continue outer; + } + } + result.push(value); + } else if (indexOf(values, value, 0) < 0) { + result.push(value); + } + } + return result; + } + var baseEach = createBaseEach(baseForOwn); + var baseEachRight = createBaseEach(baseForOwnRight, true); + function baseEvery(collection, predicate) { + var result = true; + baseEach(collection, function(value, index, collection) { + result = !!predicate(value, index, collection); + return result; + }); + return result; + } + function baseExtremum(collection, iteratee, comparator, exValue) { + var computed = exValue, result = computed; + baseEach(collection, function(value, index, collection) { + var current = +iteratee(value, index, collection); + if (comparator(current, computed) || current === exValue && current === result) { + computed = current; + result = value; + } + }); + return result; + } + function baseFill(array, value, start, end) { + var length = array.length; + start = start == null ? 0 : +start || 0; + if (start < 0) { + start = -start > length ? 0 : length + start; + } + end = end === undefined || end > length ? length : +end || 0; + if (end < 0) { + end += length; + } + length = start > end ? 0 : end >>> 0; + start >>>= 0; + while (start < length) { + array[start++] = value; + } + return array; + } + function baseFilter(collection, predicate) { + var result = []; + baseEach(collection, function(value, index, collection) { + if (predicate(value, index, collection)) { + result.push(value); + } + }); + return result; + } + function baseFind(collection, predicate, eachFunc, retKey) { + var result; + eachFunc(collection, function(value, key, collection) { + if (predicate(value, key, collection)) { + result = retKey ? key : value; + return false; + } + }); + return result; + } + function baseFlatten(array, isDeep, isStrict, result) { + result || (result = []); + var index = -1, length = array.length; + while (++index < length) { + var value = array[index]; + if (isObjectLike(value) && isArrayLike(value) && (isStrict || isArray(value) || isArguments(value))) { + if (isDeep) { + baseFlatten(value, isDeep, isStrict, result); + } else { + arrayPush(result, value); + } + } else if (!isStrict) { + result[result.length] = value; + } + } + return result; + } + var baseFor = createBaseFor(); + var baseForRight = createBaseFor(true); + function baseForIn(object, iteratee) { + return baseFor(object, iteratee, keysIn); + } + function baseForOwn(object, iteratee) { + return baseFor(object, iteratee, keys); + } + function baseForOwnRight(object, iteratee) { + return baseForRight(object, iteratee, keys); + } + function baseFunctions(object, props) { + var index = -1, length = props.length, resIndex = -1, result = []; + while (++index < length) { + var key = props[index]; + if (isFunction(object[key])) { + result[++resIndex] = key; + } + } + return result; + } + function baseGet(object, path, pathKey) { + if (object == null) { + return; + } + if (pathKey !== undefined && pathKey in toObject(object)) { + path = [ pathKey ]; + } + var index = 0, length = path.length; + while (object != null && index < length) { + object = object[path[index++]]; + } + return index && index == length ? object : undefined; + } + function baseIsEqual(value, other, customizer, isLoose, stackA, stackB) { + if (value === other) { + return true; + } + if (value == null || other == null || !isObject(value) && !isObjectLike(other)) { + return value !== value && other !== other; + } + return baseIsEqualDeep(value, other, baseIsEqual, customizer, isLoose, stackA, stackB); + } + function baseIsEqualDeep(object, other, equalFunc, customizer, isLoose, stackA, stackB) { + var objIsArr = isArray(object), othIsArr = isArray(other), objTag = arrayTag, othTag = arrayTag; + if (!objIsArr) { + objTag = objToString.call(object); + if (objTag == argsTag) { + objTag = objectTag; + } else if (objTag != objectTag) { + objIsArr = isTypedArray(object); + } + } + if (!othIsArr) { + othTag = objToString.call(other); + if (othTag == argsTag) { + othTag = objectTag; + } else if (othTag != objectTag) { + othIsArr = isTypedArray(other); + } + } + var objIsObj = objTag == objectTag, othIsObj = othTag == objectTag, isSameTag = objTag == othTag; + if (isSameTag && !(objIsArr || objIsObj)) { + return equalByTag(object, other, objTag); + } + if (!isLoose) { + var objIsWrapped = objIsObj && hasOwnProperty.call(object, "__wrapped__"), othIsWrapped = othIsObj && hasOwnProperty.call(other, "__wrapped__"); + if (objIsWrapped || othIsWrapped) { + return equalFunc(objIsWrapped ? object.value() : object, othIsWrapped ? other.value() : other, customizer, isLoose, stackA, stackB); + } + } + if (!isSameTag) { + return false; + } + stackA || (stackA = []); + stackB || (stackB = []); + var length = stackA.length; + while (length--) { + if (stackA[length] == object) { + return stackB[length] == other; + } + } + stackA.push(object); + stackB.push(other); + var result = (objIsArr ? equalArrays : equalObjects)(object, other, equalFunc, customizer, isLoose, stackA, stackB); + stackA.pop(); + stackB.pop(); + return result; + } + function baseIsMatch(object, matchData, customizer) { + var index = matchData.length, length = index, noCustomizer = !customizer; + if (object == null) { + return !length; + } + object = toObject(object); + while (index--) { + var data = matchData[index]; + if (noCustomizer && data[2] ? data[1] !== object[data[0]] : !(data[0] in object)) { + return false; + } + } + while (++index < length) { + data = matchData[index]; + var key = data[0], objValue = object[key], srcValue = data[1]; + if (noCustomizer && data[2]) { + if (objValue === undefined && !(key in object)) { + return false; + } + } else { + var result = customizer ? customizer(objValue, srcValue, key) : undefined; + if (!(result === undefined ? baseIsEqual(srcValue, objValue, customizer, true) : result)) { + return false; + } + } + } + return true; + } + function baseMap(collection, iteratee) { + var index = -1, result = isArrayLike(collection) ? Array(collection.length) : []; + baseEach(collection, function(value, key, collection) { + result[++index] = iteratee(value, key, collection); + }); + return result; + } + function baseMatches(source) { + var matchData = getMatchData(source); + if (matchData.length == 1 && matchData[0][2]) { + var key = matchData[0][0], value = matchData[0][1]; + return function(object) { + if (object == null) { + return false; + } + return object[key] === value && (value !== undefined || key in toObject(object)); + }; + } + return function(object) { + return baseIsMatch(object, matchData); + }; + } + function baseMatchesProperty(path, srcValue) { + var isArr = isArray(path), isCommon = isKey(path) && isStrictComparable(srcValue), pathKey = path + ""; + path = toPath(path); + return function(object) { + if (object == null) { + return false; + } + var key = pathKey; + object = toObject(object); + if ((isArr || !isCommon) && !(key in object)) { + object = path.length == 1 ? object : baseGet(object, baseSlice(path, 0, -1)); + if (object == null) { + return false; + } + key = last(path); + object = toObject(object); + } + return object[key] === srcValue ? srcValue !== undefined || key in object : baseIsEqual(srcValue, object[key], undefined, true); + }; + } + function baseMerge(object, source, customizer, stackA, stackB) { + if (!isObject(object)) { + return object; + } + var isSrcArr = isArrayLike(source) && (isArray(source) || isTypedArray(source)), props = isSrcArr ? undefined : keys(source); + arrayEach(props || source, function(srcValue, key) { + if (props) { + key = srcValue; + srcValue = source[key]; + } + if (isObjectLike(srcValue)) { + stackA || (stackA = []); + stackB || (stackB = []); + baseMergeDeep(object, source, key, baseMerge, customizer, stackA, stackB); + } else { + var value = object[key], result = customizer ? customizer(value, srcValue, key, object, source) : undefined, isCommon = result === undefined; + if (isCommon) { + result = srcValue; + } + if ((result !== undefined || isSrcArr && !(key in object)) && (isCommon || (result === result ? result !== value : value === value))) { + object[key] = result; + } + } + }); + return object; + } + function baseMergeDeep(object, source, key, mergeFunc, customizer, stackA, stackB) { + var length = stackA.length, srcValue = source[key]; + while (length--) { + if (stackA[length] == srcValue) { + object[key] = stackB[length]; + return; + } + } + var value = object[key], result = customizer ? customizer(value, srcValue, key, object, source) : undefined, isCommon = result === undefined; + if (isCommon) { + result = srcValue; + if (isArrayLike(srcValue) && (isArray(srcValue) || isTypedArray(srcValue))) { + result = isArray(value) ? value : isArrayLike(value) ? arrayCopy(value) : []; + } else if (isPlainObject(srcValue) || isArguments(srcValue)) { + result = isArguments(value) ? toPlainObject(value) : isPlainObject(value) ? value : {}; + } else { + isCommon = false; + } + } + stackA.push(srcValue); + stackB.push(result); + if (isCommon) { + object[key] = mergeFunc(result, srcValue, customizer, stackA, stackB); + } else if (result === result ? result !== value : value === value) { + object[key] = result; + } + } + function baseProperty(key) { + return function(object) { + return object == null ? undefined : object[key]; + }; + } + function basePropertyDeep(path) { + var pathKey = path + ""; + path = toPath(path); + return function(object) { + return baseGet(object, path, pathKey); + }; + } + function basePullAt(array, indexes) { + var length = array ? indexes.length : 0; + while (length--) { + var index = indexes[length]; + if (index != previous && isIndex(index)) { + var previous = index; + splice.call(array, index, 1); + } + } + return array; + } + function baseRandom(min, max) { + return min + nativeFloor(nativeRandom() * (max - min + 1)); + } + function baseReduce(collection, iteratee, accumulator, initFromCollection, eachFunc) { + eachFunc(collection, function(value, index, collection) { + accumulator = initFromCollection ? (initFromCollection = false, value) : iteratee(accumulator, value, index, collection); + }); + return accumulator; + } + var baseSetData = !metaMap ? identity : function(func, data) { + metaMap.set(func, data); + return func; + }; + function baseSlice(array, start, end) { + var index = -1, length = array.length; + start = start == null ? 0 : +start || 0; + if (start < 0) { + start = -start > length ? 0 : length + start; + } + end = end === undefined || end > length ? length : +end || 0; + if (end < 0) { + end += length; + } + length = start > end ? 0 : end - start >>> 0; + start >>>= 0; + var result = Array(length); + while (++index < length) { + result[index] = array[index + start]; + } + return result; + } + function baseSome(collection, predicate) { + var result; + baseEach(collection, function(value, index, collection) { + result = predicate(value, index, collection); + return !result; + }); + return !!result; + } + function baseSortBy(array, comparer) { + var length = array.length; + array.sort(comparer); + while (length--) { + array[length] = array[length].value; + } + return array; + } + function baseSortByOrder(collection, iteratees, orders) { + var callback = getCallback(), index = -1; + iteratees = arrayMap(iteratees, function(iteratee) { + return callback(iteratee); + }); + var result = baseMap(collection, function(value) { + var criteria = arrayMap(iteratees, function(iteratee) { + return iteratee(value); + }); + return { + criteria: criteria, + index: ++index, + value: value + }; + }); + return baseSortBy(result, function(object, other) { + return compareMultiple(object, other, orders); + }); + } + function baseSum(collection, iteratee) { + var result = 0; + baseEach(collection, function(value, index, collection) { + result += +iteratee(value, index, collection) || 0; + }); + return result; + } + function baseUniq(array, iteratee) { + var index = -1, indexOf = getIndexOf(), length = array.length, isCommon = indexOf === baseIndexOf, isLarge = isCommon && length >= LARGE_ARRAY_SIZE, seen = isLarge ? createCache() : null, result = []; + if (seen) { + indexOf = cacheIndexOf; + isCommon = false; + } else { + isLarge = false; + seen = iteratee ? [] : result; + } + outer: while (++index < length) { + var value = array[index], computed = iteratee ? iteratee(value, index, array) : value; + if (isCommon && value === value) { + var seenIndex = seen.length; + while (seenIndex--) { + if (seen[seenIndex] === computed) { + continue outer; + } + } + if (iteratee) { + seen.push(computed); + } + result.push(value); + } else if (indexOf(seen, computed, 0) < 0) { + if (iteratee || isLarge) { + seen.push(computed); + } + result.push(value); + } + } + return result; + } + function baseValues(object, props) { + var index = -1, length = props.length, result = Array(length); + while (++index < length) { + result[index] = object[props[index]]; + } + return result; + } + function baseWhile(array, predicate, isDrop, fromRight) { + var length = array.length, index = fromRight ? length : -1; + while ((fromRight ? index-- : ++index < length) && predicate(array[index], index, array)) {} + return isDrop ? baseSlice(array, fromRight ? 0 : index, fromRight ? index + 1 : length) : baseSlice(array, fromRight ? index + 1 : 0, fromRight ? length : index); + } + function baseWrapperValue(value, actions) { + var result = value; + if (result instanceof LazyWrapper) { + result = result.value(); + } + var index = -1, length = actions.length; + while (++index < length) { + var action = actions[index]; + result = action.func.apply(action.thisArg, arrayPush([ result ], action.args)); + } + return result; + } + function binaryIndex(array, value, retHighest) { + var low = 0, high = array ? array.length : low; + if (typeof value == "number" && value === value && high <= HALF_MAX_ARRAY_LENGTH) { + while (low < high) { + var mid = low + high >>> 1, computed = array[mid]; + if ((retHighest ? computed <= value : computed < value) && computed !== null) { + low = mid + 1; + } else { + high = mid; + } + } + return high; + } + return binaryIndexBy(array, value, identity, retHighest); + } + function binaryIndexBy(array, value, iteratee, retHighest) { + value = iteratee(value); + var low = 0, high = array ? array.length : 0, valIsNaN = value !== value, valIsNull = value === null, valIsUndef = value === undefined; + while (low < high) { + var mid = nativeFloor((low + high) / 2), computed = iteratee(array[mid]), isDef = computed !== undefined, isReflexive = computed === computed; + if (valIsNaN) { + var setLow = isReflexive || retHighest; + } else if (valIsNull) { + setLow = isReflexive && isDef && (retHighest || computed != null); + } else if (valIsUndef) { + setLow = isReflexive && (retHighest || isDef); + } else if (computed == null) { + setLow = false; + } else { + setLow = retHighest ? computed <= value : computed < value; + } + if (setLow) { + low = mid + 1; + } else { + high = mid; + } + } + return nativeMin(high, MAX_ARRAY_INDEX); + } + function bindCallback(func, thisArg, argCount) { + if (typeof func != "function") { + return identity; + } + if (thisArg === undefined) { + return func; + } + switch (argCount) { + case 1: + return function(value) { + return func.call(thisArg, value); + }; + + case 3: + return function(value, index, collection) { + return func.call(thisArg, value, index, collection); + }; + + case 4: + return function(accumulator, value, index, collection) { + return func.call(thisArg, accumulator, value, index, collection); + }; + + case 5: + return function(value, other, key, object, source) { + return func.call(thisArg, value, other, key, object, source); + }; + } + return function() { + return func.apply(thisArg, arguments); + }; + } + function bufferClone(buffer) { + var result = new ArrayBuffer(buffer.byteLength), view = new Uint8Array(result); + view.set(new Uint8Array(buffer)); + return result; + } + function composeArgs(args, partials, holders) { + var holdersLength = holders.length, argsIndex = -1, argsLength = nativeMax(args.length - holdersLength, 0), leftIndex = -1, leftLength = partials.length, result = Array(leftLength + argsLength); + while (++leftIndex < leftLength) { + result[leftIndex] = partials[leftIndex]; + } + while (++argsIndex < holdersLength) { + result[holders[argsIndex]] = args[argsIndex]; + } + while (argsLength--) { + result[leftIndex++] = args[argsIndex++]; + } + return result; + } + function composeArgsRight(args, partials, holders) { + var holdersIndex = -1, holdersLength = holders.length, argsIndex = -1, argsLength = nativeMax(args.length - holdersLength, 0), rightIndex = -1, rightLength = partials.length, result = Array(argsLength + rightLength); + while (++argsIndex < argsLength) { + result[argsIndex] = args[argsIndex]; + } + var offset = argsIndex; + while (++rightIndex < rightLength) { + result[offset + rightIndex] = partials[rightIndex]; + } + while (++holdersIndex < holdersLength) { + result[offset + holders[holdersIndex]] = args[argsIndex++]; + } + return result; + } + function createAggregator(setter, initializer) { + return function(collection, iteratee, thisArg) { + var result = initializer ? initializer() : {}; + iteratee = getCallback(iteratee, thisArg, 3); + if (isArray(collection)) { + var index = -1, length = collection.length; + while (++index < length) { + var value = collection[index]; + setter(result, value, iteratee(value, index, collection), collection); + } + } else { + baseEach(collection, function(value, key, collection) { + setter(result, value, iteratee(value, key, collection), collection); + }); + } + return result; + }; + } + function createAssigner(assigner) { + return restParam(function(object, sources) { + var index = -1, length = object == null ? 0 : sources.length, customizer = length > 2 ? sources[length - 2] : undefined, guard = length > 2 ? sources[2] : undefined, thisArg = length > 1 ? sources[length - 1] : undefined; + if (typeof customizer == "function") { + customizer = bindCallback(customizer, thisArg, 5); + length -= 2; + } else { + customizer = typeof thisArg == "function" ? thisArg : undefined; + length -= customizer ? 1 : 0; + } + if (guard && isIterateeCall(sources[0], sources[1], guard)) { + customizer = length < 3 ? undefined : customizer; + length = 1; + } + while (++index < length) { + var source = sources[index]; + if (source) { + assigner(object, source, customizer); + } + } + return object; + }); + } + function createBaseEach(eachFunc, fromRight) { + return function(collection, iteratee) { + var length = collection ? getLength(collection) : 0; + if (!isLength(length)) { + return eachFunc(collection, iteratee); + } + var index = fromRight ? length : -1, iterable = toObject(collection); + while (fromRight ? index-- : ++index < length) { + if (iteratee(iterable[index], index, iterable) === false) { + break; + } + } + return collection; + }; + } + function createBaseFor(fromRight) { + return function(object, iteratee, keysFunc) { + var iterable = toObject(object), props = keysFunc(object), length = props.length, index = fromRight ? length : -1; + while (fromRight ? index-- : ++index < length) { + var key = props[index]; + if (iteratee(iterable[key], key, iterable) === false) { + break; + } + } + return object; + }; + } + function createBindWrapper(func, thisArg) { + var Ctor = createCtorWrapper(func); + function wrapper() { + var fn = this && this !== root && this instanceof wrapper ? Ctor : func; + return fn.apply(thisArg, arguments); + } + return wrapper; + } + function createCache(values) { + return nativeCreate && Set ? new SetCache(values) : null; + } + function createCompounder(callback) { + return function(string) { + var index = -1, array = words(deburr(string)), length = array.length, result = ""; + while (++index < length) { + result = callback(result, array[index], index); + } + return result; + }; + } + function createCtorWrapper(Ctor) { + return function() { + var args = arguments; + switch (args.length) { + case 0: + return new Ctor(); + + case 1: + return new Ctor(args[0]); + + case 2: + return new Ctor(args[0], args[1]); + + case 3: + return new Ctor(args[0], args[1], args[2]); + + case 4: + return new Ctor(args[0], args[1], args[2], args[3]); + + case 5: + return new Ctor(args[0], args[1], args[2], args[3], args[4]); + + case 6: + return new Ctor(args[0], args[1], args[2], args[3], args[4], args[5]); + + case 7: + return new Ctor(args[0], args[1], args[2], args[3], args[4], args[5], args[6]); + } + var thisBinding = baseCreate(Ctor.prototype), result = Ctor.apply(thisBinding, args); + return isObject(result) ? result : thisBinding; + }; + } + function createCurry(flag) { + function curryFunc(func, arity, guard) { + if (guard && isIterateeCall(func, arity, guard)) { + arity = undefined; + } + var result = createWrapper(func, flag, undefined, undefined, undefined, undefined, undefined, arity); + result.placeholder = curryFunc.placeholder; + return result; + } + return curryFunc; + } + function createDefaults(assigner, customizer) { + return restParam(function(args) { + var object = args[0]; + if (object == null) { + return object; + } + args.push(customizer); + return assigner.apply(undefined, args); + }); + } + function createExtremum(comparator, exValue) { + return function(collection, iteratee, thisArg) { + if (thisArg && isIterateeCall(collection, iteratee, thisArg)) { + iteratee = undefined; + } + iteratee = getCallback(iteratee, thisArg, 3); + if (iteratee.length == 1) { + collection = isArray(collection) ? collection : toIterable(collection); + var result = arrayExtremum(collection, iteratee, comparator, exValue); + if (!(collection.length && result === exValue)) { + return result; + } + } + return baseExtremum(collection, iteratee, comparator, exValue); + }; + } + function createFind(eachFunc, fromRight) { + return function(collection, predicate, thisArg) { + predicate = getCallback(predicate, thisArg, 3); + if (isArray(collection)) { + var index = baseFindIndex(collection, predicate, fromRight); + return index > -1 ? collection[index] : undefined; + } + return baseFind(collection, predicate, eachFunc); + }; + } + function createFindIndex(fromRight) { + return function(array, predicate, thisArg) { + if (!(array && array.length)) { + return -1; + } + predicate = getCallback(predicate, thisArg, 3); + return baseFindIndex(array, predicate, fromRight); + }; + } + function createFindKey(objectFunc) { + return function(object, predicate, thisArg) { + predicate = getCallback(predicate, thisArg, 3); + return baseFind(object, predicate, objectFunc, true); + }; + } + function createFlow(fromRight) { + return function() { + var wrapper, length = arguments.length, index = fromRight ? length : -1, leftIndex = 0, funcs = Array(length); + while (fromRight ? index-- : ++index < length) { + var func = funcs[leftIndex++] = arguments[index]; + if (typeof func != "function") { + throw new TypeError(FUNC_ERROR_TEXT); + } + if (!wrapper && LodashWrapper.prototype.thru && getFuncName(func) == "wrapper") { + wrapper = new LodashWrapper([], true); + } + } + index = wrapper ? -1 : length; + while (++index < length) { + func = funcs[index]; + var funcName = getFuncName(func), data = funcName == "wrapper" ? getData(func) : undefined; + if (data && isLaziable(data[0]) && data[1] == (ARY_FLAG | CURRY_FLAG | PARTIAL_FLAG | REARG_FLAG) && !data[4].length && data[9] == 1) { + wrapper = wrapper[getFuncName(data[0])].apply(wrapper, data[3]); + } else { + wrapper = func.length == 1 && isLaziable(func) ? wrapper[funcName]() : wrapper.thru(func); + } + } + return function() { + var args = arguments, value = args[0]; + if (wrapper && args.length == 1 && isArray(value) && value.length >= LARGE_ARRAY_SIZE) { + return wrapper.plant(value).value(); + } + var index = 0, result = length ? funcs[index].apply(this, args) : value; + while (++index < length) { + result = funcs[index].call(this, result); + } + return result; + }; + }; + } + function createForEach(arrayFunc, eachFunc) { + return function(collection, iteratee, thisArg) { + return typeof iteratee == "function" && thisArg === undefined && isArray(collection) ? arrayFunc(collection, iteratee) : eachFunc(collection, bindCallback(iteratee, thisArg, 3)); + }; + } + function createForIn(objectFunc) { + return function(object, iteratee, thisArg) { + if (typeof iteratee != "function" || thisArg !== undefined) { + iteratee = bindCallback(iteratee, thisArg, 3); + } + return objectFunc(object, iteratee, keysIn); + }; + } + function createForOwn(objectFunc) { + return function(object, iteratee, thisArg) { + if (typeof iteratee != "function" || thisArg !== undefined) { + iteratee = bindCallback(iteratee, thisArg, 3); + } + return objectFunc(object, iteratee); + }; + } + function createObjectMapper(isMapKeys) { + return function(object, iteratee, thisArg) { + var result = {}; + iteratee = getCallback(iteratee, thisArg, 3); + baseForOwn(object, function(value, key, object) { + var mapped = iteratee(value, key, object); + key = isMapKeys ? mapped : key; + value = isMapKeys ? value : mapped; + result[key] = value; + }); + return result; + }; + } + function createPadDir(fromRight) { + return function(string, length, chars) { + string = baseToString(string); + return (fromRight ? string : "") + createPadding(string, length, chars) + (fromRight ? "" : string); + }; + } + function createPartial(flag) { + var partialFunc = restParam(function(func, partials) { + var holders = replaceHolders(partials, partialFunc.placeholder); + return createWrapper(func, flag, undefined, partials, holders); + }); + return partialFunc; + } + function createReduce(arrayFunc, eachFunc) { + return function(collection, iteratee, accumulator, thisArg) { + var initFromArray = arguments.length < 3; + return typeof iteratee == "function" && thisArg === undefined && isArray(collection) ? arrayFunc(collection, iteratee, accumulator, initFromArray) : baseReduce(collection, getCallback(iteratee, thisArg, 4), accumulator, initFromArray, eachFunc); + }; + } + function createHybridWrapper(func, bitmask, thisArg, partials, holders, partialsRight, holdersRight, argPos, ary, arity) { + var isAry = bitmask & ARY_FLAG, isBind = bitmask & BIND_FLAG, isBindKey = bitmask & BIND_KEY_FLAG, isCurry = bitmask & CURRY_FLAG, isCurryBound = bitmask & CURRY_BOUND_FLAG, isCurryRight = bitmask & CURRY_RIGHT_FLAG, Ctor = isBindKey ? undefined : createCtorWrapper(func); + function wrapper() { + var length = arguments.length, index = length, args = Array(length); + while (index--) { + args[index] = arguments[index]; + } + if (partials) { + args = composeArgs(args, partials, holders); + } + if (partialsRight) { + args = composeArgsRight(args, partialsRight, holdersRight); + } + if (isCurry || isCurryRight) { + var placeholder = wrapper.placeholder, argsHolders = replaceHolders(args, placeholder); + length -= argsHolders.length; + if (length < arity) { + var newArgPos = argPos ? arrayCopy(argPos) : undefined, newArity = nativeMax(arity - length, 0), newsHolders = isCurry ? argsHolders : undefined, newHoldersRight = isCurry ? undefined : argsHolders, newPartials = isCurry ? args : undefined, newPartialsRight = isCurry ? undefined : args; + bitmask |= isCurry ? PARTIAL_FLAG : PARTIAL_RIGHT_FLAG; + bitmask &= ~(isCurry ? PARTIAL_RIGHT_FLAG : PARTIAL_FLAG); + if (!isCurryBound) { + bitmask &= ~(BIND_FLAG | BIND_KEY_FLAG); + } + var newData = [ func, bitmask, thisArg, newPartials, newsHolders, newPartialsRight, newHoldersRight, newArgPos, ary, newArity ], result = createHybridWrapper.apply(undefined, newData); + if (isLaziable(func)) { + setData(result, newData); + } + result.placeholder = placeholder; + return result; + } + } + var thisBinding = isBind ? thisArg : this, fn = isBindKey ? thisBinding[func] : func; + if (argPos) { + args = reorder(args, argPos); + } + if (isAry && ary < args.length) { + args.length = ary; + } + if (this && this !== root && this instanceof wrapper) { + fn = Ctor || createCtorWrapper(func); + } + return fn.apply(thisBinding, args); + } + return wrapper; + } + function createPadding(string, length, chars) { + var strLength = string.length; + length = +length; + if (strLength >= length || !nativeIsFinite(length)) { + return ""; + } + var padLength = length - strLength; + chars = chars == null ? " " : chars + ""; + return repeat(chars, nativeCeil(padLength / chars.length)).slice(0, padLength); + } + function createPartialWrapper(func, bitmask, thisArg, partials) { + var isBind = bitmask & BIND_FLAG, Ctor = createCtorWrapper(func); + function wrapper() { + var argsIndex = -1, argsLength = arguments.length, leftIndex = -1, leftLength = partials.length, args = Array(leftLength + argsLength); + while (++leftIndex < leftLength) { + args[leftIndex] = partials[leftIndex]; + } + while (argsLength--) { + args[leftIndex++] = arguments[++argsIndex]; + } + var fn = this && this !== root && this instanceof wrapper ? Ctor : func; + return fn.apply(isBind ? thisArg : this, args); + } + return wrapper; + } + function createRound(methodName) { + var func = Math[methodName]; + return function(number, precision) { + precision = precision === undefined ? 0 : +precision || 0; + if (precision) { + precision = pow(10, precision); + return func(number * precision) / precision; + } + return func(number); + }; + } + function createSortedIndex(retHighest) { + return function(array, value, iteratee, thisArg) { + var callback = getCallback(iteratee); + return iteratee == null && callback === baseCallback ? binaryIndex(array, value, retHighest) : binaryIndexBy(array, value, callback(iteratee, thisArg, 1), retHighest); + }; + } + function createWrapper(func, bitmask, thisArg, partials, holders, argPos, ary, arity) { + var isBindKey = bitmask & BIND_KEY_FLAG; + if (!isBindKey && typeof func != "function") { + throw new TypeError(FUNC_ERROR_TEXT); + } + var length = partials ? partials.length : 0; + if (!length) { + bitmask &= ~(PARTIAL_FLAG | PARTIAL_RIGHT_FLAG); + partials = holders = undefined; + } + length -= holders ? holders.length : 0; + if (bitmask & PARTIAL_RIGHT_FLAG) { + var partialsRight = partials, holdersRight = holders; + partials = holders = undefined; + } + var data = isBindKey ? undefined : getData(func), newData = [ func, bitmask, thisArg, partials, holders, partialsRight, holdersRight, argPos, ary, arity ]; + if (data) { + mergeData(newData, data); + bitmask = newData[1]; + arity = newData[9]; + } + newData[9] = arity == null ? isBindKey ? 0 : func.length : nativeMax(arity - length, 0) || 0; + if (bitmask == BIND_FLAG) { + var result = createBindWrapper(newData[0], newData[2]); + } else if ((bitmask == PARTIAL_FLAG || bitmask == (BIND_FLAG | PARTIAL_FLAG)) && !newData[4].length) { + result = createPartialWrapper.apply(undefined, newData); + } else { + result = createHybridWrapper.apply(undefined, newData); + } + var setter = data ? baseSetData : setData; + return setter(result, newData); + } + function equalArrays(array, other, equalFunc, customizer, isLoose, stackA, stackB) { + var index = -1, arrLength = array.length, othLength = other.length; + if (arrLength != othLength && !(isLoose && othLength > arrLength)) { + return false; + } + while (++index < arrLength) { + var arrValue = array[index], othValue = other[index], result = customizer ? customizer(isLoose ? othValue : arrValue, isLoose ? arrValue : othValue, index) : undefined; + if (result !== undefined) { + if (result) { + continue; + } + return false; + } + if (isLoose) { + if (!arraySome(other, function(othValue) { + return arrValue === othValue || equalFunc(arrValue, othValue, customizer, isLoose, stackA, stackB); + })) { + return false; + } + } else if (!(arrValue === othValue || equalFunc(arrValue, othValue, customizer, isLoose, stackA, stackB))) { + return false; + } + } + return true; + } + function equalByTag(object, other, tag) { + switch (tag) { + case boolTag: + case dateTag: + return +object == +other; + + case errorTag: + return object.name == other.name && object.message == other.message; + + case numberTag: + return object != +object ? other != +other : object == +other; + + case regexpTag: + case stringTag: + return object == other + ""; + } + return false; + } + function equalObjects(object, other, equalFunc, customizer, isLoose, stackA, stackB) { + var objProps = keys(object), objLength = objProps.length, othProps = keys(other), othLength = othProps.length; + if (objLength != othLength && !isLoose) { + return false; + } + var index = objLength; + while (index--) { + var key = objProps[index]; + if (!(isLoose ? key in other : hasOwnProperty.call(other, key))) { + return false; + } + } + var skipCtor = isLoose; + while (++index < objLength) { + key = objProps[index]; + var objValue = object[key], othValue = other[key], result = customizer ? customizer(isLoose ? othValue : objValue, isLoose ? objValue : othValue, key) : undefined; + if (!(result === undefined ? equalFunc(objValue, othValue, customizer, isLoose, stackA, stackB) : result)) { + return false; + } + skipCtor || (skipCtor = key == "constructor"); + } + if (!skipCtor) { + var objCtor = object.constructor, othCtor = other.constructor; + if (objCtor != othCtor && ("constructor" in object && "constructor" in other) && !(typeof objCtor == "function" && objCtor instanceof objCtor && typeof othCtor == "function" && othCtor instanceof othCtor)) { + return false; + } + } + return true; + } + function getCallback(func, thisArg, argCount) { + var result = lodash.callback || callback; + result = result === callback ? baseCallback : result; + return argCount ? result(func, thisArg, argCount) : result; + } + var getData = !metaMap ? noop : function(func) { + return metaMap.get(func); + }; + function getFuncName(func) { + var result = func.name + "", array = realNames[result], length = array ? array.length : 0; + while (length--) { + var data = array[length], otherFunc = data.func; + if (otherFunc == null || otherFunc == func) { + return data.name; + } + } + return result; + } + function getIndexOf(collection, target, fromIndex) { + var result = lodash.indexOf || indexOf; + result = result === indexOf ? baseIndexOf : result; + return collection ? result(collection, target, fromIndex) : result; + } + var getLength = baseProperty("length"); + function getMatchData(object) { + var result = pairs(object), length = result.length; + while (length--) { + result[length][2] = isStrictComparable(result[length][1]); + } + return result; + } + function getNative(object, key) { + var value = object == null ? undefined : object[key]; + return isNative(value) ? value : undefined; + } + function getView(start, end, transforms) { + var index = -1, length = transforms.length; + while (++index < length) { + var data = transforms[index], size = data.size; + switch (data.type) { + case "drop": + start += size; + break; + + case "dropRight": + end -= size; + break; + + case "take": + end = nativeMin(end, start + size); + break; + + case "takeRight": + start = nativeMax(start, end - size); + break; + } + } + return { + start: start, + end: end + }; + } + function initCloneArray(array) { + var length = array.length, result = new array.constructor(length); + if (length && typeof array[0] == "string" && hasOwnProperty.call(array, "index")) { + result.index = array.index; + result.input = array.input; + } + return result; + } + function initCloneObject(object) { + var Ctor = object.constructor; + if (!(typeof Ctor == "function" && Ctor instanceof Ctor)) { + Ctor = Object; + } + return new Ctor(); + } + function initCloneByTag(object, tag, isDeep) { + var Ctor = object.constructor; + switch (tag) { + case arrayBufferTag: + return bufferClone(object); + + case boolTag: + case dateTag: + return new Ctor(+object); + + case float32Tag: + case float64Tag: + case int8Tag: + case int16Tag: + case int32Tag: + case uint8Tag: + case uint8ClampedTag: + case uint16Tag: + case uint32Tag: + var buffer = object.buffer; + return new Ctor(isDeep ? bufferClone(buffer) : buffer, object.byteOffset, object.length); + + case numberTag: + case stringTag: + return new Ctor(object); + + case regexpTag: + var result = new Ctor(object.source, reFlags.exec(object)); + result.lastIndex = object.lastIndex; + } + return result; + } + function invokePath(object, path, args) { + if (object != null && !isKey(path, object)) { + path = toPath(path); + object = path.length == 1 ? object : baseGet(object, baseSlice(path, 0, -1)); + path = last(path); + } + var func = object == null ? object : object[path]; + return func == null ? undefined : func.apply(object, args); + } + function isArrayLike(value) { + return value != null && isLength(getLength(value)); + } + function isIndex(value, length) { + value = typeof value == "number" || reIsUint.test(value) ? +value : -1; + length = length == null ? MAX_SAFE_INTEGER : length; + return value > -1 && value % 1 == 0 && value < length; + } + function isIterateeCall(value, index, object) { + if (!isObject(object)) { + return false; + } + var type = typeof index; + if (type == "number" ? isArrayLike(object) && isIndex(index, object.length) : type == "string" && index in object) { + var other = object[index]; + return value === value ? value === other : other !== other; + } + return false; + } + function isKey(value, object) { + var type = typeof value; + if (type == "string" && reIsPlainProp.test(value) || type == "number") { + return true; + } + if (isArray(value)) { + return false; + } + var result = !reIsDeepProp.test(value); + return result || object != null && value in toObject(object); + } + function isLaziable(func) { + var funcName = getFuncName(func), other = lodash[funcName]; + if (typeof other != "function" || !(funcName in LazyWrapper.prototype)) { + return false; + } + if (func === other) { + return true; + } + var data = getData(other); + return !!data && func === data[0]; + } + function isLength(value) { + return typeof value == "number" && value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER; + } + function isStrictComparable(value) { + return value === value && !isObject(value); + } + function mergeData(data, source) { + var bitmask = data[1], srcBitmask = source[1], newBitmask = bitmask | srcBitmask, isCommon = newBitmask < ARY_FLAG; + var isCombo = srcBitmask == ARY_FLAG && bitmask == CURRY_FLAG || srcBitmask == ARY_FLAG && bitmask == REARG_FLAG && data[7].length <= source[8] || srcBitmask == (ARY_FLAG | REARG_FLAG) && bitmask == CURRY_FLAG; + if (!(isCommon || isCombo)) { + return data; + } + if (srcBitmask & BIND_FLAG) { + data[2] = source[2]; + newBitmask |= bitmask & BIND_FLAG ? 0 : CURRY_BOUND_FLAG; + } + var value = source[3]; + if (value) { + var partials = data[3]; + data[3] = partials ? composeArgs(partials, value, source[4]) : arrayCopy(value); + data[4] = partials ? replaceHolders(data[3], PLACEHOLDER) : arrayCopy(source[4]); + } + value = source[5]; + if (value) { + partials = data[5]; + data[5] = partials ? composeArgsRight(partials, value, source[6]) : arrayCopy(value); + data[6] = partials ? replaceHolders(data[5], PLACEHOLDER) : arrayCopy(source[6]); + } + value = source[7]; + if (value) { + data[7] = arrayCopy(value); + } + if (srcBitmask & ARY_FLAG) { + data[8] = data[8] == null ? source[8] : nativeMin(data[8], source[8]); + } + if (data[9] == null) { + data[9] = source[9]; + } + data[0] = source[0]; + data[1] = newBitmask; + return data; + } + function mergeDefaults(objectValue, sourceValue) { + return objectValue === undefined ? sourceValue : merge(objectValue, sourceValue, mergeDefaults); + } + function pickByArray(object, props) { + object = toObject(object); + var index = -1, length = props.length, result = {}; + while (++index < length) { + var key = props[index]; + if (key in object) { + result[key] = object[key]; + } + } + return result; + } + function pickByCallback(object, predicate) { + var result = {}; + baseForIn(object, function(value, key, object) { + if (predicate(value, key, object)) { + result[key] = value; + } + }); + return result; + } + function reorder(array, indexes) { + var arrLength = array.length, length = nativeMin(indexes.length, arrLength), oldArray = arrayCopy(array); + while (length--) { + var index = indexes[length]; + array[length] = isIndex(index, arrLength) ? oldArray[index] : undefined; + } + return array; + } + var setData = function() { + var count = 0, lastCalled = 0; + return function(key, value) { + var stamp = now(), remaining = HOT_SPAN - (stamp - lastCalled); + lastCalled = stamp; + if (remaining > 0) { + if (++count >= HOT_COUNT) { + return key; + } + } else { + count = 0; + } + return baseSetData(key, value); + }; + }(); + function shimKeys(object) { + var props = keysIn(object), propsLength = props.length, length = propsLength && object.length; + var allowIndexes = !!length && isLength(length) && (isArray(object) || isArguments(object)); + var index = -1, result = []; + while (++index < propsLength) { + var key = props[index]; + if (allowIndexes && isIndex(key, length) || hasOwnProperty.call(object, key)) { + result.push(key); + } + } + return result; + } + function toIterable(value) { + if (value == null) { + return []; + } + if (!isArrayLike(value)) { + return values(value); + } + return isObject(value) ? value : Object(value); + } + function toObject(value) { + return isObject(value) ? value : Object(value); + } + function toPath(value) { + if (isArray(value)) { + return value; + } + var result = []; + baseToString(value).replace(rePropName, function(match, number, quote, string) { + result.push(quote ? string.replace(reEscapeChar, "$1") : number || match); + }); + return result; + } + function wrapperClone(wrapper) { + return wrapper instanceof LazyWrapper ? wrapper.clone() : new LodashWrapper(wrapper.__wrapped__, wrapper.__chain__, arrayCopy(wrapper.__actions__)); + } + function chunk(array, size, guard) { + if (guard ? isIterateeCall(array, size, guard) : size == null) { + size = 1; + } else { + size = nativeMax(nativeFloor(size) || 1, 1); + } + var index = 0, length = array ? array.length : 0, resIndex = -1, result = Array(nativeCeil(length / size)); + while (index < length) { + result[++resIndex] = baseSlice(array, index, index += size); + } + return result; + } + function compact(array) { + var index = -1, length = array ? array.length : 0, resIndex = -1, result = []; + while (++index < length) { + var value = array[index]; + if (value) { + result[++resIndex] = value; + } + } + return result; + } + var difference = restParam(function(array, values) { + return isObjectLike(array) && isArrayLike(array) ? baseDifference(array, baseFlatten(values, false, true)) : []; + }); + function drop(array, n, guard) { + var length = array ? array.length : 0; + if (!length) { + return []; + } + if (guard ? isIterateeCall(array, n, guard) : n == null) { + n = 1; + } + return baseSlice(array, n < 0 ? 0 : n); + } + function dropRight(array, n, guard) { + var length = array ? array.length : 0; + if (!length) { + return []; + } + if (guard ? isIterateeCall(array, n, guard) : n == null) { + n = 1; + } + n = length - (+n || 0); + return baseSlice(array, 0, n < 0 ? 0 : n); + } + function dropRightWhile(array, predicate, thisArg) { + return array && array.length ? baseWhile(array, getCallback(predicate, thisArg, 3), true, true) : []; + } + function dropWhile(array, predicate, thisArg) { + return array && array.length ? baseWhile(array, getCallback(predicate, thisArg, 3), true) : []; + } + function fill(array, value, start, end) { + var length = array ? array.length : 0; + if (!length) { + return []; + } + if (start && typeof start != "number" && isIterateeCall(array, value, start)) { + start = 0; + end = length; + } + return baseFill(array, value, start, end); + } + var findIndex = createFindIndex(); + var findLastIndex = createFindIndex(true); + function first(array) { + return array ? array[0] : undefined; + } + function flatten(array, isDeep, guard) { + var length = array ? array.length : 0; + if (guard && isIterateeCall(array, isDeep, guard)) { + isDeep = false; + } + return length ? baseFlatten(array, isDeep) : []; + } + function flattenDeep(array) { + var length = array ? array.length : 0; + return length ? baseFlatten(array, true) : []; + } + function indexOf(array, value, fromIndex) { + var length = array ? array.length : 0; + if (!length) { + return -1; + } + if (typeof fromIndex == "number") { + fromIndex = fromIndex < 0 ? nativeMax(length + fromIndex, 0) : fromIndex; + } else if (fromIndex) { + var index = binaryIndex(array, value); + if (index < length && (value === value ? value === array[index] : array[index] !== array[index])) { + return index; + } + return -1; + } + return baseIndexOf(array, value, fromIndex || 0); + } + function initial(array) { + return dropRight(array, 1); + } + var intersection = restParam(function(arrays) { + var othLength = arrays.length, othIndex = othLength, caches = Array(length), indexOf = getIndexOf(), isCommon = indexOf === baseIndexOf, result = []; + while (othIndex--) { + var value = arrays[othIndex] = isArrayLike(value = arrays[othIndex]) ? value : []; + caches[othIndex] = isCommon && value.length >= 120 ? createCache(othIndex && value) : null; + } + var array = arrays[0], index = -1, length = array ? array.length : 0, seen = caches[0]; + outer: while (++index < length) { + value = array[index]; + if ((seen ? cacheIndexOf(seen, value) : indexOf(result, value, 0)) < 0) { + var othIndex = othLength; + while (--othIndex) { + var cache = caches[othIndex]; + if ((cache ? cacheIndexOf(cache, value) : indexOf(arrays[othIndex], value, 0)) < 0) { + continue outer; + } + } + if (seen) { + seen.push(value); + } + result.push(value); + } + } + return result; + }); + function last(array) { + var length = array ? array.length : 0; + return length ? array[length - 1] : undefined; + } + function lastIndexOf(array, value, fromIndex) { + var length = array ? array.length : 0; + if (!length) { + return -1; + } + var index = length; + if (typeof fromIndex == "number") { + index = (fromIndex < 0 ? nativeMax(length + fromIndex, 0) : nativeMin(fromIndex || 0, length - 1)) + 1; + } else if (fromIndex) { + index = binaryIndex(array, value, true) - 1; + var other = array[index]; + if (value === value ? value === other : other !== other) { + return index; + } + return -1; + } + if (value !== value) { + return indexOfNaN(array, index, true); + } + while (index--) { + if (array[index] === value) { + return index; + } + } + return -1; + } + function pull() { + var args = arguments, array = args[0]; + if (!(array && array.length)) { + return array; + } + var index = 0, indexOf = getIndexOf(), length = args.length; + while (++index < length) { + var fromIndex = 0, value = args[index]; + while ((fromIndex = indexOf(array, value, fromIndex)) > -1) { + splice.call(array, fromIndex, 1); + } + } + return array; + } + var pullAt = restParam(function(array, indexes) { + indexes = baseFlatten(indexes); + var result = baseAt(array, indexes); + basePullAt(array, indexes.sort(baseCompareAscending)); + return result; + }); + function remove(array, predicate, thisArg) { + var result = []; + if (!(array && array.length)) { + return result; + } + var index = -1, indexes = [], length = array.length; + predicate = getCallback(predicate, thisArg, 3); + while (++index < length) { + var value = array[index]; + if (predicate(value, index, array)) { + result.push(value); + indexes.push(index); + } + } + basePullAt(array, indexes); + return result; + } + function rest(array) { + return drop(array, 1); + } + function slice(array, start, end) { + var length = array ? array.length : 0; + if (!length) { + return []; + } + if (end && typeof end != "number" && isIterateeCall(array, start, end)) { + start = 0; + end = length; + } + return baseSlice(array, start, end); + } + var sortedIndex = createSortedIndex(); + var sortedLastIndex = createSortedIndex(true); + function take(array, n, guard) { + var length = array ? array.length : 0; + if (!length) { + return []; + } + if (guard ? isIterateeCall(array, n, guard) : n == null) { + n = 1; + } + return baseSlice(array, 0, n < 0 ? 0 : n); + } + function takeRight(array, n, guard) { + var length = array ? array.length : 0; + if (!length) { + return []; + } + if (guard ? isIterateeCall(array, n, guard) : n == null) { + n = 1; + } + n = length - (+n || 0); + return baseSlice(array, n < 0 ? 0 : n); + } + function takeRightWhile(array, predicate, thisArg) { + return array && array.length ? baseWhile(array, getCallback(predicate, thisArg, 3), false, true) : []; + } + function takeWhile(array, predicate, thisArg) { + return array && array.length ? baseWhile(array, getCallback(predicate, thisArg, 3)) : []; + } + var union = restParam(function(arrays) { + return baseUniq(baseFlatten(arrays, false, true)); + }); + function uniq(array, isSorted, iteratee, thisArg) { + var length = array ? array.length : 0; + if (!length) { + return []; + } + if (isSorted != null && typeof isSorted != "boolean") { + thisArg = iteratee; + iteratee = isIterateeCall(array, isSorted, thisArg) ? undefined : isSorted; + isSorted = false; + } + var callback = getCallback(); + if (!(iteratee == null && callback === baseCallback)) { + iteratee = callback(iteratee, thisArg, 3); + } + return isSorted && getIndexOf() === baseIndexOf ? sortedUniq(array, iteratee) : baseUniq(array, iteratee); + } + function unzip(array) { + if (!(array && array.length)) { + return []; + } + var index = -1, length = 0; + array = arrayFilter(array, function(group) { + if (isArrayLike(group)) { + length = nativeMax(group.length, length); + return true; + } + }); + var result = Array(length); + while (++index < length) { + result[index] = arrayMap(array, baseProperty(index)); + } + return result; + } + function unzipWith(array, iteratee, thisArg) { + var length = array ? array.length : 0; + if (!length) { + return []; + } + var result = unzip(array); + if (iteratee == null) { + return result; + } + iteratee = bindCallback(iteratee, thisArg, 4); + return arrayMap(result, function(group) { + return arrayReduce(group, iteratee, undefined, true); + }); + } + var without = restParam(function(array, values) { + return isArrayLike(array) ? baseDifference(array, values) : []; + }); + function xor() { + var index = -1, length = arguments.length; + while (++index < length) { + var array = arguments[index]; + if (isArrayLike(array)) { + var result = result ? arrayPush(baseDifference(result, array), baseDifference(array, result)) : array; + } + } + return result ? baseUniq(result) : []; + } + var zip = restParam(unzip); + function zipObject(props, values) { + var index = -1, length = props ? props.length : 0, result = {}; + if (length && !values && !isArray(props[0])) { + values = []; + } + while (++index < length) { + var key = props[index]; + if (values) { + result[key] = values[index]; + } else if (key) { + result[key[0]] = key[1]; + } + } + return result; + } + var zipWith = restParam(function(arrays) { + var length = arrays.length, iteratee = length > 2 ? arrays[length - 2] : undefined, thisArg = length > 1 ? arrays[length - 1] : undefined; + if (length > 2 && typeof iteratee == "function") { + length -= 2; + } else { + iteratee = length > 1 && typeof thisArg == "function" ? (--length, thisArg) : undefined; + thisArg = undefined; + } + arrays.length = length; + return unzipWith(arrays, iteratee, thisArg); + }); + function chain(value) { + var result = lodash(value); + result.__chain__ = true; + return result; + } + function tap(value, interceptor, thisArg) { + interceptor.call(thisArg, value); + return value; + } + function thru(value, interceptor, thisArg) { + return interceptor.call(thisArg, value); + } + function wrapperChain() { + return chain(this); + } + function wrapperCommit() { + return new LodashWrapper(this.value(), this.__chain__); + } + var wrapperConcat = restParam(function(values) { + values = baseFlatten(values); + return this.thru(function(array) { + return arrayConcat(isArray(array) ? array : [ toObject(array) ], values); + }); + }); + function wrapperPlant(value) { + var result, parent = this; + while (parent instanceof baseLodash) { + var clone = wrapperClone(parent); + if (result) { + previous.__wrapped__ = clone; + } else { + result = clone; + } + var previous = clone; + parent = parent.__wrapped__; + } + previous.__wrapped__ = value; + return result; + } + function wrapperReverse() { + var value = this.__wrapped__; + var interceptor = function(value) { + return value.reverse(); + }; + if (value instanceof LazyWrapper) { + var wrapped = value; + if (this.__actions__.length) { + wrapped = new LazyWrapper(this); + } + wrapped = wrapped.reverse(); + wrapped.__actions__.push({ + func: thru, + args: [ interceptor ], + thisArg: undefined + }); + return new LodashWrapper(wrapped, this.__chain__); + } + return this.thru(interceptor); + } + function wrapperToString() { + return this.value() + ""; + } + function wrapperValue() { + return baseWrapperValue(this.__wrapped__, this.__actions__); + } + var at = restParam(function(collection, props) { + return baseAt(collection, baseFlatten(props)); + }); + var countBy = createAggregator(function(result, value, key) { + hasOwnProperty.call(result, key) ? ++result[key] : result[key] = 1; + }); + function every(collection, predicate, thisArg) { + var func = isArray(collection) ? arrayEvery : baseEvery; + if (thisArg && isIterateeCall(collection, predicate, thisArg)) { + predicate = undefined; + } + if (typeof predicate != "function" || thisArg !== undefined) { + predicate = getCallback(predicate, thisArg, 3); + } + return func(collection, predicate); + } + function filter(collection, predicate, thisArg) { + var func = isArray(collection) ? arrayFilter : baseFilter; + predicate = getCallback(predicate, thisArg, 3); + return func(collection, predicate); + } + var find = createFind(baseEach); + var findLast = createFind(baseEachRight, true); + function findWhere(collection, source) { + return find(collection, baseMatches(source)); + } + var forEach = createForEach(arrayEach, baseEach); + var forEachRight = createForEach(arrayEachRight, baseEachRight); + var groupBy = createAggregator(function(result, value, key) { + if (hasOwnProperty.call(result, key)) { + result[key].push(value); + } else { + result[key] = [ value ]; + } + }); + function includes(collection, target, fromIndex, guard) { + var length = collection ? getLength(collection) : 0; + if (!isLength(length)) { + collection = values(collection); + length = collection.length; + } + if (typeof fromIndex != "number" || guard && isIterateeCall(target, fromIndex, guard)) { + fromIndex = 0; + } else { + fromIndex = fromIndex < 0 ? nativeMax(length + fromIndex, 0) : fromIndex || 0; + } + return typeof collection == "string" || !isArray(collection) && isString(collection) ? fromIndex <= length && collection.indexOf(target, fromIndex) > -1 : !!length && getIndexOf(collection, target, fromIndex) > -1; + } + var indexBy = createAggregator(function(result, value, key) { + result[key] = value; + }); + var invoke = restParam(function(collection, path, args) { + var index = -1, isFunc = typeof path == "function", isProp = isKey(path), result = isArrayLike(collection) ? Array(collection.length) : []; + baseEach(collection, function(value) { + var func = isFunc ? path : isProp && value != null ? value[path] : undefined; + result[++index] = func ? func.apply(value, args) : invokePath(value, path, args); + }); + return result; + }); + function map(collection, iteratee, thisArg) { + var func = isArray(collection) ? arrayMap : baseMap; + iteratee = getCallback(iteratee, thisArg, 3); + return func(collection, iteratee); + } + var partition = createAggregator(function(result, value, key) { + result[key ? 0 : 1].push(value); + }, function() { + return [ [], [] ]; + }); + function pluck(collection, path) { + return map(collection, property(path)); + } + var reduce = createReduce(arrayReduce, baseEach); + var reduceRight = createReduce(arrayReduceRight, baseEachRight); + function reject(collection, predicate, thisArg) { + var func = isArray(collection) ? arrayFilter : baseFilter; + predicate = getCallback(predicate, thisArg, 3); + return func(collection, function(value, index, collection) { + return !predicate(value, index, collection); + }); + } + function sample(collection, n, guard) { + if (guard ? isIterateeCall(collection, n, guard) : n == null) { + collection = toIterable(collection); + var length = collection.length; + return length > 0 ? collection[baseRandom(0, length - 1)] : undefined; + } + var index = -1, result = toArray(collection), length = result.length, lastIndex = length - 1; + n = nativeMin(n < 0 ? 0 : +n || 0, length); + while (++index < n) { + var rand = baseRandom(index, lastIndex), value = result[rand]; + result[rand] = result[index]; + result[index] = value; + } + result.length = n; + return result; + } + function shuffle(collection) { + return sample(collection, POSITIVE_INFINITY); + } + function size(collection) { + var length = collection ? getLength(collection) : 0; + return isLength(length) ? length : keys(collection).length; + } + function some(collection, predicate, thisArg) { + var func = isArray(collection) ? arraySome : baseSome; + if (thisArg && isIterateeCall(collection, predicate, thisArg)) { + predicate = undefined; + } + if (typeof predicate != "function" || thisArg !== undefined) { + predicate = getCallback(predicate, thisArg, 3); + } + return func(collection, predicate); + } + function sortBy(collection, iteratee, thisArg) { + if (collection == null) { + return []; + } + if (thisArg && isIterateeCall(collection, iteratee, thisArg)) { + iteratee = undefined; + } + var index = -1; + iteratee = getCallback(iteratee, thisArg, 3); + var result = baseMap(collection, function(value, key, collection) { + return { + criteria: iteratee(value, key, collection), + index: ++index, + value: value + }; + }); + return baseSortBy(result, compareAscending); + } + var sortByAll = restParam(function(collection, iteratees) { + if (collection == null) { + return []; + } + var guard = iteratees[2]; + if (guard && isIterateeCall(iteratees[0], iteratees[1], guard)) { + iteratees.length = 1; + } + return baseSortByOrder(collection, baseFlatten(iteratees), []); + }); + function sortByOrder(collection, iteratees, orders, guard) { + if (collection == null) { + return []; + } + if (guard && isIterateeCall(iteratees, orders, guard)) { + orders = undefined; + } + if (!isArray(iteratees)) { + iteratees = iteratees == null ? [] : [ iteratees ]; + } + if (!isArray(orders)) { + orders = orders == null ? [] : [ orders ]; + } + return baseSortByOrder(collection, iteratees, orders); + } + function where(collection, source) { + return filter(collection, baseMatches(source)); + } + var now = nativeNow || function() { + return new Date().getTime(); + }; + function after(n, func) { + if (typeof func != "function") { + if (typeof n == "function") { + var temp = n; + n = func; + func = temp; + } else { + throw new TypeError(FUNC_ERROR_TEXT); + } + } + n = nativeIsFinite(n = +n) ? n : 0; + return function() { + if (--n < 1) { + return func.apply(this, arguments); + } + }; + } + function ary(func, n, guard) { + if (guard && isIterateeCall(func, n, guard)) { + n = undefined; + } + n = func && n == null ? func.length : nativeMax(+n || 0, 0); + return createWrapper(func, ARY_FLAG, undefined, undefined, undefined, undefined, n); + } + function before(n, func) { + var result; + if (typeof func != "function") { + if (typeof n == "function") { + var temp = n; + n = func; + func = temp; + } else { + throw new TypeError(FUNC_ERROR_TEXT); + } + } + return function() { + if (--n > 0) { + result = func.apply(this, arguments); + } + if (n <= 1) { + func = undefined; + } + return result; + }; + } + var bind = restParam(function(func, thisArg, partials) { + var bitmask = BIND_FLAG; + if (partials.length) { + var holders = replaceHolders(partials, bind.placeholder); + bitmask |= PARTIAL_FLAG; + } + return createWrapper(func, bitmask, thisArg, partials, holders); + }); + var bindAll = restParam(function(object, methodNames) { + methodNames = methodNames.length ? baseFlatten(methodNames) : functions(object); + var index = -1, length = methodNames.length; + while (++index < length) { + var key = methodNames[index]; + object[key] = createWrapper(object[key], BIND_FLAG, object); + } + return object; + }); + var bindKey = restParam(function(object, key, partials) { + var bitmask = BIND_FLAG | BIND_KEY_FLAG; + if (partials.length) { + var holders = replaceHolders(partials, bindKey.placeholder); + bitmask |= PARTIAL_FLAG; + } + return createWrapper(key, bitmask, object, partials, holders); + }); + var curry = createCurry(CURRY_FLAG); + var curryRight = createCurry(CURRY_RIGHT_FLAG); + function debounce(func, wait, options) { + var args, maxTimeoutId, result, stamp, thisArg, timeoutId, trailingCall, lastCalled = 0, maxWait = false, trailing = true; + if (typeof func != "function") { + throw new TypeError(FUNC_ERROR_TEXT); + } + wait = wait < 0 ? 0 : +wait || 0; + if (options === true) { + var leading = true; + trailing = false; + } else if (isObject(options)) { + leading = !!options.leading; + maxWait = "maxWait" in options && nativeMax(+options.maxWait || 0, wait); + trailing = "trailing" in options ? !!options.trailing : trailing; + } + function cancel() { + if (timeoutId) { + clearTimeout(timeoutId); + } + if (maxTimeoutId) { + clearTimeout(maxTimeoutId); + } + lastCalled = 0; + maxTimeoutId = timeoutId = trailingCall = undefined; + } + function complete(isCalled, id) { + if (id) { + clearTimeout(id); + } + maxTimeoutId = timeoutId = trailingCall = undefined; + if (isCalled) { + lastCalled = now(); + result = func.apply(thisArg, args); + if (!timeoutId && !maxTimeoutId) { + args = thisArg = undefined; + } + } + } + function delayed() { + var remaining = wait - (now() - stamp); + if (remaining <= 0 || remaining > wait) { + complete(trailingCall, maxTimeoutId); + } else { + timeoutId = setTimeout(delayed, remaining); + } + } + function maxDelayed() { + complete(trailing, timeoutId); + } + function debounced() { + args = arguments; + stamp = now(); + thisArg = this; + trailingCall = trailing && (timeoutId || !leading); + if (maxWait === false) { + var leadingCall = leading && !timeoutId; + } else { + if (!maxTimeoutId && !leading) { + lastCalled = stamp; + } + var remaining = maxWait - (stamp - lastCalled), isCalled = remaining <= 0 || remaining > maxWait; + if (isCalled) { + if (maxTimeoutId) { + maxTimeoutId = clearTimeout(maxTimeoutId); + } + lastCalled = stamp; + result = func.apply(thisArg, args); + } else if (!maxTimeoutId) { + maxTimeoutId = setTimeout(maxDelayed, remaining); + } + } + if (isCalled && timeoutId) { + timeoutId = clearTimeout(timeoutId); + } else if (!timeoutId && wait !== maxWait) { + timeoutId = setTimeout(delayed, wait); + } + if (leadingCall) { + isCalled = true; + result = func.apply(thisArg, args); + } + if (isCalled && !timeoutId && !maxTimeoutId) { + args = thisArg = undefined; + } + return result; + } + debounced.cancel = cancel; + return debounced; + } + var defer = restParam(function(func, args) { + return baseDelay(func, 1, args); + }); + var delay = restParam(function(func, wait, args) { + return baseDelay(func, wait, args); + }); + var flow = createFlow(); + var flowRight = createFlow(true); + function memoize(func, resolver) { + if (typeof func != "function" || resolver && typeof resolver != "function") { + throw new TypeError(FUNC_ERROR_TEXT); + } + var memoized = function() { + var args = arguments, key = resolver ? resolver.apply(this, args) : args[0], cache = memoized.cache; + if (cache.has(key)) { + return cache.get(key); + } + var result = func.apply(this, args); + memoized.cache = cache.set(key, result); + return result; + }; + memoized.cache = new memoize.Cache(); + return memoized; + } + var modArgs = restParam(function(func, transforms) { + transforms = baseFlatten(transforms); + if (typeof func != "function" || !arrayEvery(transforms, baseIsFunction)) { + throw new TypeError(FUNC_ERROR_TEXT); + } + var length = transforms.length; + return restParam(function(args) { + var index = nativeMin(args.length, length); + while (index--) { + args[index] = transforms[index](args[index]); + } + return func.apply(this, args); + }); + }); + function negate(predicate) { + if (typeof predicate != "function") { + throw new TypeError(FUNC_ERROR_TEXT); + } + return function() { + return !predicate.apply(this, arguments); + }; + } + function once(func) { + return before(2, func); + } + var partial = createPartial(PARTIAL_FLAG); + var partialRight = createPartial(PARTIAL_RIGHT_FLAG); + var rearg = restParam(function(func, indexes) { + return createWrapper(func, REARG_FLAG, undefined, undefined, undefined, baseFlatten(indexes)); + }); + function restParam(func, start) { + if (typeof func != "function") { + throw new TypeError(FUNC_ERROR_TEXT); + } + start = nativeMax(start === undefined ? func.length - 1 : +start || 0, 0); + return function() { + var args = arguments, index = -1, length = nativeMax(args.length - start, 0), rest = Array(length); + while (++index < length) { + rest[index] = args[start + index]; + } + switch (start) { + case 0: + return func.call(this, rest); + + case 1: + return func.call(this, args[0], rest); + + case 2: + return func.call(this, args[0], args[1], rest); + } + var otherArgs = Array(start + 1); + index = -1; + while (++index < start) { + otherArgs[index] = args[index]; + } + otherArgs[start] = rest; + return func.apply(this, otherArgs); + }; + } + function spread(func) { + if (typeof func != "function") { + throw new TypeError(FUNC_ERROR_TEXT); + } + return function(array) { + return func.apply(this, array); + }; + } + function throttle(func, wait, options) { + var leading = true, trailing = true; + if (typeof func != "function") { + throw new TypeError(FUNC_ERROR_TEXT); + } + if (options === false) { + leading = false; + } else if (isObject(options)) { + leading = "leading" in options ? !!options.leading : leading; + trailing = "trailing" in options ? !!options.trailing : trailing; + } + return debounce(func, wait, { + leading: leading, + maxWait: +wait, + trailing: trailing + }); + } + function wrap(value, wrapper) { + wrapper = wrapper == null ? identity : wrapper; + return createWrapper(wrapper, PARTIAL_FLAG, undefined, [ value ], []); + } + function clone(value, isDeep, customizer, thisArg) { + if (isDeep && typeof isDeep != "boolean" && isIterateeCall(value, isDeep, customizer)) { + isDeep = false; + } else if (typeof isDeep == "function") { + thisArg = customizer; + customizer = isDeep; + isDeep = false; + } + return typeof customizer == "function" ? baseClone(value, isDeep, bindCallback(customizer, thisArg, 3)) : baseClone(value, isDeep); + } + function cloneDeep(value, customizer, thisArg) { + return typeof customizer == "function" ? baseClone(value, true, bindCallback(customizer, thisArg, 3)) : baseClone(value, true); + } + function gt(value, other) { + return value > other; + } + function gte(value, other) { + return value >= other; + } + function isArguments(value) { + return isObjectLike(value) && isArrayLike(value) && hasOwnProperty.call(value, "callee") && !propertyIsEnumerable.call(value, "callee"); + } + var isArray = nativeIsArray || function(value) { + return isObjectLike(value) && isLength(value.length) && objToString.call(value) == arrayTag; + }; + function isBoolean(value) { + return value === true || value === false || isObjectLike(value) && objToString.call(value) == boolTag; + } + function isDate(value) { + return isObjectLike(value) && objToString.call(value) == dateTag; + } + function isElement(value) { + return !!value && value.nodeType === 1 && isObjectLike(value) && !isPlainObject(value); + } + function isEmpty(value) { + if (value == null) { + return true; + } + if (isArrayLike(value) && (isArray(value) || isString(value) || isArguments(value) || isObjectLike(value) && isFunction(value.splice))) { + return !value.length; + } + return !keys(value).length; + } + function isEqual(value, other, customizer, thisArg) { + customizer = typeof customizer == "function" ? bindCallback(customizer, thisArg, 3) : undefined; + var result = customizer ? customizer(value, other) : undefined; + return result === undefined ? baseIsEqual(value, other, customizer) : !!result; + } + function isError(value) { + return isObjectLike(value) && typeof value.message == "string" && objToString.call(value) == errorTag; + } + function isFinite(value) { + return typeof value == "number" && nativeIsFinite(value); + } + function isFunction(value) { + return isObject(value) && objToString.call(value) == funcTag; + } + function isObject(value) { + var type = typeof value; + return !!value && (type == "object" || type == "function"); + } + function isMatch(object, source, customizer, thisArg) { + customizer = typeof customizer == "function" ? bindCallback(customizer, thisArg, 3) : undefined; + return baseIsMatch(object, getMatchData(source), customizer); + } + function isNaN(value) { + return isNumber(value) && value != +value; + } + function isNative(value) { + if (value == null) { + return false; + } + if (isFunction(value)) { + return reIsNative.test(fnToString.call(value)); + } + return isObjectLike(value) && reIsHostCtor.test(value); + } + function isNull(value) { + return value === null; + } + function isNumber(value) { + return typeof value == "number" || isObjectLike(value) && objToString.call(value) == numberTag; + } + function isPlainObject(value) { + var Ctor; + if (!(isObjectLike(value) && objToString.call(value) == objectTag && !isArguments(value)) || !hasOwnProperty.call(value, "constructor") && (Ctor = value.constructor, + typeof Ctor == "function" && !(Ctor instanceof Ctor))) { + return false; + } + var result; + baseForIn(value, function(subValue, key) { + result = key; + }); + return result === undefined || hasOwnProperty.call(value, result); + } + function isRegExp(value) { + return isObject(value) && objToString.call(value) == regexpTag; + } + function isString(value) { + return typeof value == "string" || isObjectLike(value) && objToString.call(value) == stringTag; + } + function isTypedArray(value) { + return isObjectLike(value) && isLength(value.length) && !!typedArrayTags[objToString.call(value)]; + } + function isUndefined(value) { + return value === undefined; + } + function lt(value, other) { + return value < other; + } + function lte(value, other) { + return value <= other; + } + function toArray(value) { + var length = value ? getLength(value) : 0; + if (!isLength(length)) { + return values(value); + } + if (!length) { + return []; + } + return arrayCopy(value); + } + function toPlainObject(value) { + return baseCopy(value, keysIn(value)); + } + var merge = createAssigner(baseMerge); + var assign = createAssigner(function(object, source, customizer) { + return customizer ? assignWith(object, source, customizer) : baseAssign(object, source); + }); + function create(prototype, properties, guard) { + var result = baseCreate(prototype); + if (guard && isIterateeCall(prototype, properties, guard)) { + properties = undefined; + } + return properties ? baseAssign(result, properties) : result; + } + var defaults = createDefaults(assign, assignDefaults); + var defaultsDeep = createDefaults(merge, mergeDefaults); + var findKey = createFindKey(baseForOwn); + var findLastKey = createFindKey(baseForOwnRight); + var forIn = createForIn(baseFor); + var forInRight = createForIn(baseForRight); + var forOwn = createForOwn(baseForOwn); + var forOwnRight = createForOwn(baseForOwnRight); + function functions(object) { + return baseFunctions(object, keysIn(object)); + } + function get(object, path, defaultValue) { + var result = object == null ? undefined : baseGet(object, toPath(path), path + ""); + return result === undefined ? defaultValue : result; + } + function has(object, path) { + if (object == null) { + return false; + } + var result = hasOwnProperty.call(object, path); + if (!result && !isKey(path)) { + path = toPath(path); + object = path.length == 1 ? object : baseGet(object, baseSlice(path, 0, -1)); + if (object == null) { + return false; + } + path = last(path); + result = hasOwnProperty.call(object, path); + } + return result || isLength(object.length) && isIndex(path, object.length) && (isArray(object) || isArguments(object)); + } + function invert(object, multiValue, guard) { + if (guard && isIterateeCall(object, multiValue, guard)) { + multiValue = undefined; + } + var index = -1, props = keys(object), length = props.length, result = {}; + while (++index < length) { + var key = props[index], value = object[key]; + if (multiValue) { + if (hasOwnProperty.call(result, value)) { + result[value].push(key); + } else { + result[value] = [ key ]; + } + } else { + result[value] = key; + } + } + return result; + } + var keys = !nativeKeys ? shimKeys : function(object) { + var Ctor = object == null ? undefined : object.constructor; + if (typeof Ctor == "function" && Ctor.prototype === object || typeof object != "function" && isArrayLike(object)) { + return shimKeys(object); + } + return isObject(object) ? nativeKeys(object) : []; + }; + function keysIn(object) { + if (object == null) { + return []; + } + if (!isObject(object)) { + object = Object(object); + } + var length = object.length; + length = length && isLength(length) && (isArray(object) || isArguments(object)) && length || 0; + var Ctor = object.constructor, index = -1, isProto = typeof Ctor == "function" && Ctor.prototype === object, result = Array(length), skipIndexes = length > 0; + while (++index < length) { + result[index] = index + ""; + } + for (var key in object) { + if (!(skipIndexes && isIndex(key, length)) && !(key == "constructor" && (isProto || !hasOwnProperty.call(object, key)))) { + result.push(key); + } + } + return result; + } + var mapKeys = createObjectMapper(true); + var mapValues = createObjectMapper(); + var omit = restParam(function(object, props) { + if (object == null) { + return {}; + } + if (typeof props[0] != "function") { + var props = arrayMap(baseFlatten(props), String); + return pickByArray(object, baseDifference(keysIn(object), props)); + } + var predicate = bindCallback(props[0], props[1], 3); + return pickByCallback(object, function(value, key, object) { + return !predicate(value, key, object); + }); + }); + function pairs(object) { + object = toObject(object); + var index = -1, props = keys(object), length = props.length, result = Array(length); + while (++index < length) { + var key = props[index]; + result[index] = [ key, object[key] ]; + } + return result; + } + var pick = restParam(function(object, props) { + if (object == null) { + return {}; + } + return typeof props[0] == "function" ? pickByCallback(object, bindCallback(props[0], props[1], 3)) : pickByArray(object, baseFlatten(props)); + }); + function result(object, path, defaultValue) { + var result = object == null ? undefined : object[path]; + if (result === undefined) { + if (object != null && !isKey(path, object)) { + path = toPath(path); + object = path.length == 1 ? object : baseGet(object, baseSlice(path, 0, -1)); + result = object == null ? undefined : object[last(path)]; + } + result = result === undefined ? defaultValue : result; + } + return isFunction(result) ? result.call(object) : result; + } + function set(object, path, value) { + if (object == null) { + return object; + } + var pathKey = path + ""; + path = object[pathKey] != null || isKey(path, object) ? [ pathKey ] : toPath(path); + var index = -1, length = path.length, lastIndex = length - 1, nested = object; + while (nested != null && ++index < length) { + var key = path[index]; + if (isObject(nested)) { + if (index == lastIndex) { + nested[key] = value; + } else if (nested[key] == null) { + nested[key] = isIndex(path[index + 1]) ? [] : {}; + } + } + nested = nested[key]; + } + return object; + } + function transform(object, iteratee, accumulator, thisArg) { + var isArr = isArray(object) || isTypedArray(object); + iteratee = getCallback(iteratee, thisArg, 4); + if (accumulator == null) { + if (isArr || isObject(object)) { + var Ctor = object.constructor; + if (isArr) { + accumulator = isArray(object) ? new Ctor() : []; + } else { + accumulator = baseCreate(isFunction(Ctor) ? Ctor.prototype : undefined); + } + } else { + accumulator = {}; + } + } + (isArr ? arrayEach : baseForOwn)(object, function(value, index, object) { + return iteratee(accumulator, value, index, object); + }); + return accumulator; + } + function values(object) { + return baseValues(object, keys(object)); + } + function valuesIn(object) { + return baseValues(object, keysIn(object)); + } + function inRange(value, start, end) { + start = +start || 0; + if (end === undefined) { + end = start; + start = 0; + } else { + end = +end || 0; + } + return value >= nativeMin(start, end) && value < nativeMax(start, end); + } + function random(min, max, floating) { + if (floating && isIterateeCall(min, max, floating)) { + max = floating = undefined; + } + var noMin = min == null, noMax = max == null; + if (floating == null) { + if (noMax && typeof min == "boolean") { + floating = min; + min = 1; + } else if (typeof max == "boolean") { + floating = max; + noMax = true; + } + } + if (noMin && noMax) { + max = 1; + noMax = false; + } + min = +min || 0; + if (noMax) { + max = min; + min = 0; + } else { + max = +max || 0; + } + if (floating || min % 1 || max % 1) { + var rand = nativeRandom(); + return nativeMin(min + rand * (max - min + parseFloat("1e-" + ((rand + "").length - 1))), max); + } + return baseRandom(min, max); + } + var camelCase = createCompounder(function(result, word, index) { + word = word.toLowerCase(); + return result + (index ? word.charAt(0).toUpperCase() + word.slice(1) : word); + }); + function capitalize(string) { + string = baseToString(string); + return string && string.charAt(0).toUpperCase() + string.slice(1); + } + function deburr(string) { + string = baseToString(string); + return string && string.replace(reLatin1, deburrLetter).replace(reComboMark, ""); + } + function endsWith(string, target, position) { + string = baseToString(string); + target = target + ""; + var length = string.length; + position = position === undefined ? length : nativeMin(position < 0 ? 0 : +position || 0, length); + position -= target.length; + return position >= 0 && string.indexOf(target, position) == position; + } + function escape(string) { + string = baseToString(string); + return string && reHasUnescapedHtml.test(string) ? string.replace(reUnescapedHtml, escapeHtmlChar) : string; + } + function escapeRegExp(string) { + string = baseToString(string); + return string && reHasRegExpChars.test(string) ? string.replace(reRegExpChars, escapeRegExpChar) : string || "(?:)"; + } + var kebabCase = createCompounder(function(result, word, index) { + return result + (index ? "-" : "") + word.toLowerCase(); + }); + function pad(string, length, chars) { + string = baseToString(string); + length = +length; + var strLength = string.length; + if (strLength >= length || !nativeIsFinite(length)) { + return string; + } + var mid = (length - strLength) / 2, leftLength = nativeFloor(mid), rightLength = nativeCeil(mid); + chars = createPadding("", rightLength, chars); + return chars.slice(0, leftLength) + string + chars; + } + var padLeft = createPadDir(); + var padRight = createPadDir(true); + function parseInt(string, radix, guard) { + if (guard ? isIterateeCall(string, radix, guard) : radix == null) { + radix = 0; + } else if (radix) { + radix = +radix; + } + string = trim(string); + return nativeParseInt(string, radix || (reHasHexPrefix.test(string) ? 16 : 10)); + } + function repeat(string, n) { + var result = ""; + string = baseToString(string); + n = +n; + if (n < 1 || !string || !nativeIsFinite(n)) { + return result; + } + do { + if (n % 2) { + result += string; + } + n = nativeFloor(n / 2); + string += string; + } while (n); + return result; + } + var snakeCase = createCompounder(function(result, word, index) { + return result + (index ? "_" : "") + word.toLowerCase(); + }); + var startCase = createCompounder(function(result, word, index) { + return result + (index ? " " : "") + (word.charAt(0).toUpperCase() + word.slice(1)); + }); + function startsWith(string, target, position) { + string = baseToString(string); + position = position == null ? 0 : nativeMin(position < 0 ? 0 : +position || 0, string.length); + return string.lastIndexOf(target, position) == position; + } + function template(string, options, otherOptions) { + var settings = lodash.templateSettings; + if (otherOptions && isIterateeCall(string, options, otherOptions)) { + options = otherOptions = undefined; + } + string = baseToString(string); + options = assignWith(baseAssign({}, otherOptions || options), settings, assignOwnDefaults); + var imports = assignWith(baseAssign({}, options.imports), settings.imports, assignOwnDefaults), importsKeys = keys(imports), importsValues = baseValues(imports, importsKeys); + var isEscaping, isEvaluating, index = 0, interpolate = options.interpolate || reNoMatch, source = "__p += '"; + var reDelimiters = RegExp((options.escape || reNoMatch).source + "|" + interpolate.source + "|" + (interpolate === reInterpolate ? reEsTemplate : reNoMatch).source + "|" + (options.evaluate || reNoMatch).source + "|$", "g"); + var sourceURL = "//# sourceURL=" + ("sourceURL" in options ? options.sourceURL : "lodash.templateSources[" + ++templateCounter + "]") + "\n"; + string.replace(reDelimiters, function(match, escapeValue, interpolateValue, esTemplateValue, evaluateValue, offset) { + interpolateValue || (interpolateValue = esTemplateValue); + source += string.slice(index, offset).replace(reUnescapedString, escapeStringChar); + if (escapeValue) { + isEscaping = true; + source += "' +\n__e(" + escapeValue + ") +\n'"; + } + if (evaluateValue) { + isEvaluating = true; + source += "';\n" + evaluateValue + ";\n__p += '"; + } + if (interpolateValue) { + source += "' +\n((__t = (" + interpolateValue + ")) == null ? '' : __t) +\n'"; + } + index = offset + match.length; + return match; + }); + source += "';\n"; + var variable = options.variable; + if (!variable) { + source = "with (obj) {\n" + source + "\n}\n"; + } + source = (isEvaluating ? source.replace(reEmptyStringLeading, "") : source).replace(reEmptyStringMiddle, "$1").replace(reEmptyStringTrailing, "$1;"); + source = "function(" + (variable || "obj") + ") {\n" + (variable ? "" : "obj || (obj = {});\n") + "var __t, __p = ''" + (isEscaping ? ", __e = _.escape" : "") + (isEvaluating ? ", __j = Array.prototype.join;\n" + "function print() { __p += __j.call(arguments, '') }\n" : ";\n") + source + "return __p\n}"; + var result = attempt(function() { + return Function(importsKeys, sourceURL + "return " + source).apply(undefined, importsValues); + }); + result.source = source; + if (isError(result)) { + throw result; + } + return result; + } + function trim(string, chars, guard) { + var value = string; + string = baseToString(string); + if (!string) { + return string; + } + if (guard ? isIterateeCall(value, chars, guard) : chars == null) { + return string.slice(trimmedLeftIndex(string), trimmedRightIndex(string) + 1); + } + chars = chars + ""; + return string.slice(charsLeftIndex(string, chars), charsRightIndex(string, chars) + 1); + } + function trimLeft(string, chars, guard) { + var value = string; + string = baseToString(string); + if (!string) { + return string; + } + if (guard ? isIterateeCall(value, chars, guard) : chars == null) { + return string.slice(trimmedLeftIndex(string)); + } + return string.slice(charsLeftIndex(string, chars + "")); + } + function trimRight(string, chars, guard) { + var value = string; + string = baseToString(string); + if (!string) { + return string; + } + if (guard ? isIterateeCall(value, chars, guard) : chars == null) { + return string.slice(0, trimmedRightIndex(string) + 1); + } + return string.slice(0, charsRightIndex(string, chars + "") + 1); + } + function trunc(string, options, guard) { + if (guard && isIterateeCall(string, options, guard)) { + options = undefined; + } + var length = DEFAULT_TRUNC_LENGTH, omission = DEFAULT_TRUNC_OMISSION; + if (options != null) { + if (isObject(options)) { + var separator = "separator" in options ? options.separator : separator; + length = "length" in options ? +options.length || 0 : length; + omission = "omission" in options ? baseToString(options.omission) : omission; + } else { + length = +options || 0; + } + } + string = baseToString(string); + if (length >= string.length) { + return string; + } + var end = length - omission.length; + if (end < 1) { + return omission; + } + var result = string.slice(0, end); + if (separator == null) { + return result + omission; + } + if (isRegExp(separator)) { + if (string.slice(end).search(separator)) { + var match, newEnd, substring = string.slice(0, end); + if (!separator.global) { + separator = RegExp(separator.source, (reFlags.exec(separator) || "") + "g"); + } + separator.lastIndex = 0; + while (match = separator.exec(substring)) { + newEnd = match.index; + } + result = result.slice(0, newEnd == null ? end : newEnd); + } + } else if (string.indexOf(separator, end) != end) { + var index = result.lastIndexOf(separator); + if (index > -1) { + result = result.slice(0, index); + } + } + return result + omission; + } + function unescape(string) { + string = baseToString(string); + return string && reHasEscapedHtml.test(string) ? string.replace(reEscapedHtml, unescapeHtmlChar) : string; + } + function words(string, pattern, guard) { + if (guard && isIterateeCall(string, pattern, guard)) { + pattern = undefined; + } + string = baseToString(string); + return string.match(pattern || reWords) || []; + } + var attempt = restParam(function(func, args) { + try { + return func.apply(undefined, args); + } catch (e) { + return isError(e) ? e : new Error(e); + } + }); + function callback(func, thisArg, guard) { + if (guard && isIterateeCall(func, thisArg, guard)) { + thisArg = undefined; + } + return isObjectLike(func) ? matches(func) : baseCallback(func, thisArg); + } + function constant(value) { + return function() { + return value; + }; + } + function identity(value) { + return value; + } + function matches(source) { + return baseMatches(baseClone(source, true)); + } + function matchesProperty(path, srcValue) { + return baseMatchesProperty(path, baseClone(srcValue, true)); + } + var method = restParam(function(path, args) { + return function(object) { + return invokePath(object, path, args); + }; + }); + var methodOf = restParam(function(object, args) { + return function(path) { + return invokePath(object, path, args); + }; + }); + function mixin(object, source, options) { + if (options == null) { + var isObj = isObject(source), props = isObj ? keys(source) : undefined, methodNames = props && props.length ? baseFunctions(source, props) : undefined; + if (!(methodNames ? methodNames.length : isObj)) { + methodNames = false; + options = source; + source = object; + object = this; + } + } + if (!methodNames) { + methodNames = baseFunctions(source, keys(source)); + } + var chain = true, index = -1, isFunc = isFunction(object), length = methodNames.length; + if (options === false) { + chain = false; + } else if (isObject(options) && "chain" in options) { + chain = options.chain; + } + while (++index < length) { + var methodName = methodNames[index], func = source[methodName]; + object[methodName] = func; + if (isFunc) { + object.prototype[methodName] = function(func) { + return function() { + var chainAll = this.__chain__; + if (chain || chainAll) { + var result = object(this.__wrapped__), actions = result.__actions__ = arrayCopy(this.__actions__); + actions.push({ + func: func, + args: arguments, + thisArg: object + }); + result.__chain__ = chainAll; + return result; + } + return func.apply(object, arrayPush([ this.value() ], arguments)); + }; + }(func); + } + } + return object; + } + function noConflict() { + root._ = oldDash; + return this; + } + function noop() {} + function property(path) { + return isKey(path) ? baseProperty(path) : basePropertyDeep(path); + } + function propertyOf(object) { + return function(path) { + return baseGet(object, toPath(path), path + ""); + }; + } + function range(start, end, step) { + if (step && isIterateeCall(start, end, step)) { + end = step = undefined; + } + start = +start || 0; + step = step == null ? 1 : +step || 0; + if (end == null) { + end = start; + start = 0; + } else { + end = +end || 0; + } + var index = -1, length = nativeMax(nativeCeil((end - start) / (step || 1)), 0), result = Array(length); + while (++index < length) { + result[index] = start; + start += step; + } + return result; + } + function times(n, iteratee, thisArg) { + n = nativeFloor(n); + if (n < 1 || !nativeIsFinite(n)) { + return []; + } + var index = -1, result = Array(nativeMin(n, MAX_ARRAY_LENGTH)); + iteratee = bindCallback(iteratee, thisArg, 1); + while (++index < n) { + if (index < MAX_ARRAY_LENGTH) { + result[index] = iteratee(index); + } else { + iteratee(index); + } + } + return result; + } + function uniqueId(prefix) { + var id = ++idCounter; + return baseToString(prefix) + id; + } + function add(augend, addend) { + return (+augend || 0) + (+addend || 0); + } + var ceil = createRound("ceil"); + var floor = createRound("floor"); + var max = createExtremum(gt, NEGATIVE_INFINITY); + var min = createExtremum(lt, POSITIVE_INFINITY); + var round = createRound("round"); + function sum(collection, iteratee, thisArg) { + if (thisArg && isIterateeCall(collection, iteratee, thisArg)) { + iteratee = undefined; + } + iteratee = getCallback(iteratee, thisArg, 3); + return iteratee.length == 1 ? arraySum(isArray(collection) ? collection : toIterable(collection), iteratee) : baseSum(collection, iteratee); + } + lodash.prototype = baseLodash.prototype; + LodashWrapper.prototype = baseCreate(baseLodash.prototype); + LodashWrapper.prototype.constructor = LodashWrapper; + LazyWrapper.prototype = baseCreate(baseLodash.prototype); + LazyWrapper.prototype.constructor = LazyWrapper; + MapCache.prototype["delete"] = mapDelete; + MapCache.prototype.get = mapGet; + MapCache.prototype.has = mapHas; + MapCache.prototype.set = mapSet; + SetCache.prototype.push = cachePush; + memoize.Cache = MapCache; + lodash.after = after; + lodash.ary = ary; + lodash.assign = assign; + lodash.at = at; + lodash.before = before; + lodash.bind = bind; + lodash.bindAll = bindAll; + lodash.bindKey = bindKey; + lodash.callback = callback; + lodash.chain = chain; + lodash.chunk = chunk; + lodash.compact = compact; + lodash.constant = constant; + lodash.countBy = countBy; + lodash.create = create; + lodash.curry = curry; + lodash.curryRight = curryRight; + lodash.debounce = debounce; + lodash.defaults = defaults; + lodash.defaultsDeep = defaultsDeep; + lodash.defer = defer; + lodash.delay = delay; + lodash.difference = difference; + lodash.drop = drop; + lodash.dropRight = dropRight; + lodash.dropRightWhile = dropRightWhile; + lodash.dropWhile = dropWhile; + lodash.fill = fill; + lodash.filter = filter; + lodash.flatten = flatten; + lodash.flattenDeep = flattenDeep; + lodash.flow = flow; + lodash.flowRight = flowRight; + lodash.forEach = forEach; + lodash.forEachRight = forEachRight; + lodash.forIn = forIn; + lodash.forInRight = forInRight; + lodash.forOwn = forOwn; + lodash.forOwnRight = forOwnRight; + lodash.functions = functions; + lodash.groupBy = groupBy; + lodash.indexBy = indexBy; + lodash.initial = initial; + lodash.intersection = intersection; + lodash.invert = invert; + lodash.invoke = invoke; + lodash.keys = keys; + lodash.keysIn = keysIn; + lodash.map = map; + lodash.mapKeys = mapKeys; + lodash.mapValues = mapValues; + lodash.matches = matches; + lodash.matchesProperty = matchesProperty; + lodash.memoize = memoize; + lodash.merge = merge; + lodash.method = method; + lodash.methodOf = methodOf; + lodash.mixin = mixin; + lodash.modArgs = modArgs; + lodash.negate = negate; + lodash.omit = omit; + lodash.once = once; + lodash.pairs = pairs; + lodash.partial = partial; + lodash.partialRight = partialRight; + lodash.partition = partition; + lodash.pick = pick; + lodash.pluck = pluck; + lodash.property = property; + lodash.propertyOf = propertyOf; + lodash.pull = pull; + lodash.pullAt = pullAt; + lodash.range = range; + lodash.rearg = rearg; + lodash.reject = reject; + lodash.remove = remove; + lodash.rest = rest; + lodash.restParam = restParam; + lodash.set = set; + lodash.shuffle = shuffle; + lodash.slice = slice; + lodash.sortBy = sortBy; + lodash.sortByAll = sortByAll; + lodash.sortByOrder = sortByOrder; + lodash.spread = spread; + lodash.take = take; + lodash.takeRight = takeRight; + lodash.takeRightWhile = takeRightWhile; + lodash.takeWhile = takeWhile; + lodash.tap = tap; + lodash.throttle = throttle; + lodash.thru = thru; + lodash.times = times; + lodash.toArray = toArray; + lodash.toPlainObject = toPlainObject; + lodash.transform = transform; + lodash.union = union; + lodash.uniq = uniq; + lodash.unzip = unzip; + lodash.unzipWith = unzipWith; + lodash.values = values; + lodash.valuesIn = valuesIn; + lodash.where = where; + lodash.without = without; + lodash.wrap = wrap; + lodash.xor = xor; + lodash.zip = zip; + lodash.zipObject = zipObject; + lodash.zipWith = zipWith; + lodash.backflow = flowRight; + lodash.collect = map; + lodash.compose = flowRight; + lodash.each = forEach; + lodash.eachRight = forEachRight; + lodash.extend = assign; + lodash.iteratee = callback; + lodash.methods = functions; + lodash.object = zipObject; + lodash.select = filter; + lodash.tail = rest; + lodash.unique = uniq; + mixin(lodash, lodash); + lodash.add = add; + lodash.attempt = attempt; + lodash.camelCase = camelCase; + lodash.capitalize = capitalize; + lodash.ceil = ceil; + lodash.clone = clone; + lodash.cloneDeep = cloneDeep; + lodash.deburr = deburr; + lodash.endsWith = endsWith; + lodash.escape = escape; + lodash.escapeRegExp = escapeRegExp; + lodash.every = every; + lodash.find = find; + lodash.findIndex = findIndex; + lodash.findKey = findKey; + lodash.findLast = findLast; + lodash.findLastIndex = findLastIndex; + lodash.findLastKey = findLastKey; + lodash.findWhere = findWhere; + lodash.first = first; + lodash.floor = floor; + lodash.get = get; + lodash.gt = gt; + lodash.gte = gte; + lodash.has = has; + lodash.identity = identity; + lodash.includes = includes; + lodash.indexOf = indexOf; + lodash.inRange = inRange; + lodash.isArguments = isArguments; + lodash.isArray = isArray; + lodash.isBoolean = isBoolean; + lodash.isDate = isDate; + lodash.isElement = isElement; + lodash.isEmpty = isEmpty; + lodash.isEqual = isEqual; + lodash.isError = isError; + lodash.isFinite = isFinite; + lodash.isFunction = isFunction; + lodash.isMatch = isMatch; + lodash.isNaN = isNaN; + lodash.isNative = isNative; + lodash.isNull = isNull; + lodash.isNumber = isNumber; + lodash.isObject = isObject; + lodash.isPlainObject = isPlainObject; + lodash.isRegExp = isRegExp; + lodash.isString = isString; + lodash.isTypedArray = isTypedArray; + lodash.isUndefined = isUndefined; + lodash.kebabCase = kebabCase; + lodash.last = last; + lodash.lastIndexOf = lastIndexOf; + lodash.lt = lt; + lodash.lte = lte; + lodash.max = max; + lodash.min = min; + lodash.noConflict = noConflict; + lodash.noop = noop; + lodash.now = now; + lodash.pad = pad; + lodash.padLeft = padLeft; + lodash.padRight = padRight; + lodash.parseInt = parseInt; + lodash.random = random; + lodash.reduce = reduce; + lodash.reduceRight = reduceRight; + lodash.repeat = repeat; + lodash.result = result; + lodash.round = round; + lodash.runInContext = runInContext; + lodash.size = size; + lodash.snakeCase = snakeCase; + lodash.some = some; + lodash.sortedIndex = sortedIndex; + lodash.sortedLastIndex = sortedLastIndex; + lodash.startCase = startCase; + lodash.startsWith = startsWith; + lodash.sum = sum; + lodash.template = template; + lodash.trim = trim; + lodash.trimLeft = trimLeft; + lodash.trimRight = trimRight; + lodash.trunc = trunc; + lodash.unescape = unescape; + lodash.uniqueId = uniqueId; + lodash.words = words; + lodash.all = every; + lodash.any = some; + lodash.contains = includes; + lodash.eq = isEqual; + lodash.detect = find; + lodash.foldl = reduce; + lodash.foldr = reduceRight; + lodash.head = first; + lodash.include = includes; + lodash.inject = reduce; + mixin(lodash, function() { + var source = {}; + baseForOwn(lodash, function(func, methodName) { + if (!lodash.prototype[methodName]) { + source[methodName] = func; + } + }); + return source; + }(), false); + lodash.sample = sample; + lodash.prototype.sample = function(n) { + if (!this.__chain__ && n == null) { + return sample(this.value()); + } + return this.thru(function(value) { + return sample(value, n); + }); + }; + lodash.VERSION = VERSION; + arrayEach([ "bind", "bindKey", "curry", "curryRight", "partial", "partialRight" ], function(methodName) { + lodash[methodName].placeholder = lodash; + }); + arrayEach([ "drop", "take" ], function(methodName, index) { + LazyWrapper.prototype[methodName] = function(n) { + var filtered = this.__filtered__; + if (filtered && !index) { + return new LazyWrapper(this); + } + n = n == null ? 1 : nativeMax(nativeFloor(n) || 0, 0); + var result = this.clone(); + if (filtered) { + result.__takeCount__ = nativeMin(result.__takeCount__, n); + } else { + result.__views__.push({ + size: n, + type: methodName + (result.__dir__ < 0 ? "Right" : "") + }); + } + return result; + }; + LazyWrapper.prototype[methodName + "Right"] = function(n) { + return this.reverse()[methodName](n).reverse(); + }; + }); + arrayEach([ "filter", "map", "takeWhile" ], function(methodName, index) { + var type = index + 1, isFilter = type != LAZY_MAP_FLAG; + LazyWrapper.prototype[methodName] = function(iteratee, thisArg) { + var result = this.clone(); + result.__iteratees__.push({ + iteratee: getCallback(iteratee, thisArg, 1), + type: type + }); + result.__filtered__ = result.__filtered__ || isFilter; + return result; + }; + }); + arrayEach([ "first", "last" ], function(methodName, index) { + var takeName = "take" + (index ? "Right" : ""); + LazyWrapper.prototype[methodName] = function() { + return this[takeName](1).value()[0]; + }; + }); + arrayEach([ "initial", "rest" ], function(methodName, index) { + var dropName = "drop" + (index ? "" : "Right"); + LazyWrapper.prototype[methodName] = function() { + return this.__filtered__ ? new LazyWrapper(this) : this[dropName](1); + }; + }); + arrayEach([ "pluck", "where" ], function(methodName, index) { + var operationName = index ? "filter" : "map", createCallback = index ? baseMatches : property; + LazyWrapper.prototype[methodName] = function(value) { + return this[operationName](createCallback(value)); + }; + }); + LazyWrapper.prototype.compact = function() { + return this.filter(identity); + }; + LazyWrapper.prototype.reject = function(predicate, thisArg) { + predicate = getCallback(predicate, thisArg, 1); + return this.filter(function(value) { + return !predicate(value); + }); + }; + LazyWrapper.prototype.slice = function(start, end) { + start = start == null ? 0 : +start || 0; + var result = this; + if (result.__filtered__ && (start > 0 || end < 0)) { + return new LazyWrapper(result); + } + if (start < 0) { + result = result.takeRight(-start); + } else if (start) { + result = result.drop(start); + } + if (end !== undefined) { + end = +end || 0; + result = end < 0 ? result.dropRight(-end) : result.take(end - start); + } + return result; + }; + LazyWrapper.prototype.takeRightWhile = function(predicate, thisArg) { + return this.reverse().takeWhile(predicate, thisArg).reverse(); + }; + LazyWrapper.prototype.toArray = function() { + return this.take(POSITIVE_INFINITY); + }; + baseForOwn(LazyWrapper.prototype, function(func, methodName) { + var checkIteratee = /^(?:filter|map|reject)|While$/.test(methodName), retUnwrapped = /^(?:first|last)$/.test(methodName), lodashFunc = lodash[retUnwrapped ? "take" + (methodName == "last" ? "Right" : "") : methodName]; + if (!lodashFunc) { + return; + } + lodash.prototype[methodName] = function() { + var args = retUnwrapped ? [ 1 ] : arguments, chainAll = this.__chain__, value = this.__wrapped__, isHybrid = !!this.__actions__.length, isLazy = value instanceof LazyWrapper, iteratee = args[0], useLazy = isLazy || isArray(value); + if (useLazy && checkIteratee && typeof iteratee == "function" && iteratee.length != 1) { + isLazy = useLazy = false; + } + var interceptor = function(value) { + return retUnwrapped && chainAll ? lodashFunc(value, 1)[0] : lodashFunc.apply(undefined, arrayPush([ value ], args)); + }; + var action = { + func: thru, + args: [ interceptor ], + thisArg: undefined + }, onlyLazy = isLazy && !isHybrid; + if (retUnwrapped && !chainAll) { + if (onlyLazy) { + value = value.clone(); + value.__actions__.push(action); + return func.call(value); + } + return lodashFunc.call(undefined, this.value())[0]; + } + if (!retUnwrapped && useLazy) { + value = onlyLazy ? value : new LazyWrapper(this); + var result = func.apply(value, args); + result.__actions__.push(action); + return new LodashWrapper(result, chainAll); + } + return this.thru(interceptor); + }; + }); + arrayEach([ "join", "pop", "push", "replace", "shift", "sort", "splice", "split", "unshift" ], function(methodName) { + var func = (/^(?:replace|split)$/.test(methodName) ? stringProto : arrayProto)[methodName], chainName = /^(?:push|sort|unshift)$/.test(methodName) ? "tap" : "thru", retUnwrapped = /^(?:join|pop|replace|shift)$/.test(methodName); + lodash.prototype[methodName] = function() { + var args = arguments; + if (retUnwrapped && !this.__chain__) { + return func.apply(this.value(), args); + } + return this[chainName](function(value) { + return func.apply(value, args); + }); + }; + }); + baseForOwn(LazyWrapper.prototype, function(func, methodName) { + var lodashFunc = lodash[methodName]; + if (lodashFunc) { + var key = lodashFunc.name + "", names = realNames[key] || (realNames[key] = []); + names.push({ + name: methodName, + func: lodashFunc + }); + } + }); + realNames[createHybridWrapper(undefined, BIND_KEY_FLAG).name] = [ { + name: "wrapper", + func: undefined + } ]; + LazyWrapper.prototype.clone = lazyClone; + LazyWrapper.prototype.reverse = lazyReverse; + LazyWrapper.prototype.value = lazyValue; + lodash.prototype.chain = wrapperChain; + lodash.prototype.commit = wrapperCommit; + lodash.prototype.concat = wrapperConcat; + lodash.prototype.plant = wrapperPlant; + lodash.prototype.reverse = wrapperReverse; + lodash.prototype.toString = wrapperToString; + lodash.prototype.run = lodash.prototype.toJSON = lodash.prototype.valueOf = lodash.prototype.value = wrapperValue; + lodash.prototype.collect = lodash.prototype.map; + lodash.prototype.head = lodash.prototype.first; + lodash.prototype.select = lodash.prototype.filter; + lodash.prototype.tail = lodash.prototype.rest; + return lodash; + } + var _ = runInContext(); + if (typeof define == "function" && typeof define.amd == "object" && define.amd) { + root._ = _; + define(function() { + return _; + }); + } else if (freeExports && freeModule) { + if (moduleExports) { + (freeModule.exports = _)._ = _; + } else { + freeExports._ = _; + } + } else { + root._ = _; + } +}).call(this); + (function(window, document, undefined) { "use strict"; function minErr(module, ErrorConstructor) { @@ -5391,7 +9332,7 @@ } return match; }); - message += "\nhttp://errors.angularjs.org/1.4.6/" + (module ? module + "/" : "") + code; + message += "\nhttp://errors.angularjs.org/1.4.7/" + (module ? module + "/" : "") + code; for (i = SKIP_INDEXES, paramPrefix = "?"; i < templateArgs.length; i++, paramPrefix = "&") { message += paramPrefix + "p" + (i - SKIP_INDEXES) + "=" + encodeURIComponent(toDebugString(templateArgs[i])); } @@ -6210,11 +10151,11 @@ return obj; } var version = { - full: "1.4.6", + full: "1.4.7", major: 1, minor: 4, - dot: 6, - codeName: "multiplicative-elevation" + dot: 7, + codeName: "dark-luminescence" }; function publishExternalAPI(angular) { extend(angular, { @@ -6323,6 +10264,7 @@ $httpParamSerializer: $HttpParamSerializerProvider, $httpParamSerializerJQLike: $HttpParamSerializerJQLikeProvider, $httpBackend: $HttpBackendProvider, + $xhrFactory: $xhrFactoryProvider, $location: $LocationProvider, $log: $LogProvider, $parse: $ParseProvider, @@ -6368,10 +10310,10 @@ return offset ? letter.toUpperCase() : letter; }).replace(MOZ_HACK_REGEXP, "Moz$1"); } - var SINGLE_TAG_REGEXP = /^<(\w+)\s*\/?>(?:<\/\1>|)$/; + var SINGLE_TAG_REGEXP = /^<([\w-]+)\s*\/?>(?:<\/\1>|)$/; var HTML_REGEXP = /<|&#?\w+;/; - var TAG_NAME_REGEXP = /<([\w:]+)/; - var XHTML_TAG_REGEXP = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi; + var TAG_NAME_REGEXP = /<([\w:-]+)/; + var XHTML_TAG_REGEXP = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:-]+)[^>]*)\/>/gi; var wrapMap = { option: [ 1, '" ], thead: [ 1, "", "
" ], @@ -7614,6 +11556,9 @@ } }; return function(element, options) { + if (options.cleanupStyles) { + options.from = options.to = null; + } if (options.from) { element.css(options.from); options.from = null; @@ -8879,7 +12824,7 @@ compile: function() { return { pre: function attrInterpolatePreLinkFn(scope, element, attr) { - var $$observers = attr.$$observers || (attr.$$observers = {}); + var $$observers = attr.$$observers || (attr.$$observers = createMap()); if (EVENT_HANDLER_ATTR_REGEXP.test(name)) { throw $compileMinErr("nodomevents", "Interpolations for HTML DOM event attributes are disallowed. Please use the " + "ng- versions (such as ng-click instead of onclick) instead."); } @@ -9542,12 +13487,16 @@ } } ]; } - function createXhr() { - return new window.XMLHttpRequest(); + function $xhrFactoryProvider() { + this.$get = function() { + return function createXhr() { + return new window.XMLHttpRequest(); + }; + }; } function $HttpBackendProvider() { - this.$get = [ "$browser", "$window", "$document", function($browser, $window, $document) { - return createHttpBackend($browser, createXhr, $browser.defer, $window.angular.callbacks, $document[0]); + this.$get = [ "$browser", "$window", "$document", "$xhrFactory", function($browser, $window, $document, $xhrFactory) { + return createHttpBackend($browser, $xhrFactory, $browser.defer, $window.angular.callbacks, $document[0]); } ]; } function createHttpBackend($browser, createXhr, $browserDefer, callbacks, rawDocument) { @@ -9565,7 +13514,7 @@ callbacks[callbackId] = noop; }); } else { - var xhr = createXhr(); + var xhr = createXhr(method, url); xhr.open(method, url, true); forEach(headers, function(value, key) { if (isDefined(value)) { @@ -10273,12 +14222,18 @@ } var $parseMinErr = minErr("$parse"); function ensureSafeMemberName(name, fullExpression) { - name = isObject(name) && name.toString ? name.toString() : name; if (name === "__defineGetter__" || name === "__defineSetter__" || name === "__lookupGetter__" || name === "__lookupSetter__" || name === "__proto__") { throw $parseMinErr("isecfld", "Attempting to access a disallowed field in Angular expressions! " + "Expression: {0}", fullExpression); } return name; } + function getStringValue(name, fullExpression) { + name = name + ""; + if (!isString(name)) { + throw $parseMinErr("iseccst", "Cannot convert object to primitive value! " + "Expression: {0}", fullExpression); + } + return name; + } function ensureSafeObject(obj, fullExpression) { if (obj) { if (obj.constructor === obj) { @@ -10305,6 +14260,13 @@ } } } + function ensureSafeAssignContext(obj, fullExpression) { + if (obj) { + if (obj === 0..constructor || obj === false.constructor || obj === "".constructor || obj === {}.constructor || obj === [].constructor || obj === Function.constructor) { + throw $parseMinErr("isecaf", "Assigning to a constructor is disallowed! Expression: {0}", fullExpression); + } + } + } var OPERATORS = createMap(); forEach("+ - * / % === !== == != < > <= >= && || ! = |".split(" "), function(operator) { OPERATORS[operator] = true; @@ -11053,7 +15015,7 @@ this.stage = "main"; this.recurse(ast); var fnString = '"' + this.USE + " " + this.STRICT + '";\n' + this.filterPrefix() + "var fn=" + this.generateFunction("fn", "s,l,a,i") + extra + this.watchFns() + "return fn;"; - var fn = new Function("$filter", "ensureSafeMemberName", "ensureSafeObject", "ensureSafeFunction", "ifDefined", "plus", "text", fnString)(this.$filter, ensureSafeMemberName, ensureSafeObject, ensureSafeFunction, ifDefined, plusFn, expression); + var fn = new Function("$filter", "ensureSafeMemberName", "ensureSafeObject", "ensureSafeFunction", "getStringValue", "ensureSafeAssignContext", "ifDefined", "plus", "text", fnString)(this.$filter, ensureSafeMemberName, ensureSafeObject, ensureSafeFunction, getStringValue, ensureSafeAssignContext, ifDefined, plusFn, expression); this.state = this.stage = undefined; fn.literal = isLiteral(ast); fn.constant = isConstant(ast); @@ -11190,6 +15152,7 @@ if (ast.computed) { right = self.nextId(); self.recurse(ast.property, right); + self.getStringValue(right); self.addEnsureSafeMemberName(right); if (create && create !== 1) { self.if_(self.not(self.computedMember(left, right)), self.lazyAssign(self.computedMember(left, right), "{}")); @@ -11275,6 +15238,7 @@ self.if_(self.notNull(left.context), function() { self.recurse(ast.right, right); self.addEnsureSafeObject(self.member(left.context, left.name, left.computed)); + self.addEnsureSafeAssignContext(left.context); expression = self.member(left.context, left.name, left.computed) + ast.operator + right; self.assign(intoId, expression); recursionFn(intoId || expression); @@ -11385,6 +15349,9 @@ addEnsureSafeFunction: function(item) { this.current().body.push(this.ensureSafeFunction(item), ";"); }, + addEnsureSafeAssignContext: function(item) { + this.current().body.push(this.ensureSafeAssignContext(item), ";"); + }, ensureSafeObject: function(item) { return "ensureSafeObject(" + item + ",text)"; }, @@ -11394,6 +15361,12 @@ ensureSafeFunction: function(item) { return "ensureSafeFunction(" + item + ",text)"; }, + getStringValue: function(item) { + this.assign(item, "getStringValue(" + item + ",text)"); + }, + ensureSafeAssignContext: function(item) { + return "ensureSafeAssignContext(" + item + ",text)"; + }, lazyRecurse: function(ast, intoId, nameId, recursionFn, create, skipWatchIdCheck) { var self = this; return function() { @@ -11561,6 +15534,7 @@ var lhs = left(scope, locals, assign, inputs); var rhs = right(scope, locals, assign, inputs); ensureSafeObject(lhs.value, self.expression); + ensureSafeAssignContext(lhs.context); lhs.context[lhs.name] = rhs; return context ? { value: rhs @@ -11818,6 +15792,7 @@ var value; if (lhs != null) { rhs = right(scope, locals, assign, inputs); + rhs = getStringValue(rhs); ensureSafeMemberName(rhs, expression); if (create && create !== 1 && lhs && !lhs[rhs]) { lhs[rhs] = {}; @@ -13500,6 +17475,7 @@ if (fractionSize > 0 && number < 1) { formatedText = number.toFixed(fractionSize); number = parseFloat(formatedText); + formatedText = formatedText.replace(DECIMAL_SEP, decimalSep); } } if (number === 0) { @@ -15517,11 +19493,11 @@ function updateOptionElement(option, element) { option.element = element; element.disabled = option.disabled; - if (option.value !== element.value) element.value = option.selectValue; if (option.label !== element.label) { element.label = option.label; element.textContent = option.label; } + if (option.value !== element.value) element.value = option.selectValue; } function addOrReuseElement(parent, current, type, templateElement) { var element; @@ -15549,7 +19525,7 @@ var emptyOption_ = emptyOption && emptyOption[0]; var unknownOption_ = unknownOption && unknownOption[0]; if (emptyOption_ || unknownOption_) { - while (current && (current === emptyOption_ || current === unknownOption_)) { + while (current && (current === emptyOption_ || current === unknownOption_ || emptyOption_ && emptyOption_.nodeType === NODE_TYPE_COMMENT)) { current = current.nextSibling; } } @@ -28638,11 +32614,6 @@ if (typeof module !== "undefined" && typeof exports !== "undefined" && module.ex if (!b) return a; return a + " " + b; } - function $$BodyProvider() { - this.$get = [ "$document", function($document) { - return jqLite($document[0].body); - } ]; - } var $$rAFSchedulerFactory = [ "$$rAF", function($$rAF) { var queue, cancelFn; function scheduler(tasks) { @@ -28780,6 +32751,11 @@ if (typeof module !== "undefined" && typeof exports !== "undefined" && module.ex } }; } + function registerRestorableStyles(backup, node, properties) { + forEach(properties, function(prop) { + backup[prop] = isDefined(backup[prop]) ? backup[prop] : node.style.getPropertyValue(prop); + }); + } var $AnimateCssProvider = [ "$animateProvider", function($animateProvider) { var gcsLookup = createLocalCacheLookup(); var gcsStaggerLookup = createLocalCacheLookup(); @@ -28842,6 +32818,7 @@ if (typeof module !== "undefined" && typeof exports !== "undefined" && module.ex return timings; } return function init(element, options) { + var restoreStyles = {}; var node = getDomNode(element); if (!node || !node.parentNode || !$animate.enabled()) { return closeAndReturnNoopAnimator(); @@ -28977,7 +32954,12 @@ if (typeof module !== "undefined" && typeof exports !== "undefined" && module.ex flags.blockTransition = timings.transitionDuration > 0; flags.blockKeyframeAnimation = timings.animationDuration > 0 && stagger.animationDelay > 0 && stagger.animationDuration === 0; } - applyAnimationFromStyles(element, options); + if (options.from) { + if (options.cleanupStyles) { + registerRestorableStyles(restoreStyles, node, Object.keys(options.from)); + } + applyAnimationFromStyles(element, options); + } if (flags.blockTransition || flags.blockKeyframeAnimation) { applyBlocking(maxDuration); } else if (!options.skipBlocking) { @@ -29020,6 +33002,11 @@ if (typeof module !== "undefined" && typeof exports !== "undefined" && module.ex }); applyAnimationClasses(element, options); applyAnimationStyles(element, options); + if (Object.keys(restoreStyles).length) { + forEach(restoreStyles, function(value, prop) { + value ? node.style.setProperty(prop, value) : node.style.removeProperty(prop); + }); + } if (options.onDone) { options.onDone(); } @@ -29158,7 +33145,12 @@ if (typeof module !== "undefined" && typeof exports !== "undefined" && module.ex element.data(ANIMATE_TIMER_KEY, animationsData); } element.on(events.join(" "), onAnimationProgress); - applyAnimationToStyles(element, options); + if (options.to) { + if (options.cleanupStyles) { + registerRestorableStyles(restoreStyles, node, Object.keys(options.to)); + } + applyAnimationToStyles(element, options); + } } function onAnimationExpired() { var animationsData = element.data(ANIMATE_TIMER_KEY); @@ -29189,11 +33181,14 @@ if (typeof module !== "undefined" && typeof exports !== "undefined" && module.ex var NG_ANIMATE_ANCHOR_CLASS_NAME = "ng-anchor"; var NG_OUT_ANCHOR_CLASS_NAME = "ng-anchor-out"; var NG_IN_ANCHOR_CLASS_NAME = "ng-anchor-in"; - this.$get = [ "$animateCss", "$rootScope", "$$AnimateRunner", "$rootElement", "$$body", "$sniffer", "$$jqLite", function($animateCss, $rootScope, $$AnimateRunner, $rootElement, $$body, $sniffer, $$jqLite) { + function isDocumentFragment(node) { + return node.parentNode && node.parentNode.nodeType === 11; + } + this.$get = [ "$animateCss", "$rootScope", "$$AnimateRunner", "$rootElement", "$sniffer", "$$jqLite", "$document", function($animateCss, $rootScope, $$AnimateRunner, $rootElement, $sniffer, $$jqLite, $document) { if (!$sniffer.animations && !$sniffer.transitions) return noop; - var bodyNode = getDomNode($$body); + var bodyNode = $document[0].body; var rootNode = getDomNode($rootElement); - var rootBodyElement = jqLite(bodyNode.parentNode === rootNode ? bodyNode : rootNode); + var rootBodyElement = jqLite(isDocumentFragment(rootNode) || bodyNode.contains(rootNode) ? rootNode : bodyNode); var applyAnimationClasses = applyAnimationClassesFactory($$jqLite); return function initDriverFn(animationDetails) { return animationDetails.from && animationDetails.to ? prepareFromToAnchorAnimation(animationDetails.from, animationDetails.to, animationDetails.classes, animationDetails.anchors) : prepareRegularAnimation(animationDetails); @@ -29662,10 +33657,23 @@ if (typeof module !== "undefined" && typeof exports !== "undefined" && module.ex var cO = currentAnimation.options; return nO.addClass && nO.addClass === cO.removeClass || nO.removeClass && nO.removeClass === cO.addClass; }); - this.$get = [ "$$rAF", "$rootScope", "$rootElement", "$document", "$$body", "$$HashMap", "$$animation", "$$AnimateRunner", "$templateRequest", "$$jqLite", "$$forceReflow", function($$rAF, $rootScope, $rootElement, $document, $$body, $$HashMap, $$animation, $$AnimateRunner, $templateRequest, $$jqLite, $$forceReflow) { + this.$get = [ "$$rAF", "$rootScope", "$rootElement", "$document", "$$HashMap", "$$animation", "$$AnimateRunner", "$templateRequest", "$$jqLite", "$$forceReflow", function($$rAF, $rootScope, $rootElement, $document, $$HashMap, $$animation, $$AnimateRunner, $templateRequest, $$jqLite, $$forceReflow) { var activeAnimationsLookup = new $$HashMap(); var disabledElementsLookup = new $$HashMap(); var animationsEnabled = null; + function postDigestTaskFactory() { + var postDigestCalled = false; + return function(fn) { + if (postDigestCalled) { + fn(); + } else { + $rootScope.$$postDigest(function() { + postDigestCalled = true; + fn(); + }); + } + }; + } var deregisterWatch = $rootScope.$watch(function() { return $templateRequest.totalPendingRequests === 0; }, function(isEmpty) { @@ -29703,13 +33711,6 @@ if (typeof module !== "undefined" && typeof exports !== "undefined" && module.ex } return matches; } - function triggerCallback(event, element, phase, data) { - $$rAF(function() { - forEach(findCallbacks(element, event), function(callback) { - callback(element, phase, data); - }); - }); - } return { on: function(event, container, callback) { var node = extractElementNode(container); @@ -29776,6 +33777,7 @@ if (typeof module !== "undefined" && typeof exports !== "undefined" && module.ex } options = prepareAnimationOptions(options); var runner = new $$AnimateRunner(); + var runInNextPostDigestOrNow = postDigestTaskFactory(); if (isArray(options.addClass)) { options.addClass = options.addClass.join(" "); } @@ -29910,7 +33912,16 @@ if (typeof module !== "undefined" && typeof exports !== "undefined" && module.ex }); return runner; function notifyProgress(runner, event, phase, data) { - triggerCallback(event, element, phase, data); + runInNextPostDigestOrNow(function() { + var callbacks = findCallbacks(element, event); + if (callbacks.length) { + $$rAF(function() { + forEach(callbacks, function(callback) { + callback(element, phase, data); + }); + }); + } + }); runner.progress(event, phase, data); } function close(reject) { @@ -29948,7 +33959,8 @@ if (typeof module !== "undefined" && typeof exports !== "undefined" && module.ex return getDomNode(nodeOrElmA) === getDomNode(nodeOrElmB); } function areAnimationsAllowed(element, parentElement, event) { - var bodyElementDetected = isMatchingElement(element, $$body) || element[0].nodeName === "HTML"; + var bodyElement = jqLite($document[0].body); + var bodyElementDetected = isMatchingElement(element, bodyElement) || element[0].nodeName === "HTML"; var rootElementDetected = isMatchingElement(element, $rootElement); var parentAnimationDetected = false; var animateChildren; @@ -29985,7 +33997,7 @@ if (typeof module !== "undefined" && typeof exports !== "undefined" && module.ex } } if (!bodyElementDetected) { - bodyElementDetected = isMatchingElement(parentElement, $$body); + bodyElementDetected = isMatchingElement(parentElement, bodyElement); } parentElement = parentElement.parent(); } @@ -30445,228 +34457,9 @@ if (typeof module !== "undefined" && typeof exports !== "undefined" && module.ex }; } ]; } ]; - angular.module("ngAnimate", []).provider("$$body", $$BodyProvider).directive("ngAnimateChildren", $$AnimateChildrenDirective).factory("$$rAFScheduler", $$rAFSchedulerFactory).factory("$$AnimateRunner", $$AnimateRunnerFactory).factory("$$animateAsyncRun", $$AnimateAsyncRunFactory).provider("$$animateQueue", $$AnimateQueueProvider).provider("$$animation", $$AnimationProvider).provider("$animateCss", $AnimateCssProvider).provider("$$animateCssDriver", $$AnimateCssDriverProvider).provider("$$animateJs", $$AnimateJsProvider).provider("$$animateJsDriver", $$AnimateJsDriverProvider); + angular.module("ngAnimate", []).directive("ngAnimateChildren", $$AnimateChildrenDirective).factory("$$rAFScheduler", $$rAFSchedulerFactory).factory("$$AnimateRunner", $$AnimateRunnerFactory).factory("$$animateAsyncRun", $$AnimateAsyncRunFactory).provider("$$animateQueue", $$AnimateQueueProvider).provider("$$animation", $$AnimationProvider).provider("$animateCss", $AnimateCssProvider).provider("$$animateCssDriver", $$AnimateCssDriverProvider).provider("$$animateJs", $$AnimateJsProvider).provider("$$animateJsDriver", $$AnimateJsDriverProvider); })(window, window.angular); -var app = angular.module("autocomplete", []); - -app.directive("autocomplete", function() { - var index = -1; - return { - restrict: "E", - scope: { - searchParam: "=ngModel", - suggestions: "=data", - onType: "=onType", - onSelect: "=onSelect", - autocompleteRequired: "=" - }, - controller: [ "$scope", function($scope) { - $scope.selectedIndex = -1; - $scope.initLock = true; - $scope.setIndex = function(i) { - $scope.selectedIndex = parseInt(i); - }; - this.setIndex = function(i) { - $scope.setIndex(i); - $scope.$apply(); - }; - $scope.getIndex = function(i) { - return $scope.selectedIndex; - }; - var watching = true; - $scope.completing = false; - $scope.$watch("searchParam", function(newValue, oldValue) { - if (oldValue === newValue || !oldValue && $scope.initLock) { - return; - } - if (watching && typeof $scope.searchParam !== "undefined" && $scope.searchParam !== null) { - $scope.completing = true; - $scope.searchFilter = $scope.searchParam; - $scope.selectedIndex = -1; - } - if ($scope.onType) $scope.onType($scope.searchParam); - }); - this.preSelect = function(suggestion) { - watching = false; - $scope.$apply(); - watching = true; - }; - $scope.preSelect = this.preSelect; - this.preSelectOff = function() { - watching = true; - }; - $scope.preSelectOff = this.preSelectOff; - $scope.select = function(suggestion) { - if (suggestion) { - $scope.searchParam = suggestion; - $scope.searchFilter = suggestion; - if ($scope.onSelect) $scope.onSelect(suggestion); - } - watching = false; - $scope.completing = false; - setTimeout(function() { - watching = true; - }, 1e3); - $scope.setIndex(-1); - }; - } ], - link: function(scope, element, attrs) { - setTimeout(function() { - scope.initLock = false; - scope.$apply(); - }, 250); - var attr = ""; - scope.attrs = { - placeholder: "start typing...", - "class": "", - id: "", - inputclass: "", - inputid: "" - }; - for (var a in attrs) { - attr = a.replace("attr", "").toLowerCase(); - if (a.indexOf("attr") === 0) { - scope.attrs[attr] = attrs[a]; - } - } - if (attrs.clickActivation) { - element[0].onclick = function(e) { - if (!scope.searchParam) { - setTimeout(function() { - scope.completing = true; - scope.$apply(); - }, 200); - } - }; - } - var key = { - left: 37, - up: 38, - right: 39, - down: 40, - enter: 13, - esc: 27, - tab: 9 - }; - document.addEventListener("keydown", function(e) { - var keycode = e.keyCode || e.which; - switch (keycode) { - case key.esc: - scope.select(); - scope.setIndex(-1); - scope.$apply(); - e.preventDefault(); - } - }, true); - document.addEventListener("blur", function(e) { - setTimeout(function() { - scope.select(); - scope.setIndex(-1); - scope.$apply(); - }, 150); - }, true); - element[0].addEventListener("keydown", function(e) { - var keycode = e.keyCode || e.which; - var l = angular.element(this).find("li").length; - if (!scope.completing || l == 0) return; - switch (keycode) { - case key.up: - index = scope.getIndex() - 1; - if (index < -1) { - index = l - 1; - } else if (index >= l) { - index = -1; - scope.setIndex(index); - scope.preSelectOff(); - break; - } - scope.setIndex(index); - if (index !== -1) scope.preSelect(angular.element(angular.element(this).find("li")[index]).text()); - scope.$apply(); - break; - - case key.down: - index = scope.getIndex() + 1; - if (index < -1) { - index = l - 1; - } else if (index >= l) { - index = -1; - scope.setIndex(index); - scope.preSelectOff(); - scope.$apply(); - break; - } - scope.setIndex(index); - if (index !== -1) scope.preSelect(angular.element(angular.element(this).find("li")[index]).text()); - break; - - case key.left: - break; - - case key.right: - case key.enter: - case key.tab: - index = scope.getIndex(); - if (index !== -1) { - scope.select(angular.element(angular.element(this).find("li")[index]).text()); - if (keycode == key.enter) { - e.preventDefault(); - } - } else { - if (keycode == key.enter) { - scope.select(); - } - } - scope.setIndex(-1); - scope.$apply(); - break; - - case key.esc: - scope.select(); - scope.setIndex(-1); - scope.$apply(); - e.preventDefault(); - break; - - default: - return; - } - }); - }, - template: '
' - }; -}); - -app.filter("highlight", [ "$sce", function($sce) { - return function(input, searchParam) { - if (typeof input === "function") return ""; - if (searchParam) { - var words = "(" + searchParam.split(/\ /).join(" |") + "|" + searchParam.split(/\ /).join("|") + ")", exp = new RegExp(words, "gi"); - if (words.length) { - input = input.replace(exp, '$1'); - } - } - return $sce.trustAsHtml(input); - }; -} ]); - -app.directive("suggestion", function() { - return { - restrict: "A", - require: "^autocomplete", - link: function(scope, element, attrs, autoCtrl) { - element.bind("mouseenter", function() { - autoCtrl.preSelect(attrs.val); - autoCtrl.setIndex(attrs.index); - }); - element.bind("mouseleave", function() { - autoCtrl.preSelectOff(); - }); - } - }; -}); - function getCookie(name) { var nameEQ = name + "="; var ca = document.cookie.split(";"); @@ -30729,6 +34522,12 @@ var cloneObject = function(oldObject) { return JSON.parse(JSON.stringify(oldObject)); }; +var enableControls = function(controls, enabled) { + _.each(controls, function(value, key) { + controls[key] = enabled; + }); +}; + var lingvodoc = {}; lingvodoc.Object = function(clientId, objectId) { @@ -30736,10 +34535,7 @@ lingvodoc.Object = function(clientId, objectId) { this.object_id = objectId; this.type = "abstract"; this.getId = function() { - return this.client_id + "" + this.object_id; - }; - this.export = function() { - return {}; + return this.client_id + "_" + this.object_id; }; }; @@ -30800,13 +34596,33 @@ lingvodoc.Perspective = function(client_id, object_id, parent_client_id, parent_ this.is_template = is_template; this.marked_for_deletion = marked_for_deletion; this.fields = []; + this.location = null; + this.blobs = []; + this.additional_metadata = {}; this.equals = function(obj) { return lingvodoc.Object.prototype.equals.call(this, obj) && this.translation == obj.translation; }; }; lingvodoc.Perspective.fromJS = function(js) { - return new lingvodoc.Perspective(js.client_id, js.object_id, js.parent_client_id, js.parent_object_id, js.translation, js.translation_string, js.status, js.is_template, js.marked_for_deletion); + var perspective = new lingvodoc.Perspective(js.client_id, js.object_id, js.parent_client_id, js.parent_object_id, js.translation, js.translation_string, js.status, js.is_template, js.marked_for_deletion); + if (_.has(js, "location") && _.has(js.location, "content")) { + perspective["location"] = { + lat: js.location.content.lat, + lng: js.location.content.lng + }; + } + if (_.has(js, "info") && js.info.type == "list") { + if (_.isArray(js.info.content)) { + perspective["blobs"] = _.map(js.info.content, function(e) { + var blob = new lingvodoc.Blob(e.info.content.client_id, e.info.content.object_id, e.info.content.name, e.info.content.data_type); + blob.url = e.info.content.content; + return blob; + }); + } + } + perspective.additional_metadata = js.additional_metadata; + return perspective; }; lingvodoc.Perspective.prototype = new lingvodoc.Object(); @@ -30831,6 +34647,25 @@ lingvodoc.User.fromJS = function(js) { return new lingvodoc.User(js.id, js.login, js.name, js.email, js.intl_name, js.about, js.signup_date, js.organizations); }; +lingvodoc.Blob = function(clientId, objectId, name, data_type) { + lingvodoc.Object.call(this, clientId, objectId); + this.type = "blob"; + this.name = name; + this.data_type = data_type; + this.url = null; + this.equals = function(obj) { + return lingvodoc.Object.prototype.equals.call(this, obj) && this.name == obj.name; + }; +}; + +lingvodoc.Blob.fromJS = function(js) { + return new lingvodoc.Blob(js.client_id, js.object_id, js.name, js.data_type); +}; + +lingvodoc.Blob.prototype = new lingvodoc.Object(); + +lingvodoc.Blob.prototype.constructor = lingvodoc.Blob; + function lingvodocAPI($http, $q) { var addUrlParameter = function(url, key, value) { return url + (url.indexOf("?") >= 0 ? "&" : "?") + encodeURIComponent(key) + "=" + encodeURIComponent(value); @@ -30904,6 +34739,21 @@ function lingvodocAPI($http, $q) { }); return deferred.promise; }; + var getPerspectiveDictionaryFieldsNew = function(perspective) { + var deferred = $q.defer(); + var url = "/dictionary/" + perspective.parent_client_id + "/" + perspective.parent_object_id + "/perspective/" + perspective.client_id + "/" + perspective.object_id + "/fields"; + $http.get(url).success(function(data, status, headers, config) { + if (_.isArray(data.fields)) { + var fields = perspectiveToDictionaryFields(data.fields); + deferred.resolve(fields); + } else { + deferred.reject("An error occurred while fetching perspective fields"); + } + }).error(function(data, status, headers, config) { + deferred.reject("An error occurred while fetching perspective fields"); + }); + return deferred.promise; + }; var removeValue = function(entry, field, fieldValue, parent) { var deferred = $q.defer(); var url; @@ -31070,8 +34920,9 @@ function lingvodocAPI($http, $q) { }); return deferred.promise; }; - var getDictionaryProperties = function(url) { + var getDictionaryProperties = function(dictionary) { var deferred = $q.defer(); + var url = "/dictionary/" + encodeURIComponent(dictionary.client_id) + "/" + encodeURIComponent(dictionary.object_id); $http.get(url).success(function(data, status, headers, config) { deferred.resolve(data); }).error(function(data, status, headers, config) { @@ -31079,8 +34930,9 @@ function lingvodocAPI($http, $q) { }); return deferred.promise; }; - var setDictionaryProperties = function(url, properties) { + var setDictionaryProperties = function(dictionary, properties) { var deferred = $q.defer(); + var url = "/dictionary/" + encodeURIComponent(dictionary.client_id) + "/" + encodeURIComponent(dictionary.object_id); $http.put(url, properties).success(function(data, status, headers, config) { deferred.resolve(data); }).error(function(data, status, headers, config) { @@ -31088,6 +34940,16 @@ function lingvodocAPI($http, $q) { }); return deferred.promise; }; + var removeDictionary = function(dictionary) { + var deferred = $q.defer(); + var url = "/dictionary/" + encodeURIComponent(dictionary.client_id) + "/" + encodeURIComponent(dictionary.object_id); + $http.delete(url).success(function(data, status, headers, config) { + deferred.resolve(); + }).error(function(data, status, headers, config) { + deferred.reject("An error occurred while trying to delete dictionary"); + }); + return deferred.promise; + }; var getLanguages = function(url) { var deferred = $q.defer(); var flatLanguages = function(languages) { @@ -31171,6 +35033,16 @@ function lingvodocAPI($http, $q) { }); return deferred.promise; }; + var removePerspective = function(perspective) { + var deferred = $q.defer(); + var url = "/dictionary/" + perspective.parent_client_id + "/" + perspective.parent_object_id + "/perspective/" + perspective.client_id + "/" + perspective.object_id; + $http.delete(url).success(function(data, status, headers, config) { + deferred.resolve(); + }).error(function(data, status, headers, config) { + deferred.reject("An error occurred while trying to delete perspective"); + }); + return deferred.promise; + }; var getUserInfo = function(userId, clientId) { var deferred = $q.defer(); var url = "/user" + "?client_id= " + encodeURIComponent(clientId) + "&user_id= " + encodeURIComponent(userId); @@ -31251,13 +35123,14 @@ function lingvodocAPI($http, $q) { }; var getDictionaries = function(query) { var deferred = $q.defer(); - var dictionaries = []; $http.post("/dictionaries", query).success(function(data, status, headers, config) { - for (var i = 0; i < data.dictionaries.length; i++) { - var dictionary = data.dictionaries[i]; - dictionaries.push(lingvodoc.Dictionary.fromJS(dictionary)); + if (_.isArray(data.dictionaries)) { + deferred.resolve(_.map(data.dictionaries, function(d) { + return lingvodoc.Dictionary.fromJS(d); + })); + } else { + deferred.reject("Failed to fetch dictionaries list. Malformed response."); } - deferred.resolve(dictionaries); }).error(function(data, status, headers, config) { deferred.reject("Failed to fetch dictionaries list"); }); @@ -31474,8 +35347,8 @@ function lingvodocAPI($http, $q) { }; $http.post("/dictionaries", req).success(function(data, status, headers, config) { var dictionaries = []; - if (angular.isArray(data.dictionaries)) { - angular.forEach(data.dictionaries, function(jsdict) { + if (_.isArray(data.dictionaries)) { + _.forEach(data.dictionaries, function(jsdict) { var dictionary = lingvodoc.Dictionary.fromJS(jsdict); if (language.client_id == dictionary.parent_client_id && language.object_id == dictionary.parent_object_id) { dictionaries.push(dictionary); @@ -31484,7 +35357,7 @@ function lingvodocAPI($http, $q) { } deferred.resolve(dictionaries); }).error(function(data, status, headers, config) { - deferred.reject("Failed to move lexical entry"); + deferred.reject("Failed to fetch list of dictionaries"); }); return deferred.promise; }; @@ -31667,10 +35540,140 @@ function lingvodocAPI($http, $q) { }); return deferred.promise; }; + var getUserBlobs = function() { + var deferred = $q.defer(); + $http.get("/blobs").success(function(data, status, headers, config) { + var blobs = _.map(data, lingvodoc.Blob.fromJS); + deferred.resolve(blobs); + }).error(function(data, status, headers, config) { + deferred.reject("Failed to fetch list of available blobs"); + }); + return deferred.promise; + }; + var checkDictionaryBlob = function(blob, parent) { + var deferred = $q.defer(); + var query = { + blob_client_id: blob.client_id, + blob_object_id: blob.object_id, + parent_client_id: parent.client_id, + parent_object_id: parent.object_id + }; + $http.post("/convert_check", query).success(function(data, status, headers, config) { + var perspectives = _.map(data, lingvodoc.Perspective.fromJS); + deferred.resolve(perspectives); + }).error(function(data, status, headers, config) { + deferred.reject("Failed to convert dictionary"); + }); + return deferred.promise; + }; + var convertDictionary = function(req) { + var deferred = $q.defer(); + $http.post("/convert", req).success(function(data, status, headers, config) { + deferred.resolve(data); + }).error(function(data, status, headers, config) { + deferred.reject("Failed to convert dictionary"); + }); + return deferred.promise; + }; + var getPerspectiveMeta = function(dictionary, perspective) { + var deferred = $q.defer(); + var url = "/dictionary/" + encodeURIComponent(dictionary.client_id) + "/" + encodeURIComponent(dictionary.object_id) + "/perspective/" + encodeURIComponent(perspective.client_id) + "/" + encodeURIComponent(perspective.object_id) + "/meta"; + $http.get(url).success(function(data, status, headers, config) { + deferred.resolve(data); + }).error(function(data, status, headers, config) { + deferred.reject("Failed to get perspective meta data!"); + }); + return deferred.promise; + }; + var setPerspectiveMeta = function(dictionary, perspective, meta) { + var deferred = $q.defer(); + var url = "/dictionary/" + encodeURIComponent(dictionary.client_id) + "/" + encodeURIComponent(dictionary.object_id) + "/perspective/" + encodeURIComponent(perspective.client_id) + "/" + encodeURIComponent(perspective.object_id) + "/meta"; + $http.put(url, meta).success(function(data, status, headers, config) { + deferred.resolve(data); + }).error(function(data, status, headers, config) { + deferred.reject("Failed to set perspective meta data!"); + }); + return deferred.promise; + }; + var removePerspectiveMeta = function(dictionary, perspective, meta) { + var deferred = $q.defer(); + var url = "/dictionary/" + encodeURIComponent(dictionary.client_id) + "/" + encodeURIComponent(dictionary.object_id) + "/perspective/" + encodeURIComponent(perspective.client_id) + "/" + encodeURIComponent(perspective.object_id) + "/meta"; + var config = { + method: "DELETE", + url: url, + data: meta, + headers: { + "Content-Type": "application/json;charset=utf-8" + } + }; + $http(config).success(function(data, status, headers, config) { + deferred.resolve(data); + }).error(function(data, status, headers, config) { + deferred.reject("Failed to remove perspective meta data!"); + }); + return deferred.promise; + }; + var advancedSearch = function(query, where, adopted, etymology) { + var deferred = $q.defer(); + var url = "/advanced_search"; + var perspectives = where.map(function(o) { + if (o.type == "perspective") { + return { + client_id: o.client_id, + object_id: o.object_id + }; + } + }).filter(function(o) { + return typeof o !== "undefined"; + }); + var req = { + searchstrings: query, + perspectives: perspectives + }; + if (_.isBoolean(adopted)) { + req.adopted = adopted; + } + if (_.isBoolean(etymology)) { + req.with_etimology = etymology; + } + $http.post(url, req).success(function(data, status, headers, config) { + var r = data.map(function(e) { + var perspective = lingvodoc.Perspective.fromJS(e); + return getPerspectiveOriginById(perspective.client_id, perspective.object_id); + }); + $q.all(r).then(function(paths) { + var out = []; + _.each(data, function(entry, i) { + entry.lexical_entry["origin"] = paths[i]; + out.push(entry.lexical_entry); + }); + deferred.resolve(out); + }, function(reason) { + deferred.reject("An error occurred while doing basic search"); + }); + }).error(function(data, status, headers, config) { + deferred.reject("An error occurred while doing advanced search"); + }); + return deferred.promise; + }; + var convertMarkup = function(object) { + var deferred = $q.defer(); + var obj = { + client_id: object.client_id, + object_id: object.object_id + }; + $http.post("/convert/markup", obj).success(function(data, status, headers, config) { + deferred.resolve(data); + }).error(function(data, status, headers, config) { + deferred.reject("Failed to convert markup!"); + }); + return deferred.promise; + }; return { getLexicalEntries: getLexicalEntries, getLexicalEntriesCount: getLexicalEntriesCount, getPerspectiveDictionaryFields: getPerspectiveDictionaryFields, + getPerspectiveDictionaryFieldsNew: getPerspectiveDictionaryFieldsNew, addNewLexicalEntry: addNewLexicalEntry, saveValue: saveValue, removeValue: removeValue, @@ -31681,6 +35684,7 @@ function lingvodocAPI($http, $q) { approveAll: approveAll, getDictionaryProperties: getDictionaryProperties, setDictionaryProperties: setDictionaryProperties, + removeDictionary: removeDictionary, getLanguages: getLanguages, setDictionaryStatus: setDictionaryStatus, setPerspectiveStatus: setPerspectiveStatus, @@ -31688,6 +35692,7 @@ function lingvodocAPI($http, $q) { getPerspectiveFields: getPerspectiveFields, setPerspectiveFields: setPerspectiveFields, getPerspectiveFieldsNew: getPerspectiveFieldsNew, + removePerspective: removePerspective, getUserInfo: getUserInfo, setUserInfo: setUserInfo, getOrganizations: getOrganizations, @@ -31714,7 +35719,15 @@ function lingvodocAPI($http, $q) { deleteDictionaryRoles: deleteDictionaryRoles, getPerspectiveRoles: getPerspectiveRoles, addPerspectiveRoles: addPerspectiveRoles, - deletePerspectiveRoles: deletePerspectiveRoles + deletePerspectiveRoles: deletePerspectiveRoles, + getUserBlobs: getUserBlobs, + checkDictionaryBlob: checkDictionaryBlob, + convertDictionary: convertDictionary, + getPerspectiveMeta: getPerspectiveMeta, + setPerspectiveMeta: setPerspectiveMeta, + removePerspectiveMeta: removePerspectiveMeta, + advancedSearch: advancedSearch, + convertMarkup: convertMarkup }; } @@ -31746,13 +35759,38 @@ function responseHandler($timeout, $modal) { function error(message) { show("error", message, 5e3); } + function yesno(status, message, callback) { + var controller = function($scope, $modalInstance) { + $scope.status = status; + $scope.message = message; + $scope.yes = function() { + $modalInstance.close(true); + }; + $scope.no = function() { + $modalInstance.close(false); + }; + }; + $modal.open({ + animation: true, + templateUrl: "responseHandlerYesNoModal.html", + controller: controller, + size: "lg", + backdrop: "static", + keyboard: false + }).result.then(function(result) { + callback(result); + }, function() { + callback(false); + }); + } return { success: success, - error: error + error: error, + yesno: yesno }; } -var app = angular.module("CreateDictionaryModule", [ "ui.router", "ngAnimate", "ui.bootstrap", "autocomplete" ]); +var app = angular.module("CreateDictionaryModule", [ "ui.router", "ui.bootstrap" ]); app.service("dictionaryService", lingvodocAPI); @@ -31776,7 +35814,7 @@ app.config(function($stateProvider, $urlRouterProvider) { app.factory("responseHandler", [ "$timeout", "$modal", responseHandler ]); -app.controller("CreateDictionaryController", [ "$scope", "$http", "$modal", "$interval", "$state", "$location", "$log", "dictionaryService", "responseHandler", function($scope, $http, $modal, $interval, $state, $location, $log, dictionaryService, responseHandler) { +app.controller("CreateDictionaryController", [ "$scope", "$http", "$modal", "$interval", "$state", "$window", "$log", "dictionaryService", "responseHandler", function($scope, $http, $modal, $interval, $state, $window, $log, dictionaryService, responseHandler) { var clientId = $("#clientId").data("lingvodoc"); var userId = $("#userId").data("lingvodoc"); var languagesUrl = $("#languagesUrl").data("lingvodoc"); @@ -31877,6 +35915,14 @@ app.controller("CreateDictionaryController", [ "$scope", "$http", "$modal", "$in delete $scope.perspective.fields[fieldIndex].contains; } }; + var convert = function(req) { + dictionaryService.convertDictionary(req).then(function(response) { + responseHandler.success(response); + $window.location.href = "/dashboard"; + }, function(reason) { + responseHandler.error(reason); + }); + }; $scope.createDictionary = function() { var language = getLanguageById($scope.dictionaryData.languageId); if (!$scope.dictionaryData.name && $scope.wizard.mode == "create" || typeof $scope.wizard.importedDictionaryId != "string" && $scope.wizard.mode == "import" || !language) { @@ -31908,20 +35954,40 @@ app.controller("CreateDictionaryController", [ "$scope", "$http", "$modal", "$in if ($scope.wizard.mode == "import") { if (typeof $scope.wizard.importedDictionaryId == "string") { $scope.controls.createDictionary = false; - var ids = $scope.wizard.importedDictionaryId.split("_"); - var url = $("#convertUrl").data("lingvodoc"); - var convertObject = { - blob_client_id: parseInt(ids[0]), - blob_object_id: parseInt(ids[1]), - parent_client_id: language.client_id, - parent_object_id: language.object_id - }; - $http.post(url, convertObject).success(function(data, status, headers, config) { - $scope.controls.createDictionary = true; - responseHandler.success(data.status); - }).error(function(data, status, headers, config) { - $scope.controls.createDictionary = true; - responseHandler.error(data); + var blob = _.find($scope.uploadedDictionaries, function(d) { + return d.getId() == $scope.wizard.importedDictionaryId; + }); + dictionaryService.checkDictionaryBlob(blob, language).then(function(perspectives) { + if (_.size(perspectives) > 0) { + $modal.open({ + animation: true, + templateUrl: "importModal.html", + controller: "ImportController", + size: "lg", + backdrop: "static", + keyboard: false, + resolve: { + params: function() { + return { + perspectives: perspectives, + blob: blob, + language: language + }; + } + } + }).result.then(function(req) { + convert(req); + }, function() {}); + } else { + convert({ + blob_client_id: blob.client_id, + blob_object_id: blob.object_id, + parent_client_id: language.client_id, + parent_object_id: language.object_id + }); + } + }, function(reason) { + responseHandler.error(reason); }); } } @@ -31980,20 +36046,6 @@ app.controller("CreateDictionaryController", [ "$scope", "$http", "$modal", "$in $scope.languages = flatLanguages(data.languages); }).error(function(data, status, headers, config) {}); }; - var loadBlobs = function() { - $http.get(listBlobsUrl).success(function(data, status, headers, config) { - $scope.uploadedDictionaries = []; - for (var i = 0; i < data.length; i++) { - if (data[i].data_type = "dialeqt_dictionary") { - var id = data[i].client_id + "_" + data[i].object_id; - $scope.uploadedDictionaries.push({ - id: id, - data: data[i] - }); - } - } - }).error(function(data, status, headers, config) {}); - }; $scope.$watch("dictionaryData.perspectiveId", function(id) { if (typeof id == "string") { for (var i = 0; i < $scope.perspectives.length; i++) { @@ -32015,7 +36067,13 @@ app.controller("CreateDictionaryController", [ "$scope", "$http", "$modal", "$in responseHandler.error(reason); }); loadLanguages(); - loadBlobs(); + dictionaryService.getUserBlobs().then(function(blobs) { + $scope.uploadedDictionaries = _.filter(blobs, function(e) { + return e.data_type == "dialeqt_dictionary"; + }); + }, function(reason) { + responseHandler.error(reason); + }); } ]); app.controller("CreateLanguageController", [ "$scope", "$http", "$interval", "$modalInstance", "responseHandler", function($scope, $http, $interval, $modalInstance, responseHandler) { @@ -32073,4 +36131,86 @@ app.controller("CreateLanguageController", [ "$scope", "$http", "$interval", "$m $http.get(languagesUrl).success(function(data, status, headers, config) { $scope.languages = flatLanguages(data.languages); }).error(function(data, status, headers, config) {}); +} ]); + +app.controller("ImportController", [ "$scope", "$http", "$q", "$log", "$modalInstance", "dictionaryService", "responseHandler", "params", function($scope, $http, $q, $log, $modalInstance, dictionaryService, responseHandler, params) { + $scope.mode = "create"; + $scope.perspectives = params.perspectives; + $scope.paths = []; + $scope.import = {}; + $scope.import.dictionaryId = ""; + $scope.import.perspectiveId = ""; + $scope.import.createNewPerspective = false; + var getSelectedPerspective = function() { + return _.find($scope.perspectives, function(e) { + return e.getId() === $scope.import.perspectiveId; + }); + }; + var getSelectedDictionary = function() { + return _.find($scope.dictionaries, function(e) { + return e.getId() === $scope.import.dictionaryId; + }); + }; + $scope.ok = function() { + var req = { + blob_client_id: params.blob.client_id, + blob_object_id: params.blob.object_id, + parent_client_id: params.language.client_id, + parent_object_id: params.language.object_id + }; + if ($scope.mode === "import") { + var dictionary = getSelectedDictionary(); + if (dictionary) { + req.dictionary_client_id = dictionary.client_id; + req.dictionary_object_id = dictionary.object_id; + if (!$scope.import.createNewPerspective) { + var perspective = getSelectedPerspective(); + if (perspective) { + req.perspective_client_id = perspective.client_id; + req.perspective_object_id = perspective.object_id; + } else { + responseHandler.error("Please, select perspective."); + return; + } + } + } else { + responseHandler.error("Please, select dictionary."); + return; + } + } + $modalInstance.close(req); + }; + $scope.cancel = function() { + $modalInstance.dismiss("cancel"); + }; + $scope.$watch("import.dictionaryId", function(id) { + var dictionary = _.find($scope.dictionaries, function(d) { + return d.getId() === id; + }); + if (dictionary) { + $scope.perspectives = _.filter(params.perspectives, function(p) { + return p.parent_client_id == dictionary.client_id && p.parent_object_id == dictionary.object_id; + }); + } + }); + var r = params.perspectives.map(function(perspective) { + return dictionaryService.getPerspectiveOriginById(perspective.client_id, perspective.parent_object_id); + }); + $q.all(r).then(function(paths) { + $scope.paths = paths; + var dictionaries = _.reduce(paths, function(acc, path) { + var pathDicts = _.filter(path, function(e) { + return e.type === "dictionary"; + }); + _.each(pathDicts, function(d) { + acc.push(d); + }); + return acc; + }, []); + $scope.dictionaries = _.uniq(dictionaries, function(d, key, a) { + return d.getId(); + }); + }, function(reason) { + responseHandler.error(reason); + }); } ]); \ No newline at end of file diff --git a/lingvodoc/static/js/dashboard.js b/lingvodoc/static/js/dashboard.js index 2f5ca75e4..7d2d1268c 100644 --- a/lingvodoc/static/js/dashboard.js +++ b/lingvodoc/static/js/dashboard.js @@ -5378,1871 +5378,4758 @@ }); (function() { - var root = this; - var previousUnderscore = root._; - var ArrayProto = Array.prototype, ObjProto = Object.prototype, FuncProto = Function.prototype; - var push = ArrayProto.push, slice = ArrayProto.slice, toString = ObjProto.toString, hasOwnProperty = ObjProto.hasOwnProperty; - var nativeIsArray = Array.isArray, nativeKeys = Object.keys, nativeBind = FuncProto.bind, nativeCreate = Object.create; - var Ctor = function() {}; - var _ = function(obj) { - if (obj instanceof _) return obj; - if (!(this instanceof _)) return new _(obj); - this._wrapped = obj; - }; - if (typeof exports !== "undefined") { - if (typeof module !== "undefined" && module.exports) { - exports = module.exports = _; - } - exports._ = _; - } else { - root._ = _; - } - _.VERSION = "1.8.3"; - var optimizeCb = function(func, context, argCount) { - if (context === void 0) return func; - switch (argCount == null ? 3 : argCount) { - case 1: - return function(value) { - return func.call(context, value); - }; - - case 2: - return function(value, other) { - return func.call(context, value, other); - }; - - case 3: - return function(value, index, collection) { - return func.call(context, value, index, collection); - }; - - case 4: - return function(accumulator, value, index, collection) { - return func.call(context, accumulator, value, index, collection); - }; - } - return function() { - return func.apply(context, arguments); - }; - }; - var cb = function(value, context, argCount) { - if (value == null) return _.identity; - if (_.isFunction(value)) return optimizeCb(value, context, argCount); - if (_.isObject(value)) return _.matcher(value); - return _.property(value); - }; - _.iteratee = function(value, context) { - return cb(value, context, Infinity); + var undefined; + var VERSION = "3.10.1"; + var BIND_FLAG = 1, BIND_KEY_FLAG = 2, CURRY_BOUND_FLAG = 4, CURRY_FLAG = 8, CURRY_RIGHT_FLAG = 16, PARTIAL_FLAG = 32, PARTIAL_RIGHT_FLAG = 64, ARY_FLAG = 128, REARG_FLAG = 256; + var DEFAULT_TRUNC_LENGTH = 30, DEFAULT_TRUNC_OMISSION = "..."; + var HOT_COUNT = 150, HOT_SPAN = 16; + var LARGE_ARRAY_SIZE = 200; + var LAZY_FILTER_FLAG = 1, LAZY_MAP_FLAG = 2; + var FUNC_ERROR_TEXT = "Expected a function"; + var PLACEHOLDER = "__lodash_placeholder__"; + var argsTag = "[object Arguments]", arrayTag = "[object Array]", boolTag = "[object Boolean]", dateTag = "[object Date]", errorTag = "[object Error]", funcTag = "[object Function]", mapTag = "[object Map]", numberTag = "[object Number]", objectTag = "[object Object]", regexpTag = "[object RegExp]", setTag = "[object Set]", stringTag = "[object String]", weakMapTag = "[object WeakMap]"; + var arrayBufferTag = "[object ArrayBuffer]", float32Tag = "[object Float32Array]", float64Tag = "[object Float64Array]", int8Tag = "[object Int8Array]", int16Tag = "[object Int16Array]", int32Tag = "[object Int32Array]", uint8Tag = "[object Uint8Array]", uint8ClampedTag = "[object Uint8ClampedArray]", uint16Tag = "[object Uint16Array]", uint32Tag = "[object Uint32Array]"; + var reEmptyStringLeading = /\b__p \+= '';/g, reEmptyStringMiddle = /\b(__p \+=) '' \+/g, reEmptyStringTrailing = /(__e\(.*?\)|\b__t\)) \+\n'';/g; + var reEscapedHtml = /&(?:amp|lt|gt|quot|#39|#96);/g, reUnescapedHtml = /[&<>"'`]/g, reHasEscapedHtml = RegExp(reEscapedHtml.source), reHasUnescapedHtml = RegExp(reUnescapedHtml.source); + var reEscape = /<%-([\s\S]+?)%>/g, reEvaluate = /<%([\s\S]+?)%>/g, reInterpolate = /<%=([\s\S]+?)%>/g; + var reIsDeepProp = /\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\n\\]|\\.)*?\1)\]/, reIsPlainProp = /^\w*$/, rePropName = /[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\n\\]|\\.)*?)\2)\]/g; + var reRegExpChars = /^[:!,]|[\\^$.*+?()[\]{}|\/]|(^[0-9a-fA-Fnrtuvx])|([\n\r\u2028\u2029])/g, reHasRegExpChars = RegExp(reRegExpChars.source); + var reComboMark = /[\u0300-\u036f\ufe20-\ufe23]/g; + var reEscapeChar = /\\(\\)?/g; + var reEsTemplate = /\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g; + var reFlags = /\w*$/; + var reHasHexPrefix = /^0[xX]/; + var reIsHostCtor = /^\[object .+?Constructor\]$/; + var reIsUint = /^\d+$/; + var reLatin1 = /[\xc0-\xd6\xd8-\xde\xdf-\xf6\xf8-\xff]/g; + var reNoMatch = /($^)/; + var reUnescapedString = /['\n\r\u2028\u2029\\]/g; + var reWords = function() { + var upper = "[A-Z\\xc0-\\xd6\\xd8-\\xde]", lower = "[a-z\\xdf-\\xf6\\xf8-\\xff]+"; + return RegExp(upper + "+(?=" + upper + lower + ")|" + upper + "?" + lower + "|" + upper + "+|[0-9]+", "g"); + }(); + var contextProps = [ "Array", "ArrayBuffer", "Date", "Error", "Float32Array", "Float64Array", "Function", "Int8Array", "Int16Array", "Int32Array", "Math", "Number", "Object", "RegExp", "Set", "String", "_", "clearTimeout", "isFinite", "parseFloat", "parseInt", "setTimeout", "TypeError", "Uint8Array", "Uint8ClampedArray", "Uint16Array", "Uint32Array", "WeakMap" ]; + var templateCounter = -1; + var typedArrayTags = {}; + typedArrayTags[float32Tag] = typedArrayTags[float64Tag] = typedArrayTags[int8Tag] = typedArrayTags[int16Tag] = typedArrayTags[int32Tag] = typedArrayTags[uint8Tag] = typedArrayTags[uint8ClampedTag] = typedArrayTags[uint16Tag] = typedArrayTags[uint32Tag] = true; + typedArrayTags[argsTag] = typedArrayTags[arrayTag] = typedArrayTags[arrayBufferTag] = typedArrayTags[boolTag] = typedArrayTags[dateTag] = typedArrayTags[errorTag] = typedArrayTags[funcTag] = typedArrayTags[mapTag] = typedArrayTags[numberTag] = typedArrayTags[objectTag] = typedArrayTags[regexpTag] = typedArrayTags[setTag] = typedArrayTags[stringTag] = typedArrayTags[weakMapTag] = false; + var cloneableTags = {}; + cloneableTags[argsTag] = cloneableTags[arrayTag] = cloneableTags[arrayBufferTag] = cloneableTags[boolTag] = cloneableTags[dateTag] = cloneableTags[float32Tag] = cloneableTags[float64Tag] = cloneableTags[int8Tag] = cloneableTags[int16Tag] = cloneableTags[int32Tag] = cloneableTags[numberTag] = cloneableTags[objectTag] = cloneableTags[regexpTag] = cloneableTags[stringTag] = cloneableTags[uint8Tag] = cloneableTags[uint8ClampedTag] = cloneableTags[uint16Tag] = cloneableTags[uint32Tag] = true; + cloneableTags[errorTag] = cloneableTags[funcTag] = cloneableTags[mapTag] = cloneableTags[setTag] = cloneableTags[weakMapTag] = false; + var deburredLetters = { + "À": "A", + "Á": "A", + "Â": "A", + "Ã": "A", + "Ä": "A", + "Å": "A", + "à": "a", + "á": "a", + "â": "a", + "ã": "a", + "ä": "a", + "å": "a", + "Ç": "C", + "ç": "c", + "Ð": "D", + "ð": "d", + "È": "E", + "É": "E", + "Ê": "E", + "Ë": "E", + "è": "e", + "é": "e", + "ê": "e", + "ë": "e", + "Ì": "I", + "Í": "I", + "Î": "I", + "Ï": "I", + "ì": "i", + "í": "i", + "î": "i", + "ï": "i", + "Ñ": "N", + "ñ": "n", + "Ò": "O", + "Ó": "O", + "Ô": "O", + "Õ": "O", + "Ö": "O", + "Ø": "O", + "ò": "o", + "ó": "o", + "ô": "o", + "õ": "o", + "ö": "o", + "ø": "o", + "Ù": "U", + "Ú": "U", + "Û": "U", + "Ü": "U", + "ù": "u", + "ú": "u", + "û": "u", + "ü": "u", + "Ý": "Y", + "ý": "y", + "ÿ": "y", + "Æ": "Ae", + "æ": "ae", + "Þ": "Th", + "þ": "th", + "ß": "ss" + }; + var htmlEscapes = { + "&": "&", + "<": "<", + ">": ">", + '"': """, + "'": "'", + "`": "`" + }; + var htmlUnescapes = { + "&": "&", + "<": "<", + ">": ">", + """: '"', + "'": "'", + "`": "`" + }; + var objectTypes = { + "function": true, + object: true + }; + var regexpEscapes = { + "0": "x30", + "1": "x31", + "2": "x32", + "3": "x33", + "4": "x34", + "5": "x35", + "6": "x36", + "7": "x37", + "8": "x38", + "9": "x39", + A: "x41", + B: "x42", + C: "x43", + D: "x44", + E: "x45", + F: "x46", + a: "x61", + b: "x62", + c: "x63", + d: "x64", + e: "x65", + f: "x66", + n: "x6e", + r: "x72", + t: "x74", + u: "x75", + v: "x76", + x: "x78" + }; + var stringEscapes = { + "\\": "\\", + "'": "'", + "\n": "n", + "\r": "r", + "\u2028": "u2028", + "\u2029": "u2029" }; - var createAssigner = function(keysFunc, undefinedOnly) { - return function(obj) { - var length = arguments.length; - if (length < 2 || obj == null) return obj; - for (var index = 1; index < length; index++) { - var source = arguments[index], keys = keysFunc(source), l = keys.length; - for (var i = 0; i < l; i++) { - var key = keys[i]; - if (!undefinedOnly || obj[key] === void 0) obj[key] = source[key]; - } + var freeExports = objectTypes[typeof exports] && exports && !exports.nodeType && exports; + var freeModule = objectTypes[typeof module] && module && !module.nodeType && module; + var freeGlobal = freeExports && freeModule && typeof global == "object" && global && global.Object && global; + var freeSelf = objectTypes[typeof self] && self && self.Object && self; + var freeWindow = objectTypes[typeof window] && window && window.Object && window; + var moduleExports = freeModule && freeModule.exports === freeExports && freeExports; + var root = freeGlobal || freeWindow !== (this && this.window) && freeWindow || freeSelf || this; + function baseCompareAscending(value, other) { + if (value !== other) { + var valIsNull = value === null, valIsUndef = value === undefined, valIsReflexive = value === value; + var othIsNull = other === null, othIsUndef = other === undefined, othIsReflexive = other === other; + if (value > other && !othIsNull || !valIsReflexive || valIsNull && !othIsUndef && othIsReflexive || valIsUndef && othIsReflexive) { + return 1; } - return obj; - }; - }; - var baseCreate = function(prototype) { - if (!_.isObject(prototype)) return {}; - if (nativeCreate) return nativeCreate(prototype); - Ctor.prototype = prototype; - var result = new Ctor(); - Ctor.prototype = null; - return result; - }; - var property = function(key) { - return function(obj) { - return obj == null ? void 0 : obj[key]; - }; - }; - var MAX_ARRAY_INDEX = Math.pow(2, 53) - 1; - var getLength = property("length"); - var isArrayLike = function(collection) { - var length = getLength(collection); - return typeof length == "number" && length >= 0 && length <= MAX_ARRAY_INDEX; - }; - _.each = _.forEach = function(obj, iteratee, context) { - iteratee = optimizeCb(iteratee, context); - var i, length; - if (isArrayLike(obj)) { - for (i = 0, length = obj.length; i < length; i++) { - iteratee(obj[i], i, obj); + if (value < other && !valIsNull || !othIsReflexive || othIsNull && !valIsUndef && valIsReflexive || othIsUndef && valIsReflexive) { + return -1; } - } else { - var keys = _.keys(obj); - for (i = 0, length = keys.length; i < length; i++) { - iteratee(obj[keys[i]], keys[i], obj); + } + return 0; + } + function baseFindIndex(array, predicate, fromRight) { + var length = array.length, index = fromRight ? length : -1; + while (fromRight ? index-- : ++index < length) { + if (predicate(array[index], index, array)) { + return index; } } - return obj; - }; - _.map = _.collect = function(obj, iteratee, context) { - iteratee = cb(iteratee, context); - var keys = !isArrayLike(obj) && _.keys(obj), length = (keys || obj).length, results = Array(length); - for (var index = 0; index < length; index++) { - var currentKey = keys ? keys[index] : index; - results[index] = iteratee(obj[currentKey], currentKey, obj); + return -1; + } + function baseIndexOf(array, value, fromIndex) { + if (value !== value) { + return indexOfNaN(array, fromIndex); } - return results; - }; - function createReduce(dir) { - function iterator(obj, iteratee, memo, keys, index, length) { - for (;index >= 0 && index < length; index += dir) { - var currentKey = keys ? keys[index] : index; - memo = iteratee(memo, obj[currentKey], currentKey, obj); + var index = fromIndex - 1, length = array.length; + while (++index < length) { + if (array[index] === value) { + return index; } - return memo; } - return function(obj, iteratee, memo, context) { - iteratee = optimizeCb(iteratee, context, 4); - var keys = !isArrayLike(obj) && _.keys(obj), length = (keys || obj).length, index = dir > 0 ? 0 : length - 1; - if (arguments.length < 3) { - memo = obj[keys ? keys[index] : index]; - index += dir; - } - return iterator(obj, iteratee, memo, keys, index, length); - }; + return -1; } - _.reduce = _.foldl = _.inject = createReduce(1); - _.reduceRight = _.foldr = createReduce(-1); - _.find = _.detect = function(obj, predicate, context) { - var key; - if (isArrayLike(obj)) { - key = _.findIndex(obj, predicate, context); - } else { - key = _.findKey(obj, predicate, context); + function baseIsFunction(value) { + return typeof value == "function" || false; + } + function baseToString(value) { + return value == null ? "" : value + ""; + } + function charsLeftIndex(string, chars) { + var index = -1, length = string.length; + while (++index < length && chars.indexOf(string.charAt(index)) > -1) {} + return index; + } + function charsRightIndex(string, chars) { + var index = string.length; + while (index-- && chars.indexOf(string.charAt(index)) > -1) {} + return index; + } + function compareAscending(object, other) { + return baseCompareAscending(object.criteria, other.criteria) || object.index - other.index; + } + function compareMultiple(object, other, orders) { + var index = -1, objCriteria = object.criteria, othCriteria = other.criteria, length = objCriteria.length, ordersLength = orders.length; + while (++index < length) { + var result = baseCompareAscending(objCriteria[index], othCriteria[index]); + if (result) { + if (index >= ordersLength) { + return result; + } + var order = orders[index]; + return result * (order === "asc" || order === true ? 1 : -1); + } } - if (key !== void 0 && key !== -1) return obj[key]; - }; - _.filter = _.select = function(obj, predicate, context) { - var results = []; - predicate = cb(predicate, context); - _.each(obj, function(value, index, list) { - if (predicate(value, index, list)) results.push(value); - }); - return results; - }; - _.reject = function(obj, predicate, context) { - return _.filter(obj, _.negate(cb(predicate)), context); - }; - _.every = _.all = function(obj, predicate, context) { - predicate = cb(predicate, context); - var keys = !isArrayLike(obj) && _.keys(obj), length = (keys || obj).length; - for (var index = 0; index < length; index++) { - var currentKey = keys ? keys[index] : index; - if (!predicate(obj[currentKey], currentKey, obj)) return false; + return object.index - other.index; + } + function deburrLetter(letter) { + return deburredLetters[letter]; + } + function escapeHtmlChar(chr) { + return htmlEscapes[chr]; + } + function escapeRegExpChar(chr, leadingChar, whitespaceChar) { + if (leadingChar) { + chr = regexpEscapes[chr]; + } else if (whitespaceChar) { + chr = stringEscapes[chr]; } - return true; - }; - _.some = _.any = function(obj, predicate, context) { - predicate = cb(predicate, context); - var keys = !isArrayLike(obj) && _.keys(obj), length = (keys || obj).length; - for (var index = 0; index < length; index++) { - var currentKey = keys ? keys[index] : index; - if (predicate(obj[currentKey], currentKey, obj)) return true; + return "\\" + chr; + } + function escapeStringChar(chr) { + return "\\" + stringEscapes[chr]; + } + function indexOfNaN(array, fromIndex, fromRight) { + var length = array.length, index = fromIndex + (fromRight ? 0 : -1); + while (fromRight ? index-- : ++index < length) { + var other = array[index]; + if (other !== other) { + return index; + } } - return false; - }; - _.contains = _.includes = _.include = function(obj, item, fromIndex, guard) { - if (!isArrayLike(obj)) obj = _.values(obj); - if (typeof fromIndex != "number" || guard) fromIndex = 0; - return _.indexOf(obj, item, fromIndex) >= 0; - }; - _.invoke = function(obj, method) { - var args = slice.call(arguments, 2); - var isFunc = _.isFunction(method); - return _.map(obj, function(value) { - var func = isFunc ? method : value[method]; - return func == null ? func : func.apply(value, args); - }); - }; - _.pluck = function(obj, key) { - return _.map(obj, _.property(key)); - }; - _.where = function(obj, attrs) { - return _.filter(obj, _.matcher(attrs)); - }; - _.findWhere = function(obj, attrs) { - return _.find(obj, _.matcher(attrs)); - }; - _.max = function(obj, iteratee, context) { - var result = -Infinity, lastComputed = -Infinity, value, computed; - if (iteratee == null && obj != null) { - obj = isArrayLike(obj) ? obj : _.values(obj); - for (var i = 0, length = obj.length; i < length; i++) { - value = obj[i]; - if (value > result) { - result = value; - } + return -1; + } + function isObjectLike(value) { + return !!value && typeof value == "object"; + } + function isSpace(charCode) { + return charCode <= 160 && (charCode >= 9 && charCode <= 13) || charCode == 32 || charCode == 160 || charCode == 5760 || charCode == 6158 || charCode >= 8192 && (charCode <= 8202 || charCode == 8232 || charCode == 8233 || charCode == 8239 || charCode == 8287 || charCode == 12288 || charCode == 65279); + } + function replaceHolders(array, placeholder) { + var index = -1, length = array.length, resIndex = -1, result = []; + while (++index < length) { + if (array[index] === placeholder) { + array[index] = PLACEHOLDER; + result[++resIndex] = index; } - } else { - iteratee = cb(iteratee, context); - _.each(obj, function(value, index, list) { - computed = iteratee(value, index, list); - if (computed > lastComputed || computed === -Infinity && result === -Infinity) { - result = value; - lastComputed = computed; - } - }); } return result; - }; - _.min = function(obj, iteratee, context) { - var result = Infinity, lastComputed = Infinity, value, computed; - if (iteratee == null && obj != null) { - obj = isArrayLike(obj) ? obj : _.values(obj); - for (var i = 0, length = obj.length; i < length; i++) { - value = obj[i]; - if (value < result) { - result = value; - } + } + function sortedUniq(array, iteratee) { + var seen, index = -1, length = array.length, resIndex = -1, result = []; + while (++index < length) { + var value = array[index], computed = iteratee ? iteratee(value, index, array) : value; + if (!index || seen !== computed) { + seen = computed; + result[++resIndex] = value; } - } else { - iteratee = cb(iteratee, context); - _.each(obj, function(value, index, list) { - computed = iteratee(value, index, list); - if (computed < lastComputed || computed === Infinity && result === Infinity) { - result = value; - lastComputed = computed; - } - }); } return result; - }; - _.shuffle = function(obj) { - var set = isArrayLike(obj) ? obj : _.values(obj); - var length = set.length; - var shuffled = Array(length); - for (var index = 0, rand; index < length; index++) { - rand = _.random(0, index); - if (rand !== index) shuffled[index] = shuffled[rand]; - shuffled[rand] = set[index]; - } - return shuffled; - }; - _.sample = function(obj, n, guard) { - if (n == null || guard) { - if (!isArrayLike(obj)) obj = _.values(obj); - return obj[_.random(obj.length - 1)]; + } + function trimmedLeftIndex(string) { + var index = -1, length = string.length; + while (++index < length && isSpace(string.charCodeAt(index))) {} + return index; + } + function trimmedRightIndex(string) { + var index = string.length; + while (index-- && isSpace(string.charCodeAt(index))) {} + return index; + } + function unescapeHtmlChar(chr) { + return htmlUnescapes[chr]; + } + function runInContext(context) { + context = context ? _.defaults(root.Object(), context, _.pick(root, contextProps)) : root; + var Array = context.Array, Date = context.Date, Error = context.Error, Function = context.Function, Math = context.Math, Number = context.Number, Object = context.Object, RegExp = context.RegExp, String = context.String, TypeError = context.TypeError; + var arrayProto = Array.prototype, objectProto = Object.prototype, stringProto = String.prototype; + var fnToString = Function.prototype.toString; + var hasOwnProperty = objectProto.hasOwnProperty; + var idCounter = 0; + var objToString = objectProto.toString; + var oldDash = root._; + var reIsNative = RegExp("^" + fnToString.call(hasOwnProperty).replace(/[\\^$.*+?()[\]{}|]/g, "\\$&").replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g, "$1.*?") + "$"); + var ArrayBuffer = context.ArrayBuffer, clearTimeout = context.clearTimeout, parseFloat = context.parseFloat, pow = Math.pow, propertyIsEnumerable = objectProto.propertyIsEnumerable, Set = getNative(context, "Set"), setTimeout = context.setTimeout, splice = arrayProto.splice, Uint8Array = context.Uint8Array, WeakMap = getNative(context, "WeakMap"); + var nativeCeil = Math.ceil, nativeCreate = getNative(Object, "create"), nativeFloor = Math.floor, nativeIsArray = getNative(Array, "isArray"), nativeIsFinite = context.isFinite, nativeKeys = getNative(Object, "keys"), nativeMax = Math.max, nativeMin = Math.min, nativeNow = getNative(Date, "now"), nativeParseInt = context.parseInt, nativeRandom = Math.random; + var NEGATIVE_INFINITY = Number.NEGATIVE_INFINITY, POSITIVE_INFINITY = Number.POSITIVE_INFINITY; + var MAX_ARRAY_LENGTH = 4294967295, MAX_ARRAY_INDEX = MAX_ARRAY_LENGTH - 1, HALF_MAX_ARRAY_LENGTH = MAX_ARRAY_LENGTH >>> 1; + var MAX_SAFE_INTEGER = 9007199254740991; + var metaMap = WeakMap && new WeakMap(); + var realNames = {}; + function lodash(value) { + if (isObjectLike(value) && !isArray(value) && !(value instanceof LazyWrapper)) { + if (value instanceof LodashWrapper) { + return value; + } + if (hasOwnProperty.call(value, "__chain__") && hasOwnProperty.call(value, "__wrapped__")) { + return wrapperClone(value); + } + } + return new LodashWrapper(value); + } + function baseLodash() {} + function LodashWrapper(value, chainAll, actions) { + this.__wrapped__ = value; + this.__actions__ = actions || []; + this.__chain__ = !!chainAll; + } + var support = lodash.support = {}; + lodash.templateSettings = { + escape: reEscape, + evaluate: reEvaluate, + interpolate: reInterpolate, + variable: "", + imports: { + _: lodash + } + }; + function LazyWrapper(value) { + this.__wrapped__ = value; + this.__actions__ = []; + this.__dir__ = 1; + this.__filtered__ = false; + this.__iteratees__ = []; + this.__takeCount__ = POSITIVE_INFINITY; + this.__views__ = []; + } + function lazyClone() { + var result = new LazyWrapper(this.__wrapped__); + result.__actions__ = arrayCopy(this.__actions__); + result.__dir__ = this.__dir__; + result.__filtered__ = this.__filtered__; + result.__iteratees__ = arrayCopy(this.__iteratees__); + result.__takeCount__ = this.__takeCount__; + result.__views__ = arrayCopy(this.__views__); + return result; } - return _.shuffle(obj).slice(0, Math.max(0, n)); - }; - _.sortBy = function(obj, iteratee, context) { - iteratee = cb(iteratee, context); - return _.pluck(_.map(obj, function(value, index, list) { - return { - value: value, - index: index, - criteria: iteratee(value, index, list) - }; - }).sort(function(left, right) { - var a = left.criteria; - var b = right.criteria; - if (a !== b) { - if (a > b || a === void 0) return 1; - if (a < b || b === void 0) return -1; + function lazyReverse() { + if (this.__filtered__) { + var result = new LazyWrapper(this); + result.__dir__ = -1; + result.__filtered__ = true; + } else { + result = this.clone(); + result.__dir__ *= -1; } - return left.index - right.index; - }), "value"); - }; - var group = function(behavior) { - return function(obj, iteratee, context) { - var result = {}; - iteratee = cb(iteratee, context); - _.each(obj, function(value, index) { - var key = iteratee(value, index, obj); - behavior(result, value, key); - }); return result; - }; - }; - _.groupBy = group(function(result, value, key) { - if (_.has(result, key)) result[key].push(value); else result[key] = [ value ]; - }); - _.indexBy = group(function(result, value, key) { - result[key] = value; - }); - _.countBy = group(function(result, value, key) { - if (_.has(result, key)) result[key]++; else result[key] = 1; - }); - _.toArray = function(obj) { - if (!obj) return []; - if (_.isArray(obj)) return slice.call(obj); - if (isArrayLike(obj)) return _.map(obj, _.identity); - return _.values(obj); - }; - _.size = function(obj) { - if (obj == null) return 0; - return isArrayLike(obj) ? obj.length : _.keys(obj).length; - }; - _.partition = function(obj, predicate, context) { - predicate = cb(predicate, context); - var pass = [], fail = []; - _.each(obj, function(value, key, obj) { - (predicate(value, key, obj) ? pass : fail).push(value); - }); - return [ pass, fail ]; - }; - _.first = _.head = _.take = function(array, n, guard) { - if (array == null) return void 0; - if (n == null || guard) return array[0]; - return _.initial(array, array.length - n); - }; - _.initial = function(array, n, guard) { - return slice.call(array, 0, Math.max(0, array.length - (n == null || guard ? 1 : n))); - }; - _.last = function(array, n, guard) { - if (array == null) return void 0; - if (n == null || guard) return array[array.length - 1]; - return _.rest(array, Math.max(0, array.length - n)); - }; - _.rest = _.tail = _.drop = function(array, n, guard) { - return slice.call(array, n == null || guard ? 1 : n); - }; - _.compact = function(array) { - return _.filter(array, _.identity); - }; - var flatten = function(input, shallow, strict, startIndex) { - var output = [], idx = 0; - for (var i = startIndex || 0, length = getLength(input); i < length; i++) { - var value = input[i]; - if (isArrayLike(value) && (_.isArray(value) || _.isArguments(value))) { - if (!shallow) value = flatten(value, shallow, strict); - var j = 0, len = value.length; - output.length += len; - while (j < len) { - output[idx++] = value[j++]; - } - } else if (!strict) { - output[idx++] = value; - } - } - return output; - }; - _.flatten = function(array, shallow) { - return flatten(array, shallow, false); - }; - _.without = function(array) { - return _.difference(array, slice.call(arguments, 1)); - }; - _.uniq = _.unique = function(array, isSorted, iteratee, context) { - if (!_.isBoolean(isSorted)) { - context = iteratee; - iteratee = isSorted; - isSorted = false; - } - if (iteratee != null) iteratee = cb(iteratee, context); - var result = []; - var seen = []; - for (var i = 0, length = getLength(array); i < length; i++) { - var value = array[i], computed = iteratee ? iteratee(value, i, array) : value; - if (isSorted) { - if (!i || seen !== computed) result.push(value); - seen = computed; - } else if (iteratee) { - if (!_.contains(seen, computed)) { - seen.push(computed); - result.push(value); + } + function lazyValue() { + var array = this.__wrapped__.value(), dir = this.__dir__, isArr = isArray(array), isRight = dir < 0, arrLength = isArr ? array.length : 0, view = getView(0, arrLength, this.__views__), start = view.start, end = view.end, length = end - start, index = isRight ? end : start - 1, iteratees = this.__iteratees__, iterLength = iteratees.length, resIndex = 0, takeCount = nativeMin(length, this.__takeCount__); + if (!isArr || arrLength < LARGE_ARRAY_SIZE || arrLength == length && takeCount == length) { + return baseWrapperValue(array, this.__actions__); + } + var result = []; + outer: while (length-- && resIndex < takeCount) { + index += dir; + var iterIndex = -1, value = array[index]; + while (++iterIndex < iterLength) { + var data = iteratees[iterIndex], iteratee = data.iteratee, type = data.type, computed = iteratee(value); + if (type == LAZY_MAP_FLAG) { + value = computed; + } else if (!computed) { + if (type == LAZY_FILTER_FLAG) { + continue outer; + } else { + break outer; + } + } } - } else if (!_.contains(result, value)) { - result.push(value); + result[resIndex++] = value; } + return result; } - return result; - }; - _.union = function() { - return _.uniq(flatten(arguments, true, true)); - }; - _.intersection = function(array) { - var result = []; - var argsLength = arguments.length; - for (var i = 0, length = getLength(array); i < length; i++) { - var item = array[i]; - if (_.contains(result, item)) continue; - for (var j = 1; j < argsLength; j++) { - if (!_.contains(arguments[j], item)) break; + function MapCache() { + this.__data__ = {}; + } + function mapDelete(key) { + return this.has(key) && delete this.__data__[key]; + } + function mapGet(key) { + return key == "__proto__" ? undefined : this.__data__[key]; + } + function mapHas(key) { + return key != "__proto__" && hasOwnProperty.call(this.__data__, key); + } + function mapSet(key, value) { + if (key != "__proto__") { + this.__data__[key] = value; } - if (j === argsLength) result.push(item); + return this; } - return result; - }; - _.difference = function(array) { - var rest = flatten(arguments, true, true, 1); - return _.filter(array, function(value) { - return !_.contains(rest, value); - }); - }; - _.zip = function() { - return _.unzip(arguments); - }; - _.unzip = function(array) { - var length = array && _.max(array, getLength).length || 0; - var result = Array(length); - for (var index = 0; index < length; index++) { - result[index] = _.pluck(array, index); + function SetCache(values) { + var length = values ? values.length : 0; + this.data = { + hash: nativeCreate(null), + set: new Set() + }; + while (length--) { + this.push(values[length]); + } } - return result; - }; - _.object = function(list, values) { - var result = {}; - for (var i = 0, length = getLength(list); i < length; i++) { - if (values) { - result[list[i]] = values[i]; + function cacheIndexOf(cache, value) { + var data = cache.data, result = typeof value == "string" || isObject(value) ? data.set.has(value) : data.hash[value]; + return result ? 0 : -1; + } + function cachePush(value) { + var data = this.data; + if (typeof value == "string" || isObject(value)) { + data.set.add(value); } else { - result[list[i][0]] = list[i][1]; + data.hash[value] = true; } } - return result; - }; - function createPredicateIndexFinder(dir) { - return function(array, predicate, context) { - predicate = cb(predicate, context); - var length = getLength(array); - var index = dir > 0 ? 0 : length - 1; - for (;index >= 0 && index < length; index += dir) { - if (predicate(array[index], index, array)) return index; + function arrayConcat(array, other) { + var index = -1, length = array.length, othIndex = -1, othLength = other.length, result = Array(length + othLength); + while (++index < length) { + result[index] = array[index]; } - return -1; - }; - } - _.findIndex = createPredicateIndexFinder(1); - _.findLastIndex = createPredicateIndexFinder(-1); - _.sortedIndex = function(array, obj, iteratee, context) { - iteratee = cb(iteratee, context, 1); - var value = iteratee(obj); - var low = 0, high = getLength(array); - while (low < high) { - var mid = Math.floor((low + high) / 2); - if (iteratee(array[mid]) < value) low = mid + 1; else high = mid; - } - return low; - }; - function createIndexFinder(dir, predicateFind, sortedIndex) { - return function(array, item, idx) { - var i = 0, length = getLength(array); - if (typeof idx == "number") { - if (dir > 0) { - i = idx >= 0 ? idx : Math.max(idx + length, i); - } else { - length = idx >= 0 ? Math.min(idx + 1, length) : idx + length + 1; - } - } else if (sortedIndex && idx && length) { - idx = sortedIndex(array, item); - return array[idx] === item ? idx : -1; + while (++othIndex < othLength) { + result[index++] = other[othIndex]; } - if (item !== item) { - idx = predicateFind(slice.call(array, i, length), _.isNaN); - return idx >= 0 ? idx + i : -1; + return result; + } + function arrayCopy(source, array) { + var index = -1, length = source.length; + array || (array = Array(length)); + while (++index < length) { + array[index] = source[index]; } - for (idx = dir > 0 ? i : length - 1; idx >= 0 && idx < length; idx += dir) { - if (array[idx] === item) return idx; + return array; + } + function arrayEach(array, iteratee) { + var index = -1, length = array.length; + while (++index < length) { + if (iteratee(array[index], index, array) === false) { + break; + } } - return -1; - }; - } - _.indexOf = createIndexFinder(1, _.findIndex, _.sortedIndex); - _.lastIndexOf = createIndexFinder(-1, _.findLastIndex); - _.range = function(start, stop, step) { - if (stop == null) { - stop = start || 0; - start = 0; + return array; } - step = step || 1; - var length = Math.max(Math.ceil((stop - start) / step), 0); - var range = Array(length); - for (var idx = 0; idx < length; idx++, start += step) { - range[idx] = start; + function arrayEachRight(array, iteratee) { + var length = array.length; + while (length--) { + if (iteratee(array[length], length, array) === false) { + break; + } + } + return array; } - return range; - }; - var executeBound = function(sourceFunc, boundFunc, context, callingContext, args) { - if (!(callingContext instanceof boundFunc)) return sourceFunc.apply(context, args); - var self = baseCreate(sourceFunc.prototype); - var result = sourceFunc.apply(self, args); - if (_.isObject(result)) return result; - return self; - }; - _.bind = function(func, context) { - if (nativeBind && func.bind === nativeBind) return nativeBind.apply(func, slice.call(arguments, 1)); - if (!_.isFunction(func)) throw new TypeError("Bind must be called on a function"); - var args = slice.call(arguments, 2); - var bound = function() { - return executeBound(func, bound, context, this, args.concat(slice.call(arguments))); - }; - return bound; - }; - _.partial = function(func) { - var boundArgs = slice.call(arguments, 1); - var bound = function() { - var position = 0, length = boundArgs.length; - var args = Array(length); - for (var i = 0; i < length; i++) { - args[i] = boundArgs[i] === _ ? arguments[position++] : boundArgs[i]; + function arrayEvery(array, predicate) { + var index = -1, length = array.length; + while (++index < length) { + if (!predicate(array[index], index, array)) { + return false; + } } - while (position < arguments.length) args.push(arguments[position++]); - return executeBound(func, bound, this, this, args); - }; - return bound; - }; - _.bindAll = function(obj) { - var i, length = arguments.length, key; - if (length <= 1) throw new Error("bindAll must be passed function names"); - for (i = 1; i < length; i++) { - key = arguments[i]; - obj[key] = _.bind(obj[key], obj); + return true; } - return obj; - }; - _.memoize = function(func, hasher) { - var memoize = function(key) { - var cache = memoize.cache; - var address = "" + (hasher ? hasher.apply(this, arguments) : key); - if (!_.has(cache, address)) cache[address] = func.apply(this, arguments); - return cache[address]; - }; - memoize.cache = {}; - return memoize; - }; - _.delay = function(func, wait) { - var args = slice.call(arguments, 2); - return setTimeout(function() { - return func.apply(null, args); - }, wait); - }; - _.defer = _.partial(_.delay, _, 1); - _.throttle = function(func, wait, options) { - var context, args, result; - var timeout = null; - var previous = 0; - if (!options) options = {}; - var later = function() { - previous = options.leading === false ? 0 : _.now(); - timeout = null; - result = func.apply(context, args); - if (!timeout) context = args = null; - }; - return function() { - var now = _.now(); - if (!previous && options.leading === false) previous = now; - var remaining = wait - (now - previous); - context = this; - args = arguments; - if (remaining <= 0 || remaining > wait) { - if (timeout) { - clearTimeout(timeout); - timeout = null; - } - previous = now; - result = func.apply(context, args); - if (!timeout) context = args = null; - } else if (!timeout && options.trailing !== false) { - timeout = setTimeout(later, remaining); + function arrayExtremum(array, iteratee, comparator, exValue) { + var index = -1, length = array.length, computed = exValue, result = computed; + while (++index < length) { + var value = array[index], current = +iteratee(value); + if (comparator(current, computed)) { + computed = current; + result = value; + } } return result; - }; - }; - _.debounce = function(func, wait, immediate) { - var timeout, args, context, timestamp, result; - var later = function() { - var last = _.now() - timestamp; - if (last < wait && last >= 0) { - timeout = setTimeout(later, wait - last); - } else { - timeout = null; - if (!immediate) { - result = func.apply(context, args); - if (!timeout) context = args = null; + } + function arrayFilter(array, predicate) { + var index = -1, length = array.length, resIndex = -1, result = []; + while (++index < length) { + var value = array[index]; + if (predicate(value, index, array)) { + result[++resIndex] = value; } } - }; - return function() { - context = this; - args = arguments; - timestamp = _.now(); - var callNow = immediate && !timeout; - if (!timeout) timeout = setTimeout(later, wait); - if (callNow) { - result = func.apply(context, args); - context = args = null; - } - return result; - }; - }; - _.wrap = function(func, wrapper) { - return _.partial(wrapper, func); - }; - _.negate = function(predicate) { - return function() { - return !predicate.apply(this, arguments); - }; - }; - _.compose = function() { - var args = arguments; - var start = args.length - 1; - return function() { - var i = start; - var result = args[start].apply(this, arguments); - while (i--) result = args[i].call(this, result); return result; - }; - }; - _.after = function(times, func) { - return function() { - if (--times < 1) { - return func.apply(this, arguments); - } - }; - }; - _.before = function(times, func) { - var memo; - return function() { - if (--times > 0) { - memo = func.apply(this, arguments); - } - if (times <= 1) func = null; - return memo; - }; - }; - _.once = _.partial(_.before, 2); - var hasEnumBug = !{ - toString: null - }.propertyIsEnumerable("toString"); - var nonEnumerableProps = [ "valueOf", "isPrototypeOf", "toString", "propertyIsEnumerable", "hasOwnProperty", "toLocaleString" ]; - function collectNonEnumProps(obj, keys) { - var nonEnumIdx = nonEnumerableProps.length; - var constructor = obj.constructor; - var proto = _.isFunction(constructor) && constructor.prototype || ObjProto; - var prop = "constructor"; - if (_.has(obj, prop) && !_.contains(keys, prop)) keys.push(prop); - while (nonEnumIdx--) { - prop = nonEnumerableProps[nonEnumIdx]; - if (prop in obj && obj[prop] !== proto[prop] && !_.contains(keys, prop)) { - keys.push(prop); - } - } - } - _.keys = function(obj) { - if (!_.isObject(obj)) return []; - if (nativeKeys) return nativeKeys(obj); - var keys = []; - for (var key in obj) if (_.has(obj, key)) keys.push(key); - if (hasEnumBug) collectNonEnumProps(obj, keys); - return keys; - }; - _.allKeys = function(obj) { - if (!_.isObject(obj)) return []; - var keys = []; - for (var key in obj) keys.push(key); - if (hasEnumBug) collectNonEnumProps(obj, keys); - return keys; - }; - _.values = function(obj) { - var keys = _.keys(obj); - var length = keys.length; - var values = Array(length); - for (var i = 0; i < length; i++) { - values[i] = obj[keys[i]]; - } - return values; - }; - _.mapObject = function(obj, iteratee, context) { - iteratee = cb(iteratee, context); - var keys = _.keys(obj), length = keys.length, results = {}, currentKey; - for (var index = 0; index < length; index++) { - currentKey = keys[index]; - results[currentKey] = iteratee(obj[currentKey], currentKey, obj); } - return results; - }; - _.pairs = function(obj) { - var keys = _.keys(obj); - var length = keys.length; - var pairs = Array(length); - for (var i = 0; i < length; i++) { - pairs[i] = [ keys[i], obj[keys[i]] ]; + function arrayMap(array, iteratee) { + var index = -1, length = array.length, result = Array(length); + while (++index < length) { + result[index] = iteratee(array[index], index, array); + } + return result; } - return pairs; - }; - _.invert = function(obj) { - var result = {}; - var keys = _.keys(obj); - for (var i = 0, length = keys.length; i < length; i++) { - result[obj[keys[i]]] = keys[i]; + function arrayPush(array, values) { + var index = -1, length = values.length, offset = array.length; + while (++index < length) { + array[offset + index] = values[index]; + } + return array; } - return result; - }; - _.functions = _.methods = function(obj) { - var names = []; - for (var key in obj) { - if (_.isFunction(obj[key])) names.push(key); + function arrayReduce(array, iteratee, accumulator, initFromArray) { + var index = -1, length = array.length; + if (initFromArray && length) { + accumulator = array[++index]; + } + while (++index < length) { + accumulator = iteratee(accumulator, array[index], index, array); + } + return accumulator; } - return names.sort(); - }; - _.extend = createAssigner(_.allKeys); - _.extendOwn = _.assign = createAssigner(_.keys); - _.findKey = function(obj, predicate, context) { - predicate = cb(predicate, context); - var keys = _.keys(obj), key; - for (var i = 0, length = keys.length; i < length; i++) { - key = keys[i]; - if (predicate(obj[key], key, obj)) return key; + function arrayReduceRight(array, iteratee, accumulator, initFromArray) { + var length = array.length; + if (initFromArray && length) { + accumulator = array[--length]; + } + while (length--) { + accumulator = iteratee(accumulator, array[length], length, array); + } + return accumulator; } - }; - _.pick = function(object, oiteratee, context) { - var result = {}, obj = object, iteratee, keys; - if (obj == null) return result; - if (_.isFunction(oiteratee)) { - keys = _.allKeys(obj); - iteratee = optimizeCb(oiteratee, context); - } else { - keys = flatten(arguments, false, false, 1); - iteratee = function(value, key, obj) { - return key in obj; - }; - obj = Object(obj); + function arraySome(array, predicate) { + var index = -1, length = array.length; + while (++index < length) { + if (predicate(array[index], index, array)) { + return true; + } + } + return false; } - for (var i = 0, length = keys.length; i < length; i++) { - var key = keys[i]; - var value = obj[key]; - if (iteratee(value, key, obj)) result[key] = value; + function arraySum(array, iteratee) { + var length = array.length, result = 0; + while (length--) { + result += +iteratee(array[length]) || 0; + } + return result; } - return result; - }; - _.omit = function(obj, iteratee, context) { - if (_.isFunction(iteratee)) { - iteratee = _.negate(iteratee); - } else { - var keys = _.map(flatten(arguments, false, false, 1), String); - iteratee = function(value, key) { - return !_.contains(keys, key); - }; + function assignDefaults(objectValue, sourceValue) { + return objectValue === undefined ? sourceValue : objectValue; } - return _.pick(obj, iteratee, context); - }; - _.defaults = createAssigner(_.allKeys, true); - _.create = function(prototype, props) { - var result = baseCreate(prototype); - if (props) _.extendOwn(result, props); - return result; - }; - _.clone = function(obj) { - if (!_.isObject(obj)) return obj; - return _.isArray(obj) ? obj.slice() : _.extend({}, obj); - }; - _.tap = function(obj, interceptor) { - interceptor(obj); - return obj; - }; - _.isMatch = function(object, attrs) { - var keys = _.keys(attrs), length = keys.length; - if (object == null) return !length; - var obj = Object(object); - for (var i = 0; i < length; i++) { - var key = keys[i]; - if (attrs[key] !== obj[key] || !(key in obj)) return false; + function assignOwnDefaults(objectValue, sourceValue, key, object) { + return objectValue === undefined || !hasOwnProperty.call(object, key) ? sourceValue : objectValue; } - return true; - }; - var eq = function(a, b, aStack, bStack) { - if (a === b) return a !== 0 || 1 / a === 1 / b; - if (a == null || b == null) return a === b; - if (a instanceof _) a = a._wrapped; - if (b instanceof _) b = b._wrapped; - var className = toString.call(a); - if (className !== toString.call(b)) return false; - switch (className) { - case "[object RegExp]": - case "[object String]": - return "" + a === "" + b; - - case "[object Number]": - if (+a !== +a) return +b !== +b; - return +a === 0 ? 1 / +a === 1 / b : +a === +b; - - case "[object Date]": - case "[object Boolean]": - return +a === +b; - } - var areArrays = className === "[object Array]"; - if (!areArrays) { - if (typeof a != "object" || typeof b != "object") return false; - var aCtor = a.constructor, bCtor = b.constructor; - if (aCtor !== bCtor && !(_.isFunction(aCtor) && aCtor instanceof aCtor && _.isFunction(bCtor) && bCtor instanceof bCtor) && ("constructor" in a && "constructor" in b)) { - return false; + function assignWith(object, source, customizer) { + var index = -1, props = keys(source), length = props.length; + while (++index < length) { + var key = props[index], value = object[key], result = customizer(value, source[key], key, object, source); + if ((result === result ? result !== value : value === value) || value === undefined && !(key in object)) { + object[key] = result; + } } + return object; } - aStack = aStack || []; - bStack = bStack || []; - var length = aStack.length; - while (length--) { - if (aStack[length] === a) return bStack[length] === b; + function baseAssign(object, source) { + return source == null ? object : baseCopy(source, keys(source), object); } - aStack.push(a); - bStack.push(b); - if (areArrays) { - length = a.length; - if (length !== b.length) return false; - while (length--) { - if (!eq(a[length], b[length], aStack, bStack)) return false; - } - } else { - var keys = _.keys(a), key; - length = keys.length; - if (_.keys(b).length !== length) return false; - while (length--) { - key = keys[length]; - if (!(_.has(b, key) && eq(a[key], b[key], aStack, bStack))) return false; + function baseAt(collection, props) { + var index = -1, isNil = collection == null, isArr = !isNil && isArrayLike(collection), length = isArr ? collection.length : 0, propsLength = props.length, result = Array(propsLength); + while (++index < propsLength) { + var key = props[index]; + if (isArr) { + result[index] = isIndex(key, length) ? collection[key] : undefined; + } else { + result[index] = isNil ? undefined : collection[key]; + } } + return result; } - aStack.pop(); - bStack.pop(); - return true; - }; - _.isEqual = function(a, b) { - return eq(a, b); - }; - _.isEmpty = function(obj) { - if (obj == null) return true; - if (isArrayLike(obj) && (_.isArray(obj) || _.isString(obj) || _.isArguments(obj))) return obj.length === 0; - return _.keys(obj).length === 0; - }; - _.isElement = function(obj) { - return !!(obj && obj.nodeType === 1); - }; - _.isArray = nativeIsArray || function(obj) { - return toString.call(obj) === "[object Array]"; - }; - _.isObject = function(obj) { - var type = typeof obj; - return type === "function" || type === "object" && !!obj; - }; - _.each([ "Arguments", "Function", "String", "Number", "Date", "RegExp", "Error" ], function(name) { - _["is" + name] = function(obj) { - return toString.call(obj) === "[object " + name + "]"; - }; - }); - if (!_.isArguments(arguments)) { - _.isArguments = function(obj) { - return _.has(obj, "callee"); - }; - } - if (typeof /./ != "function" && typeof Int8Array != "object") { - _.isFunction = function(obj) { - return typeof obj == "function" || false; - }; - } - _.isFinite = function(obj) { - return isFinite(obj) && !isNaN(parseFloat(obj)); - }; - _.isNaN = function(obj) { - return _.isNumber(obj) && obj !== +obj; - }; - _.isBoolean = function(obj) { - return obj === true || obj === false || toString.call(obj) === "[object Boolean]"; - }; - _.isNull = function(obj) { - return obj === null; - }; - _.isUndefined = function(obj) { - return obj === void 0; - }; - _.has = function(obj, key) { - return obj != null && hasOwnProperty.call(obj, key); - }; - _.noConflict = function() { - root._ = previousUnderscore; - return this; - }; - _.identity = function(value) { - return value; - }; - _.constant = function(value) { - return function() { - return value; - }; - }; - _.noop = function() {}; - _.property = property; - _.propertyOf = function(obj) { - return obj == null ? function() {} : function(key) { - return obj[key]; - }; - }; - _.matcher = _.matches = function(attrs) { - attrs = _.extendOwn({}, attrs); - return function(obj) { - return _.isMatch(obj, attrs); - }; - }; - _.times = function(n, iteratee, context) { - var accum = Array(Math.max(0, n)); - iteratee = optimizeCb(iteratee, context, 1); - for (var i = 0; i < n; i++) accum[i] = iteratee(i); - return accum; - }; - _.random = function(min, max) { - if (max == null) { - max = min; - min = 0; + function baseCopy(source, props, object) { + object || (object = {}); + var index = -1, length = props.length; + while (++index < length) { + var key = props[index]; + object[key] = source[key]; + } + return object; } - return min + Math.floor(Math.random() * (max - min + 1)); - }; - _.now = Date.now || function() { - return new Date().getTime(); - }; - var escapeMap = { - "&": "&", - "<": "<", - ">": ">", - '"': """, - "'": "'", - "`": "`" - }; - var unescapeMap = _.invert(escapeMap); - var createEscaper = function(map) { - var escaper = function(match) { - return map[match]; - }; - var source = "(?:" + _.keys(map).join("|") + ")"; - var testRegexp = RegExp(source); - var replaceRegexp = RegExp(source, "g"); - return function(string) { - string = string == null ? "" : "" + string; - return testRegexp.test(string) ? string.replace(replaceRegexp, escaper) : string; - }; - }; - _.escape = createEscaper(escapeMap); - _.unescape = createEscaper(unescapeMap); - _.result = function(object, property, fallback) { - var value = object == null ? void 0 : object[property]; - if (value === void 0) { - value = fallback; - } - return _.isFunction(value) ? value.call(object) : value; - }; - var idCounter = 0; - _.uniqueId = function(prefix) { - var id = ++idCounter + ""; - return prefix ? prefix + id : id; - }; - _.templateSettings = { - evaluate: /<%([\s\S]+?)%>/g, - interpolate: /<%=([\s\S]+?)%>/g, - escape: /<%-([\s\S]+?)%>/g - }; - var noMatch = /(.)^/; - var escapes = { - "'": "'", - "\\": "\\", - "\r": "r", - "\n": "n", - "\u2028": "u2028", - "\u2029": "u2029" - }; - var escaper = /\\|'|\r|\n|\u2028|\u2029/g; - var escapeChar = function(match) { - return "\\" + escapes[match]; - }; - _.template = function(text, settings, oldSettings) { - if (!settings && oldSettings) settings = oldSettings; - settings = _.defaults({}, settings, _.templateSettings); - var matcher = RegExp([ (settings.escape || noMatch).source, (settings.interpolate || noMatch).source, (settings.evaluate || noMatch).source ].join("|") + "|$", "g"); - var index = 0; - var source = "__p+='"; - text.replace(matcher, function(match, escape, interpolate, evaluate, offset) { - source += text.slice(index, offset).replace(escaper, escapeChar); - index = offset + match.length; - if (escape) { - source += "'+\n((__t=(" + escape + "))==null?'':_.escape(__t))+\n'"; - } else if (interpolate) { - source += "'+\n((__t=(" + interpolate + "))==null?'':__t)+\n'"; - } else if (evaluate) { - source += "';\n" + evaluate + "\n__p+='"; - } - return match; - }); - source += "';\n"; - if (!settings.variable) source = "with(obj||{}){\n" + source + "}\n"; - source = "var __t,__p='',__j=Array.prototype.join," + "print=function(){__p+=__j.call(arguments,'');};\n" + source + "return __p;\n"; - try { - var render = new Function(settings.variable || "obj", "_", source); - } catch (e) { - e.source = source; - throw e; + function baseCallback(func, thisArg, argCount) { + var type = typeof func; + if (type == "function") { + return thisArg === undefined ? func : bindCallback(func, thisArg, argCount); + } + if (func == null) { + return identity; + } + if (type == "object") { + return baseMatches(func); + } + return thisArg === undefined ? property(func) : baseMatchesProperty(func, thisArg); } - var template = function(data) { - return render.call(this, data, _); - }; - var argument = settings.variable || "obj"; - template.source = "function(" + argument + "){\n" + source + "}"; - return template; - }; - _.chain = function(obj) { - var instance = _(obj); - instance._chain = true; - return instance; - }; - var result = function(instance, obj) { - return instance._chain ? _(obj).chain() : obj; - }; - _.mixin = function(obj) { - _.each(_.functions(obj), function(name) { - var func = _[name] = obj[name]; - _.prototype[name] = function() { - var args = [ this._wrapped ]; - push.apply(args, arguments); - return result(this, func.apply(_, args)); - }; - }); - }; - _.mixin(_); - _.each([ "pop", "push", "reverse", "shift", "sort", "splice", "unshift" ], function(name) { - var method = ArrayProto[name]; - _.prototype[name] = function() { - var obj = this._wrapped; - method.apply(obj, arguments); - if ((name === "shift" || name === "splice") && obj.length === 0) delete obj[0]; - return result(this, obj); - }; - }); - _.each([ "concat", "join", "slice" ], function(name) { - var method = ArrayProto[name]; - _.prototype[name] = function() { - return result(this, method.apply(this._wrapped, arguments)); - }; - }); - _.prototype.value = function() { - return this._wrapped; - }; - _.prototype.valueOf = _.prototype.toJSON = _.prototype.value; - _.prototype.toString = function() { - return "" + this._wrapped; - }; - if (typeof define === "function" && define.amd) { - define("underscore", [], function() { - return _; - }); - } -}).call(this); - -(function(window, document, undefined) { - "use strict"; - function minErr(module, ErrorConstructor) { - ErrorConstructor = ErrorConstructor || Error; - return function() { - var SKIP_INDEXES = 2; - var templateArgs = arguments, code = templateArgs[0], message = "[" + (module ? module + ":" : "") + code + "] ", template = templateArgs[1], paramPrefix, i; - message += template.replace(/\{\d+\}/g, function(match) { - var index = +match.slice(1, -1), shiftedIndex = index + SKIP_INDEXES; - if (shiftedIndex < templateArgs.length) { - return toDebugString(templateArgs[shiftedIndex]); + function baseClone(value, isDeep, customizer, key, object, stackA, stackB) { + var result; + if (customizer) { + result = object ? customizer(value, key, object) : customizer(value); + } + if (result !== undefined) { + return result; + } + if (!isObject(value)) { + return value; + } + var isArr = isArray(value); + if (isArr) { + result = initCloneArray(value); + if (!isDeep) { + return arrayCopy(value, result); + } + } else { + var tag = objToString.call(value), isFunc = tag == funcTag; + if (tag == objectTag || tag == argsTag || isFunc && !object) { + result = initCloneObject(isFunc ? {} : value); + if (!isDeep) { + return baseAssign(result, value); + } + } else { + return cloneableTags[tag] ? initCloneByTag(value, tag, isDeep) : object ? value : {}; } - return match; - }); - message += "\nhttp://errors.angularjs.org/1.4.6/" + (module ? module + "/" : "") + code; - for (i = SKIP_INDEXES, paramPrefix = "?"; i < templateArgs.length; i++, paramPrefix = "&") { - message += paramPrefix + "p" + (i - SKIP_INDEXES) + "=" + encodeURIComponent(toDebugString(templateArgs[i])); } - return new ErrorConstructor(message); - }; - } - var REGEX_STRING_REGEXP = /^\/(.+)\/([a-z]*)$/; - var VALIDITY_STATE_PROPERTY = "validity"; - var lowercase = function(string) { - return isString(string) ? string.toLowerCase() : string; - }; - var hasOwnProperty = Object.prototype.hasOwnProperty; - var uppercase = function(string) { - return isString(string) ? string.toUpperCase() : string; - }; - var manualLowercase = function(s) { - return isString(s) ? s.replace(/[A-Z]/g, function(ch) { - return String.fromCharCode(ch.charCodeAt(0) | 32); - }) : s; - }; - var manualUppercase = function(s) { - return isString(s) ? s.replace(/[a-z]/g, function(ch) { - return String.fromCharCode(ch.charCodeAt(0) & ~32); - }) : s; - }; - if ("i" !== "I".toLowerCase()) { - lowercase = manualLowercase; - uppercase = manualUppercase; - } - var msie, jqLite, jQuery, slice = [].slice, splice = [].splice, push = [].push, toString = Object.prototype.toString, getPrototypeOf = Object.getPrototypeOf, ngMinErr = minErr("ng"), angular = window.angular || (window.angular = {}), angularModule, uid = 0; - msie = document.documentMode; - function isArrayLike(obj) { - if (obj == null || isWindow(obj)) { - return false; + stackA || (stackA = []); + stackB || (stackB = []); + var length = stackA.length; + while (length--) { + if (stackA[length] == value) { + return stackB[length]; + } + } + stackA.push(value); + stackB.push(result); + (isArr ? arrayEach : baseForOwn)(value, function(subValue, key) { + result[key] = baseClone(subValue, isDeep, customizer, key, value, stackA, stackB); + }); + return result; } - var length = "length" in Object(obj) && obj.length; - if (obj.nodeType === NODE_TYPE_ELEMENT && length) { - return true; + var baseCreate = function() { + function object() {} + return function(prototype) { + if (isObject(prototype)) { + object.prototype = prototype; + var result = new object(); + object.prototype = undefined; + } + return result || {}; + }; + }(); + function baseDelay(func, wait, args) { + if (typeof func != "function") { + throw new TypeError(FUNC_ERROR_TEXT); + } + return setTimeout(function() { + func.apply(undefined, args); + }, wait); } - return isString(obj) || isArray(obj) || length === 0 || typeof length === "number" && length > 0 && length - 1 in obj; - } - function forEach(obj, iterator, context) { - var key, length; - if (obj) { - if (isFunction(obj)) { - for (key in obj) { - if (key != "prototype" && key != "length" && key != "name" && (!obj.hasOwnProperty || obj.hasOwnProperty(key))) { - iterator.call(context, obj[key], key, obj); + function baseDifference(array, values) { + var length = array ? array.length : 0, result = []; + if (!length) { + return result; + } + var index = -1, indexOf = getIndexOf(), isCommon = indexOf === baseIndexOf, cache = isCommon && values.length >= LARGE_ARRAY_SIZE ? createCache(values) : null, valuesLength = values.length; + if (cache) { + indexOf = cacheIndexOf; + isCommon = false; + values = cache; + } + outer: while (++index < length) { + var value = array[index]; + if (isCommon && value === value) { + var valuesIndex = valuesLength; + while (valuesIndex--) { + if (values[valuesIndex] === value) { + continue outer; + } } + result.push(value); + } else if (indexOf(values, value, 0) < 0) { + result.push(value); } - } else if (isArray(obj) || isArrayLike(obj)) { - var isPrimitive = typeof obj !== "object"; - for (key = 0, length = obj.length; key < length; key++) { - if (isPrimitive || key in obj) { - iterator.call(context, obj[key], key, obj); - } + } + return result; + } + var baseEach = createBaseEach(baseForOwn); + var baseEachRight = createBaseEach(baseForOwnRight, true); + function baseEvery(collection, predicate) { + var result = true; + baseEach(collection, function(value, index, collection) { + result = !!predicate(value, index, collection); + return result; + }); + return result; + } + function baseExtremum(collection, iteratee, comparator, exValue) { + var computed = exValue, result = computed; + baseEach(collection, function(value, index, collection) { + var current = +iteratee(value, index, collection); + if (comparator(current, computed) || current === exValue && current === result) { + computed = current; + result = value; } - } else if (obj.forEach && obj.forEach !== forEach) { - obj.forEach(iterator, context, obj); - } else if (isBlankObject(obj)) { - for (key in obj) { - iterator.call(context, obj[key], key, obj); + }); + return result; + } + function baseFill(array, value, start, end) { + var length = array.length; + start = start == null ? 0 : +start || 0; + if (start < 0) { + start = -start > length ? 0 : length + start; + } + end = end === undefined || end > length ? length : +end || 0; + if (end < 0) { + end += length; + } + length = start > end ? 0 : end >>> 0; + start >>>= 0; + while (start < length) { + array[start++] = value; + } + return array; + } + function baseFilter(collection, predicate) { + var result = []; + baseEach(collection, function(value, index, collection) { + if (predicate(value, index, collection)) { + result.push(value); } - } else if (typeof obj.hasOwnProperty === "function") { - for (key in obj) { - if (obj.hasOwnProperty(key)) { - iterator.call(context, obj[key], key, obj); - } + }); + return result; + } + function baseFind(collection, predicate, eachFunc, retKey) { + var result; + eachFunc(collection, function(value, key, collection) { + if (predicate(value, key, collection)) { + result = retKey ? key : value; + return false; } - } else { - for (key in obj) { - if (hasOwnProperty.call(obj, key)) { - iterator.call(context, obj[key], key, obj); + }); + return result; + } + function baseFlatten(array, isDeep, isStrict, result) { + result || (result = []); + var index = -1, length = array.length; + while (++index < length) { + var value = array[index]; + if (isObjectLike(value) && isArrayLike(value) && (isStrict || isArray(value) || isArguments(value))) { + if (isDeep) { + baseFlatten(value, isDeep, isStrict, result); + } else { + arrayPush(result, value); } + } else if (!isStrict) { + result[result.length] = value; } } + return result; } - return obj; - } - function forEachSorted(obj, iterator, context) { - var keys = Object.keys(obj).sort(); - for (var i = 0; i < keys.length; i++) { - iterator.call(context, obj[keys[i]], keys[i]); + var baseFor = createBaseFor(); + var baseForRight = createBaseFor(true); + function baseForIn(object, iteratee) { + return baseFor(object, iteratee, keysIn); } - return keys; - } - function reverseParams(iteratorFn) { - return function(value, key) { - iteratorFn(key, value); - }; - } - function nextUid() { - return ++uid; - } - function setHashKey(obj, h) { - if (h) { - obj.$$hashKey = h; - } else { - delete obj.$$hashKey; + function baseForOwn(object, iteratee) { + return baseFor(object, iteratee, keys); } - } - function baseExtend(dst, objs, deep) { - var h = dst.$$hashKey; - for (var i = 0, ii = objs.length; i < ii; ++i) { - var obj = objs[i]; - if (!isObject(obj) && !isFunction(obj)) continue; - var keys = Object.keys(obj); - for (var j = 0, jj = keys.length; j < jj; j++) { - var key = keys[j]; - var src = obj[key]; - if (deep && isObject(src)) { - if (isDate(src)) { - dst[key] = new Date(src.valueOf()); - } else if (isRegExp(src)) { - dst[key] = new RegExp(src); - } else { - if (!isObject(dst[key])) dst[key] = isArray(src) ? [] : {}; - baseExtend(dst[key], [ src ], true); - } - } else { - dst[key] = src; + function baseForOwnRight(object, iteratee) { + return baseForRight(object, iteratee, keys); + } + function baseFunctions(object, props) { + var index = -1, length = props.length, resIndex = -1, result = []; + while (++index < length) { + var key = props[index]; + if (isFunction(object[key])) { + result[++resIndex] = key; } } + return result; } - setHashKey(dst, h); - return dst; - } - function extend(dst) { - return baseExtend(dst, slice.call(arguments, 1), false); - } - function merge(dst) { - return baseExtend(dst, slice.call(arguments, 1), true); - } - function toInt(str) { - return parseInt(str, 10); - } - function inherit(parent, extra) { - return extend(Object.create(parent), extra); - } - function noop() {} - noop.$inject = []; - function identity($) { - return $; - } - identity.$inject = []; - function valueFn(value) { - return function() { - return value; - }; - } - function hasCustomToString(obj) { - return isFunction(obj.toString) && obj.toString !== Object.prototype.toString; - } - function isUndefined(value) { - return typeof value === "undefined"; - } - function isDefined(value) { - return typeof value !== "undefined"; - } - function isObject(value) { - return value !== null && typeof value === "object"; - } - function isBlankObject(value) { - return value !== null && typeof value === "object" && !getPrototypeOf(value); - } - function isString(value) { - return typeof value === "string"; - } - function isNumber(value) { - return typeof value === "number"; - } - function isDate(value) { - return toString.call(value) === "[object Date]"; - } - var isArray = Array.isArray; - function isFunction(value) { - return typeof value === "function"; - } - function isRegExp(value) { - return toString.call(value) === "[object RegExp]"; - } - function isWindow(obj) { - return obj && obj.window === obj; - } - function isScope(obj) { - return obj && obj.$evalAsync && obj.$watch; - } - function isFile(obj) { - return toString.call(obj) === "[object File]"; - } - function isFormData(obj) { - return toString.call(obj) === "[object FormData]"; - } - function isBlob(obj) { - return toString.call(obj) === "[object Blob]"; - } - function isBoolean(value) { - return typeof value === "boolean"; - } - function isPromiseLike(obj) { - return obj && isFunction(obj.then); - } - var TYPED_ARRAY_REGEXP = /^\[object (Uint8(Clamped)?)|(Uint16)|(Uint32)|(Int8)|(Int16)|(Int32)|(Float(32)|(64))Array\]$/; - function isTypedArray(value) { - return TYPED_ARRAY_REGEXP.test(toString.call(value)); - } - var trim = function(value) { - return isString(value) ? value.trim() : value; - }; - var escapeForRegexp = function(s) { - return s.replace(/([-()\[\]{}+?*.$\^|,:#= 0) { - array.splice(index, 1); - } - return index; - } - function copy(source, destination, stackSource, stackDest) { - if (isWindow(source) || isScope(source)) { - throw ngMinErr("cpws", "Can't copy! Making copies of Window or Scope instances is not supported."); + function baseGet(object, path, pathKey) { + if (object == null) { + return; + } + if (pathKey !== undefined && pathKey in toObject(object)) { + path = [ pathKey ]; + } + var index = 0, length = path.length; + while (object != null && index < length) { + object = object[path[index++]]; + } + return index && index == length ? object : undefined; } - if (isTypedArray(destination)) { - throw ngMinErr("cpta", "Can't copy! TypedArray destination cannot be mutated."); + function baseIsEqual(value, other, customizer, isLoose, stackA, stackB) { + if (value === other) { + return true; + } + if (value == null || other == null || !isObject(value) && !isObjectLike(other)) { + return value !== value && other !== other; + } + return baseIsEqualDeep(value, other, baseIsEqual, customizer, isLoose, stackA, stackB); } - if (!destination) { - destination = source; - if (isObject(source)) { - var index; - if (stackSource && (index = stackSource.indexOf(source)) !== -1) { - return stackDest[index]; + function baseIsEqualDeep(object, other, equalFunc, customizer, isLoose, stackA, stackB) { + var objIsArr = isArray(object), othIsArr = isArray(other), objTag = arrayTag, othTag = arrayTag; + if (!objIsArr) { + objTag = objToString.call(object); + if (objTag == argsTag) { + objTag = objectTag; + } else if (objTag != objectTag) { + objIsArr = isTypedArray(object); } - if (isArray(source)) { - return copy(source, [], stackSource, stackDest); - } else if (isTypedArray(source)) { - destination = new source.constructor(source); - } else if (isDate(source)) { - destination = new Date(source.getTime()); - } else if (isRegExp(source)) { - destination = new RegExp(source.source, source.toString().match(/[^\/]*$/)[0]); - destination.lastIndex = source.lastIndex; - } else if (isFunction(source.cloneNode)) { - destination = source.cloneNode(true); - } else { - var emptyObject = Object.create(getPrototypeOf(source)); - return copy(source, emptyObject, stackSource, stackDest); + } + if (!othIsArr) { + othTag = objToString.call(other); + if (othTag == argsTag) { + othTag = objectTag; + } else if (othTag != objectTag) { + othIsArr = isTypedArray(other); } - if (stackDest) { - stackSource.push(source); - stackDest.push(destination); + } + var objIsObj = objTag == objectTag, othIsObj = othTag == objectTag, isSameTag = objTag == othTag; + if (isSameTag && !(objIsArr || objIsObj)) { + return equalByTag(object, other, objTag); + } + if (!isLoose) { + var objIsWrapped = objIsObj && hasOwnProperty.call(object, "__wrapped__"), othIsWrapped = othIsObj && hasOwnProperty.call(other, "__wrapped__"); + if (objIsWrapped || othIsWrapped) { + return equalFunc(objIsWrapped ? object.value() : object, othIsWrapped ? other.value() : other, customizer, isLoose, stackA, stackB); } } - } else { - if (source === destination) throw ngMinErr("cpi", "Can't copy! Source and destination are identical."); - stackSource = stackSource || []; - stackDest = stackDest || []; - if (isObject(source)) { - stackSource.push(source); - stackDest.push(destination); + if (!isSameTag) { + return false; } - var result, key; - if (isArray(source)) { - destination.length = 0; - for (var i = 0; i < source.length; i++) { - destination.push(copy(source[i], null, stackSource, stackDest)); + stackA || (stackA = []); + stackB || (stackB = []); + var length = stackA.length; + while (length--) { + if (stackA[length] == object) { + return stackB[length] == other; } - } else { - var h = destination.$$hashKey; - if (isArray(destination)) { - destination.length = 0; - } else { - forEach(destination, function(value, key) { - delete destination[key]; - }); + } + stackA.push(object); + stackB.push(other); + var result = (objIsArr ? equalArrays : equalObjects)(object, other, equalFunc, customizer, isLoose, stackA, stackB); + stackA.pop(); + stackB.pop(); + return result; + } + function baseIsMatch(object, matchData, customizer) { + var index = matchData.length, length = index, noCustomizer = !customizer; + if (object == null) { + return !length; + } + object = toObject(object); + while (index--) { + var data = matchData[index]; + if (noCustomizer && data[2] ? data[1] !== object[data[0]] : !(data[0] in object)) { + return false; } - if (isBlankObject(source)) { - for (key in source) { - destination[key] = copy(source[key], null, stackSource, stackDest); - } - } else if (source && typeof source.hasOwnProperty === "function") { - for (key in source) { - if (source.hasOwnProperty(key)) { - destination[key] = copy(source[key], null, stackSource, stackDest); - } + } + while (++index < length) { + data = matchData[index]; + var key = data[0], objValue = object[key], srcValue = data[1]; + if (noCustomizer && data[2]) { + if (objValue === undefined && !(key in object)) { + return false; } } else { - for (key in source) { - if (hasOwnProperty.call(source, key)) { - destination[key] = copy(source[key], null, stackSource, stackDest); - } + var result = customizer ? customizer(objValue, srcValue, key) : undefined; + if (!(result === undefined ? baseIsEqual(srcValue, objValue, customizer, true) : result)) { + return false; } } - setHashKey(destination, h); } + return true; } - return destination; - } - function shallowCopy(src, dst) { - if (isArray(src)) { - dst = dst || []; - for (var i = 0, ii = src.length; i < ii; i++) { - dst[i] = src[i]; - } - } else if (isObject(src)) { - dst = dst || {}; - for (var key in src) { - if (!(key.charAt(0) === "$" && key.charAt(1) === "$")) { - dst[key] = src[key]; - } + function baseMap(collection, iteratee) { + var index = -1, result = isArrayLike(collection) ? Array(collection.length) : []; + baseEach(collection, function(value, key, collection) { + result[++index] = iteratee(value, key, collection); + }); + return result; + } + function baseMatches(source) { + var matchData = getMatchData(source); + if (matchData.length == 1 && matchData[0][2]) { + var key = matchData[0][0], value = matchData[0][1]; + return function(object) { + if (object == null) { + return false; + } + return object[key] === value && (value !== undefined || key in toObject(object)); + }; } + return function(object) { + return baseIsMatch(object, matchData); + }; } - return dst || src; - } - function equals(o1, o2) { - if (o1 === o2) return true; - if (o1 === null || o2 === null) return false; - if (o1 !== o1 && o2 !== o2) return true; - var t1 = typeof o1, t2 = typeof o2, length, key, keySet; - if (t1 == t2) { - if (t1 == "object") { - if (isArray(o1)) { - if (!isArray(o2)) return false; - if ((length = o1.length) == o2.length) { - for (key = 0; key < length; key++) { - if (!equals(o1[key], o2[key])) return false; - } - return true; + function baseMatchesProperty(path, srcValue) { + var isArr = isArray(path), isCommon = isKey(path) && isStrictComparable(srcValue), pathKey = path + ""; + path = toPath(path); + return function(object) { + if (object == null) { + return false; + } + var key = pathKey; + object = toObject(object); + if ((isArr || !isCommon) && !(key in object)) { + object = path.length == 1 ? object : baseGet(object, baseSlice(path, 0, -1)); + if (object == null) { + return false; } - } else if (isDate(o1)) { - if (!isDate(o2)) return false; - return equals(o1.getTime(), o2.getTime()); - } else if (isRegExp(o1)) { - return isRegExp(o2) ? o1.toString() == o2.toString() : false; + key = last(path); + object = toObject(object); + } + return object[key] === srcValue ? srcValue !== undefined || key in object : baseIsEqual(srcValue, object[key], undefined, true); + }; + } + function baseMerge(object, source, customizer, stackA, stackB) { + if (!isObject(object)) { + return object; + } + var isSrcArr = isArrayLike(source) && (isArray(source) || isTypedArray(source)), props = isSrcArr ? undefined : keys(source); + arrayEach(props || source, function(srcValue, key) { + if (props) { + key = srcValue; + srcValue = source[key]; + } + if (isObjectLike(srcValue)) { + stackA || (stackA = []); + stackB || (stackB = []); + baseMergeDeep(object, source, key, baseMerge, customizer, stackA, stackB); } else { - if (isScope(o1) || isScope(o2) || isWindow(o1) || isWindow(o2) || isArray(o2) || isDate(o2) || isRegExp(o2)) return false; - keySet = createMap(); - for (key in o1) { - if (key.charAt(0) === "$" || isFunction(o1[key])) continue; - if (!equals(o1[key], o2[key])) return false; - keySet[key] = true; + var value = object[key], result = customizer ? customizer(value, srcValue, key, object, source) : undefined, isCommon = result === undefined; + if (isCommon) { + result = srcValue; } - for (key in o2) { - if (!(key in keySet) && key.charAt(0) !== "$" && isDefined(o2[key]) && !isFunction(o2[key])) return false; + if ((result !== undefined || isSrcArr && !(key in object)) && (isCommon || (result === result ? result !== value : value === value))) { + object[key] = result; } - return true; } + }); + return object; + } + function baseMergeDeep(object, source, key, mergeFunc, customizer, stackA, stackB) { + var length = stackA.length, srcValue = source[key]; + while (length--) { + if (stackA[length] == srcValue) { + object[key] = stackB[length]; + return; + } + } + var value = object[key], result = customizer ? customizer(value, srcValue, key, object, source) : undefined, isCommon = result === undefined; + if (isCommon) { + result = srcValue; + if (isArrayLike(srcValue) && (isArray(srcValue) || isTypedArray(srcValue))) { + result = isArray(value) ? value : isArrayLike(value) ? arrayCopy(value) : []; + } else if (isPlainObject(srcValue) || isArguments(srcValue)) { + result = isArguments(value) ? toPlainObject(value) : isPlainObject(value) ? value : {}; + } else { + isCommon = false; + } + } + stackA.push(srcValue); + stackB.push(result); + if (isCommon) { + object[key] = mergeFunc(result, srcValue, customizer, stackA, stackB); + } else if (result === result ? result !== value : value === value) { + object[key] = result; } } - return false; - } - var csp = function() { - if (!isDefined(csp.rules)) { - var ngCspElement = document.querySelector("[ng-csp]") || document.querySelector("[data-ng-csp]"); - if (ngCspElement) { - var ngCspAttribute = ngCspElement.getAttribute("ng-csp") || ngCspElement.getAttribute("data-ng-csp"); - csp.rules = { - noUnsafeEval: !ngCspAttribute || ngCspAttribute.indexOf("no-unsafe-eval") !== -1, - noInlineStyle: !ngCspAttribute || ngCspAttribute.indexOf("no-inline-style") !== -1 - }; - } else { - csp.rules = { - noUnsafeEval: noUnsafeEval(), - noInlineStyle: false - }; - } + function baseProperty(key) { + return function(object) { + return object == null ? undefined : object[key]; + }; } - return csp.rules; - function noUnsafeEval() { - try { - new Function(""); - return false; - } catch (e) { - return true; + function basePropertyDeep(path) { + var pathKey = path + ""; + path = toPath(path); + return function(object) { + return baseGet(object, path, pathKey); + }; + } + function basePullAt(array, indexes) { + var length = array ? indexes.length : 0; + while (length--) { + var index = indexes[length]; + if (index != previous && isIndex(index)) { + var previous = index; + splice.call(array, index, 1); + } } + return array; } - }; - var jq = function() { - if (isDefined(jq.name_)) return jq.name_; - var el; - var i, ii = ngAttrPrefixes.length, prefix, name; - for (i = 0; i < ii; ++i) { - prefix = ngAttrPrefixes[i]; - if (el = document.querySelector("[" + prefix.replace(":", "\\:") + "jq]")) { - name = el.getAttribute(prefix + "jq"); - break; + function baseRandom(min, max) { + return min + nativeFloor(nativeRandom() * (max - min + 1)); + } + function baseReduce(collection, iteratee, accumulator, initFromCollection, eachFunc) { + eachFunc(collection, function(value, index, collection) { + accumulator = initFromCollection ? (initFromCollection = false, value) : iteratee(accumulator, value, index, collection); + }); + return accumulator; + } + var baseSetData = !metaMap ? identity : function(func, data) { + metaMap.set(func, data); + return func; + }; + function baseSlice(array, start, end) { + var index = -1, length = array.length; + start = start == null ? 0 : +start || 0; + if (start < 0) { + start = -start > length ? 0 : length + start; + } + end = end === undefined || end > length ? length : +end || 0; + if (end < 0) { + end += length; + } + length = start > end ? 0 : end - start >>> 0; + start >>>= 0; + var result = Array(length); + while (++index < length) { + result[index] = array[index + start]; } + return result; } - return jq.name_ = name; - }; - function concat(array1, array2, index) { - return array1.concat(slice.call(array2, index)); - } - function sliceArgs(args, startIndex) { - return slice.call(args, startIndex || 0); - } - function bind(self, fn) { - var curryArgs = arguments.length > 2 ? sliceArgs(arguments, 2) : []; - if (isFunction(fn) && !(fn instanceof RegExp)) { - return curryArgs.length ? function() { - return arguments.length ? fn.apply(self, concat(curryArgs, arguments, 0)) : fn.apply(self, curryArgs); - } : function() { - return arguments.length ? fn.apply(self, arguments) : fn.call(self); - }; - } else { - return fn; + function baseSome(collection, predicate) { + var result; + baseEach(collection, function(value, index, collection) { + result = predicate(value, index, collection); + return !result; + }); + return !!result; } - } - function toJsonReplacer(key, value) { - var val = value; - if (typeof key === "string" && key.charAt(0) === "$" && key.charAt(1) === "$") { - val = undefined; - } else if (isWindow(value)) { - val = "$WINDOW"; - } else if (value && document === value) { - val = "$DOCUMENT"; - } else if (isScope(value)) { - val = "$SCOPE"; + function baseSortBy(array, comparer) { + var length = array.length; + array.sort(comparer); + while (length--) { + array[length] = array[length].value; + } + return array; } - return val; - } - function toJson(obj, pretty) { - if (typeof obj === "undefined") return undefined; - if (!isNumber(pretty)) { - pretty = pretty ? 2 : null; + function baseSortByOrder(collection, iteratees, orders) { + var callback = getCallback(), index = -1; + iteratees = arrayMap(iteratees, function(iteratee) { + return callback(iteratee); + }); + var result = baseMap(collection, function(value) { + var criteria = arrayMap(iteratees, function(iteratee) { + return iteratee(value); + }); + return { + criteria: criteria, + index: ++index, + value: value + }; + }); + return baseSortBy(result, function(object, other) { + return compareMultiple(object, other, orders); + }); } - return JSON.stringify(obj, toJsonReplacer, pretty); - } - function fromJson(json) { - return isString(json) ? JSON.parse(json) : json; - } - function timezoneToOffset(timezone, fallback) { - var requestedTimezoneOffset = Date.parse("Jan 01, 1970 00:00:00 " + timezone) / 6e4; - return isNaN(requestedTimezoneOffset) ? fallback : requestedTimezoneOffset; - } - function addDateMinutes(date, minutes) { - date = new Date(date.getTime()); - date.setMinutes(date.getMinutes() + minutes); - return date; - } - function convertTimezoneToLocal(date, timezone, reverse) { - reverse = reverse ? -1 : 1; - var timezoneOffset = timezoneToOffset(timezone, date.getTimezoneOffset()); - return addDateMinutes(date, reverse * (timezoneOffset - date.getTimezoneOffset())); - } - function startingTag(element) { - element = jqLite(element).clone(); - try { - element.empty(); - } catch (e) {} - var elemHtml = jqLite("
").append(element).html(); - try { - return element[0].nodeType === NODE_TYPE_TEXT ? lowercase(elemHtml) : elemHtml.match(/^(<[^>]+>)/)[1].replace(/^<([\w\-]+)/, function(match, nodeName) { - return "<" + lowercase(nodeName); + function baseSum(collection, iteratee) { + var result = 0; + baseEach(collection, function(value, index, collection) { + result += +iteratee(value, index, collection) || 0; }); - } catch (e) { - return lowercase(elemHtml); + return result; } - } - function tryDecodeURIComponent(value) { - try { - return decodeURIComponent(value); - } catch (e) {} - } - function parseKeyValue(keyValue) { - var obj = {}; - forEach((keyValue || "").split("&"), function(keyValue) { - var splitPoint, key, val; - if (keyValue) { - key = keyValue = keyValue.replace(/\+/g, "%20"); - splitPoint = keyValue.indexOf("="); - if (splitPoint !== -1) { - key = keyValue.substring(0, splitPoint); - val = keyValue.substring(splitPoint + 1); + function baseUniq(array, iteratee) { + var index = -1, indexOf = getIndexOf(), length = array.length, isCommon = indexOf === baseIndexOf, isLarge = isCommon && length >= LARGE_ARRAY_SIZE, seen = isLarge ? createCache() : null, result = []; + if (seen) { + indexOf = cacheIndexOf; + isCommon = false; + } else { + isLarge = false; + seen = iteratee ? [] : result; + } + outer: while (++index < length) { + var value = array[index], computed = iteratee ? iteratee(value, index, array) : value; + if (isCommon && value === value) { + var seenIndex = seen.length; + while (seenIndex--) { + if (seen[seenIndex] === computed) { + continue outer; + } + } + if (iteratee) { + seen.push(computed); + } + result.push(value); + } else if (indexOf(seen, computed, 0) < 0) { + if (iteratee || isLarge) { + seen.push(computed); + } + result.push(value); } - key = tryDecodeURIComponent(key); - if (isDefined(key)) { - val = isDefined(val) ? tryDecodeURIComponent(val) : true; - if (!hasOwnProperty.call(obj, key)) { - obj[key] = val; - } else if (isArray(obj[key])) { - obj[key].push(val); + } + return result; + } + function baseValues(object, props) { + var index = -1, length = props.length, result = Array(length); + while (++index < length) { + result[index] = object[props[index]]; + } + return result; + } + function baseWhile(array, predicate, isDrop, fromRight) { + var length = array.length, index = fromRight ? length : -1; + while ((fromRight ? index-- : ++index < length) && predicate(array[index], index, array)) {} + return isDrop ? baseSlice(array, fromRight ? 0 : index, fromRight ? index + 1 : length) : baseSlice(array, fromRight ? index + 1 : 0, fromRight ? length : index); + } + function baseWrapperValue(value, actions) { + var result = value; + if (result instanceof LazyWrapper) { + result = result.value(); + } + var index = -1, length = actions.length; + while (++index < length) { + var action = actions[index]; + result = action.func.apply(action.thisArg, arrayPush([ result ], action.args)); + } + return result; + } + function binaryIndex(array, value, retHighest) { + var low = 0, high = array ? array.length : low; + if (typeof value == "number" && value === value && high <= HALF_MAX_ARRAY_LENGTH) { + while (low < high) { + var mid = low + high >>> 1, computed = array[mid]; + if ((retHighest ? computed <= value : computed < value) && computed !== null) { + low = mid + 1; } else { - obj[key] = [ obj[key], val ]; - } + high = mid; + } + } + return high; + } + return binaryIndexBy(array, value, identity, retHighest); + } + function binaryIndexBy(array, value, iteratee, retHighest) { + value = iteratee(value); + var low = 0, high = array ? array.length : 0, valIsNaN = value !== value, valIsNull = value === null, valIsUndef = value === undefined; + while (low < high) { + var mid = nativeFloor((low + high) / 2), computed = iteratee(array[mid]), isDef = computed !== undefined, isReflexive = computed === computed; + if (valIsNaN) { + var setLow = isReflexive || retHighest; + } else if (valIsNull) { + setLow = isReflexive && isDef && (retHighest || computed != null); + } else if (valIsUndef) { + setLow = isReflexive && (retHighest || isDef); + } else if (computed == null) { + setLow = false; + } else { + setLow = retHighest ? computed <= value : computed < value; + } + if (setLow) { + low = mid + 1; + } else { + high = mid; } } - }); - return obj; - } - function toKeyValue(obj) { - var parts = []; - forEach(obj, function(value, key) { - if (isArray(value)) { - forEach(value, function(arrayValue) { - parts.push(encodeUriQuery(key, true) + (arrayValue === true ? "" : "=" + encodeUriQuery(arrayValue, true))); - }); - } else { - parts.push(encodeUriQuery(key, true) + (value === true ? "" : "=" + encodeUriQuery(value, true))); + return nativeMin(high, MAX_ARRAY_INDEX); + } + function bindCallback(func, thisArg, argCount) { + if (typeof func != "function") { + return identity; } - }); - return parts.length ? parts.join("&") : ""; - } - function encodeUriSegment(val) { - return encodeUriQuery(val, true).replace(/%26/gi, "&").replace(/%3D/gi, "=").replace(/%2B/gi, "+"); - } - function encodeUriQuery(val, pctEncodeSpaces) { - return encodeURIComponent(val).replace(/%40/gi, "@").replace(/%3A/gi, ":").replace(/%24/g, "$").replace(/%2C/gi, ",").replace(/%3B/gi, ";").replace(/%20/g, pctEncodeSpaces ? "%20" : "+"); - } - var ngAttrPrefixes = [ "ng-", "data-ng-", "ng:", "x-ng-" ]; - function getNgAttribute(element, ngAttr) { - var attr, i, ii = ngAttrPrefixes.length; - for (i = 0; i < ii; ++i) { - attr = ngAttrPrefixes[i] + ngAttr; - if (isString(attr = element.getAttribute(attr))) { - return attr; + if (thisArg === undefined) { + return func; + } + switch (argCount) { + case 1: + return function(value) { + return func.call(thisArg, value); + }; + + case 3: + return function(value, index, collection) { + return func.call(thisArg, value, index, collection); + }; + + case 4: + return function(accumulator, value, index, collection) { + return func.call(thisArg, accumulator, value, index, collection); + }; + + case 5: + return function(value, other, key, object, source) { + return func.call(thisArg, value, other, key, object, source); + }; } + return function() { + return func.apply(thisArg, arguments); + }; } - return null; - } - function angularInit(element, bootstrap) { - var appElement, module, config = {}; - forEach(ngAttrPrefixes, function(prefix) { - var name = prefix + "app"; - if (!appElement && element.hasAttribute && element.hasAttribute(name)) { - appElement = element; - module = element.getAttribute(name); + function bufferClone(buffer) { + var result = new ArrayBuffer(buffer.byteLength), view = new Uint8Array(result); + view.set(new Uint8Array(buffer)); + return result; + } + function composeArgs(args, partials, holders) { + var holdersLength = holders.length, argsIndex = -1, argsLength = nativeMax(args.length - holdersLength, 0), leftIndex = -1, leftLength = partials.length, result = Array(leftLength + argsLength); + while (++leftIndex < leftLength) { + result[leftIndex] = partials[leftIndex]; } - }); - forEach(ngAttrPrefixes, function(prefix) { - var name = prefix + "app"; - var candidate; - if (!appElement && (candidate = element.querySelector("[" + name.replace(":", "\\:") + "]"))) { - appElement = candidate; - module = candidate.getAttribute(name); + while (++argsIndex < holdersLength) { + result[holders[argsIndex]] = args[argsIndex]; } - }); - if (appElement) { - config.strictDi = getNgAttribute(appElement, "strict-di") !== null; - bootstrap(appElement, module ? [ module ] : [], config); + while (argsLength--) { + result[leftIndex++] = args[argsIndex++]; + } + return result; } - } - function bootstrap(element, modules, config) { - if (!isObject(config)) config = {}; - var defaultConfig = { - strictDi: false - }; - config = extend(defaultConfig, config); - var doBootstrap = function() { - element = jqLite(element); - if (element.injector()) { - var tag = element[0] === document ? "document" : startingTag(element); - throw ngMinErr("btstrpd", "App Already Bootstrapped with this Element '{0}'", tag.replace(//, ">")); + function composeArgsRight(args, partials, holders) { + var holdersIndex = -1, holdersLength = holders.length, argsIndex = -1, argsLength = nativeMax(args.length - holdersLength, 0), rightIndex = -1, rightLength = partials.length, result = Array(argsLength + rightLength); + while (++argsIndex < argsLength) { + result[argsIndex] = args[argsIndex]; } - modules = modules || []; - modules.unshift([ "$provide", function($provide) { - $provide.value("$rootElement", element); - } ]); - if (config.debugInfoEnabled) { - modules.push([ "$compileProvider", function($compileProvider) { - $compileProvider.debugInfoEnabled(true); - } ]); + var offset = argsIndex; + while (++rightIndex < rightLength) { + result[offset + rightIndex] = partials[rightIndex]; } - modules.unshift("ng"); - var injector = createInjector(modules, config.strictDi); - injector.invoke([ "$rootScope", "$rootElement", "$compile", "$injector", function bootstrapApply(scope, element, compile, injector) { - scope.$apply(function() { - element.data("$injector", injector); - compile(element)(scope); - }); - } ]); - return injector; - }; - var NG_ENABLE_DEBUG_INFO = /^NG_ENABLE_DEBUG_INFO!/; - var NG_DEFER_BOOTSTRAP = /^NG_DEFER_BOOTSTRAP!/; - if (window && NG_ENABLE_DEBUG_INFO.test(window.name)) { - config.debugInfoEnabled = true; - window.name = window.name.replace(NG_ENABLE_DEBUG_INFO, ""); + while (++holdersIndex < holdersLength) { + result[offset + holders[holdersIndex]] = args[argsIndex++]; + } + return result; } - if (window && !NG_DEFER_BOOTSTRAP.test(window.name)) { - return doBootstrap(); + function createAggregator(setter, initializer) { + return function(collection, iteratee, thisArg) { + var result = initializer ? initializer() : {}; + iteratee = getCallback(iteratee, thisArg, 3); + if (isArray(collection)) { + var index = -1, length = collection.length; + while (++index < length) { + var value = collection[index]; + setter(result, value, iteratee(value, index, collection), collection); + } + } else { + baseEach(collection, function(value, key, collection) { + setter(result, value, iteratee(value, key, collection), collection); + }); + } + return result; + }; } - window.name = window.name.replace(NG_DEFER_BOOTSTRAP, ""); - angular.resumeBootstrap = function(extraModules) { - forEach(extraModules, function(module) { - modules.push(module); + function createAssigner(assigner) { + return restParam(function(object, sources) { + var index = -1, length = object == null ? 0 : sources.length, customizer = length > 2 ? sources[length - 2] : undefined, guard = length > 2 ? sources[2] : undefined, thisArg = length > 1 ? sources[length - 1] : undefined; + if (typeof customizer == "function") { + customizer = bindCallback(customizer, thisArg, 5); + length -= 2; + } else { + customizer = typeof thisArg == "function" ? thisArg : undefined; + length -= customizer ? 1 : 0; + } + if (guard && isIterateeCall(sources[0], sources[1], guard)) { + customizer = length < 3 ? undefined : customizer; + length = 1; + } + while (++index < length) { + var source = sources[index]; + if (source) { + assigner(object, source, customizer); + } + } + return object; }); - return doBootstrap(); - }; - if (isFunction(angular.resumeDeferredBootstrap)) { - angular.resumeDeferredBootstrap(); - } - } - function reloadWithDebugInfo() { - window.name = "NG_ENABLE_DEBUG_INFO!" + window.name; - window.location.reload(); - } - function getTestability(rootElement) { - var injector = angular.element(rootElement).injector(); - if (!injector) { - throw ngMinErr("test", "no injector found for element argument to getTestability"); - } - return injector.get("$$testability"); - } - var SNAKE_CASE_REGEXP = /[A-Z]/g; - function snake_case(name, separator) { - separator = separator || "_"; - return name.replace(SNAKE_CASE_REGEXP, function(letter, pos) { - return (pos ? separator : "") + letter.toLowerCase(); - }); - } - var bindJQueryFired = false; - var skipDestroyOnNextJQueryCleanData; - function bindJQuery() { - var originalCleanData; - if (bindJQueryFired) { - return; } - var jqName = jq(); - jQuery = isUndefined(jqName) ? window.jQuery : !jqName ? undefined : window[jqName]; - if (jQuery && jQuery.fn.on) { - jqLite = jQuery; - extend(jQuery.fn, { - scope: JQLitePrototype.scope, - isolateScope: JQLitePrototype.isolateScope, - controller: JQLitePrototype.controller, - injector: JQLitePrototype.injector, - inheritedData: JQLitePrototype.inheritedData - }); - originalCleanData = jQuery.cleanData; - jQuery.cleanData = function(elems) { - var events; - if (!skipDestroyOnNextJQueryCleanData) { - for (var i = 0, elem; (elem = elems[i]) != null; i++) { - events = jQuery._data(elem, "events"); - if (events && events.$destroy) { - jQuery(elem).triggerHandler("$destroy"); - } + function createBaseEach(eachFunc, fromRight) { + return function(collection, iteratee) { + var length = collection ? getLength(collection) : 0; + if (!isLength(length)) { + return eachFunc(collection, iteratee); + } + var index = fromRight ? length : -1, iterable = toObject(collection); + while (fromRight ? index-- : ++index < length) { + if (iteratee(iterable[index], index, iterable) === false) { + break; } - } else { - skipDestroyOnNextJQueryCleanData = false; } - originalCleanData(elems); + return collection; }; - } else { - jqLite = JQLite; } - angular.element = jqLite; - bindJQueryFired = true; - } - function assertArg(arg, name, reason) { - if (!arg) { - throw ngMinErr("areq", "Argument '{0}' is {1}", name || "?", reason || "required"); + function createBaseFor(fromRight) { + return function(object, iteratee, keysFunc) { + var iterable = toObject(object), props = keysFunc(object), length = props.length, index = fromRight ? length : -1; + while (fromRight ? index-- : ++index < length) { + var key = props[index]; + if (iteratee(iterable[key], key, iterable) === false) { + break; + } + } + return object; + }; } - return arg; - } - function assertArgFn(arg, name, acceptArrayAnnotation) { - if (acceptArrayAnnotation && isArray(arg)) { - arg = arg[arg.length - 1]; + function createBindWrapper(func, thisArg) { + var Ctor = createCtorWrapper(func); + function wrapper() { + var fn = this && this !== root && this instanceof wrapper ? Ctor : func; + return fn.apply(thisArg, arguments); + } + return wrapper; } - assertArg(isFunction(arg), name, "not a function, got " + (arg && typeof arg === "object" ? arg.constructor.name || "Object" : typeof arg)); - return arg; - } - function assertNotHasOwnProperty(name, context) { - if (name === "hasOwnProperty") { - throw ngMinErr("badname", "hasOwnProperty is not a valid {0} name", context); + function createCache(values) { + return nativeCreate && Set ? new SetCache(values) : null; } - } - function getter(obj, path, bindFnToScope) { - if (!path) return obj; - var keys = path.split("."); - var key; - var lastInstance = obj; - var len = keys.length; - for (var i = 0; i < len; i++) { - key = keys[i]; - if (obj) { - obj = (lastInstance = obj)[key]; - } + function createCompounder(callback) { + return function(string) { + var index = -1, array = words(deburr(string)), length = array.length, result = ""; + while (++index < length) { + result = callback(result, array[index], index); + } + return result; + }; } - if (!bindFnToScope && isFunction(obj)) { - return bind(lastInstance, obj); + function createCtorWrapper(Ctor) { + return function() { + var args = arguments; + switch (args.length) { + case 0: + return new Ctor(); + + case 1: + return new Ctor(args[0]); + + case 2: + return new Ctor(args[0], args[1]); + + case 3: + return new Ctor(args[0], args[1], args[2]); + + case 4: + return new Ctor(args[0], args[1], args[2], args[3]); + + case 5: + return new Ctor(args[0], args[1], args[2], args[3], args[4]); + + case 6: + return new Ctor(args[0], args[1], args[2], args[3], args[4], args[5]); + + case 7: + return new Ctor(args[0], args[1], args[2], args[3], args[4], args[5], args[6]); + } + var thisBinding = baseCreate(Ctor.prototype), result = Ctor.apply(thisBinding, args); + return isObject(result) ? result : thisBinding; + }; } - return obj; - } - function getBlockNodes(nodes) { - var node = nodes[0]; - var endNode = nodes[nodes.length - 1]; - var blockNodes; - for (var i = 1; node !== endNode && (node = node.nextSibling); i++) { - if (blockNodes || nodes[i] !== node) { - if (!blockNodes) { - blockNodes = jqLite(slice.call(nodes, 0, i)); + function createCurry(flag) { + function curryFunc(func, arity, guard) { + if (guard && isIterateeCall(func, arity, guard)) { + arity = undefined; } - blockNodes.push(node); + var result = createWrapper(func, flag, undefined, undefined, undefined, undefined, undefined, arity); + result.placeholder = curryFunc.placeholder; + return result; } + return curryFunc; } - return blockNodes || nodes; - } - function createMap() { - return Object.create(null); - } - var NODE_TYPE_ELEMENT = 1; - var NODE_TYPE_ATTRIBUTE = 2; - var NODE_TYPE_TEXT = 3; - var NODE_TYPE_COMMENT = 8; - var NODE_TYPE_DOCUMENT = 9; - var NODE_TYPE_DOCUMENT_FRAGMENT = 11; - function setupModuleLoader(window) { - var $injectorMinErr = minErr("$injector"); - var ngMinErr = minErr("ng"); - function ensure(obj, name, factory) { - return obj[name] || (obj[name] = factory()); + function createDefaults(assigner, customizer) { + return restParam(function(args) { + var object = args[0]; + if (object == null) { + return object; + } + args.push(customizer); + return assigner.apply(undefined, args); + }); } - var angular = ensure(window, "angular", Object); - angular.$$minErr = angular.$$minErr || minErr; - return ensure(angular, "module", function() { - var modules = {}; - return function module(name, requires, configFn) { - var assertNotHasOwnProperty = function(name, context) { - if (name === "hasOwnProperty") { - throw ngMinErr("badname", "hasOwnProperty is not a valid {0} name", context); - } - }; - assertNotHasOwnProperty(name, "module"); - if (requires && modules.hasOwnProperty(name)) { - modules[name] = null; + function createExtremum(comparator, exValue) { + return function(collection, iteratee, thisArg) { + if (thisArg && isIterateeCall(collection, iteratee, thisArg)) { + iteratee = undefined; } - return ensure(modules, name, function() { - if (!requires) { - throw $injectorMinErr("nomod", "Module '{0}' is not available! You either misspelled " + "the module name or forgot to load it. If registering a module ensure that you " + "specify the dependencies as the second argument.", name); + iteratee = getCallback(iteratee, thisArg, 3); + if (iteratee.length == 1) { + collection = isArray(collection) ? collection : toIterable(collection); + var result = arrayExtremum(collection, iteratee, comparator, exValue); + if (!(collection.length && result === exValue)) { + return result; } - var invokeQueue = []; - var configBlocks = []; - var runBlocks = []; - var config = invokeLater("$injector", "invoke", "push", configBlocks); - var moduleInstance = { - _invokeQueue: invokeQueue, - _configBlocks: configBlocks, - _runBlocks: runBlocks, - requires: requires, - name: name, - provider: invokeLaterAndSetModuleName("$provide", "provider"), - factory: invokeLaterAndSetModuleName("$provide", "factory"), - service: invokeLaterAndSetModuleName("$provide", "service"), - value: invokeLater("$provide", "value"), - constant: invokeLater("$provide", "constant", "unshift"), - decorator: invokeLaterAndSetModuleName("$provide", "decorator"), - animation: invokeLaterAndSetModuleName("$animateProvider", "register"), - filter: invokeLaterAndSetModuleName("$filterProvider", "register"), - controller: invokeLaterAndSetModuleName("$controllerProvider", "register"), - directive: invokeLaterAndSetModuleName("$compileProvider", "directive"), - config: config, - run: function(block) { - runBlocks.push(block); - return this; - } - }; - if (configFn) { - config(configFn); + } + return baseExtremum(collection, iteratee, comparator, exValue); + }; + } + function createFind(eachFunc, fromRight) { + return function(collection, predicate, thisArg) { + predicate = getCallback(predicate, thisArg, 3); + if (isArray(collection)) { + var index = baseFindIndex(collection, predicate, fromRight); + return index > -1 ? collection[index] : undefined; + } + return baseFind(collection, predicate, eachFunc); + }; + } + function createFindIndex(fromRight) { + return function(array, predicate, thisArg) { + if (!(array && array.length)) { + return -1; + } + predicate = getCallback(predicate, thisArg, 3); + return baseFindIndex(array, predicate, fromRight); + }; + } + function createFindKey(objectFunc) { + return function(object, predicate, thisArg) { + predicate = getCallback(predicate, thisArg, 3); + return baseFind(object, predicate, objectFunc, true); + }; + } + function createFlow(fromRight) { + return function() { + var wrapper, length = arguments.length, index = fromRight ? length : -1, leftIndex = 0, funcs = Array(length); + while (fromRight ? index-- : ++index < length) { + var func = funcs[leftIndex++] = arguments[index]; + if (typeof func != "function") { + throw new TypeError(FUNC_ERROR_TEXT); + } + if (!wrapper && LodashWrapper.prototype.thru && getFuncName(func) == "wrapper") { + wrapper = new LodashWrapper([], true); + } + } + index = wrapper ? -1 : length; + while (++index < length) { + func = funcs[index]; + var funcName = getFuncName(func), data = funcName == "wrapper" ? getData(func) : undefined; + if (data && isLaziable(data[0]) && data[1] == (ARY_FLAG | CURRY_FLAG | PARTIAL_FLAG | REARG_FLAG) && !data[4].length && data[9] == 1) { + wrapper = wrapper[getFuncName(data[0])].apply(wrapper, data[3]); + } else { + wrapper = func.length == 1 && isLaziable(func) ? wrapper[funcName]() : wrapper.thru(func); } - return moduleInstance; - function invokeLater(provider, method, insertMethod, queue) { - if (!queue) queue = invokeQueue; - return function() { - queue[insertMethod || "push"]([ provider, method, arguments ]); - return moduleInstance; - }; + } + return function() { + var args = arguments, value = args[0]; + if (wrapper && args.length == 1 && isArray(value) && value.length >= LARGE_ARRAY_SIZE) { + return wrapper.plant(value).value(); } - function invokeLaterAndSetModuleName(provider, method) { - return function(recipeName, factoryFunction) { - if (factoryFunction && isFunction(factoryFunction)) factoryFunction.$$moduleName = name; - invokeQueue.push([ provider, method, arguments ]); - return moduleInstance; - }; + var index = 0, result = length ? funcs[index].apply(this, args) : value; + while (++index < length) { + result = funcs[index].call(this, result); } + return result; + }; + }; + } + function createForEach(arrayFunc, eachFunc) { + return function(collection, iteratee, thisArg) { + return typeof iteratee == "function" && thisArg === undefined && isArray(collection) ? arrayFunc(collection, iteratee) : eachFunc(collection, bindCallback(iteratee, thisArg, 3)); + }; + } + function createForIn(objectFunc) { + return function(object, iteratee, thisArg) { + if (typeof iteratee != "function" || thisArg !== undefined) { + iteratee = bindCallback(iteratee, thisArg, 3); + } + return objectFunc(object, iteratee, keysIn); + }; + } + function createForOwn(objectFunc) { + return function(object, iteratee, thisArg) { + if (typeof iteratee != "function" || thisArg !== undefined) { + iteratee = bindCallback(iteratee, thisArg, 3); + } + return objectFunc(object, iteratee); + }; + } + function createObjectMapper(isMapKeys) { + return function(object, iteratee, thisArg) { + var result = {}; + iteratee = getCallback(iteratee, thisArg, 3); + baseForOwn(object, function(value, key, object) { + var mapped = iteratee(value, key, object); + key = isMapKeys ? mapped : key; + value = isMapKeys ? value : mapped; + result[key] = value; }); + return result; }; - }); - } - function serializeObject(obj) { + } + function createPadDir(fromRight) { + return function(string, length, chars) { + string = baseToString(string); + return (fromRight ? string : "") + createPadding(string, length, chars) + (fromRight ? "" : string); + }; + } + function createPartial(flag) { + var partialFunc = restParam(function(func, partials) { + var holders = replaceHolders(partials, partialFunc.placeholder); + return createWrapper(func, flag, undefined, partials, holders); + }); + return partialFunc; + } + function createReduce(arrayFunc, eachFunc) { + return function(collection, iteratee, accumulator, thisArg) { + var initFromArray = arguments.length < 3; + return typeof iteratee == "function" && thisArg === undefined && isArray(collection) ? arrayFunc(collection, iteratee, accumulator, initFromArray) : baseReduce(collection, getCallback(iteratee, thisArg, 4), accumulator, initFromArray, eachFunc); + }; + } + function createHybridWrapper(func, bitmask, thisArg, partials, holders, partialsRight, holdersRight, argPos, ary, arity) { + var isAry = bitmask & ARY_FLAG, isBind = bitmask & BIND_FLAG, isBindKey = bitmask & BIND_KEY_FLAG, isCurry = bitmask & CURRY_FLAG, isCurryBound = bitmask & CURRY_BOUND_FLAG, isCurryRight = bitmask & CURRY_RIGHT_FLAG, Ctor = isBindKey ? undefined : createCtorWrapper(func); + function wrapper() { + var length = arguments.length, index = length, args = Array(length); + while (index--) { + args[index] = arguments[index]; + } + if (partials) { + args = composeArgs(args, partials, holders); + } + if (partialsRight) { + args = composeArgsRight(args, partialsRight, holdersRight); + } + if (isCurry || isCurryRight) { + var placeholder = wrapper.placeholder, argsHolders = replaceHolders(args, placeholder); + length -= argsHolders.length; + if (length < arity) { + var newArgPos = argPos ? arrayCopy(argPos) : undefined, newArity = nativeMax(arity - length, 0), newsHolders = isCurry ? argsHolders : undefined, newHoldersRight = isCurry ? undefined : argsHolders, newPartials = isCurry ? args : undefined, newPartialsRight = isCurry ? undefined : args; + bitmask |= isCurry ? PARTIAL_FLAG : PARTIAL_RIGHT_FLAG; + bitmask &= ~(isCurry ? PARTIAL_RIGHT_FLAG : PARTIAL_FLAG); + if (!isCurryBound) { + bitmask &= ~(BIND_FLAG | BIND_KEY_FLAG); + } + var newData = [ func, bitmask, thisArg, newPartials, newsHolders, newPartialsRight, newHoldersRight, newArgPos, ary, newArity ], result = createHybridWrapper.apply(undefined, newData); + if (isLaziable(func)) { + setData(result, newData); + } + result.placeholder = placeholder; + return result; + } + } + var thisBinding = isBind ? thisArg : this, fn = isBindKey ? thisBinding[func] : func; + if (argPos) { + args = reorder(args, argPos); + } + if (isAry && ary < args.length) { + args.length = ary; + } + if (this && this !== root && this instanceof wrapper) { + fn = Ctor || createCtorWrapper(func); + } + return fn.apply(thisBinding, args); + } + return wrapper; + } + function createPadding(string, length, chars) { + var strLength = string.length; + length = +length; + if (strLength >= length || !nativeIsFinite(length)) { + return ""; + } + var padLength = length - strLength; + chars = chars == null ? " " : chars + ""; + return repeat(chars, nativeCeil(padLength / chars.length)).slice(0, padLength); + } + function createPartialWrapper(func, bitmask, thisArg, partials) { + var isBind = bitmask & BIND_FLAG, Ctor = createCtorWrapper(func); + function wrapper() { + var argsIndex = -1, argsLength = arguments.length, leftIndex = -1, leftLength = partials.length, args = Array(leftLength + argsLength); + while (++leftIndex < leftLength) { + args[leftIndex] = partials[leftIndex]; + } + while (argsLength--) { + args[leftIndex++] = arguments[++argsIndex]; + } + var fn = this && this !== root && this instanceof wrapper ? Ctor : func; + return fn.apply(isBind ? thisArg : this, args); + } + return wrapper; + } + function createRound(methodName) { + var func = Math[methodName]; + return function(number, precision) { + precision = precision === undefined ? 0 : +precision || 0; + if (precision) { + precision = pow(10, precision); + return func(number * precision) / precision; + } + return func(number); + }; + } + function createSortedIndex(retHighest) { + return function(array, value, iteratee, thisArg) { + var callback = getCallback(iteratee); + return iteratee == null && callback === baseCallback ? binaryIndex(array, value, retHighest) : binaryIndexBy(array, value, callback(iteratee, thisArg, 1), retHighest); + }; + } + function createWrapper(func, bitmask, thisArg, partials, holders, argPos, ary, arity) { + var isBindKey = bitmask & BIND_KEY_FLAG; + if (!isBindKey && typeof func != "function") { + throw new TypeError(FUNC_ERROR_TEXT); + } + var length = partials ? partials.length : 0; + if (!length) { + bitmask &= ~(PARTIAL_FLAG | PARTIAL_RIGHT_FLAG); + partials = holders = undefined; + } + length -= holders ? holders.length : 0; + if (bitmask & PARTIAL_RIGHT_FLAG) { + var partialsRight = partials, holdersRight = holders; + partials = holders = undefined; + } + var data = isBindKey ? undefined : getData(func), newData = [ func, bitmask, thisArg, partials, holders, partialsRight, holdersRight, argPos, ary, arity ]; + if (data) { + mergeData(newData, data); + bitmask = newData[1]; + arity = newData[9]; + } + newData[9] = arity == null ? isBindKey ? 0 : func.length : nativeMax(arity - length, 0) || 0; + if (bitmask == BIND_FLAG) { + var result = createBindWrapper(newData[0], newData[2]); + } else if ((bitmask == PARTIAL_FLAG || bitmask == (BIND_FLAG | PARTIAL_FLAG)) && !newData[4].length) { + result = createPartialWrapper.apply(undefined, newData); + } else { + result = createHybridWrapper.apply(undefined, newData); + } + var setter = data ? baseSetData : setData; + return setter(result, newData); + } + function equalArrays(array, other, equalFunc, customizer, isLoose, stackA, stackB) { + var index = -1, arrLength = array.length, othLength = other.length; + if (arrLength != othLength && !(isLoose && othLength > arrLength)) { + return false; + } + while (++index < arrLength) { + var arrValue = array[index], othValue = other[index], result = customizer ? customizer(isLoose ? othValue : arrValue, isLoose ? arrValue : othValue, index) : undefined; + if (result !== undefined) { + if (result) { + continue; + } + return false; + } + if (isLoose) { + if (!arraySome(other, function(othValue) { + return arrValue === othValue || equalFunc(arrValue, othValue, customizer, isLoose, stackA, stackB); + })) { + return false; + } + } else if (!(arrValue === othValue || equalFunc(arrValue, othValue, customizer, isLoose, stackA, stackB))) { + return false; + } + } + return true; + } + function equalByTag(object, other, tag) { + switch (tag) { + case boolTag: + case dateTag: + return +object == +other; + + case errorTag: + return object.name == other.name && object.message == other.message; + + case numberTag: + return object != +object ? other != +other : object == +other; + + case regexpTag: + case stringTag: + return object == other + ""; + } + return false; + } + function equalObjects(object, other, equalFunc, customizer, isLoose, stackA, stackB) { + var objProps = keys(object), objLength = objProps.length, othProps = keys(other), othLength = othProps.length; + if (objLength != othLength && !isLoose) { + return false; + } + var index = objLength; + while (index--) { + var key = objProps[index]; + if (!(isLoose ? key in other : hasOwnProperty.call(other, key))) { + return false; + } + } + var skipCtor = isLoose; + while (++index < objLength) { + key = objProps[index]; + var objValue = object[key], othValue = other[key], result = customizer ? customizer(isLoose ? othValue : objValue, isLoose ? objValue : othValue, key) : undefined; + if (!(result === undefined ? equalFunc(objValue, othValue, customizer, isLoose, stackA, stackB) : result)) { + return false; + } + skipCtor || (skipCtor = key == "constructor"); + } + if (!skipCtor) { + var objCtor = object.constructor, othCtor = other.constructor; + if (objCtor != othCtor && ("constructor" in object && "constructor" in other) && !(typeof objCtor == "function" && objCtor instanceof objCtor && typeof othCtor == "function" && othCtor instanceof othCtor)) { + return false; + } + } + return true; + } + function getCallback(func, thisArg, argCount) { + var result = lodash.callback || callback; + result = result === callback ? baseCallback : result; + return argCount ? result(func, thisArg, argCount) : result; + } + var getData = !metaMap ? noop : function(func) { + return metaMap.get(func); + }; + function getFuncName(func) { + var result = func.name + "", array = realNames[result], length = array ? array.length : 0; + while (length--) { + var data = array[length], otherFunc = data.func; + if (otherFunc == null || otherFunc == func) { + return data.name; + } + } + return result; + } + function getIndexOf(collection, target, fromIndex) { + var result = lodash.indexOf || indexOf; + result = result === indexOf ? baseIndexOf : result; + return collection ? result(collection, target, fromIndex) : result; + } + var getLength = baseProperty("length"); + function getMatchData(object) { + var result = pairs(object), length = result.length; + while (length--) { + result[length][2] = isStrictComparable(result[length][1]); + } + return result; + } + function getNative(object, key) { + var value = object == null ? undefined : object[key]; + return isNative(value) ? value : undefined; + } + function getView(start, end, transforms) { + var index = -1, length = transforms.length; + while (++index < length) { + var data = transforms[index], size = data.size; + switch (data.type) { + case "drop": + start += size; + break; + + case "dropRight": + end -= size; + break; + + case "take": + end = nativeMin(end, start + size); + break; + + case "takeRight": + start = nativeMax(start, end - size); + break; + } + } + return { + start: start, + end: end + }; + } + function initCloneArray(array) { + var length = array.length, result = new array.constructor(length); + if (length && typeof array[0] == "string" && hasOwnProperty.call(array, "index")) { + result.index = array.index; + result.input = array.input; + } + return result; + } + function initCloneObject(object) { + var Ctor = object.constructor; + if (!(typeof Ctor == "function" && Ctor instanceof Ctor)) { + Ctor = Object; + } + return new Ctor(); + } + function initCloneByTag(object, tag, isDeep) { + var Ctor = object.constructor; + switch (tag) { + case arrayBufferTag: + return bufferClone(object); + + case boolTag: + case dateTag: + return new Ctor(+object); + + case float32Tag: + case float64Tag: + case int8Tag: + case int16Tag: + case int32Tag: + case uint8Tag: + case uint8ClampedTag: + case uint16Tag: + case uint32Tag: + var buffer = object.buffer; + return new Ctor(isDeep ? bufferClone(buffer) : buffer, object.byteOffset, object.length); + + case numberTag: + case stringTag: + return new Ctor(object); + + case regexpTag: + var result = new Ctor(object.source, reFlags.exec(object)); + result.lastIndex = object.lastIndex; + } + return result; + } + function invokePath(object, path, args) { + if (object != null && !isKey(path, object)) { + path = toPath(path); + object = path.length == 1 ? object : baseGet(object, baseSlice(path, 0, -1)); + path = last(path); + } + var func = object == null ? object : object[path]; + return func == null ? undefined : func.apply(object, args); + } + function isArrayLike(value) { + return value != null && isLength(getLength(value)); + } + function isIndex(value, length) { + value = typeof value == "number" || reIsUint.test(value) ? +value : -1; + length = length == null ? MAX_SAFE_INTEGER : length; + return value > -1 && value % 1 == 0 && value < length; + } + function isIterateeCall(value, index, object) { + if (!isObject(object)) { + return false; + } + var type = typeof index; + if (type == "number" ? isArrayLike(object) && isIndex(index, object.length) : type == "string" && index in object) { + var other = object[index]; + return value === value ? value === other : other !== other; + } + return false; + } + function isKey(value, object) { + var type = typeof value; + if (type == "string" && reIsPlainProp.test(value) || type == "number") { + return true; + } + if (isArray(value)) { + return false; + } + var result = !reIsDeepProp.test(value); + return result || object != null && value in toObject(object); + } + function isLaziable(func) { + var funcName = getFuncName(func), other = lodash[funcName]; + if (typeof other != "function" || !(funcName in LazyWrapper.prototype)) { + return false; + } + if (func === other) { + return true; + } + var data = getData(other); + return !!data && func === data[0]; + } + function isLength(value) { + return typeof value == "number" && value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER; + } + function isStrictComparable(value) { + return value === value && !isObject(value); + } + function mergeData(data, source) { + var bitmask = data[1], srcBitmask = source[1], newBitmask = bitmask | srcBitmask, isCommon = newBitmask < ARY_FLAG; + var isCombo = srcBitmask == ARY_FLAG && bitmask == CURRY_FLAG || srcBitmask == ARY_FLAG && bitmask == REARG_FLAG && data[7].length <= source[8] || srcBitmask == (ARY_FLAG | REARG_FLAG) && bitmask == CURRY_FLAG; + if (!(isCommon || isCombo)) { + return data; + } + if (srcBitmask & BIND_FLAG) { + data[2] = source[2]; + newBitmask |= bitmask & BIND_FLAG ? 0 : CURRY_BOUND_FLAG; + } + var value = source[3]; + if (value) { + var partials = data[3]; + data[3] = partials ? composeArgs(partials, value, source[4]) : arrayCopy(value); + data[4] = partials ? replaceHolders(data[3], PLACEHOLDER) : arrayCopy(source[4]); + } + value = source[5]; + if (value) { + partials = data[5]; + data[5] = partials ? composeArgsRight(partials, value, source[6]) : arrayCopy(value); + data[6] = partials ? replaceHolders(data[5], PLACEHOLDER) : arrayCopy(source[6]); + } + value = source[7]; + if (value) { + data[7] = arrayCopy(value); + } + if (srcBitmask & ARY_FLAG) { + data[8] = data[8] == null ? source[8] : nativeMin(data[8], source[8]); + } + if (data[9] == null) { + data[9] = source[9]; + } + data[0] = source[0]; + data[1] = newBitmask; + return data; + } + function mergeDefaults(objectValue, sourceValue) { + return objectValue === undefined ? sourceValue : merge(objectValue, sourceValue, mergeDefaults); + } + function pickByArray(object, props) { + object = toObject(object); + var index = -1, length = props.length, result = {}; + while (++index < length) { + var key = props[index]; + if (key in object) { + result[key] = object[key]; + } + } + return result; + } + function pickByCallback(object, predicate) { + var result = {}; + baseForIn(object, function(value, key, object) { + if (predicate(value, key, object)) { + result[key] = value; + } + }); + return result; + } + function reorder(array, indexes) { + var arrLength = array.length, length = nativeMin(indexes.length, arrLength), oldArray = arrayCopy(array); + while (length--) { + var index = indexes[length]; + array[length] = isIndex(index, arrLength) ? oldArray[index] : undefined; + } + return array; + } + var setData = function() { + var count = 0, lastCalled = 0; + return function(key, value) { + var stamp = now(), remaining = HOT_SPAN - (stamp - lastCalled); + lastCalled = stamp; + if (remaining > 0) { + if (++count >= HOT_COUNT) { + return key; + } + } else { + count = 0; + } + return baseSetData(key, value); + }; + }(); + function shimKeys(object) { + var props = keysIn(object), propsLength = props.length, length = propsLength && object.length; + var allowIndexes = !!length && isLength(length) && (isArray(object) || isArguments(object)); + var index = -1, result = []; + while (++index < propsLength) { + var key = props[index]; + if (allowIndexes && isIndex(key, length) || hasOwnProperty.call(object, key)) { + result.push(key); + } + } + return result; + } + function toIterable(value) { + if (value == null) { + return []; + } + if (!isArrayLike(value)) { + return values(value); + } + return isObject(value) ? value : Object(value); + } + function toObject(value) { + return isObject(value) ? value : Object(value); + } + function toPath(value) { + if (isArray(value)) { + return value; + } + var result = []; + baseToString(value).replace(rePropName, function(match, number, quote, string) { + result.push(quote ? string.replace(reEscapeChar, "$1") : number || match); + }); + return result; + } + function wrapperClone(wrapper) { + return wrapper instanceof LazyWrapper ? wrapper.clone() : new LodashWrapper(wrapper.__wrapped__, wrapper.__chain__, arrayCopy(wrapper.__actions__)); + } + function chunk(array, size, guard) { + if (guard ? isIterateeCall(array, size, guard) : size == null) { + size = 1; + } else { + size = nativeMax(nativeFloor(size) || 1, 1); + } + var index = 0, length = array ? array.length : 0, resIndex = -1, result = Array(nativeCeil(length / size)); + while (index < length) { + result[++resIndex] = baseSlice(array, index, index += size); + } + return result; + } + function compact(array) { + var index = -1, length = array ? array.length : 0, resIndex = -1, result = []; + while (++index < length) { + var value = array[index]; + if (value) { + result[++resIndex] = value; + } + } + return result; + } + var difference = restParam(function(array, values) { + return isObjectLike(array) && isArrayLike(array) ? baseDifference(array, baseFlatten(values, false, true)) : []; + }); + function drop(array, n, guard) { + var length = array ? array.length : 0; + if (!length) { + return []; + } + if (guard ? isIterateeCall(array, n, guard) : n == null) { + n = 1; + } + return baseSlice(array, n < 0 ? 0 : n); + } + function dropRight(array, n, guard) { + var length = array ? array.length : 0; + if (!length) { + return []; + } + if (guard ? isIterateeCall(array, n, guard) : n == null) { + n = 1; + } + n = length - (+n || 0); + return baseSlice(array, 0, n < 0 ? 0 : n); + } + function dropRightWhile(array, predicate, thisArg) { + return array && array.length ? baseWhile(array, getCallback(predicate, thisArg, 3), true, true) : []; + } + function dropWhile(array, predicate, thisArg) { + return array && array.length ? baseWhile(array, getCallback(predicate, thisArg, 3), true) : []; + } + function fill(array, value, start, end) { + var length = array ? array.length : 0; + if (!length) { + return []; + } + if (start && typeof start != "number" && isIterateeCall(array, value, start)) { + start = 0; + end = length; + } + return baseFill(array, value, start, end); + } + var findIndex = createFindIndex(); + var findLastIndex = createFindIndex(true); + function first(array) { + return array ? array[0] : undefined; + } + function flatten(array, isDeep, guard) { + var length = array ? array.length : 0; + if (guard && isIterateeCall(array, isDeep, guard)) { + isDeep = false; + } + return length ? baseFlatten(array, isDeep) : []; + } + function flattenDeep(array) { + var length = array ? array.length : 0; + return length ? baseFlatten(array, true) : []; + } + function indexOf(array, value, fromIndex) { + var length = array ? array.length : 0; + if (!length) { + return -1; + } + if (typeof fromIndex == "number") { + fromIndex = fromIndex < 0 ? nativeMax(length + fromIndex, 0) : fromIndex; + } else if (fromIndex) { + var index = binaryIndex(array, value); + if (index < length && (value === value ? value === array[index] : array[index] !== array[index])) { + return index; + } + return -1; + } + return baseIndexOf(array, value, fromIndex || 0); + } + function initial(array) { + return dropRight(array, 1); + } + var intersection = restParam(function(arrays) { + var othLength = arrays.length, othIndex = othLength, caches = Array(length), indexOf = getIndexOf(), isCommon = indexOf === baseIndexOf, result = []; + while (othIndex--) { + var value = arrays[othIndex] = isArrayLike(value = arrays[othIndex]) ? value : []; + caches[othIndex] = isCommon && value.length >= 120 ? createCache(othIndex && value) : null; + } + var array = arrays[0], index = -1, length = array ? array.length : 0, seen = caches[0]; + outer: while (++index < length) { + value = array[index]; + if ((seen ? cacheIndexOf(seen, value) : indexOf(result, value, 0)) < 0) { + var othIndex = othLength; + while (--othIndex) { + var cache = caches[othIndex]; + if ((cache ? cacheIndexOf(cache, value) : indexOf(arrays[othIndex], value, 0)) < 0) { + continue outer; + } + } + if (seen) { + seen.push(value); + } + result.push(value); + } + } + return result; + }); + function last(array) { + var length = array ? array.length : 0; + return length ? array[length - 1] : undefined; + } + function lastIndexOf(array, value, fromIndex) { + var length = array ? array.length : 0; + if (!length) { + return -1; + } + var index = length; + if (typeof fromIndex == "number") { + index = (fromIndex < 0 ? nativeMax(length + fromIndex, 0) : nativeMin(fromIndex || 0, length - 1)) + 1; + } else if (fromIndex) { + index = binaryIndex(array, value, true) - 1; + var other = array[index]; + if (value === value ? value === other : other !== other) { + return index; + } + return -1; + } + if (value !== value) { + return indexOfNaN(array, index, true); + } + while (index--) { + if (array[index] === value) { + return index; + } + } + return -1; + } + function pull() { + var args = arguments, array = args[0]; + if (!(array && array.length)) { + return array; + } + var index = 0, indexOf = getIndexOf(), length = args.length; + while (++index < length) { + var fromIndex = 0, value = args[index]; + while ((fromIndex = indexOf(array, value, fromIndex)) > -1) { + splice.call(array, fromIndex, 1); + } + } + return array; + } + var pullAt = restParam(function(array, indexes) { + indexes = baseFlatten(indexes); + var result = baseAt(array, indexes); + basePullAt(array, indexes.sort(baseCompareAscending)); + return result; + }); + function remove(array, predicate, thisArg) { + var result = []; + if (!(array && array.length)) { + return result; + } + var index = -1, indexes = [], length = array.length; + predicate = getCallback(predicate, thisArg, 3); + while (++index < length) { + var value = array[index]; + if (predicate(value, index, array)) { + result.push(value); + indexes.push(index); + } + } + basePullAt(array, indexes); + return result; + } + function rest(array) { + return drop(array, 1); + } + function slice(array, start, end) { + var length = array ? array.length : 0; + if (!length) { + return []; + } + if (end && typeof end != "number" && isIterateeCall(array, start, end)) { + start = 0; + end = length; + } + return baseSlice(array, start, end); + } + var sortedIndex = createSortedIndex(); + var sortedLastIndex = createSortedIndex(true); + function take(array, n, guard) { + var length = array ? array.length : 0; + if (!length) { + return []; + } + if (guard ? isIterateeCall(array, n, guard) : n == null) { + n = 1; + } + return baseSlice(array, 0, n < 0 ? 0 : n); + } + function takeRight(array, n, guard) { + var length = array ? array.length : 0; + if (!length) { + return []; + } + if (guard ? isIterateeCall(array, n, guard) : n == null) { + n = 1; + } + n = length - (+n || 0); + return baseSlice(array, n < 0 ? 0 : n); + } + function takeRightWhile(array, predicate, thisArg) { + return array && array.length ? baseWhile(array, getCallback(predicate, thisArg, 3), false, true) : []; + } + function takeWhile(array, predicate, thisArg) { + return array && array.length ? baseWhile(array, getCallback(predicate, thisArg, 3)) : []; + } + var union = restParam(function(arrays) { + return baseUniq(baseFlatten(arrays, false, true)); + }); + function uniq(array, isSorted, iteratee, thisArg) { + var length = array ? array.length : 0; + if (!length) { + return []; + } + if (isSorted != null && typeof isSorted != "boolean") { + thisArg = iteratee; + iteratee = isIterateeCall(array, isSorted, thisArg) ? undefined : isSorted; + isSorted = false; + } + var callback = getCallback(); + if (!(iteratee == null && callback === baseCallback)) { + iteratee = callback(iteratee, thisArg, 3); + } + return isSorted && getIndexOf() === baseIndexOf ? sortedUniq(array, iteratee) : baseUniq(array, iteratee); + } + function unzip(array) { + if (!(array && array.length)) { + return []; + } + var index = -1, length = 0; + array = arrayFilter(array, function(group) { + if (isArrayLike(group)) { + length = nativeMax(group.length, length); + return true; + } + }); + var result = Array(length); + while (++index < length) { + result[index] = arrayMap(array, baseProperty(index)); + } + return result; + } + function unzipWith(array, iteratee, thisArg) { + var length = array ? array.length : 0; + if (!length) { + return []; + } + var result = unzip(array); + if (iteratee == null) { + return result; + } + iteratee = bindCallback(iteratee, thisArg, 4); + return arrayMap(result, function(group) { + return arrayReduce(group, iteratee, undefined, true); + }); + } + var without = restParam(function(array, values) { + return isArrayLike(array) ? baseDifference(array, values) : []; + }); + function xor() { + var index = -1, length = arguments.length; + while (++index < length) { + var array = arguments[index]; + if (isArrayLike(array)) { + var result = result ? arrayPush(baseDifference(result, array), baseDifference(array, result)) : array; + } + } + return result ? baseUniq(result) : []; + } + var zip = restParam(unzip); + function zipObject(props, values) { + var index = -1, length = props ? props.length : 0, result = {}; + if (length && !values && !isArray(props[0])) { + values = []; + } + while (++index < length) { + var key = props[index]; + if (values) { + result[key] = values[index]; + } else if (key) { + result[key[0]] = key[1]; + } + } + return result; + } + var zipWith = restParam(function(arrays) { + var length = arrays.length, iteratee = length > 2 ? arrays[length - 2] : undefined, thisArg = length > 1 ? arrays[length - 1] : undefined; + if (length > 2 && typeof iteratee == "function") { + length -= 2; + } else { + iteratee = length > 1 && typeof thisArg == "function" ? (--length, thisArg) : undefined; + thisArg = undefined; + } + arrays.length = length; + return unzipWith(arrays, iteratee, thisArg); + }); + function chain(value) { + var result = lodash(value); + result.__chain__ = true; + return result; + } + function tap(value, interceptor, thisArg) { + interceptor.call(thisArg, value); + return value; + } + function thru(value, interceptor, thisArg) { + return interceptor.call(thisArg, value); + } + function wrapperChain() { + return chain(this); + } + function wrapperCommit() { + return new LodashWrapper(this.value(), this.__chain__); + } + var wrapperConcat = restParam(function(values) { + values = baseFlatten(values); + return this.thru(function(array) { + return arrayConcat(isArray(array) ? array : [ toObject(array) ], values); + }); + }); + function wrapperPlant(value) { + var result, parent = this; + while (parent instanceof baseLodash) { + var clone = wrapperClone(parent); + if (result) { + previous.__wrapped__ = clone; + } else { + result = clone; + } + var previous = clone; + parent = parent.__wrapped__; + } + previous.__wrapped__ = value; + return result; + } + function wrapperReverse() { + var value = this.__wrapped__; + var interceptor = function(value) { + return value.reverse(); + }; + if (value instanceof LazyWrapper) { + var wrapped = value; + if (this.__actions__.length) { + wrapped = new LazyWrapper(this); + } + wrapped = wrapped.reverse(); + wrapped.__actions__.push({ + func: thru, + args: [ interceptor ], + thisArg: undefined + }); + return new LodashWrapper(wrapped, this.__chain__); + } + return this.thru(interceptor); + } + function wrapperToString() { + return this.value() + ""; + } + function wrapperValue() { + return baseWrapperValue(this.__wrapped__, this.__actions__); + } + var at = restParam(function(collection, props) { + return baseAt(collection, baseFlatten(props)); + }); + var countBy = createAggregator(function(result, value, key) { + hasOwnProperty.call(result, key) ? ++result[key] : result[key] = 1; + }); + function every(collection, predicate, thisArg) { + var func = isArray(collection) ? arrayEvery : baseEvery; + if (thisArg && isIterateeCall(collection, predicate, thisArg)) { + predicate = undefined; + } + if (typeof predicate != "function" || thisArg !== undefined) { + predicate = getCallback(predicate, thisArg, 3); + } + return func(collection, predicate); + } + function filter(collection, predicate, thisArg) { + var func = isArray(collection) ? arrayFilter : baseFilter; + predicate = getCallback(predicate, thisArg, 3); + return func(collection, predicate); + } + var find = createFind(baseEach); + var findLast = createFind(baseEachRight, true); + function findWhere(collection, source) { + return find(collection, baseMatches(source)); + } + var forEach = createForEach(arrayEach, baseEach); + var forEachRight = createForEach(arrayEachRight, baseEachRight); + var groupBy = createAggregator(function(result, value, key) { + if (hasOwnProperty.call(result, key)) { + result[key].push(value); + } else { + result[key] = [ value ]; + } + }); + function includes(collection, target, fromIndex, guard) { + var length = collection ? getLength(collection) : 0; + if (!isLength(length)) { + collection = values(collection); + length = collection.length; + } + if (typeof fromIndex != "number" || guard && isIterateeCall(target, fromIndex, guard)) { + fromIndex = 0; + } else { + fromIndex = fromIndex < 0 ? nativeMax(length + fromIndex, 0) : fromIndex || 0; + } + return typeof collection == "string" || !isArray(collection) && isString(collection) ? fromIndex <= length && collection.indexOf(target, fromIndex) > -1 : !!length && getIndexOf(collection, target, fromIndex) > -1; + } + var indexBy = createAggregator(function(result, value, key) { + result[key] = value; + }); + var invoke = restParam(function(collection, path, args) { + var index = -1, isFunc = typeof path == "function", isProp = isKey(path), result = isArrayLike(collection) ? Array(collection.length) : []; + baseEach(collection, function(value) { + var func = isFunc ? path : isProp && value != null ? value[path] : undefined; + result[++index] = func ? func.apply(value, args) : invokePath(value, path, args); + }); + return result; + }); + function map(collection, iteratee, thisArg) { + var func = isArray(collection) ? arrayMap : baseMap; + iteratee = getCallback(iteratee, thisArg, 3); + return func(collection, iteratee); + } + var partition = createAggregator(function(result, value, key) { + result[key ? 0 : 1].push(value); + }, function() { + return [ [], [] ]; + }); + function pluck(collection, path) { + return map(collection, property(path)); + } + var reduce = createReduce(arrayReduce, baseEach); + var reduceRight = createReduce(arrayReduceRight, baseEachRight); + function reject(collection, predicate, thisArg) { + var func = isArray(collection) ? arrayFilter : baseFilter; + predicate = getCallback(predicate, thisArg, 3); + return func(collection, function(value, index, collection) { + return !predicate(value, index, collection); + }); + } + function sample(collection, n, guard) { + if (guard ? isIterateeCall(collection, n, guard) : n == null) { + collection = toIterable(collection); + var length = collection.length; + return length > 0 ? collection[baseRandom(0, length - 1)] : undefined; + } + var index = -1, result = toArray(collection), length = result.length, lastIndex = length - 1; + n = nativeMin(n < 0 ? 0 : +n || 0, length); + while (++index < n) { + var rand = baseRandom(index, lastIndex), value = result[rand]; + result[rand] = result[index]; + result[index] = value; + } + result.length = n; + return result; + } + function shuffle(collection) { + return sample(collection, POSITIVE_INFINITY); + } + function size(collection) { + var length = collection ? getLength(collection) : 0; + return isLength(length) ? length : keys(collection).length; + } + function some(collection, predicate, thisArg) { + var func = isArray(collection) ? arraySome : baseSome; + if (thisArg && isIterateeCall(collection, predicate, thisArg)) { + predicate = undefined; + } + if (typeof predicate != "function" || thisArg !== undefined) { + predicate = getCallback(predicate, thisArg, 3); + } + return func(collection, predicate); + } + function sortBy(collection, iteratee, thisArg) { + if (collection == null) { + return []; + } + if (thisArg && isIterateeCall(collection, iteratee, thisArg)) { + iteratee = undefined; + } + var index = -1; + iteratee = getCallback(iteratee, thisArg, 3); + var result = baseMap(collection, function(value, key, collection) { + return { + criteria: iteratee(value, key, collection), + index: ++index, + value: value + }; + }); + return baseSortBy(result, compareAscending); + } + var sortByAll = restParam(function(collection, iteratees) { + if (collection == null) { + return []; + } + var guard = iteratees[2]; + if (guard && isIterateeCall(iteratees[0], iteratees[1], guard)) { + iteratees.length = 1; + } + return baseSortByOrder(collection, baseFlatten(iteratees), []); + }); + function sortByOrder(collection, iteratees, orders, guard) { + if (collection == null) { + return []; + } + if (guard && isIterateeCall(iteratees, orders, guard)) { + orders = undefined; + } + if (!isArray(iteratees)) { + iteratees = iteratees == null ? [] : [ iteratees ]; + } + if (!isArray(orders)) { + orders = orders == null ? [] : [ orders ]; + } + return baseSortByOrder(collection, iteratees, orders); + } + function where(collection, source) { + return filter(collection, baseMatches(source)); + } + var now = nativeNow || function() { + return new Date().getTime(); + }; + function after(n, func) { + if (typeof func != "function") { + if (typeof n == "function") { + var temp = n; + n = func; + func = temp; + } else { + throw new TypeError(FUNC_ERROR_TEXT); + } + } + n = nativeIsFinite(n = +n) ? n : 0; + return function() { + if (--n < 1) { + return func.apply(this, arguments); + } + }; + } + function ary(func, n, guard) { + if (guard && isIterateeCall(func, n, guard)) { + n = undefined; + } + n = func && n == null ? func.length : nativeMax(+n || 0, 0); + return createWrapper(func, ARY_FLAG, undefined, undefined, undefined, undefined, n); + } + function before(n, func) { + var result; + if (typeof func != "function") { + if (typeof n == "function") { + var temp = n; + n = func; + func = temp; + } else { + throw new TypeError(FUNC_ERROR_TEXT); + } + } + return function() { + if (--n > 0) { + result = func.apply(this, arguments); + } + if (n <= 1) { + func = undefined; + } + return result; + }; + } + var bind = restParam(function(func, thisArg, partials) { + var bitmask = BIND_FLAG; + if (partials.length) { + var holders = replaceHolders(partials, bind.placeholder); + bitmask |= PARTIAL_FLAG; + } + return createWrapper(func, bitmask, thisArg, partials, holders); + }); + var bindAll = restParam(function(object, methodNames) { + methodNames = methodNames.length ? baseFlatten(methodNames) : functions(object); + var index = -1, length = methodNames.length; + while (++index < length) { + var key = methodNames[index]; + object[key] = createWrapper(object[key], BIND_FLAG, object); + } + return object; + }); + var bindKey = restParam(function(object, key, partials) { + var bitmask = BIND_FLAG | BIND_KEY_FLAG; + if (partials.length) { + var holders = replaceHolders(partials, bindKey.placeholder); + bitmask |= PARTIAL_FLAG; + } + return createWrapper(key, bitmask, object, partials, holders); + }); + var curry = createCurry(CURRY_FLAG); + var curryRight = createCurry(CURRY_RIGHT_FLAG); + function debounce(func, wait, options) { + var args, maxTimeoutId, result, stamp, thisArg, timeoutId, trailingCall, lastCalled = 0, maxWait = false, trailing = true; + if (typeof func != "function") { + throw new TypeError(FUNC_ERROR_TEXT); + } + wait = wait < 0 ? 0 : +wait || 0; + if (options === true) { + var leading = true; + trailing = false; + } else if (isObject(options)) { + leading = !!options.leading; + maxWait = "maxWait" in options && nativeMax(+options.maxWait || 0, wait); + trailing = "trailing" in options ? !!options.trailing : trailing; + } + function cancel() { + if (timeoutId) { + clearTimeout(timeoutId); + } + if (maxTimeoutId) { + clearTimeout(maxTimeoutId); + } + lastCalled = 0; + maxTimeoutId = timeoutId = trailingCall = undefined; + } + function complete(isCalled, id) { + if (id) { + clearTimeout(id); + } + maxTimeoutId = timeoutId = trailingCall = undefined; + if (isCalled) { + lastCalled = now(); + result = func.apply(thisArg, args); + if (!timeoutId && !maxTimeoutId) { + args = thisArg = undefined; + } + } + } + function delayed() { + var remaining = wait - (now() - stamp); + if (remaining <= 0 || remaining > wait) { + complete(trailingCall, maxTimeoutId); + } else { + timeoutId = setTimeout(delayed, remaining); + } + } + function maxDelayed() { + complete(trailing, timeoutId); + } + function debounced() { + args = arguments; + stamp = now(); + thisArg = this; + trailingCall = trailing && (timeoutId || !leading); + if (maxWait === false) { + var leadingCall = leading && !timeoutId; + } else { + if (!maxTimeoutId && !leading) { + lastCalled = stamp; + } + var remaining = maxWait - (stamp - lastCalled), isCalled = remaining <= 0 || remaining > maxWait; + if (isCalled) { + if (maxTimeoutId) { + maxTimeoutId = clearTimeout(maxTimeoutId); + } + lastCalled = stamp; + result = func.apply(thisArg, args); + } else if (!maxTimeoutId) { + maxTimeoutId = setTimeout(maxDelayed, remaining); + } + } + if (isCalled && timeoutId) { + timeoutId = clearTimeout(timeoutId); + } else if (!timeoutId && wait !== maxWait) { + timeoutId = setTimeout(delayed, wait); + } + if (leadingCall) { + isCalled = true; + result = func.apply(thisArg, args); + } + if (isCalled && !timeoutId && !maxTimeoutId) { + args = thisArg = undefined; + } + return result; + } + debounced.cancel = cancel; + return debounced; + } + var defer = restParam(function(func, args) { + return baseDelay(func, 1, args); + }); + var delay = restParam(function(func, wait, args) { + return baseDelay(func, wait, args); + }); + var flow = createFlow(); + var flowRight = createFlow(true); + function memoize(func, resolver) { + if (typeof func != "function" || resolver && typeof resolver != "function") { + throw new TypeError(FUNC_ERROR_TEXT); + } + var memoized = function() { + var args = arguments, key = resolver ? resolver.apply(this, args) : args[0], cache = memoized.cache; + if (cache.has(key)) { + return cache.get(key); + } + var result = func.apply(this, args); + memoized.cache = cache.set(key, result); + return result; + }; + memoized.cache = new memoize.Cache(); + return memoized; + } + var modArgs = restParam(function(func, transforms) { + transforms = baseFlatten(transforms); + if (typeof func != "function" || !arrayEvery(transforms, baseIsFunction)) { + throw new TypeError(FUNC_ERROR_TEXT); + } + var length = transforms.length; + return restParam(function(args) { + var index = nativeMin(args.length, length); + while (index--) { + args[index] = transforms[index](args[index]); + } + return func.apply(this, args); + }); + }); + function negate(predicate) { + if (typeof predicate != "function") { + throw new TypeError(FUNC_ERROR_TEXT); + } + return function() { + return !predicate.apply(this, arguments); + }; + } + function once(func) { + return before(2, func); + } + var partial = createPartial(PARTIAL_FLAG); + var partialRight = createPartial(PARTIAL_RIGHT_FLAG); + var rearg = restParam(function(func, indexes) { + return createWrapper(func, REARG_FLAG, undefined, undefined, undefined, baseFlatten(indexes)); + }); + function restParam(func, start) { + if (typeof func != "function") { + throw new TypeError(FUNC_ERROR_TEXT); + } + start = nativeMax(start === undefined ? func.length - 1 : +start || 0, 0); + return function() { + var args = arguments, index = -1, length = nativeMax(args.length - start, 0), rest = Array(length); + while (++index < length) { + rest[index] = args[start + index]; + } + switch (start) { + case 0: + return func.call(this, rest); + + case 1: + return func.call(this, args[0], rest); + + case 2: + return func.call(this, args[0], args[1], rest); + } + var otherArgs = Array(start + 1); + index = -1; + while (++index < start) { + otherArgs[index] = args[index]; + } + otherArgs[start] = rest; + return func.apply(this, otherArgs); + }; + } + function spread(func) { + if (typeof func != "function") { + throw new TypeError(FUNC_ERROR_TEXT); + } + return function(array) { + return func.apply(this, array); + }; + } + function throttle(func, wait, options) { + var leading = true, trailing = true; + if (typeof func != "function") { + throw new TypeError(FUNC_ERROR_TEXT); + } + if (options === false) { + leading = false; + } else if (isObject(options)) { + leading = "leading" in options ? !!options.leading : leading; + trailing = "trailing" in options ? !!options.trailing : trailing; + } + return debounce(func, wait, { + leading: leading, + maxWait: +wait, + trailing: trailing + }); + } + function wrap(value, wrapper) { + wrapper = wrapper == null ? identity : wrapper; + return createWrapper(wrapper, PARTIAL_FLAG, undefined, [ value ], []); + } + function clone(value, isDeep, customizer, thisArg) { + if (isDeep && typeof isDeep != "boolean" && isIterateeCall(value, isDeep, customizer)) { + isDeep = false; + } else if (typeof isDeep == "function") { + thisArg = customizer; + customizer = isDeep; + isDeep = false; + } + return typeof customizer == "function" ? baseClone(value, isDeep, bindCallback(customizer, thisArg, 3)) : baseClone(value, isDeep); + } + function cloneDeep(value, customizer, thisArg) { + return typeof customizer == "function" ? baseClone(value, true, bindCallback(customizer, thisArg, 3)) : baseClone(value, true); + } + function gt(value, other) { + return value > other; + } + function gte(value, other) { + return value >= other; + } + function isArguments(value) { + return isObjectLike(value) && isArrayLike(value) && hasOwnProperty.call(value, "callee") && !propertyIsEnumerable.call(value, "callee"); + } + var isArray = nativeIsArray || function(value) { + return isObjectLike(value) && isLength(value.length) && objToString.call(value) == arrayTag; + }; + function isBoolean(value) { + return value === true || value === false || isObjectLike(value) && objToString.call(value) == boolTag; + } + function isDate(value) { + return isObjectLike(value) && objToString.call(value) == dateTag; + } + function isElement(value) { + return !!value && value.nodeType === 1 && isObjectLike(value) && !isPlainObject(value); + } + function isEmpty(value) { + if (value == null) { + return true; + } + if (isArrayLike(value) && (isArray(value) || isString(value) || isArguments(value) || isObjectLike(value) && isFunction(value.splice))) { + return !value.length; + } + return !keys(value).length; + } + function isEqual(value, other, customizer, thisArg) { + customizer = typeof customizer == "function" ? bindCallback(customizer, thisArg, 3) : undefined; + var result = customizer ? customizer(value, other) : undefined; + return result === undefined ? baseIsEqual(value, other, customizer) : !!result; + } + function isError(value) { + return isObjectLike(value) && typeof value.message == "string" && objToString.call(value) == errorTag; + } + function isFinite(value) { + return typeof value == "number" && nativeIsFinite(value); + } + function isFunction(value) { + return isObject(value) && objToString.call(value) == funcTag; + } + function isObject(value) { + var type = typeof value; + return !!value && (type == "object" || type == "function"); + } + function isMatch(object, source, customizer, thisArg) { + customizer = typeof customizer == "function" ? bindCallback(customizer, thisArg, 3) : undefined; + return baseIsMatch(object, getMatchData(source), customizer); + } + function isNaN(value) { + return isNumber(value) && value != +value; + } + function isNative(value) { + if (value == null) { + return false; + } + if (isFunction(value)) { + return reIsNative.test(fnToString.call(value)); + } + return isObjectLike(value) && reIsHostCtor.test(value); + } + function isNull(value) { + return value === null; + } + function isNumber(value) { + return typeof value == "number" || isObjectLike(value) && objToString.call(value) == numberTag; + } + function isPlainObject(value) { + var Ctor; + if (!(isObjectLike(value) && objToString.call(value) == objectTag && !isArguments(value)) || !hasOwnProperty.call(value, "constructor") && (Ctor = value.constructor, + typeof Ctor == "function" && !(Ctor instanceof Ctor))) { + return false; + } + var result; + baseForIn(value, function(subValue, key) { + result = key; + }); + return result === undefined || hasOwnProperty.call(value, result); + } + function isRegExp(value) { + return isObject(value) && objToString.call(value) == regexpTag; + } + function isString(value) { + return typeof value == "string" || isObjectLike(value) && objToString.call(value) == stringTag; + } + function isTypedArray(value) { + return isObjectLike(value) && isLength(value.length) && !!typedArrayTags[objToString.call(value)]; + } + function isUndefined(value) { + return value === undefined; + } + function lt(value, other) { + return value < other; + } + function lte(value, other) { + return value <= other; + } + function toArray(value) { + var length = value ? getLength(value) : 0; + if (!isLength(length)) { + return values(value); + } + if (!length) { + return []; + } + return arrayCopy(value); + } + function toPlainObject(value) { + return baseCopy(value, keysIn(value)); + } + var merge = createAssigner(baseMerge); + var assign = createAssigner(function(object, source, customizer) { + return customizer ? assignWith(object, source, customizer) : baseAssign(object, source); + }); + function create(prototype, properties, guard) { + var result = baseCreate(prototype); + if (guard && isIterateeCall(prototype, properties, guard)) { + properties = undefined; + } + return properties ? baseAssign(result, properties) : result; + } + var defaults = createDefaults(assign, assignDefaults); + var defaultsDeep = createDefaults(merge, mergeDefaults); + var findKey = createFindKey(baseForOwn); + var findLastKey = createFindKey(baseForOwnRight); + var forIn = createForIn(baseFor); + var forInRight = createForIn(baseForRight); + var forOwn = createForOwn(baseForOwn); + var forOwnRight = createForOwn(baseForOwnRight); + function functions(object) { + return baseFunctions(object, keysIn(object)); + } + function get(object, path, defaultValue) { + var result = object == null ? undefined : baseGet(object, toPath(path), path + ""); + return result === undefined ? defaultValue : result; + } + function has(object, path) { + if (object == null) { + return false; + } + var result = hasOwnProperty.call(object, path); + if (!result && !isKey(path)) { + path = toPath(path); + object = path.length == 1 ? object : baseGet(object, baseSlice(path, 0, -1)); + if (object == null) { + return false; + } + path = last(path); + result = hasOwnProperty.call(object, path); + } + return result || isLength(object.length) && isIndex(path, object.length) && (isArray(object) || isArguments(object)); + } + function invert(object, multiValue, guard) { + if (guard && isIterateeCall(object, multiValue, guard)) { + multiValue = undefined; + } + var index = -1, props = keys(object), length = props.length, result = {}; + while (++index < length) { + var key = props[index], value = object[key]; + if (multiValue) { + if (hasOwnProperty.call(result, value)) { + result[value].push(key); + } else { + result[value] = [ key ]; + } + } else { + result[value] = key; + } + } + return result; + } + var keys = !nativeKeys ? shimKeys : function(object) { + var Ctor = object == null ? undefined : object.constructor; + if (typeof Ctor == "function" && Ctor.prototype === object || typeof object != "function" && isArrayLike(object)) { + return shimKeys(object); + } + return isObject(object) ? nativeKeys(object) : []; + }; + function keysIn(object) { + if (object == null) { + return []; + } + if (!isObject(object)) { + object = Object(object); + } + var length = object.length; + length = length && isLength(length) && (isArray(object) || isArguments(object)) && length || 0; + var Ctor = object.constructor, index = -1, isProto = typeof Ctor == "function" && Ctor.prototype === object, result = Array(length), skipIndexes = length > 0; + while (++index < length) { + result[index] = index + ""; + } + for (var key in object) { + if (!(skipIndexes && isIndex(key, length)) && !(key == "constructor" && (isProto || !hasOwnProperty.call(object, key)))) { + result.push(key); + } + } + return result; + } + var mapKeys = createObjectMapper(true); + var mapValues = createObjectMapper(); + var omit = restParam(function(object, props) { + if (object == null) { + return {}; + } + if (typeof props[0] != "function") { + var props = arrayMap(baseFlatten(props), String); + return pickByArray(object, baseDifference(keysIn(object), props)); + } + var predicate = bindCallback(props[0], props[1], 3); + return pickByCallback(object, function(value, key, object) { + return !predicate(value, key, object); + }); + }); + function pairs(object) { + object = toObject(object); + var index = -1, props = keys(object), length = props.length, result = Array(length); + while (++index < length) { + var key = props[index]; + result[index] = [ key, object[key] ]; + } + return result; + } + var pick = restParam(function(object, props) { + if (object == null) { + return {}; + } + return typeof props[0] == "function" ? pickByCallback(object, bindCallback(props[0], props[1], 3)) : pickByArray(object, baseFlatten(props)); + }); + function result(object, path, defaultValue) { + var result = object == null ? undefined : object[path]; + if (result === undefined) { + if (object != null && !isKey(path, object)) { + path = toPath(path); + object = path.length == 1 ? object : baseGet(object, baseSlice(path, 0, -1)); + result = object == null ? undefined : object[last(path)]; + } + result = result === undefined ? defaultValue : result; + } + return isFunction(result) ? result.call(object) : result; + } + function set(object, path, value) { + if (object == null) { + return object; + } + var pathKey = path + ""; + path = object[pathKey] != null || isKey(path, object) ? [ pathKey ] : toPath(path); + var index = -1, length = path.length, lastIndex = length - 1, nested = object; + while (nested != null && ++index < length) { + var key = path[index]; + if (isObject(nested)) { + if (index == lastIndex) { + nested[key] = value; + } else if (nested[key] == null) { + nested[key] = isIndex(path[index + 1]) ? [] : {}; + } + } + nested = nested[key]; + } + return object; + } + function transform(object, iteratee, accumulator, thisArg) { + var isArr = isArray(object) || isTypedArray(object); + iteratee = getCallback(iteratee, thisArg, 4); + if (accumulator == null) { + if (isArr || isObject(object)) { + var Ctor = object.constructor; + if (isArr) { + accumulator = isArray(object) ? new Ctor() : []; + } else { + accumulator = baseCreate(isFunction(Ctor) ? Ctor.prototype : undefined); + } + } else { + accumulator = {}; + } + } + (isArr ? arrayEach : baseForOwn)(object, function(value, index, object) { + return iteratee(accumulator, value, index, object); + }); + return accumulator; + } + function values(object) { + return baseValues(object, keys(object)); + } + function valuesIn(object) { + return baseValues(object, keysIn(object)); + } + function inRange(value, start, end) { + start = +start || 0; + if (end === undefined) { + end = start; + start = 0; + } else { + end = +end || 0; + } + return value >= nativeMin(start, end) && value < nativeMax(start, end); + } + function random(min, max, floating) { + if (floating && isIterateeCall(min, max, floating)) { + max = floating = undefined; + } + var noMin = min == null, noMax = max == null; + if (floating == null) { + if (noMax && typeof min == "boolean") { + floating = min; + min = 1; + } else if (typeof max == "boolean") { + floating = max; + noMax = true; + } + } + if (noMin && noMax) { + max = 1; + noMax = false; + } + min = +min || 0; + if (noMax) { + max = min; + min = 0; + } else { + max = +max || 0; + } + if (floating || min % 1 || max % 1) { + var rand = nativeRandom(); + return nativeMin(min + rand * (max - min + parseFloat("1e-" + ((rand + "").length - 1))), max); + } + return baseRandom(min, max); + } + var camelCase = createCompounder(function(result, word, index) { + word = word.toLowerCase(); + return result + (index ? word.charAt(0).toUpperCase() + word.slice(1) : word); + }); + function capitalize(string) { + string = baseToString(string); + return string && string.charAt(0).toUpperCase() + string.slice(1); + } + function deburr(string) { + string = baseToString(string); + return string && string.replace(reLatin1, deburrLetter).replace(reComboMark, ""); + } + function endsWith(string, target, position) { + string = baseToString(string); + target = target + ""; + var length = string.length; + position = position === undefined ? length : nativeMin(position < 0 ? 0 : +position || 0, length); + position -= target.length; + return position >= 0 && string.indexOf(target, position) == position; + } + function escape(string) { + string = baseToString(string); + return string && reHasUnescapedHtml.test(string) ? string.replace(reUnescapedHtml, escapeHtmlChar) : string; + } + function escapeRegExp(string) { + string = baseToString(string); + return string && reHasRegExpChars.test(string) ? string.replace(reRegExpChars, escapeRegExpChar) : string || "(?:)"; + } + var kebabCase = createCompounder(function(result, word, index) { + return result + (index ? "-" : "") + word.toLowerCase(); + }); + function pad(string, length, chars) { + string = baseToString(string); + length = +length; + var strLength = string.length; + if (strLength >= length || !nativeIsFinite(length)) { + return string; + } + var mid = (length - strLength) / 2, leftLength = nativeFloor(mid), rightLength = nativeCeil(mid); + chars = createPadding("", rightLength, chars); + return chars.slice(0, leftLength) + string + chars; + } + var padLeft = createPadDir(); + var padRight = createPadDir(true); + function parseInt(string, radix, guard) { + if (guard ? isIterateeCall(string, radix, guard) : radix == null) { + radix = 0; + } else if (radix) { + radix = +radix; + } + string = trim(string); + return nativeParseInt(string, radix || (reHasHexPrefix.test(string) ? 16 : 10)); + } + function repeat(string, n) { + var result = ""; + string = baseToString(string); + n = +n; + if (n < 1 || !string || !nativeIsFinite(n)) { + return result; + } + do { + if (n % 2) { + result += string; + } + n = nativeFloor(n / 2); + string += string; + } while (n); + return result; + } + var snakeCase = createCompounder(function(result, word, index) { + return result + (index ? "_" : "") + word.toLowerCase(); + }); + var startCase = createCompounder(function(result, word, index) { + return result + (index ? " " : "") + (word.charAt(0).toUpperCase() + word.slice(1)); + }); + function startsWith(string, target, position) { + string = baseToString(string); + position = position == null ? 0 : nativeMin(position < 0 ? 0 : +position || 0, string.length); + return string.lastIndexOf(target, position) == position; + } + function template(string, options, otherOptions) { + var settings = lodash.templateSettings; + if (otherOptions && isIterateeCall(string, options, otherOptions)) { + options = otherOptions = undefined; + } + string = baseToString(string); + options = assignWith(baseAssign({}, otherOptions || options), settings, assignOwnDefaults); + var imports = assignWith(baseAssign({}, options.imports), settings.imports, assignOwnDefaults), importsKeys = keys(imports), importsValues = baseValues(imports, importsKeys); + var isEscaping, isEvaluating, index = 0, interpolate = options.interpolate || reNoMatch, source = "__p += '"; + var reDelimiters = RegExp((options.escape || reNoMatch).source + "|" + interpolate.source + "|" + (interpolate === reInterpolate ? reEsTemplate : reNoMatch).source + "|" + (options.evaluate || reNoMatch).source + "|$", "g"); + var sourceURL = "//# sourceURL=" + ("sourceURL" in options ? options.sourceURL : "lodash.templateSources[" + ++templateCounter + "]") + "\n"; + string.replace(reDelimiters, function(match, escapeValue, interpolateValue, esTemplateValue, evaluateValue, offset) { + interpolateValue || (interpolateValue = esTemplateValue); + source += string.slice(index, offset).replace(reUnescapedString, escapeStringChar); + if (escapeValue) { + isEscaping = true; + source += "' +\n__e(" + escapeValue + ") +\n'"; + } + if (evaluateValue) { + isEvaluating = true; + source += "';\n" + evaluateValue + ";\n__p += '"; + } + if (interpolateValue) { + source += "' +\n((__t = (" + interpolateValue + ")) == null ? '' : __t) +\n'"; + } + index = offset + match.length; + return match; + }); + source += "';\n"; + var variable = options.variable; + if (!variable) { + source = "with (obj) {\n" + source + "\n}\n"; + } + source = (isEvaluating ? source.replace(reEmptyStringLeading, "") : source).replace(reEmptyStringMiddle, "$1").replace(reEmptyStringTrailing, "$1;"); + source = "function(" + (variable || "obj") + ") {\n" + (variable ? "" : "obj || (obj = {});\n") + "var __t, __p = ''" + (isEscaping ? ", __e = _.escape" : "") + (isEvaluating ? ", __j = Array.prototype.join;\n" + "function print() { __p += __j.call(arguments, '') }\n" : ";\n") + source + "return __p\n}"; + var result = attempt(function() { + return Function(importsKeys, sourceURL + "return " + source).apply(undefined, importsValues); + }); + result.source = source; + if (isError(result)) { + throw result; + } + return result; + } + function trim(string, chars, guard) { + var value = string; + string = baseToString(string); + if (!string) { + return string; + } + if (guard ? isIterateeCall(value, chars, guard) : chars == null) { + return string.slice(trimmedLeftIndex(string), trimmedRightIndex(string) + 1); + } + chars = chars + ""; + return string.slice(charsLeftIndex(string, chars), charsRightIndex(string, chars) + 1); + } + function trimLeft(string, chars, guard) { + var value = string; + string = baseToString(string); + if (!string) { + return string; + } + if (guard ? isIterateeCall(value, chars, guard) : chars == null) { + return string.slice(trimmedLeftIndex(string)); + } + return string.slice(charsLeftIndex(string, chars + "")); + } + function trimRight(string, chars, guard) { + var value = string; + string = baseToString(string); + if (!string) { + return string; + } + if (guard ? isIterateeCall(value, chars, guard) : chars == null) { + return string.slice(0, trimmedRightIndex(string) + 1); + } + return string.slice(0, charsRightIndex(string, chars + "") + 1); + } + function trunc(string, options, guard) { + if (guard && isIterateeCall(string, options, guard)) { + options = undefined; + } + var length = DEFAULT_TRUNC_LENGTH, omission = DEFAULT_TRUNC_OMISSION; + if (options != null) { + if (isObject(options)) { + var separator = "separator" in options ? options.separator : separator; + length = "length" in options ? +options.length || 0 : length; + omission = "omission" in options ? baseToString(options.omission) : omission; + } else { + length = +options || 0; + } + } + string = baseToString(string); + if (length >= string.length) { + return string; + } + var end = length - omission.length; + if (end < 1) { + return omission; + } + var result = string.slice(0, end); + if (separator == null) { + return result + omission; + } + if (isRegExp(separator)) { + if (string.slice(end).search(separator)) { + var match, newEnd, substring = string.slice(0, end); + if (!separator.global) { + separator = RegExp(separator.source, (reFlags.exec(separator) || "") + "g"); + } + separator.lastIndex = 0; + while (match = separator.exec(substring)) { + newEnd = match.index; + } + result = result.slice(0, newEnd == null ? end : newEnd); + } + } else if (string.indexOf(separator, end) != end) { + var index = result.lastIndexOf(separator); + if (index > -1) { + result = result.slice(0, index); + } + } + return result + omission; + } + function unescape(string) { + string = baseToString(string); + return string && reHasEscapedHtml.test(string) ? string.replace(reEscapedHtml, unescapeHtmlChar) : string; + } + function words(string, pattern, guard) { + if (guard && isIterateeCall(string, pattern, guard)) { + pattern = undefined; + } + string = baseToString(string); + return string.match(pattern || reWords) || []; + } + var attempt = restParam(function(func, args) { + try { + return func.apply(undefined, args); + } catch (e) { + return isError(e) ? e : new Error(e); + } + }); + function callback(func, thisArg, guard) { + if (guard && isIterateeCall(func, thisArg, guard)) { + thisArg = undefined; + } + return isObjectLike(func) ? matches(func) : baseCallback(func, thisArg); + } + function constant(value) { + return function() { + return value; + }; + } + function identity(value) { + return value; + } + function matches(source) { + return baseMatches(baseClone(source, true)); + } + function matchesProperty(path, srcValue) { + return baseMatchesProperty(path, baseClone(srcValue, true)); + } + var method = restParam(function(path, args) { + return function(object) { + return invokePath(object, path, args); + }; + }); + var methodOf = restParam(function(object, args) { + return function(path) { + return invokePath(object, path, args); + }; + }); + function mixin(object, source, options) { + if (options == null) { + var isObj = isObject(source), props = isObj ? keys(source) : undefined, methodNames = props && props.length ? baseFunctions(source, props) : undefined; + if (!(methodNames ? methodNames.length : isObj)) { + methodNames = false; + options = source; + source = object; + object = this; + } + } + if (!methodNames) { + methodNames = baseFunctions(source, keys(source)); + } + var chain = true, index = -1, isFunc = isFunction(object), length = methodNames.length; + if (options === false) { + chain = false; + } else if (isObject(options) && "chain" in options) { + chain = options.chain; + } + while (++index < length) { + var methodName = methodNames[index], func = source[methodName]; + object[methodName] = func; + if (isFunc) { + object.prototype[methodName] = function(func) { + return function() { + var chainAll = this.__chain__; + if (chain || chainAll) { + var result = object(this.__wrapped__), actions = result.__actions__ = arrayCopy(this.__actions__); + actions.push({ + func: func, + args: arguments, + thisArg: object + }); + result.__chain__ = chainAll; + return result; + } + return func.apply(object, arrayPush([ this.value() ], arguments)); + }; + }(func); + } + } + return object; + } + function noConflict() { + root._ = oldDash; + return this; + } + function noop() {} + function property(path) { + return isKey(path) ? baseProperty(path) : basePropertyDeep(path); + } + function propertyOf(object) { + return function(path) { + return baseGet(object, toPath(path), path + ""); + }; + } + function range(start, end, step) { + if (step && isIterateeCall(start, end, step)) { + end = step = undefined; + } + start = +start || 0; + step = step == null ? 1 : +step || 0; + if (end == null) { + end = start; + start = 0; + } else { + end = +end || 0; + } + var index = -1, length = nativeMax(nativeCeil((end - start) / (step || 1)), 0), result = Array(length); + while (++index < length) { + result[index] = start; + start += step; + } + return result; + } + function times(n, iteratee, thisArg) { + n = nativeFloor(n); + if (n < 1 || !nativeIsFinite(n)) { + return []; + } + var index = -1, result = Array(nativeMin(n, MAX_ARRAY_LENGTH)); + iteratee = bindCallback(iteratee, thisArg, 1); + while (++index < n) { + if (index < MAX_ARRAY_LENGTH) { + result[index] = iteratee(index); + } else { + iteratee(index); + } + } + return result; + } + function uniqueId(prefix) { + var id = ++idCounter; + return baseToString(prefix) + id; + } + function add(augend, addend) { + return (+augend || 0) + (+addend || 0); + } + var ceil = createRound("ceil"); + var floor = createRound("floor"); + var max = createExtremum(gt, NEGATIVE_INFINITY); + var min = createExtremum(lt, POSITIVE_INFINITY); + var round = createRound("round"); + function sum(collection, iteratee, thisArg) { + if (thisArg && isIterateeCall(collection, iteratee, thisArg)) { + iteratee = undefined; + } + iteratee = getCallback(iteratee, thisArg, 3); + return iteratee.length == 1 ? arraySum(isArray(collection) ? collection : toIterable(collection), iteratee) : baseSum(collection, iteratee); + } + lodash.prototype = baseLodash.prototype; + LodashWrapper.prototype = baseCreate(baseLodash.prototype); + LodashWrapper.prototype.constructor = LodashWrapper; + LazyWrapper.prototype = baseCreate(baseLodash.prototype); + LazyWrapper.prototype.constructor = LazyWrapper; + MapCache.prototype["delete"] = mapDelete; + MapCache.prototype.get = mapGet; + MapCache.prototype.has = mapHas; + MapCache.prototype.set = mapSet; + SetCache.prototype.push = cachePush; + memoize.Cache = MapCache; + lodash.after = after; + lodash.ary = ary; + lodash.assign = assign; + lodash.at = at; + lodash.before = before; + lodash.bind = bind; + lodash.bindAll = bindAll; + lodash.bindKey = bindKey; + lodash.callback = callback; + lodash.chain = chain; + lodash.chunk = chunk; + lodash.compact = compact; + lodash.constant = constant; + lodash.countBy = countBy; + lodash.create = create; + lodash.curry = curry; + lodash.curryRight = curryRight; + lodash.debounce = debounce; + lodash.defaults = defaults; + lodash.defaultsDeep = defaultsDeep; + lodash.defer = defer; + lodash.delay = delay; + lodash.difference = difference; + lodash.drop = drop; + lodash.dropRight = dropRight; + lodash.dropRightWhile = dropRightWhile; + lodash.dropWhile = dropWhile; + lodash.fill = fill; + lodash.filter = filter; + lodash.flatten = flatten; + lodash.flattenDeep = flattenDeep; + lodash.flow = flow; + lodash.flowRight = flowRight; + lodash.forEach = forEach; + lodash.forEachRight = forEachRight; + lodash.forIn = forIn; + lodash.forInRight = forInRight; + lodash.forOwn = forOwn; + lodash.forOwnRight = forOwnRight; + lodash.functions = functions; + lodash.groupBy = groupBy; + lodash.indexBy = indexBy; + lodash.initial = initial; + lodash.intersection = intersection; + lodash.invert = invert; + lodash.invoke = invoke; + lodash.keys = keys; + lodash.keysIn = keysIn; + lodash.map = map; + lodash.mapKeys = mapKeys; + lodash.mapValues = mapValues; + lodash.matches = matches; + lodash.matchesProperty = matchesProperty; + lodash.memoize = memoize; + lodash.merge = merge; + lodash.method = method; + lodash.methodOf = methodOf; + lodash.mixin = mixin; + lodash.modArgs = modArgs; + lodash.negate = negate; + lodash.omit = omit; + lodash.once = once; + lodash.pairs = pairs; + lodash.partial = partial; + lodash.partialRight = partialRight; + lodash.partition = partition; + lodash.pick = pick; + lodash.pluck = pluck; + lodash.property = property; + lodash.propertyOf = propertyOf; + lodash.pull = pull; + lodash.pullAt = pullAt; + lodash.range = range; + lodash.rearg = rearg; + lodash.reject = reject; + lodash.remove = remove; + lodash.rest = rest; + lodash.restParam = restParam; + lodash.set = set; + lodash.shuffle = shuffle; + lodash.slice = slice; + lodash.sortBy = sortBy; + lodash.sortByAll = sortByAll; + lodash.sortByOrder = sortByOrder; + lodash.spread = spread; + lodash.take = take; + lodash.takeRight = takeRight; + lodash.takeRightWhile = takeRightWhile; + lodash.takeWhile = takeWhile; + lodash.tap = tap; + lodash.throttle = throttle; + lodash.thru = thru; + lodash.times = times; + lodash.toArray = toArray; + lodash.toPlainObject = toPlainObject; + lodash.transform = transform; + lodash.union = union; + lodash.uniq = uniq; + lodash.unzip = unzip; + lodash.unzipWith = unzipWith; + lodash.values = values; + lodash.valuesIn = valuesIn; + lodash.where = where; + lodash.without = without; + lodash.wrap = wrap; + lodash.xor = xor; + lodash.zip = zip; + lodash.zipObject = zipObject; + lodash.zipWith = zipWith; + lodash.backflow = flowRight; + lodash.collect = map; + lodash.compose = flowRight; + lodash.each = forEach; + lodash.eachRight = forEachRight; + lodash.extend = assign; + lodash.iteratee = callback; + lodash.methods = functions; + lodash.object = zipObject; + lodash.select = filter; + lodash.tail = rest; + lodash.unique = uniq; + mixin(lodash, lodash); + lodash.add = add; + lodash.attempt = attempt; + lodash.camelCase = camelCase; + lodash.capitalize = capitalize; + lodash.ceil = ceil; + lodash.clone = clone; + lodash.cloneDeep = cloneDeep; + lodash.deburr = deburr; + lodash.endsWith = endsWith; + lodash.escape = escape; + lodash.escapeRegExp = escapeRegExp; + lodash.every = every; + lodash.find = find; + lodash.findIndex = findIndex; + lodash.findKey = findKey; + lodash.findLast = findLast; + lodash.findLastIndex = findLastIndex; + lodash.findLastKey = findLastKey; + lodash.findWhere = findWhere; + lodash.first = first; + lodash.floor = floor; + lodash.get = get; + lodash.gt = gt; + lodash.gte = gte; + lodash.has = has; + lodash.identity = identity; + lodash.includes = includes; + lodash.indexOf = indexOf; + lodash.inRange = inRange; + lodash.isArguments = isArguments; + lodash.isArray = isArray; + lodash.isBoolean = isBoolean; + lodash.isDate = isDate; + lodash.isElement = isElement; + lodash.isEmpty = isEmpty; + lodash.isEqual = isEqual; + lodash.isError = isError; + lodash.isFinite = isFinite; + lodash.isFunction = isFunction; + lodash.isMatch = isMatch; + lodash.isNaN = isNaN; + lodash.isNative = isNative; + lodash.isNull = isNull; + lodash.isNumber = isNumber; + lodash.isObject = isObject; + lodash.isPlainObject = isPlainObject; + lodash.isRegExp = isRegExp; + lodash.isString = isString; + lodash.isTypedArray = isTypedArray; + lodash.isUndefined = isUndefined; + lodash.kebabCase = kebabCase; + lodash.last = last; + lodash.lastIndexOf = lastIndexOf; + lodash.lt = lt; + lodash.lte = lte; + lodash.max = max; + lodash.min = min; + lodash.noConflict = noConflict; + lodash.noop = noop; + lodash.now = now; + lodash.pad = pad; + lodash.padLeft = padLeft; + lodash.padRight = padRight; + lodash.parseInt = parseInt; + lodash.random = random; + lodash.reduce = reduce; + lodash.reduceRight = reduceRight; + lodash.repeat = repeat; + lodash.result = result; + lodash.round = round; + lodash.runInContext = runInContext; + lodash.size = size; + lodash.snakeCase = snakeCase; + lodash.some = some; + lodash.sortedIndex = sortedIndex; + lodash.sortedLastIndex = sortedLastIndex; + lodash.startCase = startCase; + lodash.startsWith = startsWith; + lodash.sum = sum; + lodash.template = template; + lodash.trim = trim; + lodash.trimLeft = trimLeft; + lodash.trimRight = trimRight; + lodash.trunc = trunc; + lodash.unescape = unescape; + lodash.uniqueId = uniqueId; + lodash.words = words; + lodash.all = every; + lodash.any = some; + lodash.contains = includes; + lodash.eq = isEqual; + lodash.detect = find; + lodash.foldl = reduce; + lodash.foldr = reduceRight; + lodash.head = first; + lodash.include = includes; + lodash.inject = reduce; + mixin(lodash, function() { + var source = {}; + baseForOwn(lodash, function(func, methodName) { + if (!lodash.prototype[methodName]) { + source[methodName] = func; + } + }); + return source; + }(), false); + lodash.sample = sample; + lodash.prototype.sample = function(n) { + if (!this.__chain__ && n == null) { + return sample(this.value()); + } + return this.thru(function(value) { + return sample(value, n); + }); + }; + lodash.VERSION = VERSION; + arrayEach([ "bind", "bindKey", "curry", "curryRight", "partial", "partialRight" ], function(methodName) { + lodash[methodName].placeholder = lodash; + }); + arrayEach([ "drop", "take" ], function(methodName, index) { + LazyWrapper.prototype[methodName] = function(n) { + var filtered = this.__filtered__; + if (filtered && !index) { + return new LazyWrapper(this); + } + n = n == null ? 1 : nativeMax(nativeFloor(n) || 0, 0); + var result = this.clone(); + if (filtered) { + result.__takeCount__ = nativeMin(result.__takeCount__, n); + } else { + result.__views__.push({ + size: n, + type: methodName + (result.__dir__ < 0 ? "Right" : "") + }); + } + return result; + }; + LazyWrapper.prototype[methodName + "Right"] = function(n) { + return this.reverse()[methodName](n).reverse(); + }; + }); + arrayEach([ "filter", "map", "takeWhile" ], function(methodName, index) { + var type = index + 1, isFilter = type != LAZY_MAP_FLAG; + LazyWrapper.prototype[methodName] = function(iteratee, thisArg) { + var result = this.clone(); + result.__iteratees__.push({ + iteratee: getCallback(iteratee, thisArg, 1), + type: type + }); + result.__filtered__ = result.__filtered__ || isFilter; + return result; + }; + }); + arrayEach([ "first", "last" ], function(methodName, index) { + var takeName = "take" + (index ? "Right" : ""); + LazyWrapper.prototype[methodName] = function() { + return this[takeName](1).value()[0]; + }; + }); + arrayEach([ "initial", "rest" ], function(methodName, index) { + var dropName = "drop" + (index ? "" : "Right"); + LazyWrapper.prototype[methodName] = function() { + return this.__filtered__ ? new LazyWrapper(this) : this[dropName](1); + }; + }); + arrayEach([ "pluck", "where" ], function(methodName, index) { + var operationName = index ? "filter" : "map", createCallback = index ? baseMatches : property; + LazyWrapper.prototype[methodName] = function(value) { + return this[operationName](createCallback(value)); + }; + }); + LazyWrapper.prototype.compact = function() { + return this.filter(identity); + }; + LazyWrapper.prototype.reject = function(predicate, thisArg) { + predicate = getCallback(predicate, thisArg, 1); + return this.filter(function(value) { + return !predicate(value); + }); + }; + LazyWrapper.prototype.slice = function(start, end) { + start = start == null ? 0 : +start || 0; + var result = this; + if (result.__filtered__ && (start > 0 || end < 0)) { + return new LazyWrapper(result); + } + if (start < 0) { + result = result.takeRight(-start); + } else if (start) { + result = result.drop(start); + } + if (end !== undefined) { + end = +end || 0; + result = end < 0 ? result.dropRight(-end) : result.take(end - start); + } + return result; + }; + LazyWrapper.prototype.takeRightWhile = function(predicate, thisArg) { + return this.reverse().takeWhile(predicate, thisArg).reverse(); + }; + LazyWrapper.prototype.toArray = function() { + return this.take(POSITIVE_INFINITY); + }; + baseForOwn(LazyWrapper.prototype, function(func, methodName) { + var checkIteratee = /^(?:filter|map|reject)|While$/.test(methodName), retUnwrapped = /^(?:first|last)$/.test(methodName), lodashFunc = lodash[retUnwrapped ? "take" + (methodName == "last" ? "Right" : "") : methodName]; + if (!lodashFunc) { + return; + } + lodash.prototype[methodName] = function() { + var args = retUnwrapped ? [ 1 ] : arguments, chainAll = this.__chain__, value = this.__wrapped__, isHybrid = !!this.__actions__.length, isLazy = value instanceof LazyWrapper, iteratee = args[0], useLazy = isLazy || isArray(value); + if (useLazy && checkIteratee && typeof iteratee == "function" && iteratee.length != 1) { + isLazy = useLazy = false; + } + var interceptor = function(value) { + return retUnwrapped && chainAll ? lodashFunc(value, 1)[0] : lodashFunc.apply(undefined, arrayPush([ value ], args)); + }; + var action = { + func: thru, + args: [ interceptor ], + thisArg: undefined + }, onlyLazy = isLazy && !isHybrid; + if (retUnwrapped && !chainAll) { + if (onlyLazy) { + value = value.clone(); + value.__actions__.push(action); + return func.call(value); + } + return lodashFunc.call(undefined, this.value())[0]; + } + if (!retUnwrapped && useLazy) { + value = onlyLazy ? value : new LazyWrapper(this); + var result = func.apply(value, args); + result.__actions__.push(action); + return new LodashWrapper(result, chainAll); + } + return this.thru(interceptor); + }; + }); + arrayEach([ "join", "pop", "push", "replace", "shift", "sort", "splice", "split", "unshift" ], function(methodName) { + var func = (/^(?:replace|split)$/.test(methodName) ? stringProto : arrayProto)[methodName], chainName = /^(?:push|sort|unshift)$/.test(methodName) ? "tap" : "thru", retUnwrapped = /^(?:join|pop|replace|shift)$/.test(methodName); + lodash.prototype[methodName] = function() { + var args = arguments; + if (retUnwrapped && !this.__chain__) { + return func.apply(this.value(), args); + } + return this[chainName](function(value) { + return func.apply(value, args); + }); + }; + }); + baseForOwn(LazyWrapper.prototype, function(func, methodName) { + var lodashFunc = lodash[methodName]; + if (lodashFunc) { + var key = lodashFunc.name + "", names = realNames[key] || (realNames[key] = []); + names.push({ + name: methodName, + func: lodashFunc + }); + } + }); + realNames[createHybridWrapper(undefined, BIND_KEY_FLAG).name] = [ { + name: "wrapper", + func: undefined + } ]; + LazyWrapper.prototype.clone = lazyClone; + LazyWrapper.prototype.reverse = lazyReverse; + LazyWrapper.prototype.value = lazyValue; + lodash.prototype.chain = wrapperChain; + lodash.prototype.commit = wrapperCommit; + lodash.prototype.concat = wrapperConcat; + lodash.prototype.plant = wrapperPlant; + lodash.prototype.reverse = wrapperReverse; + lodash.prototype.toString = wrapperToString; + lodash.prototype.run = lodash.prototype.toJSON = lodash.prototype.valueOf = lodash.prototype.value = wrapperValue; + lodash.prototype.collect = lodash.prototype.map; + lodash.prototype.head = lodash.prototype.first; + lodash.prototype.select = lodash.prototype.filter; + lodash.prototype.tail = lodash.prototype.rest; + return lodash; + } + var _ = runInContext(); + if (typeof define == "function" && typeof define.amd == "object" && define.amd) { + root._ = _; + define(function() { + return _; + }); + } else if (freeExports && freeModule) { + if (moduleExports) { + (freeModule.exports = _)._ = _; + } else { + freeExports._ = _; + } + } else { + root._ = _; + } +}).call(this); + +(function(window, document, undefined) { + "use strict"; + function minErr(module, ErrorConstructor) { + ErrorConstructor = ErrorConstructor || Error; + return function() { + var SKIP_INDEXES = 2; + var templateArgs = arguments, code = templateArgs[0], message = "[" + (module ? module + ":" : "") + code + "] ", template = templateArgs[1], paramPrefix, i; + message += template.replace(/\{\d+\}/g, function(match) { + var index = +match.slice(1, -1), shiftedIndex = index + SKIP_INDEXES; + if (shiftedIndex < templateArgs.length) { + return toDebugString(templateArgs[shiftedIndex]); + } + return match; + }); + message += "\nhttp://errors.angularjs.org/1.4.7/" + (module ? module + "/" : "") + code; + for (i = SKIP_INDEXES, paramPrefix = "?"; i < templateArgs.length; i++, paramPrefix = "&") { + message += paramPrefix + "p" + (i - SKIP_INDEXES) + "=" + encodeURIComponent(toDebugString(templateArgs[i])); + } + return new ErrorConstructor(message); + }; + } + var REGEX_STRING_REGEXP = /^\/(.+)\/([a-z]*)$/; + var VALIDITY_STATE_PROPERTY = "validity"; + var lowercase = function(string) { + return isString(string) ? string.toLowerCase() : string; + }; + var hasOwnProperty = Object.prototype.hasOwnProperty; + var uppercase = function(string) { + return isString(string) ? string.toUpperCase() : string; + }; + var manualLowercase = function(s) { + return isString(s) ? s.replace(/[A-Z]/g, function(ch) { + return String.fromCharCode(ch.charCodeAt(0) | 32); + }) : s; + }; + var manualUppercase = function(s) { + return isString(s) ? s.replace(/[a-z]/g, function(ch) { + return String.fromCharCode(ch.charCodeAt(0) & ~32); + }) : s; + }; + if ("i" !== "I".toLowerCase()) { + lowercase = manualLowercase; + uppercase = manualUppercase; + } + var msie, jqLite, jQuery, slice = [].slice, splice = [].splice, push = [].push, toString = Object.prototype.toString, getPrototypeOf = Object.getPrototypeOf, ngMinErr = minErr("ng"), angular = window.angular || (window.angular = {}), angularModule, uid = 0; + msie = document.documentMode; + function isArrayLike(obj) { + if (obj == null || isWindow(obj)) { + return false; + } + var length = "length" in Object(obj) && obj.length; + if (obj.nodeType === NODE_TYPE_ELEMENT && length) { + return true; + } + return isString(obj) || isArray(obj) || length === 0 || typeof length === "number" && length > 0 && length - 1 in obj; + } + function forEach(obj, iterator, context) { + var key, length; + if (obj) { + if (isFunction(obj)) { + for (key in obj) { + if (key != "prototype" && key != "length" && key != "name" && (!obj.hasOwnProperty || obj.hasOwnProperty(key))) { + iterator.call(context, obj[key], key, obj); + } + } + } else if (isArray(obj) || isArrayLike(obj)) { + var isPrimitive = typeof obj !== "object"; + for (key = 0, length = obj.length; key < length; key++) { + if (isPrimitive || key in obj) { + iterator.call(context, obj[key], key, obj); + } + } + } else if (obj.forEach && obj.forEach !== forEach) { + obj.forEach(iterator, context, obj); + } else if (isBlankObject(obj)) { + for (key in obj) { + iterator.call(context, obj[key], key, obj); + } + } else if (typeof obj.hasOwnProperty === "function") { + for (key in obj) { + if (obj.hasOwnProperty(key)) { + iterator.call(context, obj[key], key, obj); + } + } + } else { + for (key in obj) { + if (hasOwnProperty.call(obj, key)) { + iterator.call(context, obj[key], key, obj); + } + } + } + } + return obj; + } + function forEachSorted(obj, iterator, context) { + var keys = Object.keys(obj).sort(); + for (var i = 0; i < keys.length; i++) { + iterator.call(context, obj[keys[i]], keys[i]); + } + return keys; + } + function reverseParams(iteratorFn) { + return function(value, key) { + iteratorFn(key, value); + }; + } + function nextUid() { + return ++uid; + } + function setHashKey(obj, h) { + if (h) { + obj.$$hashKey = h; + } else { + delete obj.$$hashKey; + } + } + function baseExtend(dst, objs, deep) { + var h = dst.$$hashKey; + for (var i = 0, ii = objs.length; i < ii; ++i) { + var obj = objs[i]; + if (!isObject(obj) && !isFunction(obj)) continue; + var keys = Object.keys(obj); + for (var j = 0, jj = keys.length; j < jj; j++) { + var key = keys[j]; + var src = obj[key]; + if (deep && isObject(src)) { + if (isDate(src)) { + dst[key] = new Date(src.valueOf()); + } else if (isRegExp(src)) { + dst[key] = new RegExp(src); + } else { + if (!isObject(dst[key])) dst[key] = isArray(src) ? [] : {}; + baseExtend(dst[key], [ src ], true); + } + } else { + dst[key] = src; + } + } + } + setHashKey(dst, h); + return dst; + } + function extend(dst) { + return baseExtend(dst, slice.call(arguments, 1), false); + } + function merge(dst) { + return baseExtend(dst, slice.call(arguments, 1), true); + } + function toInt(str) { + return parseInt(str, 10); + } + function inherit(parent, extra) { + return extend(Object.create(parent), extra); + } + function noop() {} + noop.$inject = []; + function identity($) { + return $; + } + identity.$inject = []; + function valueFn(value) { + return function() { + return value; + }; + } + function hasCustomToString(obj) { + return isFunction(obj.toString) && obj.toString !== Object.prototype.toString; + } + function isUndefined(value) { + return typeof value === "undefined"; + } + function isDefined(value) { + return typeof value !== "undefined"; + } + function isObject(value) { + return value !== null && typeof value === "object"; + } + function isBlankObject(value) { + return value !== null && typeof value === "object" && !getPrototypeOf(value); + } + function isString(value) { + return typeof value === "string"; + } + function isNumber(value) { + return typeof value === "number"; + } + function isDate(value) { + return toString.call(value) === "[object Date]"; + } + var isArray = Array.isArray; + function isFunction(value) { + return typeof value === "function"; + } + function isRegExp(value) { + return toString.call(value) === "[object RegExp]"; + } + function isWindow(obj) { + return obj && obj.window === obj; + } + function isScope(obj) { + return obj && obj.$evalAsync && obj.$watch; + } + function isFile(obj) { + return toString.call(obj) === "[object File]"; + } + function isFormData(obj) { + return toString.call(obj) === "[object FormData]"; + } + function isBlob(obj) { + return toString.call(obj) === "[object Blob]"; + } + function isBoolean(value) { + return typeof value === "boolean"; + } + function isPromiseLike(obj) { + return obj && isFunction(obj.then); + } + var TYPED_ARRAY_REGEXP = /^\[object (Uint8(Clamped)?)|(Uint16)|(Uint32)|(Int8)|(Int16)|(Int32)|(Float(32)|(64))Array\]$/; + function isTypedArray(value) { + return TYPED_ARRAY_REGEXP.test(toString.call(value)); + } + var trim = function(value) { + return isString(value) ? value.trim() : value; + }; + var escapeForRegexp = function(s) { + return s.replace(/([-()\[\]{}+?*.$\^|,:#= 0) { + array.splice(index, 1); + } + return index; + } + function copy(source, destination, stackSource, stackDest) { + if (isWindow(source) || isScope(source)) { + throw ngMinErr("cpws", "Can't copy! Making copies of Window or Scope instances is not supported."); + } + if (isTypedArray(destination)) { + throw ngMinErr("cpta", "Can't copy! TypedArray destination cannot be mutated."); + } + if (!destination) { + destination = source; + if (isObject(source)) { + var index; + if (stackSource && (index = stackSource.indexOf(source)) !== -1) { + return stackDest[index]; + } + if (isArray(source)) { + return copy(source, [], stackSource, stackDest); + } else if (isTypedArray(source)) { + destination = new source.constructor(source); + } else if (isDate(source)) { + destination = new Date(source.getTime()); + } else if (isRegExp(source)) { + destination = new RegExp(source.source, source.toString().match(/[^\/]*$/)[0]); + destination.lastIndex = source.lastIndex; + } else if (isFunction(source.cloneNode)) { + destination = source.cloneNode(true); + } else { + var emptyObject = Object.create(getPrototypeOf(source)); + return copy(source, emptyObject, stackSource, stackDest); + } + if (stackDest) { + stackSource.push(source); + stackDest.push(destination); + } + } + } else { + if (source === destination) throw ngMinErr("cpi", "Can't copy! Source and destination are identical."); + stackSource = stackSource || []; + stackDest = stackDest || []; + if (isObject(source)) { + stackSource.push(source); + stackDest.push(destination); + } + var result, key; + if (isArray(source)) { + destination.length = 0; + for (var i = 0; i < source.length; i++) { + destination.push(copy(source[i], null, stackSource, stackDest)); + } + } else { + var h = destination.$$hashKey; + if (isArray(destination)) { + destination.length = 0; + } else { + forEach(destination, function(value, key) { + delete destination[key]; + }); + } + if (isBlankObject(source)) { + for (key in source) { + destination[key] = copy(source[key], null, stackSource, stackDest); + } + } else if (source && typeof source.hasOwnProperty === "function") { + for (key in source) { + if (source.hasOwnProperty(key)) { + destination[key] = copy(source[key], null, stackSource, stackDest); + } + } + } else { + for (key in source) { + if (hasOwnProperty.call(source, key)) { + destination[key] = copy(source[key], null, stackSource, stackDest); + } + } + } + setHashKey(destination, h); + } + } + return destination; + } + function shallowCopy(src, dst) { + if (isArray(src)) { + dst = dst || []; + for (var i = 0, ii = src.length; i < ii; i++) { + dst[i] = src[i]; + } + } else if (isObject(src)) { + dst = dst || {}; + for (var key in src) { + if (!(key.charAt(0) === "$" && key.charAt(1) === "$")) { + dst[key] = src[key]; + } + } + } + return dst || src; + } + function equals(o1, o2) { + if (o1 === o2) return true; + if (o1 === null || o2 === null) return false; + if (o1 !== o1 && o2 !== o2) return true; + var t1 = typeof o1, t2 = typeof o2, length, key, keySet; + if (t1 == t2) { + if (t1 == "object") { + if (isArray(o1)) { + if (!isArray(o2)) return false; + if ((length = o1.length) == o2.length) { + for (key = 0; key < length; key++) { + if (!equals(o1[key], o2[key])) return false; + } + return true; + } + } else if (isDate(o1)) { + if (!isDate(o2)) return false; + return equals(o1.getTime(), o2.getTime()); + } else if (isRegExp(o1)) { + return isRegExp(o2) ? o1.toString() == o2.toString() : false; + } else { + if (isScope(o1) || isScope(o2) || isWindow(o1) || isWindow(o2) || isArray(o2) || isDate(o2) || isRegExp(o2)) return false; + keySet = createMap(); + for (key in o1) { + if (key.charAt(0) === "$" || isFunction(o1[key])) continue; + if (!equals(o1[key], o2[key])) return false; + keySet[key] = true; + } + for (key in o2) { + if (!(key in keySet) && key.charAt(0) !== "$" && isDefined(o2[key]) && !isFunction(o2[key])) return false; + } + return true; + } + } + } + return false; + } + var csp = function() { + if (!isDefined(csp.rules)) { + var ngCspElement = document.querySelector("[ng-csp]") || document.querySelector("[data-ng-csp]"); + if (ngCspElement) { + var ngCspAttribute = ngCspElement.getAttribute("ng-csp") || ngCspElement.getAttribute("data-ng-csp"); + csp.rules = { + noUnsafeEval: !ngCspAttribute || ngCspAttribute.indexOf("no-unsafe-eval") !== -1, + noInlineStyle: !ngCspAttribute || ngCspAttribute.indexOf("no-inline-style") !== -1 + }; + } else { + csp.rules = { + noUnsafeEval: noUnsafeEval(), + noInlineStyle: false + }; + } + } + return csp.rules; + function noUnsafeEval() { + try { + new Function(""); + return false; + } catch (e) { + return true; + } + } + }; + var jq = function() { + if (isDefined(jq.name_)) return jq.name_; + var el; + var i, ii = ngAttrPrefixes.length, prefix, name; + for (i = 0; i < ii; ++i) { + prefix = ngAttrPrefixes[i]; + if (el = document.querySelector("[" + prefix.replace(":", "\\:") + "jq]")) { + name = el.getAttribute(prefix + "jq"); + break; + } + } + return jq.name_ = name; + }; + function concat(array1, array2, index) { + return array1.concat(slice.call(array2, index)); + } + function sliceArgs(args, startIndex) { + return slice.call(args, startIndex || 0); + } + function bind(self, fn) { + var curryArgs = arguments.length > 2 ? sliceArgs(arguments, 2) : []; + if (isFunction(fn) && !(fn instanceof RegExp)) { + return curryArgs.length ? function() { + return arguments.length ? fn.apply(self, concat(curryArgs, arguments, 0)) : fn.apply(self, curryArgs); + } : function() { + return arguments.length ? fn.apply(self, arguments) : fn.call(self); + }; + } else { + return fn; + } + } + function toJsonReplacer(key, value) { + var val = value; + if (typeof key === "string" && key.charAt(0) === "$" && key.charAt(1) === "$") { + val = undefined; + } else if (isWindow(value)) { + val = "$WINDOW"; + } else if (value && document === value) { + val = "$DOCUMENT"; + } else if (isScope(value)) { + val = "$SCOPE"; + } + return val; + } + function toJson(obj, pretty) { + if (typeof obj === "undefined") return undefined; + if (!isNumber(pretty)) { + pretty = pretty ? 2 : null; + } + return JSON.stringify(obj, toJsonReplacer, pretty); + } + function fromJson(json) { + return isString(json) ? JSON.parse(json) : json; + } + function timezoneToOffset(timezone, fallback) { + var requestedTimezoneOffset = Date.parse("Jan 01, 1970 00:00:00 " + timezone) / 6e4; + return isNaN(requestedTimezoneOffset) ? fallback : requestedTimezoneOffset; + } + function addDateMinutes(date, minutes) { + date = new Date(date.getTime()); + date.setMinutes(date.getMinutes() + minutes); + return date; + } + function convertTimezoneToLocal(date, timezone, reverse) { + reverse = reverse ? -1 : 1; + var timezoneOffset = timezoneToOffset(timezone, date.getTimezoneOffset()); + return addDateMinutes(date, reverse * (timezoneOffset - date.getTimezoneOffset())); + } + function startingTag(element) { + element = jqLite(element).clone(); + try { + element.empty(); + } catch (e) {} + var elemHtml = jqLite("
").append(element).html(); + try { + return element[0].nodeType === NODE_TYPE_TEXT ? lowercase(elemHtml) : elemHtml.match(/^(<[^>]+>)/)[1].replace(/^<([\w\-]+)/, function(match, nodeName) { + return "<" + lowercase(nodeName); + }); + } catch (e) { + return lowercase(elemHtml); + } + } + function tryDecodeURIComponent(value) { + try { + return decodeURIComponent(value); + } catch (e) {} + } + function parseKeyValue(keyValue) { + var obj = {}; + forEach((keyValue || "").split("&"), function(keyValue) { + var splitPoint, key, val; + if (keyValue) { + key = keyValue = keyValue.replace(/\+/g, "%20"); + splitPoint = keyValue.indexOf("="); + if (splitPoint !== -1) { + key = keyValue.substring(0, splitPoint); + val = keyValue.substring(splitPoint + 1); + } + key = tryDecodeURIComponent(key); + if (isDefined(key)) { + val = isDefined(val) ? tryDecodeURIComponent(val) : true; + if (!hasOwnProperty.call(obj, key)) { + obj[key] = val; + } else if (isArray(obj[key])) { + obj[key].push(val); + } else { + obj[key] = [ obj[key], val ]; + } + } + } + }); + return obj; + } + function toKeyValue(obj) { + var parts = []; + forEach(obj, function(value, key) { + if (isArray(value)) { + forEach(value, function(arrayValue) { + parts.push(encodeUriQuery(key, true) + (arrayValue === true ? "" : "=" + encodeUriQuery(arrayValue, true))); + }); + } else { + parts.push(encodeUriQuery(key, true) + (value === true ? "" : "=" + encodeUriQuery(value, true))); + } + }); + return parts.length ? parts.join("&") : ""; + } + function encodeUriSegment(val) { + return encodeUriQuery(val, true).replace(/%26/gi, "&").replace(/%3D/gi, "=").replace(/%2B/gi, "+"); + } + function encodeUriQuery(val, pctEncodeSpaces) { + return encodeURIComponent(val).replace(/%40/gi, "@").replace(/%3A/gi, ":").replace(/%24/g, "$").replace(/%2C/gi, ",").replace(/%3B/gi, ";").replace(/%20/g, pctEncodeSpaces ? "%20" : "+"); + } + var ngAttrPrefixes = [ "ng-", "data-ng-", "ng:", "x-ng-" ]; + function getNgAttribute(element, ngAttr) { + var attr, i, ii = ngAttrPrefixes.length; + for (i = 0; i < ii; ++i) { + attr = ngAttrPrefixes[i] + ngAttr; + if (isString(attr = element.getAttribute(attr))) { + return attr; + } + } + return null; + } + function angularInit(element, bootstrap) { + var appElement, module, config = {}; + forEach(ngAttrPrefixes, function(prefix) { + var name = prefix + "app"; + if (!appElement && element.hasAttribute && element.hasAttribute(name)) { + appElement = element; + module = element.getAttribute(name); + } + }); + forEach(ngAttrPrefixes, function(prefix) { + var name = prefix + "app"; + var candidate; + if (!appElement && (candidate = element.querySelector("[" + name.replace(":", "\\:") + "]"))) { + appElement = candidate; + module = candidate.getAttribute(name); + } + }); + if (appElement) { + config.strictDi = getNgAttribute(appElement, "strict-di") !== null; + bootstrap(appElement, module ? [ module ] : [], config); + } + } + function bootstrap(element, modules, config) { + if (!isObject(config)) config = {}; + var defaultConfig = { + strictDi: false + }; + config = extend(defaultConfig, config); + var doBootstrap = function() { + element = jqLite(element); + if (element.injector()) { + var tag = element[0] === document ? "document" : startingTag(element); + throw ngMinErr("btstrpd", "App Already Bootstrapped with this Element '{0}'", tag.replace(//, ">")); + } + modules = modules || []; + modules.unshift([ "$provide", function($provide) { + $provide.value("$rootElement", element); + } ]); + if (config.debugInfoEnabled) { + modules.push([ "$compileProvider", function($compileProvider) { + $compileProvider.debugInfoEnabled(true); + } ]); + } + modules.unshift("ng"); + var injector = createInjector(modules, config.strictDi); + injector.invoke([ "$rootScope", "$rootElement", "$compile", "$injector", function bootstrapApply(scope, element, compile, injector) { + scope.$apply(function() { + element.data("$injector", injector); + compile(element)(scope); + }); + } ]); + return injector; + }; + var NG_ENABLE_DEBUG_INFO = /^NG_ENABLE_DEBUG_INFO!/; + var NG_DEFER_BOOTSTRAP = /^NG_DEFER_BOOTSTRAP!/; + if (window && NG_ENABLE_DEBUG_INFO.test(window.name)) { + config.debugInfoEnabled = true; + window.name = window.name.replace(NG_ENABLE_DEBUG_INFO, ""); + } + if (window && !NG_DEFER_BOOTSTRAP.test(window.name)) { + return doBootstrap(); + } + window.name = window.name.replace(NG_DEFER_BOOTSTRAP, ""); + angular.resumeBootstrap = function(extraModules) { + forEach(extraModules, function(module) { + modules.push(module); + }); + return doBootstrap(); + }; + if (isFunction(angular.resumeDeferredBootstrap)) { + angular.resumeDeferredBootstrap(); + } + } + function reloadWithDebugInfo() { + window.name = "NG_ENABLE_DEBUG_INFO!" + window.name; + window.location.reload(); + } + function getTestability(rootElement) { + var injector = angular.element(rootElement).injector(); + if (!injector) { + throw ngMinErr("test", "no injector found for element argument to getTestability"); + } + return injector.get("$$testability"); + } + var SNAKE_CASE_REGEXP = /[A-Z]/g; + function snake_case(name, separator) { + separator = separator || "_"; + return name.replace(SNAKE_CASE_REGEXP, function(letter, pos) { + return (pos ? separator : "") + letter.toLowerCase(); + }); + } + var bindJQueryFired = false; + var skipDestroyOnNextJQueryCleanData; + function bindJQuery() { + var originalCleanData; + if (bindJQueryFired) { + return; + } + var jqName = jq(); + jQuery = isUndefined(jqName) ? window.jQuery : !jqName ? undefined : window[jqName]; + if (jQuery && jQuery.fn.on) { + jqLite = jQuery; + extend(jQuery.fn, { + scope: JQLitePrototype.scope, + isolateScope: JQLitePrototype.isolateScope, + controller: JQLitePrototype.controller, + injector: JQLitePrototype.injector, + inheritedData: JQLitePrototype.inheritedData + }); + originalCleanData = jQuery.cleanData; + jQuery.cleanData = function(elems) { + var events; + if (!skipDestroyOnNextJQueryCleanData) { + for (var i = 0, elem; (elem = elems[i]) != null; i++) { + events = jQuery._data(elem, "events"); + if (events && events.$destroy) { + jQuery(elem).triggerHandler("$destroy"); + } + } + } else { + skipDestroyOnNextJQueryCleanData = false; + } + originalCleanData(elems); + }; + } else { + jqLite = JQLite; + } + angular.element = jqLite; + bindJQueryFired = true; + } + function assertArg(arg, name, reason) { + if (!arg) { + throw ngMinErr("areq", "Argument '{0}' is {1}", name || "?", reason || "required"); + } + return arg; + } + function assertArgFn(arg, name, acceptArrayAnnotation) { + if (acceptArrayAnnotation && isArray(arg)) { + arg = arg[arg.length - 1]; + } + assertArg(isFunction(arg), name, "not a function, got " + (arg && typeof arg === "object" ? arg.constructor.name || "Object" : typeof arg)); + return arg; + } + function assertNotHasOwnProperty(name, context) { + if (name === "hasOwnProperty") { + throw ngMinErr("badname", "hasOwnProperty is not a valid {0} name", context); + } + } + function getter(obj, path, bindFnToScope) { + if (!path) return obj; + var keys = path.split("."); + var key; + var lastInstance = obj; + var len = keys.length; + for (var i = 0; i < len; i++) { + key = keys[i]; + if (obj) { + obj = (lastInstance = obj)[key]; + } + } + if (!bindFnToScope && isFunction(obj)) { + return bind(lastInstance, obj); + } + return obj; + } + function getBlockNodes(nodes) { + var node = nodes[0]; + var endNode = nodes[nodes.length - 1]; + var blockNodes; + for (var i = 1; node !== endNode && (node = node.nextSibling); i++) { + if (blockNodes || nodes[i] !== node) { + if (!blockNodes) { + blockNodes = jqLite(slice.call(nodes, 0, i)); + } + blockNodes.push(node); + } + } + return blockNodes || nodes; + } + function createMap() { + return Object.create(null); + } + var NODE_TYPE_ELEMENT = 1; + var NODE_TYPE_ATTRIBUTE = 2; + var NODE_TYPE_TEXT = 3; + var NODE_TYPE_COMMENT = 8; + var NODE_TYPE_DOCUMENT = 9; + var NODE_TYPE_DOCUMENT_FRAGMENT = 11; + function setupModuleLoader(window) { + var $injectorMinErr = minErr("$injector"); + var ngMinErr = minErr("ng"); + function ensure(obj, name, factory) { + return obj[name] || (obj[name] = factory()); + } + var angular = ensure(window, "angular", Object); + angular.$$minErr = angular.$$minErr || minErr; + return ensure(angular, "module", function() { + var modules = {}; + return function module(name, requires, configFn) { + var assertNotHasOwnProperty = function(name, context) { + if (name === "hasOwnProperty") { + throw ngMinErr("badname", "hasOwnProperty is not a valid {0} name", context); + } + }; + assertNotHasOwnProperty(name, "module"); + if (requires && modules.hasOwnProperty(name)) { + modules[name] = null; + } + return ensure(modules, name, function() { + if (!requires) { + throw $injectorMinErr("nomod", "Module '{0}' is not available! You either misspelled " + "the module name or forgot to load it. If registering a module ensure that you " + "specify the dependencies as the second argument.", name); + } + var invokeQueue = []; + var configBlocks = []; + var runBlocks = []; + var config = invokeLater("$injector", "invoke", "push", configBlocks); + var moduleInstance = { + _invokeQueue: invokeQueue, + _configBlocks: configBlocks, + _runBlocks: runBlocks, + requires: requires, + name: name, + provider: invokeLaterAndSetModuleName("$provide", "provider"), + factory: invokeLaterAndSetModuleName("$provide", "factory"), + service: invokeLaterAndSetModuleName("$provide", "service"), + value: invokeLater("$provide", "value"), + constant: invokeLater("$provide", "constant", "unshift"), + decorator: invokeLaterAndSetModuleName("$provide", "decorator"), + animation: invokeLaterAndSetModuleName("$animateProvider", "register"), + filter: invokeLaterAndSetModuleName("$filterProvider", "register"), + controller: invokeLaterAndSetModuleName("$controllerProvider", "register"), + directive: invokeLaterAndSetModuleName("$compileProvider", "directive"), + config: config, + run: function(block) { + runBlocks.push(block); + return this; + } + }; + if (configFn) { + config(configFn); + } + return moduleInstance; + function invokeLater(provider, method, insertMethod, queue) { + if (!queue) queue = invokeQueue; + return function() { + queue[insertMethod || "push"]([ provider, method, arguments ]); + return moduleInstance; + }; + } + function invokeLaterAndSetModuleName(provider, method) { + return function(recipeName, factoryFunction) { + if (factoryFunction && isFunction(factoryFunction)) factoryFunction.$$moduleName = name; + invokeQueue.push([ provider, method, arguments ]); + return moduleInstance; + }; + } + }); + }; + }); + } + function serializeObject(obj) { var seen = []; return JSON.stringify(obj, function(key, val) { val = toJsonReplacer(key, val); @@ -7264,11 +10151,11 @@ return obj; } var version = { - full: "1.4.6", + full: "1.4.7", major: 1, minor: 4, - dot: 6, - codeName: "multiplicative-elevation" + dot: 7, + codeName: "dark-luminescence" }; function publishExternalAPI(angular) { extend(angular, { @@ -7377,6 +10264,7 @@ $httpParamSerializer: $HttpParamSerializerProvider, $httpParamSerializerJQLike: $HttpParamSerializerJQLikeProvider, $httpBackend: $HttpBackendProvider, + $xhrFactory: $xhrFactoryProvider, $location: $LocationProvider, $log: $LogProvider, $parse: $ParseProvider, @@ -7422,10 +10310,10 @@ return offset ? letter.toUpperCase() : letter; }).replace(MOZ_HACK_REGEXP, "Moz$1"); } - var SINGLE_TAG_REGEXP = /^<(\w+)\s*\/?>(?:<\/\1>|)$/; + var SINGLE_TAG_REGEXP = /^<([\w-]+)\s*\/?>(?:<\/\1>|)$/; var HTML_REGEXP = /<|&#?\w+;/; - var TAG_NAME_REGEXP = /<([\w:]+)/; - var XHTML_TAG_REGEXP = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi; + var TAG_NAME_REGEXP = /<([\w:-]+)/; + var XHTML_TAG_REGEXP = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:-]+)[^>]*)\/>/gi; var wrapMap = { option: [ 1, '" ], thead: [ 1, "", "
" ], @@ -8668,6 +11556,9 @@ } }; return function(element, options) { + if (options.cleanupStyles) { + options.from = options.to = null; + } if (options.from) { element.css(options.from); options.from = null; @@ -9933,7 +12824,7 @@ compile: function() { return { pre: function attrInterpolatePreLinkFn(scope, element, attr) { - var $$observers = attr.$$observers || (attr.$$observers = {}); + var $$observers = attr.$$observers || (attr.$$observers = createMap()); if (EVENT_HANDLER_ATTR_REGEXP.test(name)) { throw $compileMinErr("nodomevents", "Interpolations for HTML DOM event attributes are disallowed. Please use the " + "ng- versions (such as ng-click instead of onclick) instead."); } @@ -10596,12 +13487,16 @@ } } ]; } - function createXhr() { - return new window.XMLHttpRequest(); + function $xhrFactoryProvider() { + this.$get = function() { + return function createXhr() { + return new window.XMLHttpRequest(); + }; + }; } function $HttpBackendProvider() { - this.$get = [ "$browser", "$window", "$document", function($browser, $window, $document) { - return createHttpBackend($browser, createXhr, $browser.defer, $window.angular.callbacks, $document[0]); + this.$get = [ "$browser", "$window", "$document", "$xhrFactory", function($browser, $window, $document, $xhrFactory) { + return createHttpBackend($browser, $xhrFactory, $browser.defer, $window.angular.callbacks, $document[0]); } ]; } function createHttpBackend($browser, createXhr, $browserDefer, callbacks, rawDocument) { @@ -10619,7 +13514,7 @@ callbacks[callbackId] = noop; }); } else { - var xhr = createXhr(); + var xhr = createXhr(method, url); xhr.open(method, url, true); forEach(headers, function(value, key) { if (isDefined(value)) { @@ -11327,12 +14222,18 @@ } var $parseMinErr = minErr("$parse"); function ensureSafeMemberName(name, fullExpression) { - name = isObject(name) && name.toString ? name.toString() : name; if (name === "__defineGetter__" || name === "__defineSetter__" || name === "__lookupGetter__" || name === "__lookupSetter__" || name === "__proto__") { throw $parseMinErr("isecfld", "Attempting to access a disallowed field in Angular expressions! " + "Expression: {0}", fullExpression); } return name; } + function getStringValue(name, fullExpression) { + name = name + ""; + if (!isString(name)) { + throw $parseMinErr("iseccst", "Cannot convert object to primitive value! " + "Expression: {0}", fullExpression); + } + return name; + } function ensureSafeObject(obj, fullExpression) { if (obj) { if (obj.constructor === obj) { @@ -11359,6 +14260,13 @@ } } } + function ensureSafeAssignContext(obj, fullExpression) { + if (obj) { + if (obj === 0..constructor || obj === false.constructor || obj === "".constructor || obj === {}.constructor || obj === [].constructor || obj === Function.constructor) { + throw $parseMinErr("isecaf", "Assigning to a constructor is disallowed! Expression: {0}", fullExpression); + } + } + } var OPERATORS = createMap(); forEach("+ - * / % === !== == != < > <= >= && || ! = |".split(" "), function(operator) { OPERATORS[operator] = true; @@ -12107,7 +15015,7 @@ this.stage = "main"; this.recurse(ast); var fnString = '"' + this.USE + " " + this.STRICT + '";\n' + this.filterPrefix() + "var fn=" + this.generateFunction("fn", "s,l,a,i") + extra + this.watchFns() + "return fn;"; - var fn = new Function("$filter", "ensureSafeMemberName", "ensureSafeObject", "ensureSafeFunction", "ifDefined", "plus", "text", fnString)(this.$filter, ensureSafeMemberName, ensureSafeObject, ensureSafeFunction, ifDefined, plusFn, expression); + var fn = new Function("$filter", "ensureSafeMemberName", "ensureSafeObject", "ensureSafeFunction", "getStringValue", "ensureSafeAssignContext", "ifDefined", "plus", "text", fnString)(this.$filter, ensureSafeMemberName, ensureSafeObject, ensureSafeFunction, getStringValue, ensureSafeAssignContext, ifDefined, plusFn, expression); this.state = this.stage = undefined; fn.literal = isLiteral(ast); fn.constant = isConstant(ast); @@ -12244,6 +15152,7 @@ if (ast.computed) { right = self.nextId(); self.recurse(ast.property, right); + self.getStringValue(right); self.addEnsureSafeMemberName(right); if (create && create !== 1) { self.if_(self.not(self.computedMember(left, right)), self.lazyAssign(self.computedMember(left, right), "{}")); @@ -12329,6 +15238,7 @@ self.if_(self.notNull(left.context), function() { self.recurse(ast.right, right); self.addEnsureSafeObject(self.member(left.context, left.name, left.computed)); + self.addEnsureSafeAssignContext(left.context); expression = self.member(left.context, left.name, left.computed) + ast.operator + right; self.assign(intoId, expression); recursionFn(intoId || expression); @@ -12439,6 +15349,9 @@ addEnsureSafeFunction: function(item) { this.current().body.push(this.ensureSafeFunction(item), ";"); }, + addEnsureSafeAssignContext: function(item) { + this.current().body.push(this.ensureSafeAssignContext(item), ";"); + }, ensureSafeObject: function(item) { return "ensureSafeObject(" + item + ",text)"; }, @@ -12448,6 +15361,12 @@ ensureSafeFunction: function(item) { return "ensureSafeFunction(" + item + ",text)"; }, + getStringValue: function(item) { + this.assign(item, "getStringValue(" + item + ",text)"); + }, + ensureSafeAssignContext: function(item) { + return "ensureSafeAssignContext(" + item + ",text)"; + }, lazyRecurse: function(ast, intoId, nameId, recursionFn, create, skipWatchIdCheck) { var self = this; return function() { @@ -12615,6 +15534,7 @@ var lhs = left(scope, locals, assign, inputs); var rhs = right(scope, locals, assign, inputs); ensureSafeObject(lhs.value, self.expression); + ensureSafeAssignContext(lhs.context); lhs.context[lhs.name] = rhs; return context ? { value: rhs @@ -12872,6 +15792,7 @@ var value; if (lhs != null) { rhs = right(scope, locals, assign, inputs); + rhs = getStringValue(rhs); ensureSafeMemberName(rhs, expression); if (create && create !== 1 && lhs && !lhs[rhs]) { lhs[rhs] = {}; @@ -14554,6 +17475,7 @@ if (fractionSize > 0 && number < 1) { formatedText = number.toFixed(fractionSize); number = parseFloat(formatedText); + formatedText = formatedText.replace(DECIMAL_SEP, decimalSep); } } if (number === 0) { @@ -16571,11 +19493,11 @@ function updateOptionElement(option, element) { option.element = element; element.disabled = option.disabled; - if (option.value !== element.value) element.value = option.selectValue; if (option.label !== element.label) { element.label = option.label; element.textContent = option.label; } + if (option.value !== element.value) element.value = option.selectValue; } function addOrReuseElement(parent, current, type, templateElement) { var element; @@ -16603,7 +19525,7 @@ var emptyOption_ = emptyOption && emptyOption[0]; var unknownOption_ = unknownOption && unknownOption[0]; if (emptyOption_ || unknownOption_) { - while (current && (current === emptyOption_ || current === unknownOption_)) { + while (current && (current === emptyOption_ || current === unknownOption_ || emptyOption_ && emptyOption_.nodeType === NODE_TYPE_COMMENT)) { current = current.nextSibling; } } @@ -27136,148 +30058,1837 @@ angular.module("ui.bootstrap.typeahead", [ "ui.bootstrap.position" ]).factory("t }); } }; -} ]).filter("typeaheadHighlight", [ "$sce", "$injector", "$log", function($sce, $injector, $log) { - var isSanitizePresent; - isSanitizePresent = $injector.has("$sanitize"); - function escapeRegexp(queryToEscape) { - return queryToEscape.replace(/([.?*+^$[\]\\(){}|-])/g, "\\$1"); - } - function containsHtml(matchItem) { - return /<.*>/g.test(matchItem); - } - return function(matchItem, query) { - if (!isSanitizePresent && containsHtml(matchItem)) { - $log.warn("Unsafe use of typeahead please use ngSanitize"); +} ]).filter("typeaheadHighlight", [ "$sce", "$injector", "$log", function($sce, $injector, $log) { + var isSanitizePresent; + isSanitizePresent = $injector.has("$sanitize"); + function escapeRegexp(queryToEscape) { + return queryToEscape.replace(/([.?*+^$[\]\\(){}|-])/g, "\\$1"); + } + function containsHtml(matchItem) { + return /<.*>/g.test(matchItem); + } + return function(matchItem, query) { + if (!isSanitizePresent && containsHtml(matchItem)) { + $log.warn("Unsafe use of typeahead please use ngSanitize"); + } + matchItem = query ? ("" + matchItem).replace(new RegExp(escapeRegexp(query), "gi"), "$&") : matchItem; + if (!isSanitizePresent) { + matchItem = $sce.trustAsHtml(matchItem); + } + return matchItem; + }; +} ]); + +angular.module("template/accordion/accordion-group.html", []).run([ "$templateCache", function($templateCache) { + $templateCache.put("template/accordion/accordion-group.html", "
\n" + '
\n' + '

\n' + ' {{heading}}\n' + "

\n" + "
\n" + '
\n' + '
\n' + "
\n" + "
\n" + ""); +} ]); + +angular.module("template/accordion/accordion.html", []).run([ "$templateCache", function($templateCache) { + $templateCache.put("template/accordion/accordion.html", '
'); +} ]); + +angular.module("template/alert/alert.html", []).run([ "$templateCache", function($templateCache) { + $templateCache.put("template/alert/alert.html", "
\n" + ' \n" + "
\n" + "
\n" + ""); +} ]); + +angular.module("template/carousel/carousel.html", []).run([ "$templateCache", function($templateCache) { + $templateCache.put("template/carousel/carousel.html", '\n" + ""); +} ]); + +angular.module("template/carousel/slide.html", []).run([ "$templateCache", function($templateCache) { + $templateCache.put("template/carousel/slide.html", '
\n' + ""); +} ]); + +angular.module("template/datepicker/datepicker.html", []).run([ "$templateCache", function($templateCache) { + $templateCache.put("template/datepicker/datepicker.html", '
\n' + ' \n' + ' \n' + ' \n' + "
"); +} ]); + +angular.module("template/datepicker/day.html", []).run([ "$templateCache", function($templateCache) { + $templateCache.put("template/datepicker/day.html", '\n' + " \n" + " \n" + ' \n' + ' \n' + ' \n' + " \n" + " \n" + ' \n' + ' \n' + " \n" + " \n" + " \n" + ' \n' + ' \n' + ' \n" + " \n" + " \n" + "
{{::label.abbr}}
{{ weekNumbers[$index] }}\n' + ' \n' + "
\n" + ""); +} ]); + +angular.module("template/datepicker/month.html", []).run([ "$templateCache", function($templateCache) { + $templateCache.put("template/datepicker/month.html", '\n' + " \n" + " \n" + ' \n' + ' \n' + ' \n' + " \n" + " \n" + " \n" + ' \n' + ' \n" + " \n" + " \n" + "
\n' + ' \n' + "
\n" + ""); +} ]); + +angular.module("template/datepicker/popup.html", []).run([ "$templateCache", function($templateCache) { + $templateCache.put("template/datepicker/popup.html", '\n" + ""); +} ]); + +angular.module("template/datepicker/year.html", []).run([ "$templateCache", function($templateCache) { + $templateCache.put("template/datepicker/year.html", '\n' + " \n" + " \n" + ' \n' + ' \n' + ' \n' + " \n" + " \n" + " \n" + ' \n' + ' \n" + " \n" + " \n" + "
\n' + ' \n' + "
\n" + ""); +} ]); + +angular.module("template/modal/backdrop.html", []).run([ "$templateCache", function($templateCache) { + $templateCache.put("template/modal/backdrop.html", '\n" + ""); +} ]); + +angular.module("template/modal/window.html", []).run([ "$templateCache", function($templateCache) { + $templateCache.put("template/modal/window.html", '\n" + ""); +} ]); + +angular.module("template/pagination/pager.html", []).run([ "$templateCache", function($templateCache) { + $templateCache.put("template/pagination/pager.html", '\n" + ""); +} ]); + +angular.module("template/pagination/pagination.html", []).run([ "$templateCache", function($templateCache) { + $templateCache.put("template/pagination/pagination.html", '\n" + ""); +} ]); + +angular.module("template/tooltip/tooltip-html-popup.html", []).run([ "$templateCache", function($templateCache) { + $templateCache.put("template/tooltip/tooltip-html-popup.html", '
\n' + '
\n' + '
\n' + "
\n" + ""); +} ]); + +angular.module("template/tooltip/tooltip-html-unsafe-popup.html", []).run([ "$templateCache", function($templateCache) { + $templateCache.put("template/tooltip/tooltip-html-unsafe-popup.html", '
\n' + '
\n' + '
\n' + "
\n" + ""); +} ]); + +angular.module("template/tooltip/tooltip-popup.html", []).run([ "$templateCache", function($templateCache) { + $templateCache.put("template/tooltip/tooltip-popup.html", '
\n' + '
\n' + '
\n' + "
\n" + ""); +} ]); + +angular.module("template/tooltip/tooltip-template-popup.html", []).run([ "$templateCache", function($templateCache) { + $templateCache.put("template/tooltip/tooltip-template-popup.html", '
\n' + '
\n' + '
\n' + "
\n" + ""); +} ]); + +angular.module("template/popover/popover-html.html", []).run([ "$templateCache", function($templateCache) { + $templateCache.put("template/popover/popover-html.html", '
\n' + '
\n' + "\n" + '
\n' + '

\n' + '
\n' + "
\n" + "
\n" + ""); +} ]); + +angular.module("template/popover/popover-template.html", []).run([ "$templateCache", function($templateCache) { + $templateCache.put("template/popover/popover-template.html", '
\n' + '
\n' + "\n" + '
\n' + '

\n' + '
\n' + "
\n" + "
\n" + ""); +} ]); + +angular.module("template/popover/popover.html", []).run([ "$templateCache", function($templateCache) { + $templateCache.put("template/popover/popover.html", '
\n' + '
\n' + "\n" + '
\n' + '

\n' + '
\n' + "
\n" + "
\n" + ""); +} ]); + +angular.module("template/progressbar/bar.html", []).run([ "$templateCache", function($templateCache) { + $templateCache.put("template/progressbar/bar.html", '
\n' + ""); +} ]); + +angular.module("template/progressbar/progress.html", []).run([ "$templateCache", function($templateCache) { + $templateCache.put("template/progressbar/progress.html", '
'); +} ]); + +angular.module("template/progressbar/progressbar.html", []).run([ "$templateCache", function($templateCache) { + $templateCache.put("template/progressbar/progressbar.html", '
\n' + '
\n' + "
\n" + ""); +} ]); + +angular.module("template/rating/rating.html", []).run([ "$templateCache", function($templateCache) { + $templateCache.put("template/rating/rating.html", '\n' + " ({{ $index < value ? '*' : ' ' }})\n" + ' \n' + "\n" + ""); +} ]); + +angular.module("template/tabs/tab.html", []).run([ "$templateCache", function($templateCache) { + $templateCache.put("template/tabs/tab.html", '
  • \n' + ' {{heading}}\n' + "
  • \n" + ""); +} ]); + +angular.module("template/tabs/tabset.html", []).run([ "$templateCache", function($templateCache) { + $templateCache.put("template/tabs/tabset.html", "
    \n" + "
      \n" + '
      \n' + '
      \n' + "
      \n" + "
      \n" + "
      \n" + ""); +} ]); + +angular.module("template/timepicker/timepicker.html", []).run([ "$templateCache", function($templateCache) { + $templateCache.put("template/timepicker/timepicker.html", "\n" + " \n" + ' \n' + ' \n' + " \n" + ' \n' + ' \n' + " \n" + " \n" + ' \n" + " \n" + ' \n" + ' \n' + " \n" + ' \n' + ' \n' + " \n" + ' \n' + ' \n' + " \n" + " \n" + "
       
      \n' + ' \n' + " :\n' + ' \n' + "
       
      \n" + ""); +} ]); + +angular.module("template/typeahead/typeahead-match.html", []).run([ "$templateCache", function($templateCache) { + $templateCache.put("template/typeahead/typeahead-match.html", '\n' + ""); +} ]); + +angular.module("template/typeahead/typeahead-popup.html", []).run([ "$templateCache", function($templateCache) { + $templateCache.put("template/typeahead/typeahead-popup.html", '\n" + ""); +} ]); + +!angular.$$csp() && angular.element(document).find("head").prepend(''); + +angular.module("ngMap", []); + +(function() { + "use strict"; + var Attr2MapOptions; + var __MapController = function($scope, $element, $attrs, $parse, _Attr2MapOptions_, NgMap) { + Attr2MapOptions = _Attr2MapOptions_; + var vm = this; + vm.mapOptions; + vm.mapEvents; + vm.ngMapDiv; + vm.addObject = function(groupName, obj) { + if (vm.map) { + vm.map[groupName] = vm.map[groupName] || {}; + var len = Object.keys(vm.map[groupName]).length; + vm.map[groupName][obj.id || len] = obj; + if (groupName != "infoWindows" && obj.setMap) { + obj.setMap && obj.setMap(vm.map); + } + if (obj.centered && obj.position) { + vm.map.setCenter(obj.position); + } + groupName == "markers" && vm.objectChanged("markers"); + groupName == "customMarkers" && vm.objectChanged("customMarkers"); + } + }; + vm.deleteObject = function(groupName, obj) { + if (obj.map) { + var objs = obj.map[groupName]; + for (var name in objs) { + objs[name] === obj && delete objs[name]; + } + obj.map && obj.setMap && obj.setMap(null); + groupName == "markers" && vm.objectChanged("markers"); + groupName == "customMarkers" && vm.objectChanged("customMarkers"); + } + }; + vm.observeAttrSetObj = function(orgAttrs, attrs, obj) { + if (attrs.noWatcher) { + return false; + } + var attrsToObserve = Attr2MapOptions.getAttrsToObserve(orgAttrs); + for (var i = 0; i < attrsToObserve.length; i++) { + var attrName = attrsToObserve[i]; + attrs.$observe(attrName, NgMap.observeAndSet(attrName, obj)); + } + }; + vm.zoomToIncludeMarkers = function() { + var bounds = new google.maps.LatLngBounds(); + for (var k1 in vm.map.markers) { + bounds.extend(vm.map.markers[k1].getPosition()); + } + for (var k2 in vm.map.customMarkers) { + bounds.extend(vm.map.customMarkers[k2].getPosition()); + } + vm.map.fitBounds(bounds); + }; + vm.objectChanged = function(group) { + if ((group == "markers" || group == "customMarkers") && vm.map.zoomToIncludeMarkers == "auto") { + vm.zoomToIncludeMarkers(); + } + }; + vm.initializeMap = function() { + var mapOptions = vm.mapOptions, mapEvents = vm.mapEvents, ngMapDiv = vm.ngMapDiv; + vm.map = new google.maps.Map(ngMapDiv, {}); + mapOptions.zoom = mapOptions.zoom || 15; + var center = mapOptions.center; + if (!mapOptions.center || typeof center === "string" && center.match(/\{\{.*\}\}/)) { + mapOptions.center = new google.maps.LatLng(0, 0); + } else if (!(center instanceof google.maps.LatLng)) { + var geoCenter = mapOptions.center; + delete mapOptions.center; + NgMap.getGeoLocation(geoCenter, mapOptions.geoLocationOptions).then(function(latlng) { + vm.map.setCenter(latlng); + var geoCallback = mapOptions.geoCallback; + geoCallback && $parse(geoCallback)($scope); + }, function() { + if (mapOptions.geoFallbackCenter) { + vm.map.setCenter(mapOptions.geoFallbackCenter); + } + }); + } + vm.map.setOptions(mapOptions); + for (var eventName in mapEvents) { + google.maps.event.addListener(vm.map, eventName, mapEvents[eventName]); + } + vm.observeAttrSetObj(orgAttrs, $attrs, vm.map); + vm.singleInfoWindow = mapOptions.singleInfoWindow; + google.maps.event.addListenerOnce(vm.map, "idle", function() { + NgMap.addMap(vm); + if (mapOptions.zoomToIncludeMarkers) { + vm.zoomToIncludeMarkers(); + } + $scope.map = vm.map; + $scope.$emit("mapInitialized", vm.map); + if ($attrs.mapInitialized) { + $parse($attrs.mapInitialized)($scope, { + map: vm.map + }); + } + }); + }; + $scope.google = google; + var orgAttrs = Attr2MapOptions.orgAttributes($element); + var filtered = Attr2MapOptions.filter($attrs); + var options = Attr2MapOptions.getOptions(filtered); + var controlOptions = Attr2MapOptions.getControlOptions(filtered); + var mapOptions = angular.extend(options, controlOptions); + var mapEvents = Attr2MapOptions.getEvents($scope, filtered); + void 0; + vm.mapOptions = mapOptions; + vm.mapEvents = mapEvents; + vm.ngMapDiv = NgMap.getNgMapDiv($element[0]); + $element.append(vm.ngMapDiv); + if (options.lazyInit) { + vm.map = { + id: $attrs.id + }; + NgMap.addMap(vm); + } else { + vm.initializeMap(); + } + $element.bind("$destroy", function() { + NgMap.deleteMap(vm); + }); + }; + __MapController.$inject = [ "$scope", "$element", "$attrs", "$parse", "Attr2MapOptions", "NgMap" ]; + angular.module("ngMap").controller("__MapController", __MapController); +})(); + +(function() { + "use strict"; + var parser; + var linkFunc = function(scope, element, attrs, mapController) { + mapController = mapController[0] || mapController[1]; + var orgAttrs = parser.orgAttributes(element); + var filtered = parser.filter(attrs); + var options = parser.getOptions(filtered); + var events = parser.getEvents(scope, filtered); + void 0; + var layer = getLayer(options, events); + mapController.addObject("bicyclingLayers", layer); + mapController.observeAttrSetObj(orgAttrs, attrs, layer); + element.bind("$destroy", function() { + mapController.deleteObject("bicyclingLayers", layer); + }); + }; + var getLayer = function(options, events) { + var layer = new google.maps.BicyclingLayer(options); + for (var eventName in events) { + google.maps.event.addListener(layer, eventName, events[eventName]); + } + return layer; + }; + var bicyclingLayer = function(Attr2MapOptions) { + parser = Attr2MapOptions; + return { + restrict: "E", + require: [ "?^map", "?^ngMap" ], + link: linkFunc + }; + }; + bicyclingLayer.$inject = [ "Attr2MapOptions" ]; + angular.module("ngMap").directive("bicyclingLayer", bicyclingLayer); +})(); + +(function() { + "use strict"; + var parser, $compile, NgMap; + var linkFunc = function(scope, element, attrs, mapController) { + mapController = mapController[0] || mapController[1]; + var filtered = parser.filter(attrs); + var options = parser.getOptions(filtered); + var events = parser.getEvents(scope, filtered); + void 0; + var customControlEl = element[0].parentElement.removeChild(element[0]); + $compile(customControlEl.innerHTML.trim())(scope); + for (var eventName in events) { + google.maps.event.addDomListener(customControlEl, eventName, events[eventName]); + } + mapController.addObject("customControls", customControlEl); + NgMap.getMap().then(function(map) { + var position = options.position; + map.controls[google.maps.ControlPosition[position]].push(customControlEl); + }); + }; + var customControl = function(Attr2MapOptions, _$compile_, _NgMap_) { + parser = Attr2MapOptions, $compile = _$compile_, NgMap = _NgMap_; + return { + restrict: "E", + require: [ "?^map", "?^ngMap" ], + link: linkFunc + }; + }; + customControl.$inject = [ "Attr2MapOptions", "$compile", "NgMap" ]; + angular.module("ngMap").directive("customControl", customControl); +})(); + +(function() { + "use strict"; + var parser, $timeout, $compile, NgMap; + var CustomMarker = function(options) { + options = options || {}; + this.el = document.createElement("div"); + this.el.style.display = "inline-block"; + this.visible = true; + for (var key in options) { + this[key] = options[key]; + } + }; + var setCustomMarker = function() { + CustomMarker.prototype = new google.maps.OverlayView(); + CustomMarker.prototype.setContent = function(html, scope) { + this.el.innerHTML = html; + this.el.style.position = "absolute"; + if (scope) { + $compile(angular.element(this.el).contents())(scope); + } + }; + CustomMarker.prototype.getDraggable = function() { + return this.draggable; + }; + CustomMarker.prototype.setDraggable = function(draggable) { + this.draggable = draggable; + }; + CustomMarker.prototype.getPosition = function() { + return this.position; + }; + CustomMarker.prototype.setPosition = function(position) { + position && (this.position = position); + if (this.getProjection() && typeof this.position.lng == "function") { + var posPixel = this.getProjection().fromLatLngToDivPixel(this.position); + var x = Math.round(posPixel.x - this.el.offsetWidth / 2); + var y = Math.round(posPixel.y - this.el.offsetHeight - 10); + this.el.style.left = x + "px"; + this.el.style.top = y + "px"; + } + }; + CustomMarker.prototype.setZIndex = function(zIndex) { + zIndex && (this.zIndex = zIndex); + this.el.style.zIndex = this.zIndex; + }; + CustomMarker.prototype.setVisible = function(visible) { + this.el.style.display = visible ? "inline-block" : "none"; + this.visible = visible; + }; + CustomMarker.prototype.addClass = function(className) { + var classNames = this.el.className.trim().split(" "); + classNames.indexOf(className) == -1 && classNames.push(className); + this.el.className = classNames.join(" "); + }; + CustomMarker.prototype.removeClass = function(className) { + var classNames = this.el.className.split(" "); + var index = classNames.indexOf(className); + index > -1 && classNames.splice(index, 1); + this.el.className = classNames.join(" "); + }; + CustomMarker.prototype.onAdd = function() { + this.getPanes().overlayMouseTarget.appendChild(this.el); + }; + CustomMarker.prototype.draw = function() { + this.setPosition(); + this.setZIndex(this.zIndex); + this.setVisible(this.visible); + }; + CustomMarker.prototype.onRemove = function() { + this.el.parentNode.removeChild(this.el); + }; + }; + var linkFunc = function(orgHtml, varsToWatch) { + return function(scope, element, attrs, mapController) { + mapController = mapController[0] || mapController[1]; + var orgAttrs = parser.orgAttributes(element); + var filtered = parser.filter(attrs); + var options = parser.getOptions(filtered, scope); + var events = parser.getEvents(scope, filtered); + var removedEl = element[0].parentElement.removeChild(element[0]); + void 0; + var customMarker = new CustomMarker(options); + $timeout(function() { + scope.$watch("[" + varsToWatch.join(",") + "]", function() { + customMarker.setContent(orgHtml, scope); + }); + customMarker.setContent(removedEl.innerHTML, scope); + var classNames = removedEl.firstElementChild.className; + customMarker.addClass("custom-marker"); + customMarker.addClass(classNames); + void 0; + if (!(options.position instanceof google.maps.LatLng)) { + NgMap.getGeoLocation(options.position).then(function(latlng) { + customMarker.setPosition(latlng); + }); + } + }); + void 0; + for (var eventName in events) { + google.maps.event.addDomListener(customMarker.el, eventName, events[eventName]); + } + mapController.addObject("customMarkers", customMarker); + mapController.observeAttrSetObj(orgAttrs, attrs, customMarker); + element.bind("$destroy", function() { + mapController.deleteObject("customMarkers", customMarker); + }); + }; + }; + var customMarkerDirective = function(_$timeout_, _$compile_, Attr2MapOptions, _NgMap_) { + parser = Attr2MapOptions; + $timeout = _$timeout_; + $compile = _$compile_; + NgMap = _NgMap_; + return { + restrict: "E", + require: [ "?^map", "?^ngMap" ], + compile: function(element) { + setCustomMarker(); + element[0].style.display = "none"; + var orgHtml = element.html(); + var matches = orgHtml.match(/{{([^}]+)}}/g); + var varsToWatch = []; + (matches || []).forEach(function(match) { + var toWatch = match.replace("{{", "").replace("}}", ""); + if (match.indexOf("::") == -1 && match.indexOf("this.") == -1 && varsToWatch.indexOf(toWatch) == -1) { + varsToWatch.push(match.replace("{{", "").replace("}}", "")); + } + }); + return linkFunc(orgHtml, varsToWatch); + } + }; + }; + customMarkerDirective.$inject = [ "$timeout", "$compile", "Attr2MapOptions", "NgMap" ]; + angular.module("ngMap").directive("customMarker", customMarkerDirective); +})(); + +(function() { + "use strict"; + var NgMap, $timeout, NavigatorGeolocation; + var getDirectionsRenderer = function(options, events) { + if (options.panel) { + options.panel = document.getElementById(options.panel) || document.querySelector(options.panel); + } + var renderer = new google.maps.DirectionsRenderer(options); + for (var eventName in events) { + google.maps.event.addListener(renderer, eventName, events[eventName]); + } + return renderer; + }; + var updateRoute = function(renderer, options) { + var directionsService = new google.maps.DirectionsService(); + var request = options; + request.travelMode = request.travelMode || "DRIVING"; + var validKeys = [ "origin", "destination", "travelMode", "transitOptions", "unitSystem", "durationInTraffic", "waypoints", "optimizeWaypoints", "provideRouteAlternatives", "avoidHighways", "avoidTolls", "region" ]; + for (var key in request) { + validKeys.indexOf(key) === -1 && delete request[key]; } - matchItem = query ? ("" + matchItem).replace(new RegExp(escapeRegexp(query), "gi"), "$&") : matchItem; - if (!isSanitizePresent) { - matchItem = $sce.trustAsHtml(matchItem); + if (request.waypoints) { + if (request.waypoints == "[]" || request.waypoints === "") { + delete request.waypoints; + } } - return matchItem; + var showDirections = function(request) { + directionsService.route(request, function(response, status) { + if (status == google.maps.DirectionsStatus.OK) { + $timeout(function() { + renderer.setDirections(response); + }); + } + }); + }; + if (request.origin && request.destination) { + if (request.origin == "current-location") { + NavigatorGeolocation.getCurrentPosition().then(function(ll) { + request.origin = new google.maps.LatLng(ll.coords.latitude, ll.coords.longitude); + showDirections(request); + }); + } else if (request.destination == "current-location") { + NavigatorGeolocation.getCurrentPosition().then(function(ll) { + request.destination = new google.maps.LatLng(ll.coords.latitude, ll.coords.longitude); + showDirections(request); + }); + } else { + showDirections(request); + } + } + }; + var directions = function(Attr2MapOptions, _$timeout_, _NavigatorGeolocation_, _NgMap_) { + var parser = Attr2MapOptions; + NgMap = _NgMap_; + $timeout = _$timeout_; + NavigatorGeolocation = _NavigatorGeolocation_; + var linkFunc = function(scope, element, attrs, mapController) { + mapController = mapController[0] || mapController[1]; + var orgAttrs = parser.orgAttributes(element); + var filtered = parser.filter(attrs); + var options = parser.getOptions(filtered); + var events = parser.getEvents(scope, filtered); + var attrsToObserve = parser.getAttrsToObserve(orgAttrs); + var renderer = getDirectionsRenderer(options, events); + mapController.addObject("directionsRenderers", renderer); + attrsToObserve.forEach(function(attrName) { + (function(attrName) { + attrs.$observe(attrName, function(val) { + if (attrName == "panel") { + $timeout(function() { + var panel = document.getElementById(val) || document.querySelector(val); + void 0; + panel && renderer.setPanel(panel); + }); + } else if (options[attrName] !== val) { + var optionValue = parser.toOptionValue(val, { + key: attrName + }); + void 0; + options[attrName] = optionValue; + updateRoute(renderer, options); + } + }); + })(attrName); + }); + NgMap.getMap().then(function() { + updateRoute(renderer, options); + }); + element.bind("$destroy", function() { + mapController.deleteObject("directionsRenderers", renderer); + }); + }; + return { + restrict: "E", + require: [ "?^map", "?^ngMap" ], + link: linkFunc + }; }; -} ]); - -angular.module("template/accordion/accordion-group.html", []).run([ "$templateCache", function($templateCache) { - $templateCache.put("template/accordion/accordion-group.html", "
      \n" + '
      \n' + '

      \n' + ' {{heading}}\n' + "

      \n" + "
      \n" + '
      \n' + '
      \n' + "
      \n" + "
      \n" + ""); -} ]); - -angular.module("template/accordion/accordion.html", []).run([ "$templateCache", function($templateCache) { - $templateCache.put("template/accordion/accordion.html", '
      '); -} ]); + directions.$inject = [ "Attr2MapOptions", "$timeout", "NavigatorGeolocation", "NgMap" ]; + angular.module("ngMap").directive("directions", directions); +})(); -angular.module("template/alert/alert.html", []).run([ "$templateCache", function($templateCache) { - $templateCache.put("template/alert/alert.html", "
      \n" + ' \n" + "
      \n" + "
      \n" + ""); -} ]); +(function() { + "use strict"; + angular.module("ngMap").directive("drawingManager", [ "Attr2MapOptions", function(Attr2MapOptions) { + var parser = Attr2MapOptions; + return { + restrict: "E", + require: [ "?^map", "?^ngMap" ], + link: function(scope, element, attrs, mapController) { + mapController = mapController[0] || mapController[1]; + var filtered = parser.filter(attrs); + var options = parser.getOptions(filtered); + var controlOptions = parser.getControlOptions(filtered); + var events = parser.getEvents(scope, filtered); + void 0; + var drawingManager = new google.maps.drawing.DrawingManager({ + drawingMode: options.drawingmode, + drawingControl: options.drawingcontrol, + drawingControlOptions: controlOptions.drawingControlOptions, + circleOptions: options.circleoptions, + markerOptions: options.markeroptions, + polygonOptions: options.polygonoptions, + polylineOptions: options.polylineoptions, + rectangleOptions: options.rectangleoptions + }); + for (var eventName in events) { + google.maps.event.addListener(drawingManager, eventName, events[eventName]); + } + mapController.addObject("mapDrawingManager", drawingManager); + } + }; + } ]); +})(); -angular.module("template/carousel/carousel.html", []).run([ "$templateCache", function($templateCache) { - $templateCache.put("template/carousel/carousel.html", '\n" + ""); -} ]); +(function() { + "use strict"; + angular.module("ngMap").directive("dynamicMapsEngineLayer", [ "Attr2MapOptions", function(Attr2MapOptions) { + var parser = Attr2MapOptions; + var getDynamicMapsEngineLayer = function(options, events) { + var layer = new google.maps.visualization.DynamicMapsEngineLayer(options); + for (var eventName in events) { + google.maps.event.addListener(layer, eventName, events[eventName]); + } + return layer; + }; + return { + restrict: "E", + require: [ "?^map", "?^ngMap" ], + link: function(scope, element, attrs, mapController) { + mapController = mapController[0] || mapController[1]; + var filtered = parser.filter(attrs); + var options = parser.getOptions(filtered); + var events = parser.getEvents(scope, filtered, events); + void 0; + var layer = getDynamicMapsEngineLayer(options, events); + mapController.addObject("mapsEngineLayers", layer); + } + }; + } ]); +})(); -angular.module("template/carousel/slide.html", []).run([ "$templateCache", function($templateCache) { - $templateCache.put("template/carousel/slide.html", '
      \n' + ""); -} ]); +(function() { + "use strict"; + angular.module("ngMap").directive("fusionTablesLayer", [ "Attr2MapOptions", function(Attr2MapOptions) { + var parser = Attr2MapOptions; + var getLayer = function(options, events) { + var layer = new google.maps.FusionTablesLayer(options); + for (var eventName in events) { + google.maps.event.addListener(layer, eventName, events[eventName]); + } + return layer; + }; + return { + restrict: "E", + require: [ "?^map", "?^ngMap" ], + link: function(scope, element, attrs, mapController) { + mapController = mapController[0] || mapController[1]; + var filtered = parser.filter(attrs); + var options = parser.getOptions(filtered); + var events = parser.getEvents(scope, filtered, events); + void 0; + var layer = getLayer(options, events); + mapController.addObject("fusionTablesLayers", layer); + } + }; + } ]); +})(); -angular.module("template/datepicker/datepicker.html", []).run([ "$templateCache", function($templateCache) { - $templateCache.put("template/datepicker/datepicker.html", '
      \n' + ' \n' + ' \n' + ' \n' + "
      "); -} ]); +(function() { + "use strict"; + angular.module("ngMap").directive("heatmapLayer", [ "Attr2MapOptions", "$window", function(Attr2MapOptions, $window) { + var parser = Attr2MapOptions; + return { + restrict: "E", + require: [ "?^map", "?^ngMap" ], + link: function(scope, element, attrs, mapController) { + mapController = mapController[0] || mapController[1]; + var filtered = parser.filter(attrs); + var options = parser.getOptions(filtered); + options.data = $window[attrs.data] || scope[attrs.data]; + if (options.data instanceof Array) { + options.data = new google.maps.MVCArray(options.data); + } else { + throw "invalid heatmap data"; + } + var layer = new google.maps.visualization.HeatmapLayer(options); + var events = parser.getEvents(scope, filtered); + void 0; + mapController.addObject("heatmapLayers", layer); + } + }; + } ]); +})(); -angular.module("template/datepicker/day.html", []).run([ "$templateCache", function($templateCache) { - $templateCache.put("template/datepicker/day.html", '\n' + " \n" + " \n" + ' \n' + ' \n' + ' \n' + " \n" + " \n" + ' \n' + ' \n' + " \n" + " \n" + " \n" + ' \n' + ' \n' + ' \n" + " \n" + " \n" + "
      {{::label.abbr}}
      {{ weekNumbers[$index] }}\n' + ' \n' + "
      \n" + ""); -} ]); +(function() { + "use strict"; + var infoWindow = function(Attr2MapOptions, $compile, $timeout, $parse, NgMap) { + var parser = Attr2MapOptions; + var getInfoWindow = function(options, events, element) { + var infoWindow; + if (options.position && !(options.position instanceof google.maps.LatLng)) { + delete options.position; + } + infoWindow = new google.maps.InfoWindow(options); + if (Object.keys(events).length > 0) { + void 0; + } + for (var eventName in events) { + if (eventName) { + google.maps.event.addListener(infoWindow, eventName, events[eventName]); + } + } + var template = element.html().trim(); + if (angular.element(template).length != 1) { + throw "info-window working as a template must have a container"; + } + infoWindow.__template = template.replace(/\s?ng-non-bindable[='"]+/, ""); + infoWindow.__open = function(map, scope, anchor) { + $timeout(function() { + anchor && (scope.anchor = anchor); + var el = $compile(infoWindow.__template)(scope); + infoWindow.setContent(el[0]); + scope.$apply(); + if (anchor && anchor.getPosition) { + infoWindow.open(map, anchor); + } else if (anchor && anchor instanceof google.maps.LatLng) { + infoWindow.open(map); + infoWindow.setPosition(anchor); + } else { + infoWindow.open(map); + } + }); + }; + return infoWindow; + }; + var linkFunc = function(scope, element, attrs, mapController) { + mapController = mapController[0] || mapController[1]; + element.css("display", "none"); + var orgAttrs = parser.orgAttributes(element); + var filtered = parser.filter(attrs); + var options = parser.getOptions(filtered); + var events = parser.getEvents(scope, filtered); + void 0; + var address; + if (options.position && !(options.position instanceof google.maps.LatLng)) { + address = options.position; + } + var infoWindow = getInfoWindow(options, events, element); + if (address) { + NgMap.getGeoLocation(address).then(function(latlng) { + infoWindow.setPosition(latlng); + infoWindow.__open(mapController.map, scope, latlng); + var geoCallback = attrs.geoCallback; + geoCallback && $parse(geoCallback)(scope); + }); + } + mapController.addObject("infoWindows", infoWindow); + mapController.observeAttrSetObj(orgAttrs, attrs, infoWindow); + NgMap.getMap().then(function(map) { + infoWindow.visible && infoWindow.__open(map, scope); + if (infoWindow.visibleOnMarker) { + var markerId = infoWindow.visibleOnMarker; + infoWindow.__open(map, scope, map.markers[markerId]); + } + map.showInfoWindow = map.showInfoWindow || function(p1, p2, p3) { + var id = typeof p1 == "string" ? p1 : p2; + var marker = typeof p1 == "string" ? p2 : p3; + var infoWindow = mapController.map.infoWindows[id]; + var anchor = marker ? marker : this.getPosition ? this : null; + infoWindow.__open(mapController.map, scope, anchor); + if (mapController.singleInfoWindow) { + if (mapController.lastInfoWindow) { + scope.hideInfoWindow(mapController.lastInfoWindow); + } + mapController.lastInfoWindow = id; + } + }; + map.hideInfoWindow = scope.hideInfoWindow || function(p1, p2) { + var id = typeof p1 == "string" ? p1 : p2; + var infoWindow = mapController.map.infoWindows[id]; + infoWindow.close(); + }; + scope.showInfoWindow = map.showInfoWindow; + scope.hideInfoWindow = map.hideInfoWindow; + }); + }; + return { + restrict: "E", + require: [ "?^map", "?^ngMap" ], + link: linkFunc + }; + }; + infoWindow.$inject = [ "Attr2MapOptions", "$compile", "$timeout", "$parse", "NgMap" ]; + angular.module("ngMap").directive("infoWindow", infoWindow); +})(); -angular.module("template/datepicker/month.html", []).run([ "$templateCache", function($templateCache) { - $templateCache.put("template/datepicker/month.html", '\n' + " \n" + " \n" + ' \n' + ' \n' + ' \n' + " \n" + " \n" + " \n" + ' \n' + ' \n" + " \n" + " \n" + "
      \n' + ' \n' + "
      \n" + ""); -} ]); +(function() { + "use strict"; + angular.module("ngMap").directive("kmlLayer", [ "Attr2MapOptions", function(Attr2MapOptions) { + var parser = Attr2MapOptions; + var getKmlLayer = function(options, events) { + var kmlLayer = new google.maps.KmlLayer(options); + for (var eventName in events) { + google.maps.event.addListener(kmlLayer, eventName, events[eventName]); + } + return kmlLayer; + }; + return { + restrict: "E", + require: [ "?^map", "?^ngMap" ], + link: function(scope, element, attrs, mapController) { + mapController = mapController[0] || mapController[1]; + var orgAttrs = parser.orgAttributes(element); + var filtered = parser.filter(attrs); + var options = parser.getOptions(filtered); + var events = parser.getEvents(scope, filtered); + void 0; + var kmlLayer = getKmlLayer(options, events); + mapController.addObject("kmlLayers", kmlLayer); + mapController.observeAttrSetObj(orgAttrs, attrs, kmlLayer); + element.bind("$destroy", function() { + mapController.deleteObject("kmlLayers", kmlLayer); + }); + } + }; + } ]); +})(); -angular.module("template/datepicker/popup.html", []).run([ "$templateCache", function($templateCache) { - $templateCache.put("template/datepicker/popup.html", '\n" + ""); -} ]); +(function() { + "use strict"; + angular.module("ngMap").directive("mapData", [ "Attr2MapOptions", "NgMap", function(Attr2MapOptions, NgMap) { + var parser = Attr2MapOptions; + return { + restrict: "E", + require: [ "?^map", "?^ngMap" ], + link: function(scope, element, attrs) { + var filtered = parser.filter(attrs); + var options = parser.getOptions(filtered); + var events = parser.getEvents(scope, filtered, events); + void 0; + NgMap.getMap().then(function(map) { + for (var key in options) { + var val = options[key]; + if (typeof scope[val] === "function") { + map.data[key](scope[val]); + } else { + map.data[key](val); + } + } + for (var eventName in events) { + map.data.addListener(eventName, events[eventName]); + } + }); + } + }; + } ]); +})(); -angular.module("template/datepicker/year.html", []).run([ "$templateCache", function($templateCache) { - $templateCache.put("template/datepicker/year.html", '\n' + " \n" + " \n" + ' \n' + ' \n' + ' \n' + " \n" + " \n" + " \n" + ' \n' + ' \n" + " \n" + " \n" + "
      \n' + ' \n' + "
      \n" + ""); -} ]); +(function() { + "use strict"; + var $timeout, $compile, src, savedHtml; + var preLinkFunc = function(scope, element, attrs) { + var mapsUrl = attrs.mapLazyLoadParams || attrs.mapLazyLoad; + window.lazyLoadCallback = function() { + void 0; + $timeout(function() { + element.html(savedHtml); + $compile(element.contents())(scope); + }, 100); + }; + if (window.google === undefined || window.google.maps === undefined) { + var scriptEl = document.createElement("script"); + void 0; + scriptEl.src = mapsUrl + (mapsUrl.indexOf("?") > -1 ? "&" : "?") + "callback=lazyLoadCallback"; + document.body.appendChild(scriptEl); + } else { + element.html(savedHtml); + $compile(element.contents())(scope); + } + }; + var compileFunc = function(tElement, tAttrs) { + !tAttrs.mapLazyLoad && void 0; + savedHtml = tElement.html(); + src = tAttrs.mapLazyLoad; + if (document.querySelector('script[src="' + src + (src.indexOf("?") > -1 ? "&" : "?") + 'callback=lazyLoadCallback"]')) { + return false; + } + tElement.html(""); + return { + pre: preLinkFunc + }; + }; + var mapLazyLoad = function(_$compile_, _$timeout_) { + $compile = _$compile_, $timeout = _$timeout_; + return { + compile: compileFunc + }; + }; + mapLazyLoad.$inject = [ "$compile", "$timeout" ]; + angular.module("ngMap").directive("mapLazyLoad", mapLazyLoad); +})(); -angular.module("template/modal/backdrop.html", []).run([ "$templateCache", function($templateCache) { - $templateCache.put("template/modal/backdrop.html", '\n" + ""); -} ]); +(function() { + "use strict"; + angular.module("ngMap").directive("mapType", [ "$parse", "NgMap", function($parse, NgMap) { + return { + restrict: "E", + require: [ "?^map", "?^ngMap" ], + link: function(scope, element, attrs, mapController) { + mapController = mapController[0] || mapController[1]; + var mapTypeName = attrs.name, mapTypeObject; + if (!mapTypeName) { + throw "invalid map-type name"; + } + mapTypeObject = $parse(attrs.object)(scope); + if (!mapTypeObject) { + throw "invalid map-type object"; + } + NgMap.getMap().then(function(map) { + map.mapTypes.set(mapTypeName, mapTypeObject); + }); + mapController.addObject("mapTypes", mapTypeObject); + } + }; + } ]); +})(); -angular.module("template/modal/window.html", []).run([ "$templateCache", function($templateCache) { - $templateCache.put("template/modal/window.html", '\n" + ""); -} ]); +(function() { + "use strict"; + var mapDirective = function() { + return { + restrict: "AE", + controller: "__MapController", + conrollerAs: "ngmap" + }; + }; + angular.module("ngMap").directive("map", [ mapDirective ]); + angular.module("ngMap").directive("ngMap", [ mapDirective ]); +})(); -angular.module("template/pagination/pager.html", []).run([ "$templateCache", function($templateCache) { - $templateCache.put("template/pagination/pager.html", '\n" + ""); -} ]); +(function() { + "use strict"; + angular.module("ngMap").directive("mapsEngineLayer", [ "Attr2MapOptions", function(Attr2MapOptions) { + var parser = Attr2MapOptions; + var getMapsEngineLayer = function(options, events) { + var layer = new google.maps.visualization.MapsEngineLayer(options); + for (var eventName in events) { + google.maps.event.addListener(layer, eventName, events[eventName]); + } + return layer; + }; + return { + restrict: "E", + require: [ "?^map", "?^ngMap" ], + link: function(scope, element, attrs, mapController) { + mapController = mapController[0] || mapController[1]; + var filtered = parser.filter(attrs); + var options = parser.getOptions(filtered); + var events = parser.getEvents(scope, filtered, events); + void 0; + var layer = getMapsEngineLayer(options, events); + mapController.addObject("mapsEngineLayers", layer); + } + }; + } ]); +})(); -angular.module("template/pagination/pagination.html", []).run([ "$templateCache", function($templateCache) { - $templateCache.put("template/pagination/pagination.html", '\n" + ""); -} ]); +(function() { + "use strict"; + var parser, $parse, NgMap; + var getMarker = function(options, events) { + var marker; + if (NgMap.defaultOptions.marker) { + for (var key in NgMap.defaultOptions.marker) { + if (typeof options[key] == "undefined") { + void 0; + options[key] = NgMap.defaultOptions.marker[key]; + } + } + } + if (!(options.position instanceof google.maps.LatLng)) { + options.position = new google.maps.LatLng(0, 0); + } + marker = new google.maps.Marker(options); + if (Object.keys(events).length > 0) { + void 0; + } + for (var eventName in events) { + if (eventName) { + google.maps.event.addListener(marker, eventName, events[eventName]); + } + } + return marker; + }; + var linkFunc = function(scope, element, attrs, mapController) { + mapController = mapController[0] || mapController[1]; + var orgAttrs = parser.orgAttributes(element); + var filtered = parser.filter(attrs); + var markerOptions = parser.getOptions(filtered, scope); + var markerEvents = parser.getEvents(scope, filtered); + void 0; + var address; + if (!(markerOptions.position instanceof google.maps.LatLng)) { + address = markerOptions.position; + } + var marker = getMarker(markerOptions, markerEvents); + mapController.addObject("markers", marker); + if (address) { + NgMap.getGeoLocation(address).then(function(latlng) { + marker.setPosition(latlng); + markerOptions.centered && marker.map.setCenter(latlng); + var geoCallback = attrs.geoCallback; + geoCallback && $parse(geoCallback)(scope); + }); + } + mapController.observeAttrSetObj(orgAttrs, attrs, marker); + element.bind("$destroy", function() { + mapController.deleteObject("markers", marker); + }); + }; + var marker = function(Attr2MapOptions, _$parse_, _NgMap_) { + parser = Attr2MapOptions; + $parse = _$parse_; + NgMap = _NgMap_; + return { + restrict: "E", + require: [ "^?map", "?^ngMap" ], + link: linkFunc + }; + }; + marker.$inject = [ "Attr2MapOptions", "$parse", "NgMap" ]; + angular.module("ngMap").directive("marker", marker); +})(); -angular.module("template/tooltip/tooltip-html-popup.html", []).run([ "$templateCache", function($templateCache) { - $templateCache.put("template/tooltip/tooltip-html-popup.html", '
      \n' + '
      \n' + '
      \n' + "
      \n" + ""); -} ]); +(function() { + "use strict"; + angular.module("ngMap").directive("overlayMapType", [ "NgMap", function(NgMap) { + return { + restrict: "E", + require: [ "?^map", "?^ngMap" ], + link: function(scope, element, attrs, mapController) { + mapController = mapController[0] || mapController[1]; + var initMethod = attrs.initMethod || "insertAt"; + var overlayMapTypeObject = scope[attrs.object]; + NgMap.getMap().then(function(map) { + if (initMethod == "insertAt") { + var index = parseInt(attrs.index, 10); + map.overlayMapTypes.insertAt(index, overlayMapTypeObject); + } else if (initMethod == "push") { + map.overlayMapTypes.push(overlayMapTypeObject); + } + }); + mapController.addObject("overlayMapTypes", overlayMapTypeObject); + } + }; + } ]); +})(); -angular.module("template/tooltip/tooltip-html-unsafe-popup.html", []).run([ "$templateCache", function($templateCache) { - $templateCache.put("template/tooltip/tooltip-html-unsafe-popup.html", '
      \n' + '
      \n' + '
      \n' + "
      \n" + ""); -} ]); +(function() { + "use strict"; + var placesAutoComplete = function(Attr2MapOptions, $timeout) { + var parser = Attr2MapOptions; + var linkFunc = function(scope, element, attrs, ngModelCtrl) { + if (attrs.placesAutoComplete === "false") { + return false; + } + var filtered = parser.filter(attrs); + var options = parser.getOptions(filtered); + var events = parser.getEvents(scope, filtered); + void 0; + var autocomplete = new google.maps.places.Autocomplete(element[0], options); + for (var eventName in events) { + google.maps.event.addListener(autocomplete, eventName, events[eventName]); + } + var updateModel = function() { + $timeout(function() { + ngModelCtrl && ngModelCtrl.$setViewValue(element.val()); + }, 100); + }; + google.maps.event.addListener(autocomplete, "place_changed", updateModel); + element[0].addEventListener("change", updateModel); + attrs.$observe("types", function(val) { + if (val) { + void 0; + var optionValue = parser.toOptionValue(val, { + key: "types" + }); + void 0; + autocomplete.setTypes(optionValue); + } + }); + }; + return { + restrict: "A", + require: "?ngModel", + link: linkFunc + }; + }; + placesAutoComplete.$inject = [ "Attr2MapOptions", "$timeout" ]; + angular.module("ngMap").directive("placesAutoComplete", placesAutoComplete); +})(); -angular.module("template/tooltip/tooltip-popup.html", []).run([ "$templateCache", function($templateCache) { - $templateCache.put("template/tooltip/tooltip-popup.html", '
      \n' + '
      \n' + '
      \n' + "
      \n" + ""); -} ]); +(function() { + "use strict"; + var getShape = function(options, events) { + var shape; + var shapeName = options.name; + delete options.name; + void 0; + switch (shapeName) { + case "circle": + if (!(options.center instanceof google.maps.LatLng)) { + options.center = new google.maps.LatLng(0, 0); + } + shape = new google.maps.Circle(options); + break; -angular.module("template/tooltip/tooltip-template-popup.html", []).run([ "$templateCache", function($templateCache) { - $templateCache.put("template/tooltip/tooltip-template-popup.html", '
      \n' + '
      \n' + '
      \n' + "
      \n" + ""); -} ]); + case "polygon": + shape = new google.maps.Polygon(options); + break; -angular.module("template/popover/popover-html.html", []).run([ "$templateCache", function($templateCache) { - $templateCache.put("template/popover/popover-html.html", '
      \n' + '
      \n' + "\n" + '
      \n' + '

      \n' + '
      \n' + "
      \n" + "
      \n" + ""); -} ]); + case "polyline": + shape = new google.maps.Polyline(options); + break; -angular.module("template/popover/popover-template.html", []).run([ "$templateCache", function($templateCache) { - $templateCache.put("template/popover/popover-template.html", '
      \n' + '
      \n' + "\n" + '
      \n' + '

      \n' + '
      \n' + "
      \n" + "
      \n" + ""); -} ]); + case "rectangle": + shape = new google.maps.Rectangle(options); + break; -angular.module("template/popover/popover.html", []).run([ "$templateCache", function($templateCache) { - $templateCache.put("template/popover/popover.html", '
      \n' + '
      \n' + "\n" + '
      \n' + '

      \n' + '
      \n' + "
      \n" + "
      \n" + ""); -} ]); + case "groundOverlay": + case "image": + var url = options.url; + var opts = { + opacity: options.opacity, + clickable: options.clickable, + id: options.id + }; + shape = new google.maps.GroundOverlay(url, options.bounds, opts); + break; + } + for (var eventName in events) { + if (events[eventName]) { + google.maps.event.addListener(shape, eventName, events[eventName]); + } + } + return shape; + }; + var shape = function(Attr2MapOptions, $parse, NgMap) { + var parser = Attr2MapOptions; + var linkFunc = function(scope, element, attrs, mapController) { + mapController = mapController[0] || mapController[1]; + var orgAttrs = parser.orgAttributes(element); + var filtered = parser.filter(attrs); + var shapeOptions = parser.getOptions(filtered); + var shapeEvents = parser.getEvents(scope, filtered); + var address, shapeType; + shapeType = shapeOptions.name; + if (!(shapeOptions.center instanceof google.maps.LatLng)) { + address = shapeOptions.center; + } + var shape = getShape(shapeOptions, shapeEvents); + mapController.addObject("shapes", shape); + if (address && shapeType == "circle") { + NgMap.getGeoLocation(address).then(function(latlng) { + shape.setCenter(latlng); + shape.centered && shape.map.setCenter(latlng); + var geoCallback = attrs.geoCallback; + geoCallback && $parse(geoCallback)(scope); + }); + } + mapController.observeAttrSetObj(orgAttrs, attrs, shape); + element.bind("$destroy", function() { + mapController.deleteObject("shapes", shape); + }); + }; + return { + restrict: "E", + require: [ "?^map", "?^ngMap" ], + link: linkFunc + }; + }; + shape.$inject = [ "Attr2MapOptions", "$parse", "NgMap" ]; + angular.module("ngMap").directive("shape", shape); +})(); -angular.module("template/progressbar/bar.html", []).run([ "$templateCache", function($templateCache) { - $templateCache.put("template/progressbar/bar.html", '
      \n' + ""); -} ]); +(function() { + "use strict"; + var streetViewPanorama = function(Attr2MapOptions, NgMap) { + var parser = Attr2MapOptions; + var getStreetViewPanorama = function(map, options, events) { + var svp, container; + if (options.container) { + container = document.getElementById(options.container); + container = container || document.querySelector(options.container); + } + if (container) { + svp = new google.maps.StreetViewPanorama(container, options); + } else { + svp = map.getStreetView(); + svp.setOptions(options); + } + for (var eventName in events) { + eventName && google.maps.event.addListener(svp, eventName, events[eventName]); + } + return svp; + }; + var linkFunc = function(scope, element, attrs) { + var filtered = parser.filter(attrs); + var options = parser.getOptions(filtered); + var controlOptions = parser.getControlOptions(filtered); + var svpOptions = angular.extend(options, controlOptions); + var svpEvents = parser.getEvents(scope, filtered); + void 0; + NgMap.getMap().then(function(map) { + var svp = getStreetViewPanorama(map, svpOptions, svpEvents); + map.setStreetView(svp); + !svp.getPosition() && svp.setPosition(map.getCenter()); + google.maps.event.addListener(svp, "position_changed", function() { + if (svp.getPosition() !== map.getCenter()) { + map.setCenter(svp.getPosition()); + } + }); + var listener = google.maps.event.addListener(map, "center_changed", function() { + svp.setPosition(map.getCenter()); + google.maps.event.removeListener(listener); + }); + }); + }; + return { + restrict: "E", + require: [ "?^map", "?^ngMap" ], + link: linkFunc + }; + }; + streetViewPanorama.$inject = [ "Attr2MapOptions", "NgMap" ]; + angular.module("ngMap").directive("streetViewPanorama", streetViewPanorama); +})(); -angular.module("template/progressbar/progress.html", []).run([ "$templateCache", function($templateCache) { - $templateCache.put("template/progressbar/progress.html", '
      '); -} ]); +(function() { + "use strict"; + angular.module("ngMap").directive("trafficLayer", [ "Attr2MapOptions", function(Attr2MapOptions) { + var parser = Attr2MapOptions; + var getLayer = function(options, events) { + var layer = new google.maps.TrafficLayer(options); + for (var eventName in events) { + google.maps.event.addListener(layer, eventName, events[eventName]); + } + return layer; + }; + return { + restrict: "E", + require: [ "?^map", "?^ngMap" ], + link: function(scope, element, attrs, mapController) { + mapController = mapController[0] || mapController[1]; + var orgAttrs = parser.orgAttributes(element); + var filtered = parser.filter(attrs); + var options = parser.getOptions(filtered); + var events = parser.getEvents(scope, filtered); + void 0; + var layer = getLayer(options, events); + mapController.addObject("trafficLayers", layer); + mapController.observeAttrSetObj(orgAttrs, attrs, layer); + element.bind("$destroy", function() { + mapController.deleteObject("trafficLayers", layer); + }); + } + }; + } ]); +})(); -angular.module("template/progressbar/progressbar.html", []).run([ "$templateCache", function($templateCache) { - $templateCache.put("template/progressbar/progressbar.html", '
      \n' + '
      \n' + "
      \n" + ""); -} ]); +(function() { + "use strict"; + angular.module("ngMap").directive("transitLayer", [ "Attr2MapOptions", function(Attr2MapOptions) { + var parser = Attr2MapOptions; + var getLayer = function(options, events) { + var layer = new google.maps.TransitLayer(options); + for (var eventName in events) { + google.maps.event.addListener(layer, eventName, events[eventName]); + } + return layer; + }; + return { + restrict: "E", + require: [ "?^map", "?^ngMap" ], + link: function(scope, element, attrs, mapController) { + mapController = mapController[0] || mapController[1]; + var orgAttrs = parser.orgAttributes(element); + var filtered = parser.filter(attrs); + var options = parser.getOptions(filtered); + var events = parser.getEvents(scope, filtered); + void 0; + var layer = getLayer(options, events); + mapController.addObject("transitLayers", layer); + mapController.observeAttrSetObj(orgAttrs, attrs, layer); + element.bind("$destroy", function() { + mapController.deleteObject("transitLayers", layer); + }); + } + }; + } ]); +})(); -angular.module("template/rating/rating.html", []).run([ "$templateCache", function($templateCache) { - $templateCache.put("template/rating/rating.html", '\n' + " ({{ $index < value ? '*' : ' ' }})\n" + ' \n' + "\n" + ""); -} ]); +(function() { + "use strict"; + var SPECIAL_CHARS_REGEXP = /([\:\-\_]+(.))/g; + var MOZ_HACK_REGEXP = /^moz([A-Z])/; + var camelCaseFilter = function() { + return function(name) { + return name.replace(SPECIAL_CHARS_REGEXP, function(_, separator, letter, offset) { + return offset ? letter.toUpperCase() : letter; + }).replace(MOZ_HACK_REGEXP, "Moz$1"); + }; + }; + angular.module("ngMap").filter("camelCase", camelCaseFilter); +})(); -angular.module("template/tabs/tab.html", []).run([ "$templateCache", function($templateCache) { - $templateCache.put("template/tabs/tab.html", '
    • \n' + ' {{heading}}\n' + "
    • \n" + ""); -} ]); +(function() { + "use strict"; + var jsonizeFilter = function() { + return function(str) { + try { + JSON.parse(str); + return str; + } catch (e) { + return str.replace(/([\$\w]+)\s*:/g, function(_, $1) { + return '"' + $1 + '":'; + }).replace(/'([^']+)'/g, function(_, $1) { + return '"' + $1 + '"'; + }); + } + }; + }; + angular.module("ngMap").filter("jsonize", jsonizeFilter); +})(); -angular.module("template/tabs/tabset.html", []).run([ "$templateCache", function($templateCache) { - $templateCache.put("template/tabs/tabset.html", "
      \n" + "
        \n" + '
        \n' + '
        \n' + "
        \n" + "
        \n" + "
        \n" + ""); -} ]); +(function() { + "use strict"; + var isoDateRE = /^(\d{4}\-\d\d\-\d\d([tT][\d:\.]*)?)([zZ]|([+\-])(\d\d):?(\d\d))?$/; + var Attr2MapOptions = function($parse, $timeout, $log, NavigatorGeolocation, GeoCoder, camelCaseFilter, jsonizeFilter) { + var orgAttributes = function(el) { + el.length > 0 && (el = el[0]); + var orgAttributes = {}; + for (var i = 0; i < el.attributes.length; i++) { + var attr = el.attributes[i]; + orgAttributes[attr.name] = attr.value; + } + return orgAttributes; + }; + var getJSON = function(input) { + var re = /^[\+\-]?[0-9\.]+,[ ]*\ ?[\+\-]?[0-9\.]+$/; + if (input.match(re)) { + input = "[" + input + "]"; + } + return JSON.parse(jsonizeFilter(input)); + }; + var getLatLng = function(input) { + var output = input; + if (input[0].constructor == Array) { + output = input.map(function(el) { + return new google.maps.LatLng(el[0], el[1]); + }); + } else if (!isNaN(parseFloat(input[0])) && isFinite(input[0])) { + output = new google.maps.LatLng(output[0], output[1]); + } + return output; + }; + var toOptionValue = function(input, options) { + var output; + try { + output = getNumber(input); + } catch (err) { + try { + var output = getJSON(input); + if (output instanceof Array) { + if (output[0].constructor == Object) { + output = output; + } else { + output = getLatLng(output); + } + } else if (output === Object(output)) { + var newOptions = options; + newOptions.doNotConverStringToNumber = true; + output = getOptions(output, newOptions); + } + } catch (err2) { + if (input.match(/^[A-Z][a-zA-Z0-9]+\(.*\)$/)) { + try { + var exp = "new google.maps." + input; + output = eval(exp); + } catch (e) { + output = input; + } + } else if (input.match(/^([A-Z][a-zA-Z0-9]+)\.([A-Z]+)$/)) { + try { + var matches = input.match(/^([A-Z][a-zA-Z0-9]+)\.([A-Z]+)$/); + output = google.maps[matches[1]][matches[2]]; + } catch (e) { + output = input; + } + } else if (input.match(/^[A-Z]+$/)) { + try { + var capitalizedKey = options.key.charAt(0).toUpperCase() + options.key.slice(1); + if (options.key.match(/temperatureUnit|windSpeedUnit|labelColor/)) { + capitalizedKey = capitalizedKey.replace(/s$/, ""); + output = google.maps.weather[capitalizedKey][input]; + } else { + output = google.maps[capitalizedKey][input]; + } + } catch (e) { + output = input; + } + } else if (input.match(isoDateRE)) { + try { + output = new Date(input); + } catch (e) { + output = input; + } + } else { + output = input; + } + } + } + if (options.key == "bounds" && output instanceof Array) { + output = new google.maps.LatLngBounds(output[0], output[1]); + } + if (options.key == "icons" && output instanceof Array) { + for (var i = 0; i < output.length; i++) { + var el = output[i]; + if (el.icon.path.match(/^[A-Z_]+$/)) { + el.icon.path = google.maps.SymbolPath[el.icon.path]; + } + } + } + if (options.key == "icon" && output instanceof Object) { + if (("" + output.path).match(/^[A-Z_]+$/)) { + output.path = google.maps.SymbolPath[output.path]; + } + for (var key in output) { + var arr = output[key]; + if (key == "anchor" || key == "origin") { + output[key] = new google.maps.Point(arr[0], arr[1]); + } else if (key == "size" || key == "scaledSize") { + output[key] = new google.maps.Size(arr[0], arr[1]); + } + } + } + return output; + }; + var getAttrsToObserve = function(attrs) { + var attrsToObserve = []; + if (!attrs.noWatcher) { + for (var attrName in attrs) { + var attrValue = attrs[attrName]; + void 0; + if (attrValue && attrValue.match(/\{\{.*\}\}/)) { + void 0; + attrsToObserve.push(camelCaseFilter(attrName)); + } + } + } + return attrsToObserve; + }; + var filter = function(attrs) { + var options = {}; + for (var key in attrs) { + if (key.match(/^\$/) || key.match(/^ng[A-Z]/)) { + void 0; + } else { + options[key] = attrs[key]; + } + } + return options; + }; + var getOptions = function(attrs, params) { + var options = {}; + for (var key in attrs) { + if (attrs[key] || attrs[key] === 0) { + if (key.match(/^on[A-Z]/)) { + continue; + } else if (key.match(/ControlOptions$/)) { + continue; + } else { + if (typeof attrs[key] !== "string") { + options[key] = attrs[key]; + } else { + if (params && params.doNotConverStringToNumber && attrs[key].match(/^[0-9]+$/)) { + options[key] = attrs[key]; + } else { + options[key] = toOptionValue(attrs[key], { + key: key + }); + } + } + } + } + } + return options; + }; + var getEvents = function(scope, attrs) { + var events = {}; + var toLowercaseFunc = function($1) { + return "_" + $1.toLowerCase(); + }; + var EventFunc = function(attrValue) { + var matches = attrValue.match(/([^\(]+)\(([^\)]*)\)/); + var funcName = matches[1]; + var argsStr = matches[2].replace(/event[ ,]*/, ""); + var argsExpr = $parse("[" + argsStr + "]"); + return function(event) { + var args = argsExpr(scope); + function index(obj, i) { + return obj[i]; + } + var f = funcName.split(".").reduce(index, scope); + f && f.apply(this, [ event ].concat(args)); + $timeout(function() { + scope.$apply(); + }); + }; + }; + for (var key in attrs) { + if (attrs[key]) { + if (!key.match(/^on[A-Z]/)) { + continue; + } + var eventName = key.replace(/^on/, ""); + eventName = eventName.charAt(0).toLowerCase() + eventName.slice(1); + eventName = eventName.replace(/([A-Z])/g, toLowercaseFunc); + var attrValue = attrs[key]; + events[eventName] = new EventFunc(attrValue); + } + } + return events; + }; + var getControlOptions = function(filtered) { + var controlOptions = {}; + if (typeof filtered != "object") { + return false; + } + for (var attr in filtered) { + if (filtered[attr]) { + if (!attr.match(/(.*)ControlOptions$/)) { + continue; + } + var orgValue = filtered[attr]; + var newValue = orgValue.replace(/'/g, '"'); + newValue = newValue.replace(/([^"]+)|("[^"]+")/g, function($0, $1, $2) { + if ($1) { + return $1.replace(/([a-zA-Z0-9]+?):/g, '"$1":'); + } else { + return $2; + } + }); + try { + var options = JSON.parse(newValue); + for (var key in options) { + if (options[key]) { + var value = options[key]; + if (typeof value === "string") { + value = value.toUpperCase(); + } else if (key === "mapTypeIds") { + value = value.map(function(str) { + if (str.match(/^[A-Z]+$/)) { + return google.maps.MapTypeId[str.toUpperCase()]; + } else { + return str; + } + }); + } + if (key === "style") { + var str = attr.charAt(0).toUpperCase() + attr.slice(1); + var objName = str.replace(/Options$/, "") + "Style"; + options[key] = google.maps[objName][value]; + } else if (key === "position") { + options[key] = google.maps.ControlPosition[value]; + } else { + options[key] = value; + } + } + } + controlOptions[attr] = options; + } catch (e) { + void 0; + } + } + } + return controlOptions; + }; + return { + filter: filter, + getOptions: getOptions, + getEvents: getEvents, + getControlOptions: getControlOptions, + toOptionValue: toOptionValue, + getAttrsToObserve: getAttrsToObserve, + orgAttributes: orgAttributes + }; + }; + Attr2MapOptions.$inject = [ "$parse", "$timeout", "$log", "NavigatorGeolocation", "GeoCoder", "camelCaseFilter", "jsonizeFilter" ]; + angular.module("ngMap").service("Attr2MapOptions", Attr2MapOptions); +})(); -angular.module("template/timepicker/timepicker.html", []).run([ "$templateCache", function($templateCache) { - $templateCache.put("template/timepicker/timepicker.html", "\n" + " \n" + ' \n' + ' \n' + " \n" + ' \n' + ' \n' + " \n" + " \n" + ' \n" + " \n" + ' \n" + ' \n' + " \n" + ' \n' + ' \n' + " \n" + ' \n' + ' \n' + " \n" + " \n" + "
         
        \n' + ' \n' + " :\n' + ' \n' + "
         
        \n" + ""); -} ]); +(function() { + "use strict"; + var $q; + var geocodeFunc = function(options) { + var deferred = $q.defer(); + var geocoder = new google.maps.Geocoder(); + geocoder.geocode(options, function(results, status) { + if (status == google.maps.GeocoderStatus.OK) { + deferred.resolve(results); + } else { + deferred.reject(status); + } + }); + return deferred.promise; + }; + var GeoCoder = function(_$q_) { + $q = _$q_; + return { + geocode: geocodeFunc + }; + }; + GeoCoder.$inject = [ "$q" ]; + angular.module("ngMap").service("GeoCoder", GeoCoder); +})(); -angular.module("template/typeahead/typeahead-match.html", []).run([ "$templateCache", function($templateCache) { - $templateCache.put("template/typeahead/typeahead-match.html", '\n' + ""); -} ]); +(function() { + "use strict"; + var $q; + var getCurrentPosition = function(geoLocationOptions) { + var deferred = $q.defer(); + if (navigator.geolocation) { + if (geoLocationOptions === undefined) { + geoLocationOptions = { + timeout: 5e3 + }; + } else if (geoLocationOptions.timeout === undefined) { + geoLocationOptions.timeout = 5e3; + } + navigator.geolocation.getCurrentPosition(function(position) { + deferred.resolve(position); + }, function(evt) { + void 0; + deferred.reject(evt); + }, geoLocationOptions); + } else { + deferred.reject("Browser Geolocation service failed."); + } + return deferred.promise; + }; + var NavigatorGeolocation = function(_$q_) { + $q = _$q_; + return { + getCurrentPosition: getCurrentPosition + }; + }; + NavigatorGeolocation.$inject = [ "$q" ]; + angular.module("ngMap").service("NavigatorGeolocation", NavigatorGeolocation); +})(); -angular.module("template/typeahead/typeahead-popup.html", []).run([ "$templateCache", function($templateCache) { - $templateCache.put("template/typeahead/typeahead-popup.html", '\n" + ""); -} ]); +(function() { + "use strict"; + var $window, $document, $q; + var NavigatorGeolocation, Attr2MapOptions, GeoCoder, camelCaseFilter; + var mapControllers = {}; + var initMap = function(id) { + var ctrl = mapControllers[id || 0]; + ctrl.initializeMap(); + }; + var getMap = function(options) { + options = options || {}; + var deferred = $q.defer(); + var id = options.id || 0; + var timeout = options.timeout || 2e3; + function waitForMap(timeElapsed) { + if (mapControllers[id]) { + deferred.resolve(mapControllers[id].map); + } else if (timeElapsed > timeout) { + deferred.reject("could not find map"); + } else { + $window.setTimeout(function() { + waitForMap(timeElapsed + 100); + }, 100); + } + } + waitForMap(0); + return deferred.promise; + }; + var addMap = function(mapCtrl) { + var len = Object.keys(mapControllers).length; + mapControllers[mapCtrl.map.id || len] = mapCtrl; + }; + var deleteMap = function(mapCtrl) { + var len = Object.keys(mapControllers).length - 1; + delete mapControllers[mapCtrl.map.id || len]; + }; + var getStyle = function(el, styleProp) { + var y; + if (el.currentStyle) { + y = el.currentStyle[styleProp]; + } else if ($window.getComputedStyle) { + y = $document.defaultView.getComputedStyle(el, null).getPropertyValue(styleProp); + } + return y; + }; + var getNgMapDiv = function(ngMapEl) { + var el = $document.createElement("div"); + var defaultStyle = ngMapEl.getAttribute("default-style"); + el.style.width = "100%"; + el.style.height = "100%"; + if (defaultStyle == "true") { + ngMapEl.style.display = "block"; + ngMapEl.style.height = "300px"; + } else { + if (getStyle(ngMapEl, "display") != "block") { + ngMapEl.style.display = "block"; + } + if (getStyle(ngMapEl, "height").match(/^(0|auto)/)) { + ngMapEl.style.height = "300px"; + } + } + el.addEventListener("dragstart", function(event) { + event.preventDefault(); + return false; + }); + return el; + }; + var getGeoLocation = function(string, options) { + var deferred = $q.defer(); + if (!string || string.match(/^current/i)) { + NavigatorGeolocation.getCurrentPosition(options).then(function(position) { + var lat = position.coords.latitude; + var lng = position.coords.longitude; + var latLng = new google.maps.LatLng(lat, lng); + deferred.resolve(latLng); + }, function(error) { + deferred.reject(error); + }); + } else { + GeoCoder.geocode({ + address: string + }).then(function(results) { + deferred.resolve(results[0].geometry.location); + }, function(error) { + deferred.reject(error); + }); + } + return deferred.promise; + }; + var observeAndSet = function(attrName, object) { + return function(val) { + if (val) { + void 0; + var setMethod = camelCaseFilter("set-" + attrName); + var optionValue = Attr2MapOptions.toOptionValue(val, { + key: attrName + }); + void 0; + if (object[setMethod]) { + if (attrName.match(/center|position/) && typeof optionValue == "string") { + getGeoLocation(optionValue).then(function(latlng) { + object[setMethod](latlng); + }); + } else { + object[setMethod](optionValue); + } + } + } + }; + }; + angular.module("ngMap").provider("NgMap", function() { + var defaultOptions = {}; + var useTinfoilShielding = false; + this.setDefaultOptions = function(options) { + defaultOptions = options; + }; + var NgMap = function(_$window_, _$document_, _$q_, _NavigatorGeolocation_, _Attr2MapOptions_, _GeoCoder_, _camelCaseFilter_) { + $window = _$window_; + $document = _$document_[0]; + $q = _$q_; + NavigatorGeolocation = _NavigatorGeolocation_; + Attr2MapOptions = _Attr2MapOptions_; + GeoCoder = _GeoCoder_; + camelCaseFilter = _camelCaseFilter_; + return { + defaultOptions: defaultOptions, + addMap: addMap, + deleteMap: deleteMap, + getMap: getMap, + initMap: initMap, + getStyle: getStyle, + getNgMapDiv: getNgMapDiv, + getGeoLocation: getGeoLocation, + observeAndSet: observeAndSet + }; + }; + NgMap.$inject = [ "$window", "$document", "$q", "NavigatorGeolocation", "Attr2MapOptions", "GeoCoder", "camelCaseFilter" ]; + this.$get = NgMap; + }); +})(); -!angular.$$csp() && angular.element(document).find("head").prepend(''); +(function() { + "use strict"; + var $q; + var getPanorama = function(map, latlng) { + latlng = latlng || map.getCenter(); + var deferred = $q.defer(); + var svs = new google.maps.StreetViewService(); + svs.getPanoramaByLocation(latlng || map.getCenter, 100, function(data, status) { + if (status === google.maps.StreetViewStatus.OK) { + deferred.resolve(data.location.pano); + } else { + deferred.resolve(false); + } + }); + return deferred.promise; + }; + var setPanorama = function(map, panoId) { + var svp = new google.maps.StreetViewPanorama(map.getDiv(), { + enableCloseButton: true + }); + svp.setPano(panoId); + }; + var StreetView = function(_$q_) { + $q = _$q_; + return { + getPanorama: getPanorama, + setPanorama: setPanorama + }; + }; + StreetView.$inject = [ "$q" ]; + angular.module("ngMap").service("StreetView", StreetView); +})(); function getCookie(name) { var nameEQ = name + "="; @@ -27341,6 +31952,12 @@ var cloneObject = function(oldObject) { return JSON.parse(JSON.stringify(oldObject)); }; +var enableControls = function(controls, enabled) { + _.each(controls, function(value, key) { + controls[key] = enabled; + }); +}; + var lingvodoc = {}; lingvodoc.Object = function(clientId, objectId) { @@ -27348,10 +31965,7 @@ lingvodoc.Object = function(clientId, objectId) { this.object_id = objectId; this.type = "abstract"; this.getId = function() { - return this.client_id + "" + this.object_id; - }; - this.export = function() { - return {}; + return this.client_id + "_" + this.object_id; }; }; @@ -27412,13 +32026,33 @@ lingvodoc.Perspective = function(client_id, object_id, parent_client_id, parent_ this.is_template = is_template; this.marked_for_deletion = marked_for_deletion; this.fields = []; + this.location = null; + this.blobs = []; + this.additional_metadata = {}; this.equals = function(obj) { return lingvodoc.Object.prototype.equals.call(this, obj) && this.translation == obj.translation; }; }; lingvodoc.Perspective.fromJS = function(js) { - return new lingvodoc.Perspective(js.client_id, js.object_id, js.parent_client_id, js.parent_object_id, js.translation, js.translation_string, js.status, js.is_template, js.marked_for_deletion); + var perspective = new lingvodoc.Perspective(js.client_id, js.object_id, js.parent_client_id, js.parent_object_id, js.translation, js.translation_string, js.status, js.is_template, js.marked_for_deletion); + if (_.has(js, "location") && _.has(js.location, "content")) { + perspective["location"] = { + lat: js.location.content.lat, + lng: js.location.content.lng + }; + } + if (_.has(js, "info") && js.info.type == "list") { + if (_.isArray(js.info.content)) { + perspective["blobs"] = _.map(js.info.content, function(e) { + var blob = new lingvodoc.Blob(e.info.content.client_id, e.info.content.object_id, e.info.content.name, e.info.content.data_type); + blob.url = e.info.content.content; + return blob; + }); + } + } + perspective.additional_metadata = js.additional_metadata; + return perspective; }; lingvodoc.Perspective.prototype = new lingvodoc.Object(); @@ -27443,6 +32077,25 @@ lingvodoc.User.fromJS = function(js) { return new lingvodoc.User(js.id, js.login, js.name, js.email, js.intl_name, js.about, js.signup_date, js.organizations); }; +lingvodoc.Blob = function(clientId, objectId, name, data_type) { + lingvodoc.Object.call(this, clientId, objectId); + this.type = "blob"; + this.name = name; + this.data_type = data_type; + this.url = null; + this.equals = function(obj) { + return lingvodoc.Object.prototype.equals.call(this, obj) && this.name == obj.name; + }; +}; + +lingvodoc.Blob.fromJS = function(js) { + return new lingvodoc.Blob(js.client_id, js.object_id, js.name, js.data_type); +}; + +lingvodoc.Blob.prototype = new lingvodoc.Object(); + +lingvodoc.Blob.prototype.constructor = lingvodoc.Blob; + function lingvodocAPI($http, $q) { var addUrlParameter = function(url, key, value) { return url + (url.indexOf("?") >= 0 ? "&" : "?") + encodeURIComponent(key) + "=" + encodeURIComponent(value); @@ -27516,6 +32169,21 @@ function lingvodocAPI($http, $q) { }); return deferred.promise; }; + var getPerspectiveDictionaryFieldsNew = function(perspective) { + var deferred = $q.defer(); + var url = "/dictionary/" + perspective.parent_client_id + "/" + perspective.parent_object_id + "/perspective/" + perspective.client_id + "/" + perspective.object_id + "/fields"; + $http.get(url).success(function(data, status, headers, config) { + if (_.isArray(data.fields)) { + var fields = perspectiveToDictionaryFields(data.fields); + deferred.resolve(fields); + } else { + deferred.reject("An error occurred while fetching perspective fields"); + } + }).error(function(data, status, headers, config) { + deferred.reject("An error occurred while fetching perspective fields"); + }); + return deferred.promise; + }; var removeValue = function(entry, field, fieldValue, parent) { var deferred = $q.defer(); var url; @@ -27682,8 +32350,9 @@ function lingvodocAPI($http, $q) { }); return deferred.promise; }; - var getDictionaryProperties = function(url) { + var getDictionaryProperties = function(dictionary) { var deferred = $q.defer(); + var url = "/dictionary/" + encodeURIComponent(dictionary.client_id) + "/" + encodeURIComponent(dictionary.object_id); $http.get(url).success(function(data, status, headers, config) { deferred.resolve(data); }).error(function(data, status, headers, config) { @@ -27691,8 +32360,9 @@ function lingvodocAPI($http, $q) { }); return deferred.promise; }; - var setDictionaryProperties = function(url, properties) { + var setDictionaryProperties = function(dictionary, properties) { var deferred = $q.defer(); + var url = "/dictionary/" + encodeURIComponent(dictionary.client_id) + "/" + encodeURIComponent(dictionary.object_id); $http.put(url, properties).success(function(data, status, headers, config) { deferred.resolve(data); }).error(function(data, status, headers, config) { @@ -27700,6 +32370,16 @@ function lingvodocAPI($http, $q) { }); return deferred.promise; }; + var removeDictionary = function(dictionary) { + var deferred = $q.defer(); + var url = "/dictionary/" + encodeURIComponent(dictionary.client_id) + "/" + encodeURIComponent(dictionary.object_id); + $http.delete(url).success(function(data, status, headers, config) { + deferred.resolve(); + }).error(function(data, status, headers, config) { + deferred.reject("An error occurred while trying to delete dictionary"); + }); + return deferred.promise; + }; var getLanguages = function(url) { var deferred = $q.defer(); var flatLanguages = function(languages) { @@ -27783,6 +32463,16 @@ function lingvodocAPI($http, $q) { }); return deferred.promise; }; + var removePerspective = function(perspective) { + var deferred = $q.defer(); + var url = "/dictionary/" + perspective.parent_client_id + "/" + perspective.parent_object_id + "/perspective/" + perspective.client_id + "/" + perspective.object_id; + $http.delete(url).success(function(data, status, headers, config) { + deferred.resolve(); + }).error(function(data, status, headers, config) { + deferred.reject("An error occurred while trying to delete perspective"); + }); + return deferred.promise; + }; var getUserInfo = function(userId, clientId) { var deferred = $q.defer(); var url = "/user" + "?client_id= " + encodeURIComponent(clientId) + "&user_id= " + encodeURIComponent(userId); @@ -27863,13 +32553,14 @@ function lingvodocAPI($http, $q) { }; var getDictionaries = function(query) { var deferred = $q.defer(); - var dictionaries = []; $http.post("/dictionaries", query).success(function(data, status, headers, config) { - for (var i = 0; i < data.dictionaries.length; i++) { - var dictionary = data.dictionaries[i]; - dictionaries.push(lingvodoc.Dictionary.fromJS(dictionary)); + if (_.isArray(data.dictionaries)) { + deferred.resolve(_.map(data.dictionaries, function(d) { + return lingvodoc.Dictionary.fromJS(d); + })); + } else { + deferred.reject("Failed to fetch dictionaries list. Malformed response."); } - deferred.resolve(dictionaries); }).error(function(data, status, headers, config) { deferred.reject("Failed to fetch dictionaries list"); }); @@ -28086,8 +32777,8 @@ function lingvodocAPI($http, $q) { }; $http.post("/dictionaries", req).success(function(data, status, headers, config) { var dictionaries = []; - if (angular.isArray(data.dictionaries)) { - angular.forEach(data.dictionaries, function(jsdict) { + if (_.isArray(data.dictionaries)) { + _.forEach(data.dictionaries, function(jsdict) { var dictionary = lingvodoc.Dictionary.fromJS(jsdict); if (language.client_id == dictionary.parent_client_id && language.object_id == dictionary.parent_object_id) { dictionaries.push(dictionary); @@ -28096,7 +32787,7 @@ function lingvodocAPI($http, $q) { } deferred.resolve(dictionaries); }).error(function(data, status, headers, config) { - deferred.reject("Failed to move lexical entry"); + deferred.reject("Failed to fetch list of dictionaries"); }); return deferred.promise; }; @@ -28279,10 +32970,140 @@ function lingvodocAPI($http, $q) { }); return deferred.promise; }; + var getUserBlobs = function() { + var deferred = $q.defer(); + $http.get("/blobs").success(function(data, status, headers, config) { + var blobs = _.map(data, lingvodoc.Blob.fromJS); + deferred.resolve(blobs); + }).error(function(data, status, headers, config) { + deferred.reject("Failed to fetch list of available blobs"); + }); + return deferred.promise; + }; + var checkDictionaryBlob = function(blob, parent) { + var deferred = $q.defer(); + var query = { + blob_client_id: blob.client_id, + blob_object_id: blob.object_id, + parent_client_id: parent.client_id, + parent_object_id: parent.object_id + }; + $http.post("/convert_check", query).success(function(data, status, headers, config) { + var perspectives = _.map(data, lingvodoc.Perspective.fromJS); + deferred.resolve(perspectives); + }).error(function(data, status, headers, config) { + deferred.reject("Failed to convert dictionary"); + }); + return deferred.promise; + }; + var convertDictionary = function(req) { + var deferred = $q.defer(); + $http.post("/convert", req).success(function(data, status, headers, config) { + deferred.resolve(data); + }).error(function(data, status, headers, config) { + deferred.reject("Failed to convert dictionary"); + }); + return deferred.promise; + }; + var getPerspectiveMeta = function(dictionary, perspective) { + var deferred = $q.defer(); + var url = "/dictionary/" + encodeURIComponent(dictionary.client_id) + "/" + encodeURIComponent(dictionary.object_id) + "/perspective/" + encodeURIComponent(perspective.client_id) + "/" + encodeURIComponent(perspective.object_id) + "/meta"; + $http.get(url).success(function(data, status, headers, config) { + deferred.resolve(data); + }).error(function(data, status, headers, config) { + deferred.reject("Failed to get perspective meta data!"); + }); + return deferred.promise; + }; + var setPerspectiveMeta = function(dictionary, perspective, meta) { + var deferred = $q.defer(); + var url = "/dictionary/" + encodeURIComponent(dictionary.client_id) + "/" + encodeURIComponent(dictionary.object_id) + "/perspective/" + encodeURIComponent(perspective.client_id) + "/" + encodeURIComponent(perspective.object_id) + "/meta"; + $http.put(url, meta).success(function(data, status, headers, config) { + deferred.resolve(data); + }).error(function(data, status, headers, config) { + deferred.reject("Failed to set perspective meta data!"); + }); + return deferred.promise; + }; + var removePerspectiveMeta = function(dictionary, perspective, meta) { + var deferred = $q.defer(); + var url = "/dictionary/" + encodeURIComponent(dictionary.client_id) + "/" + encodeURIComponent(dictionary.object_id) + "/perspective/" + encodeURIComponent(perspective.client_id) + "/" + encodeURIComponent(perspective.object_id) + "/meta"; + var config = { + method: "DELETE", + url: url, + data: meta, + headers: { + "Content-Type": "application/json;charset=utf-8" + } + }; + $http(config).success(function(data, status, headers, config) { + deferred.resolve(data); + }).error(function(data, status, headers, config) { + deferred.reject("Failed to remove perspective meta data!"); + }); + return deferred.promise; + }; + var advancedSearch = function(query, where, adopted, etymology) { + var deferred = $q.defer(); + var url = "/advanced_search"; + var perspectives = where.map(function(o) { + if (o.type == "perspective") { + return { + client_id: o.client_id, + object_id: o.object_id + }; + } + }).filter(function(o) { + return typeof o !== "undefined"; + }); + var req = { + searchstrings: query, + perspectives: perspectives + }; + if (_.isBoolean(adopted)) { + req.adopted = adopted; + } + if (_.isBoolean(etymology)) { + req.with_etimology = etymology; + } + $http.post(url, req).success(function(data, status, headers, config) { + var r = data.map(function(e) { + var perspective = lingvodoc.Perspective.fromJS(e); + return getPerspectiveOriginById(perspective.client_id, perspective.object_id); + }); + $q.all(r).then(function(paths) { + var out = []; + _.each(data, function(entry, i) { + entry.lexical_entry["origin"] = paths[i]; + out.push(entry.lexical_entry); + }); + deferred.resolve(out); + }, function(reason) { + deferred.reject("An error occurred while doing basic search"); + }); + }).error(function(data, status, headers, config) { + deferred.reject("An error occurred while doing advanced search"); + }); + return deferred.promise; + }; + var convertMarkup = function(object) { + var deferred = $q.defer(); + var obj = { + client_id: object.client_id, + object_id: object.object_id + }; + $http.post("/convert/markup", obj).success(function(data, status, headers, config) { + deferred.resolve(data); + }).error(function(data, status, headers, config) { + deferred.reject("Failed to convert markup!"); + }); + return deferred.promise; + }; return { getLexicalEntries: getLexicalEntries, getLexicalEntriesCount: getLexicalEntriesCount, getPerspectiveDictionaryFields: getPerspectiveDictionaryFields, + getPerspectiveDictionaryFieldsNew: getPerspectiveDictionaryFieldsNew, addNewLexicalEntry: addNewLexicalEntry, saveValue: saveValue, removeValue: removeValue, @@ -28293,6 +33114,7 @@ function lingvodocAPI($http, $q) { approveAll: approveAll, getDictionaryProperties: getDictionaryProperties, setDictionaryProperties: setDictionaryProperties, + removeDictionary: removeDictionary, getLanguages: getLanguages, setDictionaryStatus: setDictionaryStatus, setPerspectiveStatus: setPerspectiveStatus, @@ -28300,6 +33122,7 @@ function lingvodocAPI($http, $q) { getPerspectiveFields: getPerspectiveFields, setPerspectiveFields: setPerspectiveFields, getPerspectiveFieldsNew: getPerspectiveFieldsNew, + removePerspective: removePerspective, getUserInfo: getUserInfo, setUserInfo: setUserInfo, getOrganizations: getOrganizations, @@ -28326,7 +33149,15 @@ function lingvodocAPI($http, $q) { deleteDictionaryRoles: deleteDictionaryRoles, getPerspectiveRoles: getPerspectiveRoles, addPerspectiveRoles: addPerspectiveRoles, - deletePerspectiveRoles: deletePerspectiveRoles + deletePerspectiveRoles: deletePerspectiveRoles, + getUserBlobs: getUserBlobs, + checkDictionaryBlob: checkDictionaryBlob, + convertDictionary: convertDictionary, + getPerspectiveMeta: getPerspectiveMeta, + setPerspectiveMeta: setPerspectiveMeta, + removePerspectiveMeta: removePerspectiveMeta, + advancedSearch: advancedSearch, + convertMarkup: convertMarkup }; } @@ -28358,15 +33189,40 @@ function responseHandler($timeout, $modal) { function error(message) { show("error", message, 5e3); } + function yesno(status, message, callback) { + var controller = function($scope, $modalInstance) { + $scope.status = status; + $scope.message = message; + $scope.yes = function() { + $modalInstance.close(true); + }; + $scope.no = function() { + $modalInstance.close(false); + }; + }; + $modal.open({ + animation: true, + templateUrl: "responseHandlerYesNoModal.html", + controller: controller, + size: "lg", + backdrop: "static", + keyboard: false + }).result.then(function(result) { + callback(result); + }, function() { + callback(false); + }); + } return { success: success, - error: error + error: error, + yesno: yesno }; } "use strict"; -var app = angular.module("DashboardModule", [ "ui.bootstrap" ]); +var app = angular.module("DashboardModule", [ "ui.bootstrap", "ngMap" ]); app.service("dictionaryService", lingvodocAPI); @@ -28375,17 +33231,7 @@ app.factory("responseHandler", [ "$timeout", "$modal", responseHandler ]); app.controller("DashboardController", [ "$scope", "$http", "$q", "$modal", "$log", "dictionaryService", "responseHandler", function($scope, $http, $q, $modal, $log, dictionaryService, responseHandler) { var userId = $("#userId").data("lingvodoc"); var languagesUrl = $("#languagesUrl").data("lingvodoc"); - var dictionariesUrl = $("#dictionariesUrl").data("lingvodoc"); - var getUserInfoUrl = $("#getUserInfoUrl").data("lingvodoc"); $scope.dictionaries = []; - var getObjectByCompositeKey = function(id, arr) { - if (typeof id == "string") { - var ids = id.split("_"); - for (var i = 0; i < arr.length; i++) { - if (arr[i].client_id == ids[0] && arr[i].object_id == ids[1]) return arr[i]; - } - } - }; $scope.getActionLink = function(dictionary, perspective, action) { return "/dictionary/" + encodeURIComponent(dictionary.client_id) + "/" + encodeURIComponent(dictionary.object_id) + "/perspective/" + encodeURIComponent(perspective.client_id) + "/" + encodeURIComponent(perspective.object_id) + "/" + action; }; @@ -28479,18 +33325,6 @@ app.controller("DashboardController", [ "$scope", "$http", "$q", "$modal", "$log } }); }; - $scope.follow = function(link) { - if (!link) { - alert("Please, select perspective first."); - return; - } - window.location = link; - }; - $scope.getCompositeKey = function(object) { - if (object) { - return object.client_id + "_" + object.object_id; - } - }; $scope.setPerspectiveStatus = function(dictionary, perspective, status) { dictionaryService.setPerspectiveStatus(dictionary, perspective, status).then(function(data) { perspective.status = status; @@ -28505,6 +33339,32 @@ app.controller("DashboardController", [ "$scope", "$http", "$q", "$modal", "$log responseHandler.error(reason); }); }; + $scope.removeDictionary = function(dictionary) { + responseHandler.yesno("", "Do you really want to remove dictionary?", function(confirmed) { + if (confirmed) { + dictionaryService.removeDictionary(dictionary).then(function() { + _.remove($scope.dictionaries, function(d) { + return d.equals(dictionary); + }); + }, function(reason) { + responseHandler.error(reason); + }); + } + }); + }; + $scope.removePerspective = function(dictionary, perspective) { + responseHandler.yesno("", "Do you really want to remove perspective?", function(confirmed) { + if (confirmed) { + dictionaryService.removePerspective(perspective).then(function() { + _.remove(dictionary.perspectives, function(p) { + return p.equals(perspective); + }); + }, function(reason) { + responseHandler.error(reason); + }); + } + }); + }; $scope.loadMyDictionaries = function() { var dictionaryQuery = { user_created: [ userId ] @@ -28543,7 +33403,8 @@ app.controller("createPerspectiveController", [ "$scope", "$http", "$q", "$modal }; $scope.isTemplate = false; $scope.controls = { - ok: true + ok: true, + cancel: true }; $scope.addField = function() { $scope.perspective.fields.push({ @@ -28583,13 +33444,13 @@ app.controller("createPerspectiveController", [ "$scope", "$http", "$q", "$modal translation: $scope.perspectiveName, is_template: $scope.isTemplate }; - $scope.controls.ok = false; + enableControls($scope.controls, false); var fields = exportPerspective($scope.perspective); dictionaryService.createPerspective($scope.dictionary, perspectiveObj, fields).then(function(perspective) { - $scope.controls.ok = true; + enableControls($scope.controls, true); $modalInstance.close(perspective); }, function(reason) { - $scope.controls.ok = true; + enableControls($scope.controls, true); responseHandler.error(reason); }); }; @@ -28634,8 +33495,7 @@ app.controller("editDictionaryPropertiesController", [ "$scope", "$http", "$q", langs.push(language); }); $scope.languages = langs; - var url = "/dictionary/" + encodeURIComponent(params.dictionary.client_id) + "/" + encodeURIComponent(params.dictionary.object_id); - dictionaryService.getDictionaryProperties(url).then(function(dictionaryProperties) { + dictionaryService.getDictionaryProperties(params.dictionary).then(function(dictionaryProperties) { var selectedLanguageCompositeId = getCompositeKey(dictionaryProperties, "parent_client_id", "parent_object_id"); $scope.dictionaryProperties = dictionaryProperties; $scope.data.selectedLanguage = selectedLanguageCompositeId; @@ -28666,8 +33526,7 @@ app.controller("editDictionaryPropertiesController", [ "$scope", "$http", "$q", $scope.dictionaryProperties["parent_client_id"] = null; $scope.dictionaryProperties["parent_object_id"] = null; } - var url = "/dictionary/" + encodeURIComponent(params.dictionary.client_id) + "/" + encodeURIComponent(params.dictionary.object_id); - dictionaryService.setDictionaryProperties(url, $scope.dictionaryProperties).then(function() { + dictionaryService.setDictionaryProperties(params.dictionary, $scope.dictionaryProperties).then(function() { $modalInstance.close(); }); }; @@ -28676,12 +33535,16 @@ app.controller("editDictionaryPropertiesController", [ "$scope", "$http", "$q", }; } ]); -app.controller("editPerspectivePropertiesController", [ "$scope", "$http", "$q", "$modalInstance", "$log", "dictionaryService", "responseHandler", "params", function($scope, $http, $q, $modalInstance, $log, dictionaryService, responseHandler, params) { +app.controller("editPerspectivePropertiesController", [ "$scope", "$http", "$q", "$modal", "$modalInstance", "$log", "dictionaryService", "responseHandler", "params", function($scope, $http, $q, $modal, $modalInstance, $log, dictionaryService, responseHandler, params) { $scope.dictionary = params.dictionary; $scope.perspective = {}; + $scope.blobs = []; + $scope.blobId = ""; $scope.controls = { - ok: true + ok: true, + cancel: true }; + $scope.authors = ""; $scope.addField = function() { $scope.perspective.fields.push({ entity_type: "", @@ -28696,19 +33559,122 @@ app.controller("editPerspectivePropertiesController", [ "$scope", "$http", "$q", } } }; + $scope.editGeoLabels = function() { + $modal.open({ + animation: true, + templateUrl: "perspectiveGeoLabelsModal.html", + controller: "perspectiveGeoLabelsController", + size: "lg", + backdrop: "static", + keyboard: false, + resolve: { + params: function() { + return { + dictionary: params.dictionary, + perspective: params.perspective + }; + } + } + }); + }; + $scope.addBlob = function() { + var b1 = _.find($scope.perspective.blobs, function(b) { + return b.getId() == $scope.blobId; + }); + $log.info(b1); + if (!!b1) { + return; + } + var blob = _.find($scope.blobs, function(b) { + return b.getId() == $scope.blobId; + }); + if (blob) { + var blobs = $scope.perspective.blobs.map(function(b) { + return { + info: { + type: "blob", + content: { + client_id: b.client_id, + object_id: b.object_id + } + } + }; + }); + blobs.push({ + info: { + type: "blob", + content: { + client_id: blob.client_id, + object_id: blob.object_id + } + } + }); + var meta = { + info: { + type: "list", + content: blobs + } + }; + dictionaryService.setPerspectiveMeta(params.dictionary, params.perspective, meta).then(function(response) { + $scope.perspective.blobs.push(blob); + }, function(reason) { + responseHandler.error(reason); + }); + } + }; + $scope.removeBlob = function(blob) { + var blobs = _.filter($scope.perspective.blobs, function(b) { + return !b.equals(blob); + }); + var blobsMeta = blobs.map(function(b) { + return { + info: { + type: "blob", + content: { + client_id: b.client_id, + object_id: b.object_id + } + } + }; + }); + var meta = { + info: { + type: "list", + content: blobsMeta + } + }; + dictionaryService.setPerspectiveMeta(params.dictionary, params.perspective, meta).then(function(response) { + _.remove($scope.perspective.blobs, function(b) { + return b.equals(blob); + }); + }, function(reason) { + responseHandler.error(reason); + }); + }; $scope.ok = function() { - $scope.controls.ok = false; - dictionaryService.setPerspectiveProperties($scope.dictionary, $scope.perspective).then(function(data) { - var url = "/dictionary/" + encodeURIComponent(params.dictionary.client_id) + "/" + encodeURIComponent(params.dictionary.object_id) + "/perspective/" + encodeURIComponent(params.perspective.client_id) + "/" + encodeURIComponent(params.perspective.object_id) + "/fields"; - dictionaryService.setPerspectiveFields(url, exportPerspective($scope.perspective)).then(function(fields) { - $scope.controls.ok = true; - $modalInstance.close(); + enableControls($scope.controls, false); + var meta = { + authors: { + type: "authors", + content: $scope.authors + } + }; + dictionaryService.setPerspectiveMeta($scope.dictionary, $scope.perspective, meta).then(function(response) { + dictionaryService.setPerspectiveProperties($scope.dictionary, $scope.perspective).then(function(data) { + var url = "/dictionary/" + encodeURIComponent(params.dictionary.client_id) + "/" + encodeURIComponent(params.dictionary.object_id) + "/perspective/" + encodeURIComponent(params.perspective.client_id) + "/" + encodeURIComponent(params.perspective.object_id) + "/fields"; + dictionaryService.setPerspectiveFields(url, exportPerspective($scope.perspective)).then(function(fields) { + enableControls($scope.controls, true); + $modalInstance.close(); + }, function(reason) { + enableControls($scope.controls, true); + responseHandler.error(reason); + }); }, function(reason) { - $scope.controls.ok = true; + enableControls($scope.controls, true); responseHandler.error(reason); }); }, function(reason) { - $scope.controls.ok = true; + enableControls($scope.controls, true); responseHandler.error(reason); }); }; @@ -28722,6 +33688,20 @@ app.controller("editPerspectivePropertiesController", [ "$scope", "$http", "$q", }, function(reason) { responseHandler.error(reason); }); + dictionaryService.getUserBlobs().then(function(blobs) { + $scope.blobs = blobs.filter(function(b) { + return b.data_type != "dialeqt_dictionary"; + }); + }, function(reason) { + responseHandler.error(reason); + }); + dictionaryService.getPerspectiveMeta(params.dictionary, params.perspective).then(function(meta) { + if (_.has(meta, "authors") && _.has(meta.authors, "content") && _.isString(meta.authors.content)) { + $scope.authors = meta.authors.content; + } + }, function(reason) { + responseHandler.error(reason); + }); } ]); app.controller("editDictionaryRolesController", [ "$scope", "$http", "$q", "$modalInstance", "$log", "dictionaryService", "responseHandler", "params", function($scope, $http, $q, $modalInstance, $log, dictionaryService, responseHandler, params) { @@ -28987,4 +33967,66 @@ app.controller("editPerspectiveRolesController", [ "$scope", "$http", "$q", "$mo }, function(reason) { responseHandler.error(reason); }); +} ]); + +app.controller("perspectiveGeoLabelsController", [ "$scope", "$http", "$q", "$modalInstance", "$log", "NgMap", "dictionaryService", "responseHandler", "params", function($scope, $http, $q, $modalInstance, $log, NgMap, dictionaryService, responseHandler, params) { + var key = "AIzaSyB6l1ciVMcP1pIUkqvSx8vmuRJL14lbPXk"; + $scope.googleMapsUrl = "http://maps.google.com/maps/api/js?v=3.20&key=" + encodeURIComponent(key); + $scope.positions = []; + $modalInstance.opened.then(function() { + NgMap.getMap().then(function(map) { + google.maps.event.trigger(map, "resize"); + }); + }); + $scope.addMarker = function(event) { + if ($scope.positions.length > 0) { + return; + } + var latLng = event.latLng; + var meta = { + location: { + type: "location", + content: { + lat: latLng.lat(), + lng: latLng.lng() + } + } + }; + dictionaryService.setPerspectiveMeta(params.dictionary, params.perspective, meta).then(function(response) { + $scope.positions.push({ + lat: latLng.lat(), + lng: latLng.lng() + }); + }, function(reason) { + responseHandler.error(reason); + }); + }; + $scope.removeMarker = function(marker) { + var meta = { + location: { + type: "location", + content: { + lat: marker.latLng.lat(), + lng: marker.latLng.lng() + } + } + }; + dictionaryService.removePerspectiveMeta(params.dictionary, params.perspective, meta).then(function(response) { + _.remove($scope.positions, function(e) { + var p = new google.maps.LatLng(e.lat, e.lng); + return p.equals(marker.latLng); + }); + }, function(reason) { + responseHandler.error(reason); + }); + }; + $scope.ok = function() { + $modalInstance.close(); + }; + dictionaryService.getPerspectiveMeta(params.dictionary, params.perspective).then(function(data) { + $scope.positions = []; + if (!_.isEmpty(data) && _.has(data, "location")) { + $scope.positions.push(data.location.content); + } + }); } ]); \ No newline at end of file diff --git a/lingvodoc/static/js/edit-dictionary.js b/lingvodoc/static/js/edit-dictionary.js index 4381568ba..aac11ef92 100644 --- a/lingvodoc/static/js/edit-dictionary.js +++ b/lingvodoc/static/js/edit-dictionary.js @@ -5378,1056 +5378,3943 @@ }); (function() { - var root = this; - var previousUnderscore = root._; - var ArrayProto = Array.prototype, ObjProto = Object.prototype, FuncProto = Function.prototype; - var push = ArrayProto.push, slice = ArrayProto.slice, toString = ObjProto.toString, hasOwnProperty = ObjProto.hasOwnProperty; - var nativeIsArray = Array.isArray, nativeKeys = Object.keys, nativeBind = FuncProto.bind, nativeCreate = Object.create; - var Ctor = function() {}; - var _ = function(obj) { - if (obj instanceof _) return obj; - if (!(this instanceof _)) return new _(obj); - this._wrapped = obj; - }; - if (typeof exports !== "undefined") { - if (typeof module !== "undefined" && module.exports) { - exports = module.exports = _; - } - exports._ = _; - } else { - root._ = _; - } - _.VERSION = "1.8.3"; - var optimizeCb = function(func, context, argCount) { - if (context === void 0) return func; - switch (argCount == null ? 3 : argCount) { - case 1: - return function(value) { - return func.call(context, value); - }; - - case 2: - return function(value, other) { - return func.call(context, value, other); - }; - - case 3: - return function(value, index, collection) { - return func.call(context, value, index, collection); - }; - - case 4: - return function(accumulator, value, index, collection) { - return func.call(context, accumulator, value, index, collection); - }; - } - return function() { - return func.apply(context, arguments); - }; - }; - var cb = function(value, context, argCount) { - if (value == null) return _.identity; - if (_.isFunction(value)) return optimizeCb(value, context, argCount); - if (_.isObject(value)) return _.matcher(value); - return _.property(value); - }; - _.iteratee = function(value, context) { - return cb(value, context, Infinity); + var undefined; + var VERSION = "3.10.1"; + var BIND_FLAG = 1, BIND_KEY_FLAG = 2, CURRY_BOUND_FLAG = 4, CURRY_FLAG = 8, CURRY_RIGHT_FLAG = 16, PARTIAL_FLAG = 32, PARTIAL_RIGHT_FLAG = 64, ARY_FLAG = 128, REARG_FLAG = 256; + var DEFAULT_TRUNC_LENGTH = 30, DEFAULT_TRUNC_OMISSION = "..."; + var HOT_COUNT = 150, HOT_SPAN = 16; + var LARGE_ARRAY_SIZE = 200; + var LAZY_FILTER_FLAG = 1, LAZY_MAP_FLAG = 2; + var FUNC_ERROR_TEXT = "Expected a function"; + var PLACEHOLDER = "__lodash_placeholder__"; + var argsTag = "[object Arguments]", arrayTag = "[object Array]", boolTag = "[object Boolean]", dateTag = "[object Date]", errorTag = "[object Error]", funcTag = "[object Function]", mapTag = "[object Map]", numberTag = "[object Number]", objectTag = "[object Object]", regexpTag = "[object RegExp]", setTag = "[object Set]", stringTag = "[object String]", weakMapTag = "[object WeakMap]"; + var arrayBufferTag = "[object ArrayBuffer]", float32Tag = "[object Float32Array]", float64Tag = "[object Float64Array]", int8Tag = "[object Int8Array]", int16Tag = "[object Int16Array]", int32Tag = "[object Int32Array]", uint8Tag = "[object Uint8Array]", uint8ClampedTag = "[object Uint8ClampedArray]", uint16Tag = "[object Uint16Array]", uint32Tag = "[object Uint32Array]"; + var reEmptyStringLeading = /\b__p \+= '';/g, reEmptyStringMiddle = /\b(__p \+=) '' \+/g, reEmptyStringTrailing = /(__e\(.*?\)|\b__t\)) \+\n'';/g; + var reEscapedHtml = /&(?:amp|lt|gt|quot|#39|#96);/g, reUnescapedHtml = /[&<>"'`]/g, reHasEscapedHtml = RegExp(reEscapedHtml.source), reHasUnescapedHtml = RegExp(reUnescapedHtml.source); + var reEscape = /<%-([\s\S]+?)%>/g, reEvaluate = /<%([\s\S]+?)%>/g, reInterpolate = /<%=([\s\S]+?)%>/g; + var reIsDeepProp = /\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\n\\]|\\.)*?\1)\]/, reIsPlainProp = /^\w*$/, rePropName = /[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\n\\]|\\.)*?)\2)\]/g; + var reRegExpChars = /^[:!,]|[\\^$.*+?()[\]{}|\/]|(^[0-9a-fA-Fnrtuvx])|([\n\r\u2028\u2029])/g, reHasRegExpChars = RegExp(reRegExpChars.source); + var reComboMark = /[\u0300-\u036f\ufe20-\ufe23]/g; + var reEscapeChar = /\\(\\)?/g; + var reEsTemplate = /\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g; + var reFlags = /\w*$/; + var reHasHexPrefix = /^0[xX]/; + var reIsHostCtor = /^\[object .+?Constructor\]$/; + var reIsUint = /^\d+$/; + var reLatin1 = /[\xc0-\xd6\xd8-\xde\xdf-\xf6\xf8-\xff]/g; + var reNoMatch = /($^)/; + var reUnescapedString = /['\n\r\u2028\u2029\\]/g; + var reWords = function() { + var upper = "[A-Z\\xc0-\\xd6\\xd8-\\xde]", lower = "[a-z\\xdf-\\xf6\\xf8-\\xff]+"; + return RegExp(upper + "+(?=" + upper + lower + ")|" + upper + "?" + lower + "|" + upper + "+|[0-9]+", "g"); + }(); + var contextProps = [ "Array", "ArrayBuffer", "Date", "Error", "Float32Array", "Float64Array", "Function", "Int8Array", "Int16Array", "Int32Array", "Math", "Number", "Object", "RegExp", "Set", "String", "_", "clearTimeout", "isFinite", "parseFloat", "parseInt", "setTimeout", "TypeError", "Uint8Array", "Uint8ClampedArray", "Uint16Array", "Uint32Array", "WeakMap" ]; + var templateCounter = -1; + var typedArrayTags = {}; + typedArrayTags[float32Tag] = typedArrayTags[float64Tag] = typedArrayTags[int8Tag] = typedArrayTags[int16Tag] = typedArrayTags[int32Tag] = typedArrayTags[uint8Tag] = typedArrayTags[uint8ClampedTag] = typedArrayTags[uint16Tag] = typedArrayTags[uint32Tag] = true; + typedArrayTags[argsTag] = typedArrayTags[arrayTag] = typedArrayTags[arrayBufferTag] = typedArrayTags[boolTag] = typedArrayTags[dateTag] = typedArrayTags[errorTag] = typedArrayTags[funcTag] = typedArrayTags[mapTag] = typedArrayTags[numberTag] = typedArrayTags[objectTag] = typedArrayTags[regexpTag] = typedArrayTags[setTag] = typedArrayTags[stringTag] = typedArrayTags[weakMapTag] = false; + var cloneableTags = {}; + cloneableTags[argsTag] = cloneableTags[arrayTag] = cloneableTags[arrayBufferTag] = cloneableTags[boolTag] = cloneableTags[dateTag] = cloneableTags[float32Tag] = cloneableTags[float64Tag] = cloneableTags[int8Tag] = cloneableTags[int16Tag] = cloneableTags[int32Tag] = cloneableTags[numberTag] = cloneableTags[objectTag] = cloneableTags[regexpTag] = cloneableTags[stringTag] = cloneableTags[uint8Tag] = cloneableTags[uint8ClampedTag] = cloneableTags[uint16Tag] = cloneableTags[uint32Tag] = true; + cloneableTags[errorTag] = cloneableTags[funcTag] = cloneableTags[mapTag] = cloneableTags[setTag] = cloneableTags[weakMapTag] = false; + var deburredLetters = { + "À": "A", + "Á": "A", + "Â": "A", + "Ã": "A", + "Ä": "A", + "Å": "A", + "à": "a", + "á": "a", + "â": "a", + "ã": "a", + "ä": "a", + "å": "a", + "Ç": "C", + "ç": "c", + "Ð": "D", + "ð": "d", + "È": "E", + "É": "E", + "Ê": "E", + "Ë": "E", + "è": "e", + "é": "e", + "ê": "e", + "ë": "e", + "Ì": "I", + "Í": "I", + "Î": "I", + "Ï": "I", + "ì": "i", + "í": "i", + "î": "i", + "ï": "i", + "Ñ": "N", + "ñ": "n", + "Ò": "O", + "Ó": "O", + "Ô": "O", + "Õ": "O", + "Ö": "O", + "Ø": "O", + "ò": "o", + "ó": "o", + "ô": "o", + "õ": "o", + "ö": "o", + "ø": "o", + "Ù": "U", + "Ú": "U", + "Û": "U", + "Ü": "U", + "ù": "u", + "ú": "u", + "û": "u", + "ü": "u", + "Ý": "Y", + "ý": "y", + "ÿ": "y", + "Æ": "Ae", + "æ": "ae", + "Þ": "Th", + "þ": "th", + "ß": "ss" + }; + var htmlEscapes = { + "&": "&", + "<": "<", + ">": ">", + '"': """, + "'": "'", + "`": "`" + }; + var htmlUnescapes = { + "&": "&", + "<": "<", + ">": ">", + """: '"', + "'": "'", + "`": "`" + }; + var objectTypes = { + "function": true, + object: true + }; + var regexpEscapes = { + "0": "x30", + "1": "x31", + "2": "x32", + "3": "x33", + "4": "x34", + "5": "x35", + "6": "x36", + "7": "x37", + "8": "x38", + "9": "x39", + A: "x41", + B: "x42", + C: "x43", + D: "x44", + E: "x45", + F: "x46", + a: "x61", + b: "x62", + c: "x63", + d: "x64", + e: "x65", + f: "x66", + n: "x6e", + r: "x72", + t: "x74", + u: "x75", + v: "x76", + x: "x78" + }; + var stringEscapes = { + "\\": "\\", + "'": "'", + "\n": "n", + "\r": "r", + "\u2028": "u2028", + "\u2029": "u2029" }; - var createAssigner = function(keysFunc, undefinedOnly) { - return function(obj) { - var length = arguments.length; - if (length < 2 || obj == null) return obj; - for (var index = 1; index < length; index++) { - var source = arguments[index], keys = keysFunc(source), l = keys.length; - for (var i = 0; i < l; i++) { - var key = keys[i]; - if (!undefinedOnly || obj[key] === void 0) obj[key] = source[key]; - } + var freeExports = objectTypes[typeof exports] && exports && !exports.nodeType && exports; + var freeModule = objectTypes[typeof module] && module && !module.nodeType && module; + var freeGlobal = freeExports && freeModule && typeof global == "object" && global && global.Object && global; + var freeSelf = objectTypes[typeof self] && self && self.Object && self; + var freeWindow = objectTypes[typeof window] && window && window.Object && window; + var moduleExports = freeModule && freeModule.exports === freeExports && freeExports; + var root = freeGlobal || freeWindow !== (this && this.window) && freeWindow || freeSelf || this; + function baseCompareAscending(value, other) { + if (value !== other) { + var valIsNull = value === null, valIsUndef = value === undefined, valIsReflexive = value === value; + var othIsNull = other === null, othIsUndef = other === undefined, othIsReflexive = other === other; + if (value > other && !othIsNull || !valIsReflexive || valIsNull && !othIsUndef && othIsReflexive || valIsUndef && othIsReflexive) { + return 1; } - return obj; - }; - }; - var baseCreate = function(prototype) { - if (!_.isObject(prototype)) return {}; - if (nativeCreate) return nativeCreate(prototype); - Ctor.prototype = prototype; - var result = new Ctor(); - Ctor.prototype = null; - return result; - }; - var property = function(key) { - return function(obj) { - return obj == null ? void 0 : obj[key]; - }; - }; - var MAX_ARRAY_INDEX = Math.pow(2, 53) - 1; - var getLength = property("length"); - var isArrayLike = function(collection) { - var length = getLength(collection); - return typeof length == "number" && length >= 0 && length <= MAX_ARRAY_INDEX; - }; - _.each = _.forEach = function(obj, iteratee, context) { - iteratee = optimizeCb(iteratee, context); - var i, length; - if (isArrayLike(obj)) { - for (i = 0, length = obj.length; i < length; i++) { - iteratee(obj[i], i, obj); + if (value < other && !valIsNull || !othIsReflexive || othIsNull && !valIsUndef && valIsReflexive || othIsUndef && valIsReflexive) { + return -1; } - } else { - var keys = _.keys(obj); - for (i = 0, length = keys.length; i < length; i++) { - iteratee(obj[keys[i]], keys[i], obj); + } + return 0; + } + function baseFindIndex(array, predicate, fromRight) { + var length = array.length, index = fromRight ? length : -1; + while (fromRight ? index-- : ++index < length) { + if (predicate(array[index], index, array)) { + return index; } } - return obj; - }; - _.map = _.collect = function(obj, iteratee, context) { - iteratee = cb(iteratee, context); - var keys = !isArrayLike(obj) && _.keys(obj), length = (keys || obj).length, results = Array(length); - for (var index = 0; index < length; index++) { - var currentKey = keys ? keys[index] : index; - results[index] = iteratee(obj[currentKey], currentKey, obj); + return -1; + } + function baseIndexOf(array, value, fromIndex) { + if (value !== value) { + return indexOfNaN(array, fromIndex); } - return results; - }; - function createReduce(dir) { - function iterator(obj, iteratee, memo, keys, index, length) { - for (;index >= 0 && index < length; index += dir) { - var currentKey = keys ? keys[index] : index; - memo = iteratee(memo, obj[currentKey], currentKey, obj); + var index = fromIndex - 1, length = array.length; + while (++index < length) { + if (array[index] === value) { + return index; } - return memo; } - return function(obj, iteratee, memo, context) { - iteratee = optimizeCb(iteratee, context, 4); - var keys = !isArrayLike(obj) && _.keys(obj), length = (keys || obj).length, index = dir > 0 ? 0 : length - 1; - if (arguments.length < 3) { - memo = obj[keys ? keys[index] : index]; - index += dir; - } - return iterator(obj, iteratee, memo, keys, index, length); - }; + return -1; } - _.reduce = _.foldl = _.inject = createReduce(1); - _.reduceRight = _.foldr = createReduce(-1); - _.find = _.detect = function(obj, predicate, context) { - var key; - if (isArrayLike(obj)) { - key = _.findIndex(obj, predicate, context); - } else { - key = _.findKey(obj, predicate, context); + function baseIsFunction(value) { + return typeof value == "function" || false; + } + function baseToString(value) { + return value == null ? "" : value + ""; + } + function charsLeftIndex(string, chars) { + var index = -1, length = string.length; + while (++index < length && chars.indexOf(string.charAt(index)) > -1) {} + return index; + } + function charsRightIndex(string, chars) { + var index = string.length; + while (index-- && chars.indexOf(string.charAt(index)) > -1) {} + return index; + } + function compareAscending(object, other) { + return baseCompareAscending(object.criteria, other.criteria) || object.index - other.index; + } + function compareMultiple(object, other, orders) { + var index = -1, objCriteria = object.criteria, othCriteria = other.criteria, length = objCriteria.length, ordersLength = orders.length; + while (++index < length) { + var result = baseCompareAscending(objCriteria[index], othCriteria[index]); + if (result) { + if (index >= ordersLength) { + return result; + } + var order = orders[index]; + return result * (order === "asc" || order === true ? 1 : -1); + } } - if (key !== void 0 && key !== -1) return obj[key]; - }; - _.filter = _.select = function(obj, predicate, context) { - var results = []; - predicate = cb(predicate, context); - _.each(obj, function(value, index, list) { - if (predicate(value, index, list)) results.push(value); - }); - return results; - }; - _.reject = function(obj, predicate, context) { - return _.filter(obj, _.negate(cb(predicate)), context); - }; - _.every = _.all = function(obj, predicate, context) { - predicate = cb(predicate, context); - var keys = !isArrayLike(obj) && _.keys(obj), length = (keys || obj).length; - for (var index = 0; index < length; index++) { - var currentKey = keys ? keys[index] : index; - if (!predicate(obj[currentKey], currentKey, obj)) return false; + return object.index - other.index; + } + function deburrLetter(letter) { + return deburredLetters[letter]; + } + function escapeHtmlChar(chr) { + return htmlEscapes[chr]; + } + function escapeRegExpChar(chr, leadingChar, whitespaceChar) { + if (leadingChar) { + chr = regexpEscapes[chr]; + } else if (whitespaceChar) { + chr = stringEscapes[chr]; } - return true; - }; - _.some = _.any = function(obj, predicate, context) { - predicate = cb(predicate, context); - var keys = !isArrayLike(obj) && _.keys(obj), length = (keys || obj).length; - for (var index = 0; index < length; index++) { - var currentKey = keys ? keys[index] : index; - if (predicate(obj[currentKey], currentKey, obj)) return true; + return "\\" + chr; + } + function escapeStringChar(chr) { + return "\\" + stringEscapes[chr]; + } + function indexOfNaN(array, fromIndex, fromRight) { + var length = array.length, index = fromIndex + (fromRight ? 0 : -1); + while (fromRight ? index-- : ++index < length) { + var other = array[index]; + if (other !== other) { + return index; + } } - return false; - }; - _.contains = _.includes = _.include = function(obj, item, fromIndex, guard) { - if (!isArrayLike(obj)) obj = _.values(obj); - if (typeof fromIndex != "number" || guard) fromIndex = 0; - return _.indexOf(obj, item, fromIndex) >= 0; - }; - _.invoke = function(obj, method) { - var args = slice.call(arguments, 2); - var isFunc = _.isFunction(method); - return _.map(obj, function(value) { - var func = isFunc ? method : value[method]; - return func == null ? func : func.apply(value, args); - }); - }; - _.pluck = function(obj, key) { - return _.map(obj, _.property(key)); - }; - _.where = function(obj, attrs) { - return _.filter(obj, _.matcher(attrs)); - }; - _.findWhere = function(obj, attrs) { - return _.find(obj, _.matcher(attrs)); - }; - _.max = function(obj, iteratee, context) { - var result = -Infinity, lastComputed = -Infinity, value, computed; - if (iteratee == null && obj != null) { - obj = isArrayLike(obj) ? obj : _.values(obj); - for (var i = 0, length = obj.length; i < length; i++) { - value = obj[i]; - if (value > result) { - result = value; - } + return -1; + } + function isObjectLike(value) { + return !!value && typeof value == "object"; + } + function isSpace(charCode) { + return charCode <= 160 && (charCode >= 9 && charCode <= 13) || charCode == 32 || charCode == 160 || charCode == 5760 || charCode == 6158 || charCode >= 8192 && (charCode <= 8202 || charCode == 8232 || charCode == 8233 || charCode == 8239 || charCode == 8287 || charCode == 12288 || charCode == 65279); + } + function replaceHolders(array, placeholder) { + var index = -1, length = array.length, resIndex = -1, result = []; + while (++index < length) { + if (array[index] === placeholder) { + array[index] = PLACEHOLDER; + result[++resIndex] = index; } - } else { - iteratee = cb(iteratee, context); - _.each(obj, function(value, index, list) { - computed = iteratee(value, index, list); - if (computed > lastComputed || computed === -Infinity && result === -Infinity) { - result = value; - lastComputed = computed; - } - }); } return result; - }; - _.min = function(obj, iteratee, context) { - var result = Infinity, lastComputed = Infinity, value, computed; - if (iteratee == null && obj != null) { - obj = isArrayLike(obj) ? obj : _.values(obj); - for (var i = 0, length = obj.length; i < length; i++) { - value = obj[i]; - if (value < result) { - result = value; - } + } + function sortedUniq(array, iteratee) { + var seen, index = -1, length = array.length, resIndex = -1, result = []; + while (++index < length) { + var value = array[index], computed = iteratee ? iteratee(value, index, array) : value; + if (!index || seen !== computed) { + seen = computed; + result[++resIndex] = value; } - } else { - iteratee = cb(iteratee, context); - _.each(obj, function(value, index, list) { - computed = iteratee(value, index, list); - if (computed < lastComputed || computed === Infinity && result === Infinity) { - result = value; - lastComputed = computed; - } - }); } return result; - }; - _.shuffle = function(obj) { - var set = isArrayLike(obj) ? obj : _.values(obj); - var length = set.length; - var shuffled = Array(length); - for (var index = 0, rand; index < length; index++) { - rand = _.random(0, index); - if (rand !== index) shuffled[index] = shuffled[rand]; - shuffled[rand] = set[index]; - } - return shuffled; - }; - _.sample = function(obj, n, guard) { - if (n == null || guard) { - if (!isArrayLike(obj)) obj = _.values(obj); - return obj[_.random(obj.length - 1)]; + } + function trimmedLeftIndex(string) { + var index = -1, length = string.length; + while (++index < length && isSpace(string.charCodeAt(index))) {} + return index; + } + function trimmedRightIndex(string) { + var index = string.length; + while (index-- && isSpace(string.charCodeAt(index))) {} + return index; + } + function unescapeHtmlChar(chr) { + return htmlUnescapes[chr]; + } + function runInContext(context) { + context = context ? _.defaults(root.Object(), context, _.pick(root, contextProps)) : root; + var Array = context.Array, Date = context.Date, Error = context.Error, Function = context.Function, Math = context.Math, Number = context.Number, Object = context.Object, RegExp = context.RegExp, String = context.String, TypeError = context.TypeError; + var arrayProto = Array.prototype, objectProto = Object.prototype, stringProto = String.prototype; + var fnToString = Function.prototype.toString; + var hasOwnProperty = objectProto.hasOwnProperty; + var idCounter = 0; + var objToString = objectProto.toString; + var oldDash = root._; + var reIsNative = RegExp("^" + fnToString.call(hasOwnProperty).replace(/[\\^$.*+?()[\]{}|]/g, "\\$&").replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g, "$1.*?") + "$"); + var ArrayBuffer = context.ArrayBuffer, clearTimeout = context.clearTimeout, parseFloat = context.parseFloat, pow = Math.pow, propertyIsEnumerable = objectProto.propertyIsEnumerable, Set = getNative(context, "Set"), setTimeout = context.setTimeout, splice = arrayProto.splice, Uint8Array = context.Uint8Array, WeakMap = getNative(context, "WeakMap"); + var nativeCeil = Math.ceil, nativeCreate = getNative(Object, "create"), nativeFloor = Math.floor, nativeIsArray = getNative(Array, "isArray"), nativeIsFinite = context.isFinite, nativeKeys = getNative(Object, "keys"), nativeMax = Math.max, nativeMin = Math.min, nativeNow = getNative(Date, "now"), nativeParseInt = context.parseInt, nativeRandom = Math.random; + var NEGATIVE_INFINITY = Number.NEGATIVE_INFINITY, POSITIVE_INFINITY = Number.POSITIVE_INFINITY; + var MAX_ARRAY_LENGTH = 4294967295, MAX_ARRAY_INDEX = MAX_ARRAY_LENGTH - 1, HALF_MAX_ARRAY_LENGTH = MAX_ARRAY_LENGTH >>> 1; + var MAX_SAFE_INTEGER = 9007199254740991; + var metaMap = WeakMap && new WeakMap(); + var realNames = {}; + function lodash(value) { + if (isObjectLike(value) && !isArray(value) && !(value instanceof LazyWrapper)) { + if (value instanceof LodashWrapper) { + return value; + } + if (hasOwnProperty.call(value, "__chain__") && hasOwnProperty.call(value, "__wrapped__")) { + return wrapperClone(value); + } + } + return new LodashWrapper(value); + } + function baseLodash() {} + function LodashWrapper(value, chainAll, actions) { + this.__wrapped__ = value; + this.__actions__ = actions || []; + this.__chain__ = !!chainAll; + } + var support = lodash.support = {}; + lodash.templateSettings = { + escape: reEscape, + evaluate: reEvaluate, + interpolate: reInterpolate, + variable: "", + imports: { + _: lodash + } + }; + function LazyWrapper(value) { + this.__wrapped__ = value; + this.__actions__ = []; + this.__dir__ = 1; + this.__filtered__ = false; + this.__iteratees__ = []; + this.__takeCount__ = POSITIVE_INFINITY; + this.__views__ = []; + } + function lazyClone() { + var result = new LazyWrapper(this.__wrapped__); + result.__actions__ = arrayCopy(this.__actions__); + result.__dir__ = this.__dir__; + result.__filtered__ = this.__filtered__; + result.__iteratees__ = arrayCopy(this.__iteratees__); + result.__takeCount__ = this.__takeCount__; + result.__views__ = arrayCopy(this.__views__); + return result; } - return _.shuffle(obj).slice(0, Math.max(0, n)); - }; - _.sortBy = function(obj, iteratee, context) { - iteratee = cb(iteratee, context); - return _.pluck(_.map(obj, function(value, index, list) { - return { - value: value, - index: index, - criteria: iteratee(value, index, list) - }; - }).sort(function(left, right) { - var a = left.criteria; - var b = right.criteria; - if (a !== b) { - if (a > b || a === void 0) return 1; - if (a < b || b === void 0) return -1; + function lazyReverse() { + if (this.__filtered__) { + var result = new LazyWrapper(this); + result.__dir__ = -1; + result.__filtered__ = true; + } else { + result = this.clone(); + result.__dir__ *= -1; } - return left.index - right.index; - }), "value"); - }; - var group = function(behavior) { - return function(obj, iteratee, context) { - var result = {}; - iteratee = cb(iteratee, context); - _.each(obj, function(value, index) { - var key = iteratee(value, index, obj); - behavior(result, value, key); - }); return result; - }; - }; - _.groupBy = group(function(result, value, key) { - if (_.has(result, key)) result[key].push(value); else result[key] = [ value ]; - }); - _.indexBy = group(function(result, value, key) { - result[key] = value; - }); - _.countBy = group(function(result, value, key) { - if (_.has(result, key)) result[key]++; else result[key] = 1; - }); - _.toArray = function(obj) { - if (!obj) return []; - if (_.isArray(obj)) return slice.call(obj); - if (isArrayLike(obj)) return _.map(obj, _.identity); - return _.values(obj); - }; - _.size = function(obj) { - if (obj == null) return 0; - return isArrayLike(obj) ? obj.length : _.keys(obj).length; - }; - _.partition = function(obj, predicate, context) { - predicate = cb(predicate, context); - var pass = [], fail = []; - _.each(obj, function(value, key, obj) { - (predicate(value, key, obj) ? pass : fail).push(value); - }); - return [ pass, fail ]; - }; - _.first = _.head = _.take = function(array, n, guard) { - if (array == null) return void 0; - if (n == null || guard) return array[0]; - return _.initial(array, array.length - n); - }; - _.initial = function(array, n, guard) { - return slice.call(array, 0, Math.max(0, array.length - (n == null || guard ? 1 : n))); - }; - _.last = function(array, n, guard) { - if (array == null) return void 0; - if (n == null || guard) return array[array.length - 1]; - return _.rest(array, Math.max(0, array.length - n)); - }; - _.rest = _.tail = _.drop = function(array, n, guard) { - return slice.call(array, n == null || guard ? 1 : n); - }; - _.compact = function(array) { - return _.filter(array, _.identity); - }; - var flatten = function(input, shallow, strict, startIndex) { - var output = [], idx = 0; - for (var i = startIndex || 0, length = getLength(input); i < length; i++) { - var value = input[i]; - if (isArrayLike(value) && (_.isArray(value) || _.isArguments(value))) { - if (!shallow) value = flatten(value, shallow, strict); - var j = 0, len = value.length; - output.length += len; - while (j < len) { - output[idx++] = value[j++]; + } + function lazyValue() { + var array = this.__wrapped__.value(), dir = this.__dir__, isArr = isArray(array), isRight = dir < 0, arrLength = isArr ? array.length : 0, view = getView(0, arrLength, this.__views__), start = view.start, end = view.end, length = end - start, index = isRight ? end : start - 1, iteratees = this.__iteratees__, iterLength = iteratees.length, resIndex = 0, takeCount = nativeMin(length, this.__takeCount__); + if (!isArr || arrLength < LARGE_ARRAY_SIZE || arrLength == length && takeCount == length) { + return baseWrapperValue(array, this.__actions__); + } + var result = []; + outer: while (length-- && resIndex < takeCount) { + index += dir; + var iterIndex = -1, value = array[index]; + while (++iterIndex < iterLength) { + var data = iteratees[iterIndex], iteratee = data.iteratee, type = data.type, computed = iteratee(value); + if (type == LAZY_MAP_FLAG) { + value = computed; + } else if (!computed) { + if (type == LAZY_FILTER_FLAG) { + continue outer; + } else { + break outer; + } + } } - } else if (!strict) { - output[idx++] = value; + result[resIndex++] = value; } + return result; } - return output; - }; - _.flatten = function(array, shallow) { - return flatten(array, shallow, false); - }; - _.without = function(array) { - return _.difference(array, slice.call(arguments, 1)); - }; - _.uniq = _.unique = function(array, isSorted, iteratee, context) { - if (!_.isBoolean(isSorted)) { - context = iteratee; - iteratee = isSorted; - isSorted = false; + function MapCache() { + this.__data__ = {}; } - if (iteratee != null) iteratee = cb(iteratee, context); - var result = []; - var seen = []; - for (var i = 0, length = getLength(array); i < length; i++) { - var value = array[i], computed = iteratee ? iteratee(value, i, array) : value; - if (isSorted) { - if (!i || seen !== computed) result.push(value); - seen = computed; - } else if (iteratee) { - if (!_.contains(seen, computed)) { - seen.push(computed); - result.push(value); - } - } else if (!_.contains(result, value)) { - result.push(value); + function mapDelete(key) { + return this.has(key) && delete this.__data__[key]; + } + function mapGet(key) { + return key == "__proto__" ? undefined : this.__data__[key]; + } + function mapHas(key) { + return key != "__proto__" && hasOwnProperty.call(this.__data__, key); + } + function mapSet(key, value) { + if (key != "__proto__") { + this.__data__[key] = value; } + return this; } - return result; - }; - _.union = function() { - return _.uniq(flatten(arguments, true, true)); - }; - _.intersection = function(array) { - var result = []; - var argsLength = arguments.length; - for (var i = 0, length = getLength(array); i < length; i++) { - var item = array[i]; - if (_.contains(result, item)) continue; - for (var j = 1; j < argsLength; j++) { - if (!_.contains(arguments[j], item)) break; + function SetCache(values) { + var length = values ? values.length : 0; + this.data = { + hash: nativeCreate(null), + set: new Set() + }; + while (length--) { + this.push(values[length]); } - if (j === argsLength) result.push(item); } - return result; - }; - _.difference = function(array) { - var rest = flatten(arguments, true, true, 1); - return _.filter(array, function(value) { - return !_.contains(rest, value); - }); - }; - _.zip = function() { - return _.unzip(arguments); - }; - _.unzip = function(array) { - var length = array && _.max(array, getLength).length || 0; - var result = Array(length); - for (var index = 0; index < length; index++) { - result[index] = _.pluck(array, index); + function cacheIndexOf(cache, value) { + var data = cache.data, result = typeof value == "string" || isObject(value) ? data.set.has(value) : data.hash[value]; + return result ? 0 : -1; } - return result; - }; - _.object = function(list, values) { - var result = {}; - for (var i = 0, length = getLength(list); i < length; i++) { - if (values) { - result[list[i]] = values[i]; + function cachePush(value) { + var data = this.data; + if (typeof value == "string" || isObject(value)) { + data.set.add(value); } else { - result[list[i][0]] = list[i][1]; + data.hash[value] = true; } } - return result; - }; - function createPredicateIndexFinder(dir) { - return function(array, predicate, context) { - predicate = cb(predicate, context); - var length = getLength(array); - var index = dir > 0 ? 0 : length - 1; - for (;index >= 0 && index < length; index += dir) { - if (predicate(array[index], index, array)) return index; + function arrayConcat(array, other) { + var index = -1, length = array.length, othIndex = -1, othLength = other.length, result = Array(length + othLength); + while (++index < length) { + result[index] = array[index]; } - return -1; - }; - } - _.findIndex = createPredicateIndexFinder(1); - _.findLastIndex = createPredicateIndexFinder(-1); - _.sortedIndex = function(array, obj, iteratee, context) { - iteratee = cb(iteratee, context, 1); - var value = iteratee(obj); - var low = 0, high = getLength(array); - while (low < high) { - var mid = Math.floor((low + high) / 2); - if (iteratee(array[mid]) < value) low = mid + 1; else high = mid; - } - return low; - }; - function createIndexFinder(dir, predicateFind, sortedIndex) { - return function(array, item, idx) { - var i = 0, length = getLength(array); - if (typeof idx == "number") { - if (dir > 0) { - i = idx >= 0 ? idx : Math.max(idx + length, i); - } else { - length = idx >= 0 ? Math.min(idx + 1, length) : idx + length + 1; - } - } else if (sortedIndex && idx && length) { - idx = sortedIndex(array, item); - return array[idx] === item ? idx : -1; + while (++othIndex < othLength) { + result[index++] = other[othIndex]; } - if (item !== item) { - idx = predicateFind(slice.call(array, i, length), _.isNaN); - return idx >= 0 ? idx + i : -1; + return result; + } + function arrayCopy(source, array) { + var index = -1, length = source.length; + array || (array = Array(length)); + while (++index < length) { + array[index] = source[index]; } - for (idx = dir > 0 ? i : length - 1; idx >= 0 && idx < length; idx += dir) { - if (array[idx] === item) return idx; + return array; + } + function arrayEach(array, iteratee) { + var index = -1, length = array.length; + while (++index < length) { + if (iteratee(array[index], index, array) === false) { + break; + } } - return -1; - }; - } - _.indexOf = createIndexFinder(1, _.findIndex, _.sortedIndex); - _.lastIndexOf = createIndexFinder(-1, _.findLastIndex); - _.range = function(start, stop, step) { - if (stop == null) { - stop = start || 0; - start = 0; + return array; } - step = step || 1; - var length = Math.max(Math.ceil((stop - start) / step), 0); - var range = Array(length); - for (var idx = 0; idx < length; idx++, start += step) { - range[idx] = start; - } - return range; - }; - var executeBound = function(sourceFunc, boundFunc, context, callingContext, args) { - if (!(callingContext instanceof boundFunc)) return sourceFunc.apply(context, args); - var self = baseCreate(sourceFunc.prototype); - var result = sourceFunc.apply(self, args); - if (_.isObject(result)) return result; - return self; - }; - _.bind = function(func, context) { - if (nativeBind && func.bind === nativeBind) return nativeBind.apply(func, slice.call(arguments, 1)); - if (!_.isFunction(func)) throw new TypeError("Bind must be called on a function"); - var args = slice.call(arguments, 2); - var bound = function() { - return executeBound(func, bound, context, this, args.concat(slice.call(arguments))); - }; - return bound; - }; - _.partial = function(func) { - var boundArgs = slice.call(arguments, 1); - var bound = function() { - var position = 0, length = boundArgs.length; - var args = Array(length); - for (var i = 0; i < length; i++) { - args[i] = boundArgs[i] === _ ? arguments[position++] : boundArgs[i]; + function arrayEachRight(array, iteratee) { + var length = array.length; + while (length--) { + if (iteratee(array[length], length, array) === false) { + break; + } } - while (position < arguments.length) args.push(arguments[position++]); - return executeBound(func, bound, this, this, args); - }; - return bound; - }; - _.bindAll = function(obj) { - var i, length = arguments.length, key; - if (length <= 1) throw new Error("bindAll must be passed function names"); - for (i = 1; i < length; i++) { - key = arguments[i]; - obj[key] = _.bind(obj[key], obj); + return array; } - return obj; - }; - _.memoize = function(func, hasher) { - var memoize = function(key) { - var cache = memoize.cache; - var address = "" + (hasher ? hasher.apply(this, arguments) : key); - if (!_.has(cache, address)) cache[address] = func.apply(this, arguments); - return cache[address]; - }; - memoize.cache = {}; - return memoize; - }; - _.delay = function(func, wait) { - var args = slice.call(arguments, 2); - return setTimeout(function() { - return func.apply(null, args); - }, wait); - }; - _.defer = _.partial(_.delay, _, 1); - _.throttle = function(func, wait, options) { - var context, args, result; - var timeout = null; - var previous = 0; - if (!options) options = {}; - var later = function() { - previous = options.leading === false ? 0 : _.now(); - timeout = null; - result = func.apply(context, args); - if (!timeout) context = args = null; - }; - return function() { - var now = _.now(); - if (!previous && options.leading === false) previous = now; - var remaining = wait - (now - previous); - context = this; - args = arguments; - if (remaining <= 0 || remaining > wait) { - if (timeout) { - clearTimeout(timeout); - timeout = null; - } - previous = now; - result = func.apply(context, args); - if (!timeout) context = args = null; - } else if (!timeout && options.trailing !== false) { - timeout = setTimeout(later, remaining); + function arrayEvery(array, predicate) { + var index = -1, length = array.length; + while (++index < length) { + if (!predicate(array[index], index, array)) { + return false; + } } - return result; - }; - }; - _.debounce = function(func, wait, immediate) { - var timeout, args, context, timestamp, result; - var later = function() { - var last = _.now() - timestamp; - if (last < wait && last >= 0) { - timeout = setTimeout(later, wait - last); - } else { - timeout = null; - if (!immediate) { - result = func.apply(context, args); - if (!timeout) context = args = null; + return true; + } + function arrayExtremum(array, iteratee, comparator, exValue) { + var index = -1, length = array.length, computed = exValue, result = computed; + while (++index < length) { + var value = array[index], current = +iteratee(value); + if (comparator(current, computed)) { + computed = current; + result = value; } } - }; - return function() { - context = this; - args = arguments; - timestamp = _.now(); - var callNow = immediate && !timeout; - if (!timeout) timeout = setTimeout(later, wait); - if (callNow) { - result = func.apply(context, args); - context = args = null; + return result; + } + function arrayFilter(array, predicate) { + var index = -1, length = array.length, resIndex = -1, result = []; + while (++index < length) { + var value = array[index]; + if (predicate(value, index, array)) { + result[++resIndex] = value; + } } return result; - }; - }; - _.wrap = function(func, wrapper) { - return _.partial(wrapper, func); - }; - _.negate = function(predicate) { - return function() { - return !predicate.apply(this, arguments); - }; - }; - _.compose = function() { - var args = arguments; - var start = args.length - 1; - return function() { - var i = start; - var result = args[start].apply(this, arguments); - while (i--) result = args[i].call(this, result); + } + function arrayMap(array, iteratee) { + var index = -1, length = array.length, result = Array(length); + while (++index < length) { + result[index] = iteratee(array[index], index, array); + } return result; - }; - }; - _.after = function(times, func) { - return function() { - if (--times < 1) { - return func.apply(this, arguments); + } + function arrayPush(array, values) { + var index = -1, length = values.length, offset = array.length; + while (++index < length) { + array[offset + index] = values[index]; } - }; - }; - _.before = function(times, func) { - var memo; - return function() { - if (--times > 0) { - memo = func.apply(this, arguments); - } - if (times <= 1) func = null; - return memo; - }; - }; - _.once = _.partial(_.before, 2); - var hasEnumBug = !{ - toString: null - }.propertyIsEnumerable("toString"); - var nonEnumerableProps = [ "valueOf", "isPrototypeOf", "toString", "propertyIsEnumerable", "hasOwnProperty", "toLocaleString" ]; - function collectNonEnumProps(obj, keys) { - var nonEnumIdx = nonEnumerableProps.length; - var constructor = obj.constructor; - var proto = _.isFunction(constructor) && constructor.prototype || ObjProto; - var prop = "constructor"; - if (_.has(obj, prop) && !_.contains(keys, prop)) keys.push(prop); - while (nonEnumIdx--) { - prop = nonEnumerableProps[nonEnumIdx]; - if (prop in obj && obj[prop] !== proto[prop] && !_.contains(keys, prop)) { - keys.push(prop); - } - } - } - _.keys = function(obj) { - if (!_.isObject(obj)) return []; - if (nativeKeys) return nativeKeys(obj); - var keys = []; - for (var key in obj) if (_.has(obj, key)) keys.push(key); - if (hasEnumBug) collectNonEnumProps(obj, keys); - return keys; - }; - _.allKeys = function(obj) { - if (!_.isObject(obj)) return []; - var keys = []; - for (var key in obj) keys.push(key); - if (hasEnumBug) collectNonEnumProps(obj, keys); - return keys; - }; - _.values = function(obj) { - var keys = _.keys(obj); - var length = keys.length; - var values = Array(length); - for (var i = 0; i < length; i++) { - values[i] = obj[keys[i]]; + return array; } - return values; - }; - _.mapObject = function(obj, iteratee, context) { - iteratee = cb(iteratee, context); - var keys = _.keys(obj), length = keys.length, results = {}, currentKey; - for (var index = 0; index < length; index++) { - currentKey = keys[index]; - results[currentKey] = iteratee(obj[currentKey], currentKey, obj); + function arrayReduce(array, iteratee, accumulator, initFromArray) { + var index = -1, length = array.length; + if (initFromArray && length) { + accumulator = array[++index]; + } + while (++index < length) { + accumulator = iteratee(accumulator, array[index], index, array); + } + return accumulator; } - return results; - }; - _.pairs = function(obj) { - var keys = _.keys(obj); - var length = keys.length; - var pairs = Array(length); - for (var i = 0; i < length; i++) { - pairs[i] = [ keys[i], obj[keys[i]] ]; + function arrayReduceRight(array, iteratee, accumulator, initFromArray) { + var length = array.length; + if (initFromArray && length) { + accumulator = array[--length]; + } + while (length--) { + accumulator = iteratee(accumulator, array[length], length, array); + } + return accumulator; } - return pairs; - }; - _.invert = function(obj) { - var result = {}; - var keys = _.keys(obj); - for (var i = 0, length = keys.length; i < length; i++) { - result[obj[keys[i]]] = keys[i]; + function arraySome(array, predicate) { + var index = -1, length = array.length; + while (++index < length) { + if (predicate(array[index], index, array)) { + return true; + } + } + return false; } - return result; - }; - _.functions = _.methods = function(obj) { - var names = []; - for (var key in obj) { - if (_.isFunction(obj[key])) names.push(key); + function arraySum(array, iteratee) { + var length = array.length, result = 0; + while (length--) { + result += +iteratee(array[length]) || 0; + } + return result; } - return names.sort(); - }; - _.extend = createAssigner(_.allKeys); - _.extendOwn = _.assign = createAssigner(_.keys); - _.findKey = function(obj, predicate, context) { - predicate = cb(predicate, context); - var keys = _.keys(obj), key; - for (var i = 0, length = keys.length; i < length; i++) { - key = keys[i]; - if (predicate(obj[key], key, obj)) return key; + function assignDefaults(objectValue, sourceValue) { + return objectValue === undefined ? sourceValue : objectValue; } - }; - _.pick = function(object, oiteratee, context) { - var result = {}, obj = object, iteratee, keys; - if (obj == null) return result; - if (_.isFunction(oiteratee)) { - keys = _.allKeys(obj); - iteratee = optimizeCb(oiteratee, context); - } else { - keys = flatten(arguments, false, false, 1); - iteratee = function(value, key, obj) { - return key in obj; - }; - obj = Object(obj); + function assignOwnDefaults(objectValue, sourceValue, key, object) { + return objectValue === undefined || !hasOwnProperty.call(object, key) ? sourceValue : objectValue; } - for (var i = 0, length = keys.length; i < length; i++) { - var key = keys[i]; - var value = obj[key]; - if (iteratee(value, key, obj)) result[key] = value; + function assignWith(object, source, customizer) { + var index = -1, props = keys(source), length = props.length; + while (++index < length) { + var key = props[index], value = object[key], result = customizer(value, source[key], key, object, source); + if ((result === result ? result !== value : value === value) || value === undefined && !(key in object)) { + object[key] = result; + } + } + return object; } - return result; - }; - _.omit = function(obj, iteratee, context) { - if (_.isFunction(iteratee)) { - iteratee = _.negate(iteratee); - } else { - var keys = _.map(flatten(arguments, false, false, 1), String); - iteratee = function(value, key) { - return !_.contains(keys, key); + function baseAssign(object, source) { + return source == null ? object : baseCopy(source, keys(source), object); + } + function baseAt(collection, props) { + var index = -1, isNil = collection == null, isArr = !isNil && isArrayLike(collection), length = isArr ? collection.length : 0, propsLength = props.length, result = Array(propsLength); + while (++index < propsLength) { + var key = props[index]; + if (isArr) { + result[index] = isIndex(key, length) ? collection[key] : undefined; + } else { + result[index] = isNil ? undefined : collection[key]; + } + } + return result; + } + function baseCopy(source, props, object) { + object || (object = {}); + var index = -1, length = props.length; + while (++index < length) { + var key = props[index]; + object[key] = source[key]; + } + return object; + } + function baseCallback(func, thisArg, argCount) { + var type = typeof func; + if (type == "function") { + return thisArg === undefined ? func : bindCallback(func, thisArg, argCount); + } + if (func == null) { + return identity; + } + if (type == "object") { + return baseMatches(func); + } + return thisArg === undefined ? property(func) : baseMatchesProperty(func, thisArg); + } + function baseClone(value, isDeep, customizer, key, object, stackA, stackB) { + var result; + if (customizer) { + result = object ? customizer(value, key, object) : customizer(value); + } + if (result !== undefined) { + return result; + } + if (!isObject(value)) { + return value; + } + var isArr = isArray(value); + if (isArr) { + result = initCloneArray(value); + if (!isDeep) { + return arrayCopy(value, result); + } + } else { + var tag = objToString.call(value), isFunc = tag == funcTag; + if (tag == objectTag || tag == argsTag || isFunc && !object) { + result = initCloneObject(isFunc ? {} : value); + if (!isDeep) { + return baseAssign(result, value); + } + } else { + return cloneableTags[tag] ? initCloneByTag(value, tag, isDeep) : object ? value : {}; + } + } + stackA || (stackA = []); + stackB || (stackB = []); + var length = stackA.length; + while (length--) { + if (stackA[length] == value) { + return stackB[length]; + } + } + stackA.push(value); + stackB.push(result); + (isArr ? arrayEach : baseForOwn)(value, function(subValue, key) { + result[key] = baseClone(subValue, isDeep, customizer, key, value, stackA, stackB); + }); + return result; + } + var baseCreate = function() { + function object() {} + return function(prototype) { + if (isObject(prototype)) { + object.prototype = prototype; + var result = new object(); + object.prototype = undefined; + } + return result || {}; + }; + }(); + function baseDelay(func, wait, args) { + if (typeof func != "function") { + throw new TypeError(FUNC_ERROR_TEXT); + } + return setTimeout(function() { + func.apply(undefined, args); + }, wait); + } + function baseDifference(array, values) { + var length = array ? array.length : 0, result = []; + if (!length) { + return result; + } + var index = -1, indexOf = getIndexOf(), isCommon = indexOf === baseIndexOf, cache = isCommon && values.length >= LARGE_ARRAY_SIZE ? createCache(values) : null, valuesLength = values.length; + if (cache) { + indexOf = cacheIndexOf; + isCommon = false; + values = cache; + } + outer: while (++index < length) { + var value = array[index]; + if (isCommon && value === value) { + var valuesIndex = valuesLength; + while (valuesIndex--) { + if (values[valuesIndex] === value) { + continue outer; + } + } + result.push(value); + } else if (indexOf(values, value, 0) < 0) { + result.push(value); + } + } + return result; + } + var baseEach = createBaseEach(baseForOwn); + var baseEachRight = createBaseEach(baseForOwnRight, true); + function baseEvery(collection, predicate) { + var result = true; + baseEach(collection, function(value, index, collection) { + result = !!predicate(value, index, collection); + return result; + }); + return result; + } + function baseExtremum(collection, iteratee, comparator, exValue) { + var computed = exValue, result = computed; + baseEach(collection, function(value, index, collection) { + var current = +iteratee(value, index, collection); + if (comparator(current, computed) || current === exValue && current === result) { + computed = current; + result = value; + } + }); + return result; + } + function baseFill(array, value, start, end) { + var length = array.length; + start = start == null ? 0 : +start || 0; + if (start < 0) { + start = -start > length ? 0 : length + start; + } + end = end === undefined || end > length ? length : +end || 0; + if (end < 0) { + end += length; + } + length = start > end ? 0 : end >>> 0; + start >>>= 0; + while (start < length) { + array[start++] = value; + } + return array; + } + function baseFilter(collection, predicate) { + var result = []; + baseEach(collection, function(value, index, collection) { + if (predicate(value, index, collection)) { + result.push(value); + } + }); + return result; + } + function baseFind(collection, predicate, eachFunc, retKey) { + var result; + eachFunc(collection, function(value, key, collection) { + if (predicate(value, key, collection)) { + result = retKey ? key : value; + return false; + } + }); + return result; + } + function baseFlatten(array, isDeep, isStrict, result) { + result || (result = []); + var index = -1, length = array.length; + while (++index < length) { + var value = array[index]; + if (isObjectLike(value) && isArrayLike(value) && (isStrict || isArray(value) || isArguments(value))) { + if (isDeep) { + baseFlatten(value, isDeep, isStrict, result); + } else { + arrayPush(result, value); + } + } else if (!isStrict) { + result[result.length] = value; + } + } + return result; + } + var baseFor = createBaseFor(); + var baseForRight = createBaseFor(true); + function baseForIn(object, iteratee) { + return baseFor(object, iteratee, keysIn); + } + function baseForOwn(object, iteratee) { + return baseFor(object, iteratee, keys); + } + function baseForOwnRight(object, iteratee) { + return baseForRight(object, iteratee, keys); + } + function baseFunctions(object, props) { + var index = -1, length = props.length, resIndex = -1, result = []; + while (++index < length) { + var key = props[index]; + if (isFunction(object[key])) { + result[++resIndex] = key; + } + } + return result; + } + function baseGet(object, path, pathKey) { + if (object == null) { + return; + } + if (pathKey !== undefined && pathKey in toObject(object)) { + path = [ pathKey ]; + } + var index = 0, length = path.length; + while (object != null && index < length) { + object = object[path[index++]]; + } + return index && index == length ? object : undefined; + } + function baseIsEqual(value, other, customizer, isLoose, stackA, stackB) { + if (value === other) { + return true; + } + if (value == null || other == null || !isObject(value) && !isObjectLike(other)) { + return value !== value && other !== other; + } + return baseIsEqualDeep(value, other, baseIsEqual, customizer, isLoose, stackA, stackB); + } + function baseIsEqualDeep(object, other, equalFunc, customizer, isLoose, stackA, stackB) { + var objIsArr = isArray(object), othIsArr = isArray(other), objTag = arrayTag, othTag = arrayTag; + if (!objIsArr) { + objTag = objToString.call(object); + if (objTag == argsTag) { + objTag = objectTag; + } else if (objTag != objectTag) { + objIsArr = isTypedArray(object); + } + } + if (!othIsArr) { + othTag = objToString.call(other); + if (othTag == argsTag) { + othTag = objectTag; + } else if (othTag != objectTag) { + othIsArr = isTypedArray(other); + } + } + var objIsObj = objTag == objectTag, othIsObj = othTag == objectTag, isSameTag = objTag == othTag; + if (isSameTag && !(objIsArr || objIsObj)) { + return equalByTag(object, other, objTag); + } + if (!isLoose) { + var objIsWrapped = objIsObj && hasOwnProperty.call(object, "__wrapped__"), othIsWrapped = othIsObj && hasOwnProperty.call(other, "__wrapped__"); + if (objIsWrapped || othIsWrapped) { + return equalFunc(objIsWrapped ? object.value() : object, othIsWrapped ? other.value() : other, customizer, isLoose, stackA, stackB); + } + } + if (!isSameTag) { + return false; + } + stackA || (stackA = []); + stackB || (stackB = []); + var length = stackA.length; + while (length--) { + if (stackA[length] == object) { + return stackB[length] == other; + } + } + stackA.push(object); + stackB.push(other); + var result = (objIsArr ? equalArrays : equalObjects)(object, other, equalFunc, customizer, isLoose, stackA, stackB); + stackA.pop(); + stackB.pop(); + return result; + } + function baseIsMatch(object, matchData, customizer) { + var index = matchData.length, length = index, noCustomizer = !customizer; + if (object == null) { + return !length; + } + object = toObject(object); + while (index--) { + var data = matchData[index]; + if (noCustomizer && data[2] ? data[1] !== object[data[0]] : !(data[0] in object)) { + return false; + } + } + while (++index < length) { + data = matchData[index]; + var key = data[0], objValue = object[key], srcValue = data[1]; + if (noCustomizer && data[2]) { + if (objValue === undefined && !(key in object)) { + return false; + } + } else { + var result = customizer ? customizer(objValue, srcValue, key) : undefined; + if (!(result === undefined ? baseIsEqual(srcValue, objValue, customizer, true) : result)) { + return false; + } + } + } + return true; + } + function baseMap(collection, iteratee) { + var index = -1, result = isArrayLike(collection) ? Array(collection.length) : []; + baseEach(collection, function(value, key, collection) { + result[++index] = iteratee(value, key, collection); + }); + return result; + } + function baseMatches(source) { + var matchData = getMatchData(source); + if (matchData.length == 1 && matchData[0][2]) { + var key = matchData[0][0], value = matchData[0][1]; + return function(object) { + if (object == null) { + return false; + } + return object[key] === value && (value !== undefined || key in toObject(object)); + }; + } + return function(object) { + return baseIsMatch(object, matchData); + }; + } + function baseMatchesProperty(path, srcValue) { + var isArr = isArray(path), isCommon = isKey(path) && isStrictComparable(srcValue), pathKey = path + ""; + path = toPath(path); + return function(object) { + if (object == null) { + return false; + } + var key = pathKey; + object = toObject(object); + if ((isArr || !isCommon) && !(key in object)) { + object = path.length == 1 ? object : baseGet(object, baseSlice(path, 0, -1)); + if (object == null) { + return false; + } + key = last(path); + object = toObject(object); + } + return object[key] === srcValue ? srcValue !== undefined || key in object : baseIsEqual(srcValue, object[key], undefined, true); + }; + } + function baseMerge(object, source, customizer, stackA, stackB) { + if (!isObject(object)) { + return object; + } + var isSrcArr = isArrayLike(source) && (isArray(source) || isTypedArray(source)), props = isSrcArr ? undefined : keys(source); + arrayEach(props || source, function(srcValue, key) { + if (props) { + key = srcValue; + srcValue = source[key]; + } + if (isObjectLike(srcValue)) { + stackA || (stackA = []); + stackB || (stackB = []); + baseMergeDeep(object, source, key, baseMerge, customizer, stackA, stackB); + } else { + var value = object[key], result = customizer ? customizer(value, srcValue, key, object, source) : undefined, isCommon = result === undefined; + if (isCommon) { + result = srcValue; + } + if ((result !== undefined || isSrcArr && !(key in object)) && (isCommon || (result === result ? result !== value : value === value))) { + object[key] = result; + } + } + }); + return object; + } + function baseMergeDeep(object, source, key, mergeFunc, customizer, stackA, stackB) { + var length = stackA.length, srcValue = source[key]; + while (length--) { + if (stackA[length] == srcValue) { + object[key] = stackB[length]; + return; + } + } + var value = object[key], result = customizer ? customizer(value, srcValue, key, object, source) : undefined, isCommon = result === undefined; + if (isCommon) { + result = srcValue; + if (isArrayLike(srcValue) && (isArray(srcValue) || isTypedArray(srcValue))) { + result = isArray(value) ? value : isArrayLike(value) ? arrayCopy(value) : []; + } else if (isPlainObject(srcValue) || isArguments(srcValue)) { + result = isArguments(value) ? toPlainObject(value) : isPlainObject(value) ? value : {}; + } else { + isCommon = false; + } + } + stackA.push(srcValue); + stackB.push(result); + if (isCommon) { + object[key] = mergeFunc(result, srcValue, customizer, stackA, stackB); + } else if (result === result ? result !== value : value === value) { + object[key] = result; + } + } + function baseProperty(key) { + return function(object) { + return object == null ? undefined : object[key]; + }; + } + function basePropertyDeep(path) { + var pathKey = path + ""; + path = toPath(path); + return function(object) { + return baseGet(object, path, pathKey); + }; + } + function basePullAt(array, indexes) { + var length = array ? indexes.length : 0; + while (length--) { + var index = indexes[length]; + if (index != previous && isIndex(index)) { + var previous = index; + splice.call(array, index, 1); + } + } + return array; + } + function baseRandom(min, max) { + return min + nativeFloor(nativeRandom() * (max - min + 1)); + } + function baseReduce(collection, iteratee, accumulator, initFromCollection, eachFunc) { + eachFunc(collection, function(value, index, collection) { + accumulator = initFromCollection ? (initFromCollection = false, value) : iteratee(accumulator, value, index, collection); + }); + return accumulator; + } + var baseSetData = !metaMap ? identity : function(func, data) { + metaMap.set(func, data); + return func; + }; + function baseSlice(array, start, end) { + var index = -1, length = array.length; + start = start == null ? 0 : +start || 0; + if (start < 0) { + start = -start > length ? 0 : length + start; + } + end = end === undefined || end > length ? length : +end || 0; + if (end < 0) { + end += length; + } + length = start > end ? 0 : end - start >>> 0; + start >>>= 0; + var result = Array(length); + while (++index < length) { + result[index] = array[index + start]; + } + return result; + } + function baseSome(collection, predicate) { + var result; + baseEach(collection, function(value, index, collection) { + result = predicate(value, index, collection); + return !result; + }); + return !!result; + } + function baseSortBy(array, comparer) { + var length = array.length; + array.sort(comparer); + while (length--) { + array[length] = array[length].value; + } + return array; + } + function baseSortByOrder(collection, iteratees, orders) { + var callback = getCallback(), index = -1; + iteratees = arrayMap(iteratees, function(iteratee) { + return callback(iteratee); + }); + var result = baseMap(collection, function(value) { + var criteria = arrayMap(iteratees, function(iteratee) { + return iteratee(value); + }); + return { + criteria: criteria, + index: ++index, + value: value + }; + }); + return baseSortBy(result, function(object, other) { + return compareMultiple(object, other, orders); + }); + } + function baseSum(collection, iteratee) { + var result = 0; + baseEach(collection, function(value, index, collection) { + result += +iteratee(value, index, collection) || 0; + }); + return result; + } + function baseUniq(array, iteratee) { + var index = -1, indexOf = getIndexOf(), length = array.length, isCommon = indexOf === baseIndexOf, isLarge = isCommon && length >= LARGE_ARRAY_SIZE, seen = isLarge ? createCache() : null, result = []; + if (seen) { + indexOf = cacheIndexOf; + isCommon = false; + } else { + isLarge = false; + seen = iteratee ? [] : result; + } + outer: while (++index < length) { + var value = array[index], computed = iteratee ? iteratee(value, index, array) : value; + if (isCommon && value === value) { + var seenIndex = seen.length; + while (seenIndex--) { + if (seen[seenIndex] === computed) { + continue outer; + } + } + if (iteratee) { + seen.push(computed); + } + result.push(value); + } else if (indexOf(seen, computed, 0) < 0) { + if (iteratee || isLarge) { + seen.push(computed); + } + result.push(value); + } + } + return result; + } + function baseValues(object, props) { + var index = -1, length = props.length, result = Array(length); + while (++index < length) { + result[index] = object[props[index]]; + } + return result; + } + function baseWhile(array, predicate, isDrop, fromRight) { + var length = array.length, index = fromRight ? length : -1; + while ((fromRight ? index-- : ++index < length) && predicate(array[index], index, array)) {} + return isDrop ? baseSlice(array, fromRight ? 0 : index, fromRight ? index + 1 : length) : baseSlice(array, fromRight ? index + 1 : 0, fromRight ? length : index); + } + function baseWrapperValue(value, actions) { + var result = value; + if (result instanceof LazyWrapper) { + result = result.value(); + } + var index = -1, length = actions.length; + while (++index < length) { + var action = actions[index]; + result = action.func.apply(action.thisArg, arrayPush([ result ], action.args)); + } + return result; + } + function binaryIndex(array, value, retHighest) { + var low = 0, high = array ? array.length : low; + if (typeof value == "number" && value === value && high <= HALF_MAX_ARRAY_LENGTH) { + while (low < high) { + var mid = low + high >>> 1, computed = array[mid]; + if ((retHighest ? computed <= value : computed < value) && computed !== null) { + low = mid + 1; + } else { + high = mid; + } + } + return high; + } + return binaryIndexBy(array, value, identity, retHighest); + } + function binaryIndexBy(array, value, iteratee, retHighest) { + value = iteratee(value); + var low = 0, high = array ? array.length : 0, valIsNaN = value !== value, valIsNull = value === null, valIsUndef = value === undefined; + while (low < high) { + var mid = nativeFloor((low + high) / 2), computed = iteratee(array[mid]), isDef = computed !== undefined, isReflexive = computed === computed; + if (valIsNaN) { + var setLow = isReflexive || retHighest; + } else if (valIsNull) { + setLow = isReflexive && isDef && (retHighest || computed != null); + } else if (valIsUndef) { + setLow = isReflexive && (retHighest || isDef); + } else if (computed == null) { + setLow = false; + } else { + setLow = retHighest ? computed <= value : computed < value; + } + if (setLow) { + low = mid + 1; + } else { + high = mid; + } + } + return nativeMin(high, MAX_ARRAY_INDEX); + } + function bindCallback(func, thisArg, argCount) { + if (typeof func != "function") { + return identity; + } + if (thisArg === undefined) { + return func; + } + switch (argCount) { + case 1: + return function(value) { + return func.call(thisArg, value); + }; + + case 3: + return function(value, index, collection) { + return func.call(thisArg, value, index, collection); + }; + + case 4: + return function(accumulator, value, index, collection) { + return func.call(thisArg, accumulator, value, index, collection); + }; + + case 5: + return function(value, other, key, object, source) { + return func.call(thisArg, value, other, key, object, source); + }; + } + return function() { + return func.apply(thisArg, arguments); + }; + } + function bufferClone(buffer) { + var result = new ArrayBuffer(buffer.byteLength), view = new Uint8Array(result); + view.set(new Uint8Array(buffer)); + return result; + } + function composeArgs(args, partials, holders) { + var holdersLength = holders.length, argsIndex = -1, argsLength = nativeMax(args.length - holdersLength, 0), leftIndex = -1, leftLength = partials.length, result = Array(leftLength + argsLength); + while (++leftIndex < leftLength) { + result[leftIndex] = partials[leftIndex]; + } + while (++argsIndex < holdersLength) { + result[holders[argsIndex]] = args[argsIndex]; + } + while (argsLength--) { + result[leftIndex++] = args[argsIndex++]; + } + return result; + } + function composeArgsRight(args, partials, holders) { + var holdersIndex = -1, holdersLength = holders.length, argsIndex = -1, argsLength = nativeMax(args.length - holdersLength, 0), rightIndex = -1, rightLength = partials.length, result = Array(argsLength + rightLength); + while (++argsIndex < argsLength) { + result[argsIndex] = args[argsIndex]; + } + var offset = argsIndex; + while (++rightIndex < rightLength) { + result[offset + rightIndex] = partials[rightIndex]; + } + while (++holdersIndex < holdersLength) { + result[offset + holders[holdersIndex]] = args[argsIndex++]; + } + return result; + } + function createAggregator(setter, initializer) { + return function(collection, iteratee, thisArg) { + var result = initializer ? initializer() : {}; + iteratee = getCallback(iteratee, thisArg, 3); + if (isArray(collection)) { + var index = -1, length = collection.length; + while (++index < length) { + var value = collection[index]; + setter(result, value, iteratee(value, index, collection), collection); + } + } else { + baseEach(collection, function(value, key, collection) { + setter(result, value, iteratee(value, key, collection), collection); + }); + } + return result; + }; + } + function createAssigner(assigner) { + return restParam(function(object, sources) { + var index = -1, length = object == null ? 0 : sources.length, customizer = length > 2 ? sources[length - 2] : undefined, guard = length > 2 ? sources[2] : undefined, thisArg = length > 1 ? sources[length - 1] : undefined; + if (typeof customizer == "function") { + customizer = bindCallback(customizer, thisArg, 5); + length -= 2; + } else { + customizer = typeof thisArg == "function" ? thisArg : undefined; + length -= customizer ? 1 : 0; + } + if (guard && isIterateeCall(sources[0], sources[1], guard)) { + customizer = length < 3 ? undefined : customizer; + length = 1; + } + while (++index < length) { + var source = sources[index]; + if (source) { + assigner(object, source, customizer); + } + } + return object; + }); + } + function createBaseEach(eachFunc, fromRight) { + return function(collection, iteratee) { + var length = collection ? getLength(collection) : 0; + if (!isLength(length)) { + return eachFunc(collection, iteratee); + } + var index = fromRight ? length : -1, iterable = toObject(collection); + while (fromRight ? index-- : ++index < length) { + if (iteratee(iterable[index], index, iterable) === false) { + break; + } + } + return collection; + }; + } + function createBaseFor(fromRight) { + return function(object, iteratee, keysFunc) { + var iterable = toObject(object), props = keysFunc(object), length = props.length, index = fromRight ? length : -1; + while (fromRight ? index-- : ++index < length) { + var key = props[index]; + if (iteratee(iterable[key], key, iterable) === false) { + break; + } + } + return object; + }; + } + function createBindWrapper(func, thisArg) { + var Ctor = createCtorWrapper(func); + function wrapper() { + var fn = this && this !== root && this instanceof wrapper ? Ctor : func; + return fn.apply(thisArg, arguments); + } + return wrapper; + } + function createCache(values) { + return nativeCreate && Set ? new SetCache(values) : null; + } + function createCompounder(callback) { + return function(string) { + var index = -1, array = words(deburr(string)), length = array.length, result = ""; + while (++index < length) { + result = callback(result, array[index], index); + } + return result; + }; + } + function createCtorWrapper(Ctor) { + return function() { + var args = arguments; + switch (args.length) { + case 0: + return new Ctor(); + + case 1: + return new Ctor(args[0]); + + case 2: + return new Ctor(args[0], args[1]); + + case 3: + return new Ctor(args[0], args[1], args[2]); + + case 4: + return new Ctor(args[0], args[1], args[2], args[3]); + + case 5: + return new Ctor(args[0], args[1], args[2], args[3], args[4]); + + case 6: + return new Ctor(args[0], args[1], args[2], args[3], args[4], args[5]); + + case 7: + return new Ctor(args[0], args[1], args[2], args[3], args[4], args[5], args[6]); + } + var thisBinding = baseCreate(Ctor.prototype), result = Ctor.apply(thisBinding, args); + return isObject(result) ? result : thisBinding; + }; + } + function createCurry(flag) { + function curryFunc(func, arity, guard) { + if (guard && isIterateeCall(func, arity, guard)) { + arity = undefined; + } + var result = createWrapper(func, flag, undefined, undefined, undefined, undefined, undefined, arity); + result.placeholder = curryFunc.placeholder; + return result; + } + return curryFunc; + } + function createDefaults(assigner, customizer) { + return restParam(function(args) { + var object = args[0]; + if (object == null) { + return object; + } + args.push(customizer); + return assigner.apply(undefined, args); + }); + } + function createExtremum(comparator, exValue) { + return function(collection, iteratee, thisArg) { + if (thisArg && isIterateeCall(collection, iteratee, thisArg)) { + iteratee = undefined; + } + iteratee = getCallback(iteratee, thisArg, 3); + if (iteratee.length == 1) { + collection = isArray(collection) ? collection : toIterable(collection); + var result = arrayExtremum(collection, iteratee, comparator, exValue); + if (!(collection.length && result === exValue)) { + return result; + } + } + return baseExtremum(collection, iteratee, comparator, exValue); + }; + } + function createFind(eachFunc, fromRight) { + return function(collection, predicate, thisArg) { + predicate = getCallback(predicate, thisArg, 3); + if (isArray(collection)) { + var index = baseFindIndex(collection, predicate, fromRight); + return index > -1 ? collection[index] : undefined; + } + return baseFind(collection, predicate, eachFunc); + }; + } + function createFindIndex(fromRight) { + return function(array, predicate, thisArg) { + if (!(array && array.length)) { + return -1; + } + predicate = getCallback(predicate, thisArg, 3); + return baseFindIndex(array, predicate, fromRight); + }; + } + function createFindKey(objectFunc) { + return function(object, predicate, thisArg) { + predicate = getCallback(predicate, thisArg, 3); + return baseFind(object, predicate, objectFunc, true); + }; + } + function createFlow(fromRight) { + return function() { + var wrapper, length = arguments.length, index = fromRight ? length : -1, leftIndex = 0, funcs = Array(length); + while (fromRight ? index-- : ++index < length) { + var func = funcs[leftIndex++] = arguments[index]; + if (typeof func != "function") { + throw new TypeError(FUNC_ERROR_TEXT); + } + if (!wrapper && LodashWrapper.prototype.thru && getFuncName(func) == "wrapper") { + wrapper = new LodashWrapper([], true); + } + } + index = wrapper ? -1 : length; + while (++index < length) { + func = funcs[index]; + var funcName = getFuncName(func), data = funcName == "wrapper" ? getData(func) : undefined; + if (data && isLaziable(data[0]) && data[1] == (ARY_FLAG | CURRY_FLAG | PARTIAL_FLAG | REARG_FLAG) && !data[4].length && data[9] == 1) { + wrapper = wrapper[getFuncName(data[0])].apply(wrapper, data[3]); + } else { + wrapper = func.length == 1 && isLaziable(func) ? wrapper[funcName]() : wrapper.thru(func); + } + } + return function() { + var args = arguments, value = args[0]; + if (wrapper && args.length == 1 && isArray(value) && value.length >= LARGE_ARRAY_SIZE) { + return wrapper.plant(value).value(); + } + var index = 0, result = length ? funcs[index].apply(this, args) : value; + while (++index < length) { + result = funcs[index].call(this, result); + } + return result; + }; + }; + } + function createForEach(arrayFunc, eachFunc) { + return function(collection, iteratee, thisArg) { + return typeof iteratee == "function" && thisArg === undefined && isArray(collection) ? arrayFunc(collection, iteratee) : eachFunc(collection, bindCallback(iteratee, thisArg, 3)); + }; + } + function createForIn(objectFunc) { + return function(object, iteratee, thisArg) { + if (typeof iteratee != "function" || thisArg !== undefined) { + iteratee = bindCallback(iteratee, thisArg, 3); + } + return objectFunc(object, iteratee, keysIn); + }; + } + function createForOwn(objectFunc) { + return function(object, iteratee, thisArg) { + if (typeof iteratee != "function" || thisArg !== undefined) { + iteratee = bindCallback(iteratee, thisArg, 3); + } + return objectFunc(object, iteratee); + }; + } + function createObjectMapper(isMapKeys) { + return function(object, iteratee, thisArg) { + var result = {}; + iteratee = getCallback(iteratee, thisArg, 3); + baseForOwn(object, function(value, key, object) { + var mapped = iteratee(value, key, object); + key = isMapKeys ? mapped : key; + value = isMapKeys ? value : mapped; + result[key] = value; + }); + return result; + }; + } + function createPadDir(fromRight) { + return function(string, length, chars) { + string = baseToString(string); + return (fromRight ? string : "") + createPadding(string, length, chars) + (fromRight ? "" : string); + }; + } + function createPartial(flag) { + var partialFunc = restParam(function(func, partials) { + var holders = replaceHolders(partials, partialFunc.placeholder); + return createWrapper(func, flag, undefined, partials, holders); + }); + return partialFunc; + } + function createReduce(arrayFunc, eachFunc) { + return function(collection, iteratee, accumulator, thisArg) { + var initFromArray = arguments.length < 3; + return typeof iteratee == "function" && thisArg === undefined && isArray(collection) ? arrayFunc(collection, iteratee, accumulator, initFromArray) : baseReduce(collection, getCallback(iteratee, thisArg, 4), accumulator, initFromArray, eachFunc); + }; + } + function createHybridWrapper(func, bitmask, thisArg, partials, holders, partialsRight, holdersRight, argPos, ary, arity) { + var isAry = bitmask & ARY_FLAG, isBind = bitmask & BIND_FLAG, isBindKey = bitmask & BIND_KEY_FLAG, isCurry = bitmask & CURRY_FLAG, isCurryBound = bitmask & CURRY_BOUND_FLAG, isCurryRight = bitmask & CURRY_RIGHT_FLAG, Ctor = isBindKey ? undefined : createCtorWrapper(func); + function wrapper() { + var length = arguments.length, index = length, args = Array(length); + while (index--) { + args[index] = arguments[index]; + } + if (partials) { + args = composeArgs(args, partials, holders); + } + if (partialsRight) { + args = composeArgsRight(args, partialsRight, holdersRight); + } + if (isCurry || isCurryRight) { + var placeholder = wrapper.placeholder, argsHolders = replaceHolders(args, placeholder); + length -= argsHolders.length; + if (length < arity) { + var newArgPos = argPos ? arrayCopy(argPos) : undefined, newArity = nativeMax(arity - length, 0), newsHolders = isCurry ? argsHolders : undefined, newHoldersRight = isCurry ? undefined : argsHolders, newPartials = isCurry ? args : undefined, newPartialsRight = isCurry ? undefined : args; + bitmask |= isCurry ? PARTIAL_FLAG : PARTIAL_RIGHT_FLAG; + bitmask &= ~(isCurry ? PARTIAL_RIGHT_FLAG : PARTIAL_FLAG); + if (!isCurryBound) { + bitmask &= ~(BIND_FLAG | BIND_KEY_FLAG); + } + var newData = [ func, bitmask, thisArg, newPartials, newsHolders, newPartialsRight, newHoldersRight, newArgPos, ary, newArity ], result = createHybridWrapper.apply(undefined, newData); + if (isLaziable(func)) { + setData(result, newData); + } + result.placeholder = placeholder; + return result; + } + } + var thisBinding = isBind ? thisArg : this, fn = isBindKey ? thisBinding[func] : func; + if (argPos) { + args = reorder(args, argPos); + } + if (isAry && ary < args.length) { + args.length = ary; + } + if (this && this !== root && this instanceof wrapper) { + fn = Ctor || createCtorWrapper(func); + } + return fn.apply(thisBinding, args); + } + return wrapper; + } + function createPadding(string, length, chars) { + var strLength = string.length; + length = +length; + if (strLength >= length || !nativeIsFinite(length)) { + return ""; + } + var padLength = length - strLength; + chars = chars == null ? " " : chars + ""; + return repeat(chars, nativeCeil(padLength / chars.length)).slice(0, padLength); + } + function createPartialWrapper(func, bitmask, thisArg, partials) { + var isBind = bitmask & BIND_FLAG, Ctor = createCtorWrapper(func); + function wrapper() { + var argsIndex = -1, argsLength = arguments.length, leftIndex = -1, leftLength = partials.length, args = Array(leftLength + argsLength); + while (++leftIndex < leftLength) { + args[leftIndex] = partials[leftIndex]; + } + while (argsLength--) { + args[leftIndex++] = arguments[++argsIndex]; + } + var fn = this && this !== root && this instanceof wrapper ? Ctor : func; + return fn.apply(isBind ? thisArg : this, args); + } + return wrapper; + } + function createRound(methodName) { + var func = Math[methodName]; + return function(number, precision) { + precision = precision === undefined ? 0 : +precision || 0; + if (precision) { + precision = pow(10, precision); + return func(number * precision) / precision; + } + return func(number); + }; + } + function createSortedIndex(retHighest) { + return function(array, value, iteratee, thisArg) { + var callback = getCallback(iteratee); + return iteratee == null && callback === baseCallback ? binaryIndex(array, value, retHighest) : binaryIndexBy(array, value, callback(iteratee, thisArg, 1), retHighest); + }; + } + function createWrapper(func, bitmask, thisArg, partials, holders, argPos, ary, arity) { + var isBindKey = bitmask & BIND_KEY_FLAG; + if (!isBindKey && typeof func != "function") { + throw new TypeError(FUNC_ERROR_TEXT); + } + var length = partials ? partials.length : 0; + if (!length) { + bitmask &= ~(PARTIAL_FLAG | PARTIAL_RIGHT_FLAG); + partials = holders = undefined; + } + length -= holders ? holders.length : 0; + if (bitmask & PARTIAL_RIGHT_FLAG) { + var partialsRight = partials, holdersRight = holders; + partials = holders = undefined; + } + var data = isBindKey ? undefined : getData(func), newData = [ func, bitmask, thisArg, partials, holders, partialsRight, holdersRight, argPos, ary, arity ]; + if (data) { + mergeData(newData, data); + bitmask = newData[1]; + arity = newData[9]; + } + newData[9] = arity == null ? isBindKey ? 0 : func.length : nativeMax(arity - length, 0) || 0; + if (bitmask == BIND_FLAG) { + var result = createBindWrapper(newData[0], newData[2]); + } else if ((bitmask == PARTIAL_FLAG || bitmask == (BIND_FLAG | PARTIAL_FLAG)) && !newData[4].length) { + result = createPartialWrapper.apply(undefined, newData); + } else { + result = createHybridWrapper.apply(undefined, newData); + } + var setter = data ? baseSetData : setData; + return setter(result, newData); + } + function equalArrays(array, other, equalFunc, customizer, isLoose, stackA, stackB) { + var index = -1, arrLength = array.length, othLength = other.length; + if (arrLength != othLength && !(isLoose && othLength > arrLength)) { + return false; + } + while (++index < arrLength) { + var arrValue = array[index], othValue = other[index], result = customizer ? customizer(isLoose ? othValue : arrValue, isLoose ? arrValue : othValue, index) : undefined; + if (result !== undefined) { + if (result) { + continue; + } + return false; + } + if (isLoose) { + if (!arraySome(other, function(othValue) { + return arrValue === othValue || equalFunc(arrValue, othValue, customizer, isLoose, stackA, stackB); + })) { + return false; + } + } else if (!(arrValue === othValue || equalFunc(arrValue, othValue, customizer, isLoose, stackA, stackB))) { + return false; + } + } + return true; + } + function equalByTag(object, other, tag) { + switch (tag) { + case boolTag: + case dateTag: + return +object == +other; + + case errorTag: + return object.name == other.name && object.message == other.message; + + case numberTag: + return object != +object ? other != +other : object == +other; + + case regexpTag: + case stringTag: + return object == other + ""; + } + return false; + } + function equalObjects(object, other, equalFunc, customizer, isLoose, stackA, stackB) { + var objProps = keys(object), objLength = objProps.length, othProps = keys(other), othLength = othProps.length; + if (objLength != othLength && !isLoose) { + return false; + } + var index = objLength; + while (index--) { + var key = objProps[index]; + if (!(isLoose ? key in other : hasOwnProperty.call(other, key))) { + return false; + } + } + var skipCtor = isLoose; + while (++index < objLength) { + key = objProps[index]; + var objValue = object[key], othValue = other[key], result = customizer ? customizer(isLoose ? othValue : objValue, isLoose ? objValue : othValue, key) : undefined; + if (!(result === undefined ? equalFunc(objValue, othValue, customizer, isLoose, stackA, stackB) : result)) { + return false; + } + skipCtor || (skipCtor = key == "constructor"); + } + if (!skipCtor) { + var objCtor = object.constructor, othCtor = other.constructor; + if (objCtor != othCtor && ("constructor" in object && "constructor" in other) && !(typeof objCtor == "function" && objCtor instanceof objCtor && typeof othCtor == "function" && othCtor instanceof othCtor)) { + return false; + } + } + return true; + } + function getCallback(func, thisArg, argCount) { + var result = lodash.callback || callback; + result = result === callback ? baseCallback : result; + return argCount ? result(func, thisArg, argCount) : result; + } + var getData = !metaMap ? noop : function(func) { + return metaMap.get(func); + }; + function getFuncName(func) { + var result = func.name + "", array = realNames[result], length = array ? array.length : 0; + while (length--) { + var data = array[length], otherFunc = data.func; + if (otherFunc == null || otherFunc == func) { + return data.name; + } + } + return result; + } + function getIndexOf(collection, target, fromIndex) { + var result = lodash.indexOf || indexOf; + result = result === indexOf ? baseIndexOf : result; + return collection ? result(collection, target, fromIndex) : result; + } + var getLength = baseProperty("length"); + function getMatchData(object) { + var result = pairs(object), length = result.length; + while (length--) { + result[length][2] = isStrictComparable(result[length][1]); + } + return result; + } + function getNative(object, key) { + var value = object == null ? undefined : object[key]; + return isNative(value) ? value : undefined; + } + function getView(start, end, transforms) { + var index = -1, length = transforms.length; + while (++index < length) { + var data = transforms[index], size = data.size; + switch (data.type) { + case "drop": + start += size; + break; + + case "dropRight": + end -= size; + break; + + case "take": + end = nativeMin(end, start + size); + break; + + case "takeRight": + start = nativeMax(start, end - size); + break; + } + } + return { + start: start, + end: end + }; + } + function initCloneArray(array) { + var length = array.length, result = new array.constructor(length); + if (length && typeof array[0] == "string" && hasOwnProperty.call(array, "index")) { + result.index = array.index; + result.input = array.input; + } + return result; + } + function initCloneObject(object) { + var Ctor = object.constructor; + if (!(typeof Ctor == "function" && Ctor instanceof Ctor)) { + Ctor = Object; + } + return new Ctor(); + } + function initCloneByTag(object, tag, isDeep) { + var Ctor = object.constructor; + switch (tag) { + case arrayBufferTag: + return bufferClone(object); + + case boolTag: + case dateTag: + return new Ctor(+object); + + case float32Tag: + case float64Tag: + case int8Tag: + case int16Tag: + case int32Tag: + case uint8Tag: + case uint8ClampedTag: + case uint16Tag: + case uint32Tag: + var buffer = object.buffer; + return new Ctor(isDeep ? bufferClone(buffer) : buffer, object.byteOffset, object.length); + + case numberTag: + case stringTag: + return new Ctor(object); + + case regexpTag: + var result = new Ctor(object.source, reFlags.exec(object)); + result.lastIndex = object.lastIndex; + } + return result; + } + function invokePath(object, path, args) { + if (object != null && !isKey(path, object)) { + path = toPath(path); + object = path.length == 1 ? object : baseGet(object, baseSlice(path, 0, -1)); + path = last(path); + } + var func = object == null ? object : object[path]; + return func == null ? undefined : func.apply(object, args); + } + function isArrayLike(value) { + return value != null && isLength(getLength(value)); + } + function isIndex(value, length) { + value = typeof value == "number" || reIsUint.test(value) ? +value : -1; + length = length == null ? MAX_SAFE_INTEGER : length; + return value > -1 && value % 1 == 0 && value < length; + } + function isIterateeCall(value, index, object) { + if (!isObject(object)) { + return false; + } + var type = typeof index; + if (type == "number" ? isArrayLike(object) && isIndex(index, object.length) : type == "string" && index in object) { + var other = object[index]; + return value === value ? value === other : other !== other; + } + return false; + } + function isKey(value, object) { + var type = typeof value; + if (type == "string" && reIsPlainProp.test(value) || type == "number") { + return true; + } + if (isArray(value)) { + return false; + } + var result = !reIsDeepProp.test(value); + return result || object != null && value in toObject(object); + } + function isLaziable(func) { + var funcName = getFuncName(func), other = lodash[funcName]; + if (typeof other != "function" || !(funcName in LazyWrapper.prototype)) { + return false; + } + if (func === other) { + return true; + } + var data = getData(other); + return !!data && func === data[0]; + } + function isLength(value) { + return typeof value == "number" && value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER; + } + function isStrictComparable(value) { + return value === value && !isObject(value); + } + function mergeData(data, source) { + var bitmask = data[1], srcBitmask = source[1], newBitmask = bitmask | srcBitmask, isCommon = newBitmask < ARY_FLAG; + var isCombo = srcBitmask == ARY_FLAG && bitmask == CURRY_FLAG || srcBitmask == ARY_FLAG && bitmask == REARG_FLAG && data[7].length <= source[8] || srcBitmask == (ARY_FLAG | REARG_FLAG) && bitmask == CURRY_FLAG; + if (!(isCommon || isCombo)) { + return data; + } + if (srcBitmask & BIND_FLAG) { + data[2] = source[2]; + newBitmask |= bitmask & BIND_FLAG ? 0 : CURRY_BOUND_FLAG; + } + var value = source[3]; + if (value) { + var partials = data[3]; + data[3] = partials ? composeArgs(partials, value, source[4]) : arrayCopy(value); + data[4] = partials ? replaceHolders(data[3], PLACEHOLDER) : arrayCopy(source[4]); + } + value = source[5]; + if (value) { + partials = data[5]; + data[5] = partials ? composeArgsRight(partials, value, source[6]) : arrayCopy(value); + data[6] = partials ? replaceHolders(data[5], PLACEHOLDER) : arrayCopy(source[6]); + } + value = source[7]; + if (value) { + data[7] = arrayCopy(value); + } + if (srcBitmask & ARY_FLAG) { + data[8] = data[8] == null ? source[8] : nativeMin(data[8], source[8]); + } + if (data[9] == null) { + data[9] = source[9]; + } + data[0] = source[0]; + data[1] = newBitmask; + return data; + } + function mergeDefaults(objectValue, sourceValue) { + return objectValue === undefined ? sourceValue : merge(objectValue, sourceValue, mergeDefaults); + } + function pickByArray(object, props) { + object = toObject(object); + var index = -1, length = props.length, result = {}; + while (++index < length) { + var key = props[index]; + if (key in object) { + result[key] = object[key]; + } + } + return result; + } + function pickByCallback(object, predicate) { + var result = {}; + baseForIn(object, function(value, key, object) { + if (predicate(value, key, object)) { + result[key] = value; + } + }); + return result; + } + function reorder(array, indexes) { + var arrLength = array.length, length = nativeMin(indexes.length, arrLength), oldArray = arrayCopy(array); + while (length--) { + var index = indexes[length]; + array[length] = isIndex(index, arrLength) ? oldArray[index] : undefined; + } + return array; + } + var setData = function() { + var count = 0, lastCalled = 0; + return function(key, value) { + var stamp = now(), remaining = HOT_SPAN - (stamp - lastCalled); + lastCalled = stamp; + if (remaining > 0) { + if (++count >= HOT_COUNT) { + return key; + } + } else { + count = 0; + } + return baseSetData(key, value); + }; + }(); + function shimKeys(object) { + var props = keysIn(object), propsLength = props.length, length = propsLength && object.length; + var allowIndexes = !!length && isLength(length) && (isArray(object) || isArguments(object)); + var index = -1, result = []; + while (++index < propsLength) { + var key = props[index]; + if (allowIndexes && isIndex(key, length) || hasOwnProperty.call(object, key)) { + result.push(key); + } + } + return result; + } + function toIterable(value) { + if (value == null) { + return []; + } + if (!isArrayLike(value)) { + return values(value); + } + return isObject(value) ? value : Object(value); + } + function toObject(value) { + return isObject(value) ? value : Object(value); + } + function toPath(value) { + if (isArray(value)) { + return value; + } + var result = []; + baseToString(value).replace(rePropName, function(match, number, quote, string) { + result.push(quote ? string.replace(reEscapeChar, "$1") : number || match); + }); + return result; + } + function wrapperClone(wrapper) { + return wrapper instanceof LazyWrapper ? wrapper.clone() : new LodashWrapper(wrapper.__wrapped__, wrapper.__chain__, arrayCopy(wrapper.__actions__)); + } + function chunk(array, size, guard) { + if (guard ? isIterateeCall(array, size, guard) : size == null) { + size = 1; + } else { + size = nativeMax(nativeFloor(size) || 1, 1); + } + var index = 0, length = array ? array.length : 0, resIndex = -1, result = Array(nativeCeil(length / size)); + while (index < length) { + result[++resIndex] = baseSlice(array, index, index += size); + } + return result; + } + function compact(array) { + var index = -1, length = array ? array.length : 0, resIndex = -1, result = []; + while (++index < length) { + var value = array[index]; + if (value) { + result[++resIndex] = value; + } + } + return result; + } + var difference = restParam(function(array, values) { + return isObjectLike(array) && isArrayLike(array) ? baseDifference(array, baseFlatten(values, false, true)) : []; + }); + function drop(array, n, guard) { + var length = array ? array.length : 0; + if (!length) { + return []; + } + if (guard ? isIterateeCall(array, n, guard) : n == null) { + n = 1; + } + return baseSlice(array, n < 0 ? 0 : n); + } + function dropRight(array, n, guard) { + var length = array ? array.length : 0; + if (!length) { + return []; + } + if (guard ? isIterateeCall(array, n, guard) : n == null) { + n = 1; + } + n = length - (+n || 0); + return baseSlice(array, 0, n < 0 ? 0 : n); + } + function dropRightWhile(array, predicate, thisArg) { + return array && array.length ? baseWhile(array, getCallback(predicate, thisArg, 3), true, true) : []; + } + function dropWhile(array, predicate, thisArg) { + return array && array.length ? baseWhile(array, getCallback(predicate, thisArg, 3), true) : []; + } + function fill(array, value, start, end) { + var length = array ? array.length : 0; + if (!length) { + return []; + } + if (start && typeof start != "number" && isIterateeCall(array, value, start)) { + start = 0; + end = length; + } + return baseFill(array, value, start, end); + } + var findIndex = createFindIndex(); + var findLastIndex = createFindIndex(true); + function first(array) { + return array ? array[0] : undefined; + } + function flatten(array, isDeep, guard) { + var length = array ? array.length : 0; + if (guard && isIterateeCall(array, isDeep, guard)) { + isDeep = false; + } + return length ? baseFlatten(array, isDeep) : []; + } + function flattenDeep(array) { + var length = array ? array.length : 0; + return length ? baseFlatten(array, true) : []; + } + function indexOf(array, value, fromIndex) { + var length = array ? array.length : 0; + if (!length) { + return -1; + } + if (typeof fromIndex == "number") { + fromIndex = fromIndex < 0 ? nativeMax(length + fromIndex, 0) : fromIndex; + } else if (fromIndex) { + var index = binaryIndex(array, value); + if (index < length && (value === value ? value === array[index] : array[index] !== array[index])) { + return index; + } + return -1; + } + return baseIndexOf(array, value, fromIndex || 0); + } + function initial(array) { + return dropRight(array, 1); + } + var intersection = restParam(function(arrays) { + var othLength = arrays.length, othIndex = othLength, caches = Array(length), indexOf = getIndexOf(), isCommon = indexOf === baseIndexOf, result = []; + while (othIndex--) { + var value = arrays[othIndex] = isArrayLike(value = arrays[othIndex]) ? value : []; + caches[othIndex] = isCommon && value.length >= 120 ? createCache(othIndex && value) : null; + } + var array = arrays[0], index = -1, length = array ? array.length : 0, seen = caches[0]; + outer: while (++index < length) { + value = array[index]; + if ((seen ? cacheIndexOf(seen, value) : indexOf(result, value, 0)) < 0) { + var othIndex = othLength; + while (--othIndex) { + var cache = caches[othIndex]; + if ((cache ? cacheIndexOf(cache, value) : indexOf(arrays[othIndex], value, 0)) < 0) { + continue outer; + } + } + if (seen) { + seen.push(value); + } + result.push(value); + } + } + return result; + }); + function last(array) { + var length = array ? array.length : 0; + return length ? array[length - 1] : undefined; + } + function lastIndexOf(array, value, fromIndex) { + var length = array ? array.length : 0; + if (!length) { + return -1; + } + var index = length; + if (typeof fromIndex == "number") { + index = (fromIndex < 0 ? nativeMax(length + fromIndex, 0) : nativeMin(fromIndex || 0, length - 1)) + 1; + } else if (fromIndex) { + index = binaryIndex(array, value, true) - 1; + var other = array[index]; + if (value === value ? value === other : other !== other) { + return index; + } + return -1; + } + if (value !== value) { + return indexOfNaN(array, index, true); + } + while (index--) { + if (array[index] === value) { + return index; + } + } + return -1; + } + function pull() { + var args = arguments, array = args[0]; + if (!(array && array.length)) { + return array; + } + var index = 0, indexOf = getIndexOf(), length = args.length; + while (++index < length) { + var fromIndex = 0, value = args[index]; + while ((fromIndex = indexOf(array, value, fromIndex)) > -1) { + splice.call(array, fromIndex, 1); + } + } + return array; + } + var pullAt = restParam(function(array, indexes) { + indexes = baseFlatten(indexes); + var result = baseAt(array, indexes); + basePullAt(array, indexes.sort(baseCompareAscending)); + return result; + }); + function remove(array, predicate, thisArg) { + var result = []; + if (!(array && array.length)) { + return result; + } + var index = -1, indexes = [], length = array.length; + predicate = getCallback(predicate, thisArg, 3); + while (++index < length) { + var value = array[index]; + if (predicate(value, index, array)) { + result.push(value); + indexes.push(index); + } + } + basePullAt(array, indexes); + return result; + } + function rest(array) { + return drop(array, 1); + } + function slice(array, start, end) { + var length = array ? array.length : 0; + if (!length) { + return []; + } + if (end && typeof end != "number" && isIterateeCall(array, start, end)) { + start = 0; + end = length; + } + return baseSlice(array, start, end); + } + var sortedIndex = createSortedIndex(); + var sortedLastIndex = createSortedIndex(true); + function take(array, n, guard) { + var length = array ? array.length : 0; + if (!length) { + return []; + } + if (guard ? isIterateeCall(array, n, guard) : n == null) { + n = 1; + } + return baseSlice(array, 0, n < 0 ? 0 : n); + } + function takeRight(array, n, guard) { + var length = array ? array.length : 0; + if (!length) { + return []; + } + if (guard ? isIterateeCall(array, n, guard) : n == null) { + n = 1; + } + n = length - (+n || 0); + return baseSlice(array, n < 0 ? 0 : n); + } + function takeRightWhile(array, predicate, thisArg) { + return array && array.length ? baseWhile(array, getCallback(predicate, thisArg, 3), false, true) : []; + } + function takeWhile(array, predicate, thisArg) { + return array && array.length ? baseWhile(array, getCallback(predicate, thisArg, 3)) : []; + } + var union = restParam(function(arrays) { + return baseUniq(baseFlatten(arrays, false, true)); + }); + function uniq(array, isSorted, iteratee, thisArg) { + var length = array ? array.length : 0; + if (!length) { + return []; + } + if (isSorted != null && typeof isSorted != "boolean") { + thisArg = iteratee; + iteratee = isIterateeCall(array, isSorted, thisArg) ? undefined : isSorted; + isSorted = false; + } + var callback = getCallback(); + if (!(iteratee == null && callback === baseCallback)) { + iteratee = callback(iteratee, thisArg, 3); + } + return isSorted && getIndexOf() === baseIndexOf ? sortedUniq(array, iteratee) : baseUniq(array, iteratee); + } + function unzip(array) { + if (!(array && array.length)) { + return []; + } + var index = -1, length = 0; + array = arrayFilter(array, function(group) { + if (isArrayLike(group)) { + length = nativeMax(group.length, length); + return true; + } + }); + var result = Array(length); + while (++index < length) { + result[index] = arrayMap(array, baseProperty(index)); + } + return result; + } + function unzipWith(array, iteratee, thisArg) { + var length = array ? array.length : 0; + if (!length) { + return []; + } + var result = unzip(array); + if (iteratee == null) { + return result; + } + iteratee = bindCallback(iteratee, thisArg, 4); + return arrayMap(result, function(group) { + return arrayReduce(group, iteratee, undefined, true); + }); + } + var without = restParam(function(array, values) { + return isArrayLike(array) ? baseDifference(array, values) : []; + }); + function xor() { + var index = -1, length = arguments.length; + while (++index < length) { + var array = arguments[index]; + if (isArrayLike(array)) { + var result = result ? arrayPush(baseDifference(result, array), baseDifference(array, result)) : array; + } + } + return result ? baseUniq(result) : []; + } + var zip = restParam(unzip); + function zipObject(props, values) { + var index = -1, length = props ? props.length : 0, result = {}; + if (length && !values && !isArray(props[0])) { + values = []; + } + while (++index < length) { + var key = props[index]; + if (values) { + result[key] = values[index]; + } else if (key) { + result[key[0]] = key[1]; + } + } + return result; + } + var zipWith = restParam(function(arrays) { + var length = arrays.length, iteratee = length > 2 ? arrays[length - 2] : undefined, thisArg = length > 1 ? arrays[length - 1] : undefined; + if (length > 2 && typeof iteratee == "function") { + length -= 2; + } else { + iteratee = length > 1 && typeof thisArg == "function" ? (--length, thisArg) : undefined; + thisArg = undefined; + } + arrays.length = length; + return unzipWith(arrays, iteratee, thisArg); + }); + function chain(value) { + var result = lodash(value); + result.__chain__ = true; + return result; + } + function tap(value, interceptor, thisArg) { + interceptor.call(thisArg, value); + return value; + } + function thru(value, interceptor, thisArg) { + return interceptor.call(thisArg, value); + } + function wrapperChain() { + return chain(this); + } + function wrapperCommit() { + return new LodashWrapper(this.value(), this.__chain__); + } + var wrapperConcat = restParam(function(values) { + values = baseFlatten(values); + return this.thru(function(array) { + return arrayConcat(isArray(array) ? array : [ toObject(array) ], values); + }); + }); + function wrapperPlant(value) { + var result, parent = this; + while (parent instanceof baseLodash) { + var clone = wrapperClone(parent); + if (result) { + previous.__wrapped__ = clone; + } else { + result = clone; + } + var previous = clone; + parent = parent.__wrapped__; + } + previous.__wrapped__ = value; + return result; + } + function wrapperReverse() { + var value = this.__wrapped__; + var interceptor = function(value) { + return value.reverse(); + }; + if (value instanceof LazyWrapper) { + var wrapped = value; + if (this.__actions__.length) { + wrapped = new LazyWrapper(this); + } + wrapped = wrapped.reverse(); + wrapped.__actions__.push({ + func: thru, + args: [ interceptor ], + thisArg: undefined + }); + return new LodashWrapper(wrapped, this.__chain__); + } + return this.thru(interceptor); + } + function wrapperToString() { + return this.value() + ""; + } + function wrapperValue() { + return baseWrapperValue(this.__wrapped__, this.__actions__); + } + var at = restParam(function(collection, props) { + return baseAt(collection, baseFlatten(props)); + }); + var countBy = createAggregator(function(result, value, key) { + hasOwnProperty.call(result, key) ? ++result[key] : result[key] = 1; + }); + function every(collection, predicate, thisArg) { + var func = isArray(collection) ? arrayEvery : baseEvery; + if (thisArg && isIterateeCall(collection, predicate, thisArg)) { + predicate = undefined; + } + if (typeof predicate != "function" || thisArg !== undefined) { + predicate = getCallback(predicate, thisArg, 3); + } + return func(collection, predicate); + } + function filter(collection, predicate, thisArg) { + var func = isArray(collection) ? arrayFilter : baseFilter; + predicate = getCallback(predicate, thisArg, 3); + return func(collection, predicate); + } + var find = createFind(baseEach); + var findLast = createFind(baseEachRight, true); + function findWhere(collection, source) { + return find(collection, baseMatches(source)); + } + var forEach = createForEach(arrayEach, baseEach); + var forEachRight = createForEach(arrayEachRight, baseEachRight); + var groupBy = createAggregator(function(result, value, key) { + if (hasOwnProperty.call(result, key)) { + result[key].push(value); + } else { + result[key] = [ value ]; + } + }); + function includes(collection, target, fromIndex, guard) { + var length = collection ? getLength(collection) : 0; + if (!isLength(length)) { + collection = values(collection); + length = collection.length; + } + if (typeof fromIndex != "number" || guard && isIterateeCall(target, fromIndex, guard)) { + fromIndex = 0; + } else { + fromIndex = fromIndex < 0 ? nativeMax(length + fromIndex, 0) : fromIndex || 0; + } + return typeof collection == "string" || !isArray(collection) && isString(collection) ? fromIndex <= length && collection.indexOf(target, fromIndex) > -1 : !!length && getIndexOf(collection, target, fromIndex) > -1; + } + var indexBy = createAggregator(function(result, value, key) { + result[key] = value; + }); + var invoke = restParam(function(collection, path, args) { + var index = -1, isFunc = typeof path == "function", isProp = isKey(path), result = isArrayLike(collection) ? Array(collection.length) : []; + baseEach(collection, function(value) { + var func = isFunc ? path : isProp && value != null ? value[path] : undefined; + result[++index] = func ? func.apply(value, args) : invokePath(value, path, args); + }); + return result; + }); + function map(collection, iteratee, thisArg) { + var func = isArray(collection) ? arrayMap : baseMap; + iteratee = getCallback(iteratee, thisArg, 3); + return func(collection, iteratee); + } + var partition = createAggregator(function(result, value, key) { + result[key ? 0 : 1].push(value); + }, function() { + return [ [], [] ]; + }); + function pluck(collection, path) { + return map(collection, property(path)); + } + var reduce = createReduce(arrayReduce, baseEach); + var reduceRight = createReduce(arrayReduceRight, baseEachRight); + function reject(collection, predicate, thisArg) { + var func = isArray(collection) ? arrayFilter : baseFilter; + predicate = getCallback(predicate, thisArg, 3); + return func(collection, function(value, index, collection) { + return !predicate(value, index, collection); + }); + } + function sample(collection, n, guard) { + if (guard ? isIterateeCall(collection, n, guard) : n == null) { + collection = toIterable(collection); + var length = collection.length; + return length > 0 ? collection[baseRandom(0, length - 1)] : undefined; + } + var index = -1, result = toArray(collection), length = result.length, lastIndex = length - 1; + n = nativeMin(n < 0 ? 0 : +n || 0, length); + while (++index < n) { + var rand = baseRandom(index, lastIndex), value = result[rand]; + result[rand] = result[index]; + result[index] = value; + } + result.length = n; + return result; + } + function shuffle(collection) { + return sample(collection, POSITIVE_INFINITY); + } + function size(collection) { + var length = collection ? getLength(collection) : 0; + return isLength(length) ? length : keys(collection).length; + } + function some(collection, predicate, thisArg) { + var func = isArray(collection) ? arraySome : baseSome; + if (thisArg && isIterateeCall(collection, predicate, thisArg)) { + predicate = undefined; + } + if (typeof predicate != "function" || thisArg !== undefined) { + predicate = getCallback(predicate, thisArg, 3); + } + return func(collection, predicate); + } + function sortBy(collection, iteratee, thisArg) { + if (collection == null) { + return []; + } + if (thisArg && isIterateeCall(collection, iteratee, thisArg)) { + iteratee = undefined; + } + var index = -1; + iteratee = getCallback(iteratee, thisArg, 3); + var result = baseMap(collection, function(value, key, collection) { + return { + criteria: iteratee(value, key, collection), + index: ++index, + value: value + }; + }); + return baseSortBy(result, compareAscending); + } + var sortByAll = restParam(function(collection, iteratees) { + if (collection == null) { + return []; + } + var guard = iteratees[2]; + if (guard && isIterateeCall(iteratees[0], iteratees[1], guard)) { + iteratees.length = 1; + } + return baseSortByOrder(collection, baseFlatten(iteratees), []); + }); + function sortByOrder(collection, iteratees, orders, guard) { + if (collection == null) { + return []; + } + if (guard && isIterateeCall(iteratees, orders, guard)) { + orders = undefined; + } + if (!isArray(iteratees)) { + iteratees = iteratees == null ? [] : [ iteratees ]; + } + if (!isArray(orders)) { + orders = orders == null ? [] : [ orders ]; + } + return baseSortByOrder(collection, iteratees, orders); + } + function where(collection, source) { + return filter(collection, baseMatches(source)); + } + var now = nativeNow || function() { + return new Date().getTime(); + }; + function after(n, func) { + if (typeof func != "function") { + if (typeof n == "function") { + var temp = n; + n = func; + func = temp; + } else { + throw new TypeError(FUNC_ERROR_TEXT); + } + } + n = nativeIsFinite(n = +n) ? n : 0; + return function() { + if (--n < 1) { + return func.apply(this, arguments); + } + }; + } + function ary(func, n, guard) { + if (guard && isIterateeCall(func, n, guard)) { + n = undefined; + } + n = func && n == null ? func.length : nativeMax(+n || 0, 0); + return createWrapper(func, ARY_FLAG, undefined, undefined, undefined, undefined, n); + } + function before(n, func) { + var result; + if (typeof func != "function") { + if (typeof n == "function") { + var temp = n; + n = func; + func = temp; + } else { + throw new TypeError(FUNC_ERROR_TEXT); + } + } + return function() { + if (--n > 0) { + result = func.apply(this, arguments); + } + if (n <= 1) { + func = undefined; + } + return result; + }; + } + var bind = restParam(function(func, thisArg, partials) { + var bitmask = BIND_FLAG; + if (partials.length) { + var holders = replaceHolders(partials, bind.placeholder); + bitmask |= PARTIAL_FLAG; + } + return createWrapper(func, bitmask, thisArg, partials, holders); + }); + var bindAll = restParam(function(object, methodNames) { + methodNames = methodNames.length ? baseFlatten(methodNames) : functions(object); + var index = -1, length = methodNames.length; + while (++index < length) { + var key = methodNames[index]; + object[key] = createWrapper(object[key], BIND_FLAG, object); + } + return object; + }); + var bindKey = restParam(function(object, key, partials) { + var bitmask = BIND_FLAG | BIND_KEY_FLAG; + if (partials.length) { + var holders = replaceHolders(partials, bindKey.placeholder); + bitmask |= PARTIAL_FLAG; + } + return createWrapper(key, bitmask, object, partials, holders); + }); + var curry = createCurry(CURRY_FLAG); + var curryRight = createCurry(CURRY_RIGHT_FLAG); + function debounce(func, wait, options) { + var args, maxTimeoutId, result, stamp, thisArg, timeoutId, trailingCall, lastCalled = 0, maxWait = false, trailing = true; + if (typeof func != "function") { + throw new TypeError(FUNC_ERROR_TEXT); + } + wait = wait < 0 ? 0 : +wait || 0; + if (options === true) { + var leading = true; + trailing = false; + } else if (isObject(options)) { + leading = !!options.leading; + maxWait = "maxWait" in options && nativeMax(+options.maxWait || 0, wait); + trailing = "trailing" in options ? !!options.trailing : trailing; + } + function cancel() { + if (timeoutId) { + clearTimeout(timeoutId); + } + if (maxTimeoutId) { + clearTimeout(maxTimeoutId); + } + lastCalled = 0; + maxTimeoutId = timeoutId = trailingCall = undefined; + } + function complete(isCalled, id) { + if (id) { + clearTimeout(id); + } + maxTimeoutId = timeoutId = trailingCall = undefined; + if (isCalled) { + lastCalled = now(); + result = func.apply(thisArg, args); + if (!timeoutId && !maxTimeoutId) { + args = thisArg = undefined; + } + } + } + function delayed() { + var remaining = wait - (now() - stamp); + if (remaining <= 0 || remaining > wait) { + complete(trailingCall, maxTimeoutId); + } else { + timeoutId = setTimeout(delayed, remaining); + } + } + function maxDelayed() { + complete(trailing, timeoutId); + } + function debounced() { + args = arguments; + stamp = now(); + thisArg = this; + trailingCall = trailing && (timeoutId || !leading); + if (maxWait === false) { + var leadingCall = leading && !timeoutId; + } else { + if (!maxTimeoutId && !leading) { + lastCalled = stamp; + } + var remaining = maxWait - (stamp - lastCalled), isCalled = remaining <= 0 || remaining > maxWait; + if (isCalled) { + if (maxTimeoutId) { + maxTimeoutId = clearTimeout(maxTimeoutId); + } + lastCalled = stamp; + result = func.apply(thisArg, args); + } else if (!maxTimeoutId) { + maxTimeoutId = setTimeout(maxDelayed, remaining); + } + } + if (isCalled && timeoutId) { + timeoutId = clearTimeout(timeoutId); + } else if (!timeoutId && wait !== maxWait) { + timeoutId = setTimeout(delayed, wait); + } + if (leadingCall) { + isCalled = true; + result = func.apply(thisArg, args); + } + if (isCalled && !timeoutId && !maxTimeoutId) { + args = thisArg = undefined; + } + return result; + } + debounced.cancel = cancel; + return debounced; + } + var defer = restParam(function(func, args) { + return baseDelay(func, 1, args); + }); + var delay = restParam(function(func, wait, args) { + return baseDelay(func, wait, args); + }); + var flow = createFlow(); + var flowRight = createFlow(true); + function memoize(func, resolver) { + if (typeof func != "function" || resolver && typeof resolver != "function") { + throw new TypeError(FUNC_ERROR_TEXT); + } + var memoized = function() { + var args = arguments, key = resolver ? resolver.apply(this, args) : args[0], cache = memoized.cache; + if (cache.has(key)) { + return cache.get(key); + } + var result = func.apply(this, args); + memoized.cache = cache.set(key, result); + return result; + }; + memoized.cache = new memoize.Cache(); + return memoized; + } + var modArgs = restParam(function(func, transforms) { + transforms = baseFlatten(transforms); + if (typeof func != "function" || !arrayEvery(transforms, baseIsFunction)) { + throw new TypeError(FUNC_ERROR_TEXT); + } + var length = transforms.length; + return restParam(function(args) { + var index = nativeMin(args.length, length); + while (index--) { + args[index] = transforms[index](args[index]); + } + return func.apply(this, args); + }); + }); + function negate(predicate) { + if (typeof predicate != "function") { + throw new TypeError(FUNC_ERROR_TEXT); + } + return function() { + return !predicate.apply(this, arguments); + }; + } + function once(func) { + return before(2, func); + } + var partial = createPartial(PARTIAL_FLAG); + var partialRight = createPartial(PARTIAL_RIGHT_FLAG); + var rearg = restParam(function(func, indexes) { + return createWrapper(func, REARG_FLAG, undefined, undefined, undefined, baseFlatten(indexes)); + }); + function restParam(func, start) { + if (typeof func != "function") { + throw new TypeError(FUNC_ERROR_TEXT); + } + start = nativeMax(start === undefined ? func.length - 1 : +start || 0, 0); + return function() { + var args = arguments, index = -1, length = nativeMax(args.length - start, 0), rest = Array(length); + while (++index < length) { + rest[index] = args[start + index]; + } + switch (start) { + case 0: + return func.call(this, rest); + + case 1: + return func.call(this, args[0], rest); + + case 2: + return func.call(this, args[0], args[1], rest); + } + var otherArgs = Array(start + 1); + index = -1; + while (++index < start) { + otherArgs[index] = args[index]; + } + otherArgs[start] = rest; + return func.apply(this, otherArgs); + }; + } + function spread(func) { + if (typeof func != "function") { + throw new TypeError(FUNC_ERROR_TEXT); + } + return function(array) { + return func.apply(this, array); }; } - return _.pick(obj, iteratee, context); - }; - _.defaults = createAssigner(_.allKeys, true); - _.create = function(prototype, props) { - var result = baseCreate(prototype); - if (props) _.extendOwn(result, props); - return result; - }; - _.clone = function(obj) { - if (!_.isObject(obj)) return obj; - return _.isArray(obj) ? obj.slice() : _.extend({}, obj); - }; - _.tap = function(obj, interceptor) { - interceptor(obj); - return obj; - }; - _.isMatch = function(object, attrs) { - var keys = _.keys(attrs), length = keys.length; - if (object == null) return !length; - var obj = Object(object); - for (var i = 0; i < length; i++) { - var key = keys[i]; - if (attrs[key] !== obj[key] || !(key in obj)) return false; + function throttle(func, wait, options) { + var leading = true, trailing = true; + if (typeof func != "function") { + throw new TypeError(FUNC_ERROR_TEXT); + } + if (options === false) { + leading = false; + } else if (isObject(options)) { + leading = "leading" in options ? !!options.leading : leading; + trailing = "trailing" in options ? !!options.trailing : trailing; + } + return debounce(func, wait, { + leading: leading, + maxWait: +wait, + trailing: trailing + }); + } + function wrap(value, wrapper) { + wrapper = wrapper == null ? identity : wrapper; + return createWrapper(wrapper, PARTIAL_FLAG, undefined, [ value ], []); + } + function clone(value, isDeep, customizer, thisArg) { + if (isDeep && typeof isDeep != "boolean" && isIterateeCall(value, isDeep, customizer)) { + isDeep = false; + } else if (typeof isDeep == "function") { + thisArg = customizer; + customizer = isDeep; + isDeep = false; + } + return typeof customizer == "function" ? baseClone(value, isDeep, bindCallback(customizer, thisArg, 3)) : baseClone(value, isDeep); + } + function cloneDeep(value, customizer, thisArg) { + return typeof customizer == "function" ? baseClone(value, true, bindCallback(customizer, thisArg, 3)) : baseClone(value, true); + } + function gt(value, other) { + return value > other; + } + function gte(value, other) { + return value >= other; + } + function isArguments(value) { + return isObjectLike(value) && isArrayLike(value) && hasOwnProperty.call(value, "callee") && !propertyIsEnumerable.call(value, "callee"); + } + var isArray = nativeIsArray || function(value) { + return isObjectLike(value) && isLength(value.length) && objToString.call(value) == arrayTag; + }; + function isBoolean(value) { + return value === true || value === false || isObjectLike(value) && objToString.call(value) == boolTag; + } + function isDate(value) { + return isObjectLike(value) && objToString.call(value) == dateTag; + } + function isElement(value) { + return !!value && value.nodeType === 1 && isObjectLike(value) && !isPlainObject(value); } - return true; - }; - var eq = function(a, b, aStack, bStack) { - if (a === b) return a !== 0 || 1 / a === 1 / b; - if (a == null || b == null) return a === b; - if (a instanceof _) a = a._wrapped; - if (b instanceof _) b = b._wrapped; - var className = toString.call(a); - if (className !== toString.call(b)) return false; - switch (className) { - case "[object RegExp]": - case "[object String]": - return "" + a === "" + b; - - case "[object Number]": - if (+a !== +a) return +b !== +b; - return +a === 0 ? 1 / +a === 1 / b : +a === +b; - - case "[object Date]": - case "[object Boolean]": - return +a === +b; - } - var areArrays = className === "[object Array]"; - if (!areArrays) { - if (typeof a != "object" || typeof b != "object") return false; - var aCtor = a.constructor, bCtor = b.constructor; - if (aCtor !== bCtor && !(_.isFunction(aCtor) && aCtor instanceof aCtor && _.isFunction(bCtor) && bCtor instanceof bCtor) && ("constructor" in a && "constructor" in b)) { + function isEmpty(value) { + if (value == null) { + return true; + } + if (isArrayLike(value) && (isArray(value) || isString(value) || isArguments(value) || isObjectLike(value) && isFunction(value.splice))) { + return !value.length; + } + return !keys(value).length; + } + function isEqual(value, other, customizer, thisArg) { + customizer = typeof customizer == "function" ? bindCallback(customizer, thisArg, 3) : undefined; + var result = customizer ? customizer(value, other) : undefined; + return result === undefined ? baseIsEqual(value, other, customizer) : !!result; + } + function isError(value) { + return isObjectLike(value) && typeof value.message == "string" && objToString.call(value) == errorTag; + } + function isFinite(value) { + return typeof value == "number" && nativeIsFinite(value); + } + function isFunction(value) { + return isObject(value) && objToString.call(value) == funcTag; + } + function isObject(value) { + var type = typeof value; + return !!value && (type == "object" || type == "function"); + } + function isMatch(object, source, customizer, thisArg) { + customizer = typeof customizer == "function" ? bindCallback(customizer, thisArg, 3) : undefined; + return baseIsMatch(object, getMatchData(source), customizer); + } + function isNaN(value) { + return isNumber(value) && value != +value; + } + function isNative(value) { + if (value == null) { return false; } + if (isFunction(value)) { + return reIsNative.test(fnToString.call(value)); + } + return isObjectLike(value) && reIsHostCtor.test(value); } - aStack = aStack || []; - bStack = bStack || []; - var length = aStack.length; - while (length--) { - if (aStack[length] === a) return bStack[length] === b; + function isNull(value) { + return value === null; } - aStack.push(a); - bStack.push(b); - if (areArrays) { - length = a.length; - if (length !== b.length) return false; - while (length--) { - if (!eq(a[length], b[length], aStack, bStack)) return false; + function isNumber(value) { + return typeof value == "number" || isObjectLike(value) && objToString.call(value) == numberTag; + } + function isPlainObject(value) { + var Ctor; + if (!(isObjectLike(value) && objToString.call(value) == objectTag && !isArguments(value)) || !hasOwnProperty.call(value, "constructor") && (Ctor = value.constructor, + typeof Ctor == "function" && !(Ctor instanceof Ctor))) { + return false; } - } else { - var keys = _.keys(a), key; - length = keys.length; - if (_.keys(b).length !== length) return false; - while (length--) { - key = keys[length]; - if (!(_.has(b, key) && eq(a[key], b[key], aStack, bStack))) return false; + var result; + baseForIn(value, function(subValue, key) { + result = key; + }); + return result === undefined || hasOwnProperty.call(value, result); + } + function isRegExp(value) { + return isObject(value) && objToString.call(value) == regexpTag; + } + function isString(value) { + return typeof value == "string" || isObjectLike(value) && objToString.call(value) == stringTag; + } + function isTypedArray(value) { + return isObjectLike(value) && isLength(value.length) && !!typedArrayTags[objToString.call(value)]; + } + function isUndefined(value) { + return value === undefined; + } + function lt(value, other) { + return value < other; + } + function lte(value, other) { + return value <= other; + } + function toArray(value) { + var length = value ? getLength(value) : 0; + if (!isLength(length)) { + return values(value); } + if (!length) { + return []; + } + return arrayCopy(value); } - aStack.pop(); - bStack.pop(); - return true; - }; - _.isEqual = function(a, b) { - return eq(a, b); - }; - _.isEmpty = function(obj) { - if (obj == null) return true; - if (isArrayLike(obj) && (_.isArray(obj) || _.isString(obj) || _.isArguments(obj))) return obj.length === 0; - return _.keys(obj).length === 0; - }; - _.isElement = function(obj) { - return !!(obj && obj.nodeType === 1); - }; - _.isArray = nativeIsArray || function(obj) { - return toString.call(obj) === "[object Array]"; - }; - _.isObject = function(obj) { - var type = typeof obj; - return type === "function" || type === "object" && !!obj; - }; - _.each([ "Arguments", "Function", "String", "Number", "Date", "RegExp", "Error" ], function(name) { - _["is" + name] = function(obj) { - return toString.call(obj) === "[object " + name + "]"; + function toPlainObject(value) { + return baseCopy(value, keysIn(value)); + } + var merge = createAssigner(baseMerge); + var assign = createAssigner(function(object, source, customizer) { + return customizer ? assignWith(object, source, customizer) : baseAssign(object, source); + }); + function create(prototype, properties, guard) { + var result = baseCreate(prototype); + if (guard && isIterateeCall(prototype, properties, guard)) { + properties = undefined; + } + return properties ? baseAssign(result, properties) : result; + } + var defaults = createDefaults(assign, assignDefaults); + var defaultsDeep = createDefaults(merge, mergeDefaults); + var findKey = createFindKey(baseForOwn); + var findLastKey = createFindKey(baseForOwnRight); + var forIn = createForIn(baseFor); + var forInRight = createForIn(baseForRight); + var forOwn = createForOwn(baseForOwn); + var forOwnRight = createForOwn(baseForOwnRight); + function functions(object) { + return baseFunctions(object, keysIn(object)); + } + function get(object, path, defaultValue) { + var result = object == null ? undefined : baseGet(object, toPath(path), path + ""); + return result === undefined ? defaultValue : result; + } + function has(object, path) { + if (object == null) { + return false; + } + var result = hasOwnProperty.call(object, path); + if (!result && !isKey(path)) { + path = toPath(path); + object = path.length == 1 ? object : baseGet(object, baseSlice(path, 0, -1)); + if (object == null) { + return false; + } + path = last(path); + result = hasOwnProperty.call(object, path); + } + return result || isLength(object.length) && isIndex(path, object.length) && (isArray(object) || isArguments(object)); + } + function invert(object, multiValue, guard) { + if (guard && isIterateeCall(object, multiValue, guard)) { + multiValue = undefined; + } + var index = -1, props = keys(object), length = props.length, result = {}; + while (++index < length) { + var key = props[index], value = object[key]; + if (multiValue) { + if (hasOwnProperty.call(result, value)) { + result[value].push(key); + } else { + result[value] = [ key ]; + } + } else { + result[value] = key; + } + } + return result; + } + var keys = !nativeKeys ? shimKeys : function(object) { + var Ctor = object == null ? undefined : object.constructor; + if (typeof Ctor == "function" && Ctor.prototype === object || typeof object != "function" && isArrayLike(object)) { + return shimKeys(object); + } + return isObject(object) ? nativeKeys(object) : []; }; - }); - if (!_.isArguments(arguments)) { - _.isArguments = function(obj) { - return _.has(obj, "callee"); + function keysIn(object) { + if (object == null) { + return []; + } + if (!isObject(object)) { + object = Object(object); + } + var length = object.length; + length = length && isLength(length) && (isArray(object) || isArguments(object)) && length || 0; + var Ctor = object.constructor, index = -1, isProto = typeof Ctor == "function" && Ctor.prototype === object, result = Array(length), skipIndexes = length > 0; + while (++index < length) { + result[index] = index + ""; + } + for (var key in object) { + if (!(skipIndexes && isIndex(key, length)) && !(key == "constructor" && (isProto || !hasOwnProperty.call(object, key)))) { + result.push(key); + } + } + return result; + } + var mapKeys = createObjectMapper(true); + var mapValues = createObjectMapper(); + var omit = restParam(function(object, props) { + if (object == null) { + return {}; + } + if (typeof props[0] != "function") { + var props = arrayMap(baseFlatten(props), String); + return pickByArray(object, baseDifference(keysIn(object), props)); + } + var predicate = bindCallback(props[0], props[1], 3); + return pickByCallback(object, function(value, key, object) { + return !predicate(value, key, object); + }); + }); + function pairs(object) { + object = toObject(object); + var index = -1, props = keys(object), length = props.length, result = Array(length); + while (++index < length) { + var key = props[index]; + result[index] = [ key, object[key] ]; + } + return result; + } + var pick = restParam(function(object, props) { + if (object == null) { + return {}; + } + return typeof props[0] == "function" ? pickByCallback(object, bindCallback(props[0], props[1], 3)) : pickByArray(object, baseFlatten(props)); + }); + function result(object, path, defaultValue) { + var result = object == null ? undefined : object[path]; + if (result === undefined) { + if (object != null && !isKey(path, object)) { + path = toPath(path); + object = path.length == 1 ? object : baseGet(object, baseSlice(path, 0, -1)); + result = object == null ? undefined : object[last(path)]; + } + result = result === undefined ? defaultValue : result; + } + return isFunction(result) ? result.call(object) : result; + } + function set(object, path, value) { + if (object == null) { + return object; + } + var pathKey = path + ""; + path = object[pathKey] != null || isKey(path, object) ? [ pathKey ] : toPath(path); + var index = -1, length = path.length, lastIndex = length - 1, nested = object; + while (nested != null && ++index < length) { + var key = path[index]; + if (isObject(nested)) { + if (index == lastIndex) { + nested[key] = value; + } else if (nested[key] == null) { + nested[key] = isIndex(path[index + 1]) ? [] : {}; + } + } + nested = nested[key]; + } + return object; + } + function transform(object, iteratee, accumulator, thisArg) { + var isArr = isArray(object) || isTypedArray(object); + iteratee = getCallback(iteratee, thisArg, 4); + if (accumulator == null) { + if (isArr || isObject(object)) { + var Ctor = object.constructor; + if (isArr) { + accumulator = isArray(object) ? new Ctor() : []; + } else { + accumulator = baseCreate(isFunction(Ctor) ? Ctor.prototype : undefined); + } + } else { + accumulator = {}; + } + } + (isArr ? arrayEach : baseForOwn)(object, function(value, index, object) { + return iteratee(accumulator, value, index, object); + }); + return accumulator; + } + function values(object) { + return baseValues(object, keys(object)); + } + function valuesIn(object) { + return baseValues(object, keysIn(object)); + } + function inRange(value, start, end) { + start = +start || 0; + if (end === undefined) { + end = start; + start = 0; + } else { + end = +end || 0; + } + return value >= nativeMin(start, end) && value < nativeMax(start, end); + } + function random(min, max, floating) { + if (floating && isIterateeCall(min, max, floating)) { + max = floating = undefined; + } + var noMin = min == null, noMax = max == null; + if (floating == null) { + if (noMax && typeof min == "boolean") { + floating = min; + min = 1; + } else if (typeof max == "boolean") { + floating = max; + noMax = true; + } + } + if (noMin && noMax) { + max = 1; + noMax = false; + } + min = +min || 0; + if (noMax) { + max = min; + min = 0; + } else { + max = +max || 0; + } + if (floating || min % 1 || max % 1) { + var rand = nativeRandom(); + return nativeMin(min + rand * (max - min + parseFloat("1e-" + ((rand + "").length - 1))), max); + } + return baseRandom(min, max); + } + var camelCase = createCompounder(function(result, word, index) { + word = word.toLowerCase(); + return result + (index ? word.charAt(0).toUpperCase() + word.slice(1) : word); + }); + function capitalize(string) { + string = baseToString(string); + return string && string.charAt(0).toUpperCase() + string.slice(1); + } + function deburr(string) { + string = baseToString(string); + return string && string.replace(reLatin1, deburrLetter).replace(reComboMark, ""); + } + function endsWith(string, target, position) { + string = baseToString(string); + target = target + ""; + var length = string.length; + position = position === undefined ? length : nativeMin(position < 0 ? 0 : +position || 0, length); + position -= target.length; + return position >= 0 && string.indexOf(target, position) == position; + } + function escape(string) { + string = baseToString(string); + return string && reHasUnescapedHtml.test(string) ? string.replace(reUnescapedHtml, escapeHtmlChar) : string; + } + function escapeRegExp(string) { + string = baseToString(string); + return string && reHasRegExpChars.test(string) ? string.replace(reRegExpChars, escapeRegExpChar) : string || "(?:)"; + } + var kebabCase = createCompounder(function(result, word, index) { + return result + (index ? "-" : "") + word.toLowerCase(); + }); + function pad(string, length, chars) { + string = baseToString(string); + length = +length; + var strLength = string.length; + if (strLength >= length || !nativeIsFinite(length)) { + return string; + } + var mid = (length - strLength) / 2, leftLength = nativeFloor(mid), rightLength = nativeCeil(mid); + chars = createPadding("", rightLength, chars); + return chars.slice(0, leftLength) + string + chars; + } + var padLeft = createPadDir(); + var padRight = createPadDir(true); + function parseInt(string, radix, guard) { + if (guard ? isIterateeCall(string, radix, guard) : radix == null) { + radix = 0; + } else if (radix) { + radix = +radix; + } + string = trim(string); + return nativeParseInt(string, radix || (reHasHexPrefix.test(string) ? 16 : 10)); + } + function repeat(string, n) { + var result = ""; + string = baseToString(string); + n = +n; + if (n < 1 || !string || !nativeIsFinite(n)) { + return result; + } + do { + if (n % 2) { + result += string; + } + n = nativeFloor(n / 2); + string += string; + } while (n); + return result; + } + var snakeCase = createCompounder(function(result, word, index) { + return result + (index ? "_" : "") + word.toLowerCase(); + }); + var startCase = createCompounder(function(result, word, index) { + return result + (index ? " " : "") + (word.charAt(0).toUpperCase() + word.slice(1)); + }); + function startsWith(string, target, position) { + string = baseToString(string); + position = position == null ? 0 : nativeMin(position < 0 ? 0 : +position || 0, string.length); + return string.lastIndexOf(target, position) == position; + } + function template(string, options, otherOptions) { + var settings = lodash.templateSettings; + if (otherOptions && isIterateeCall(string, options, otherOptions)) { + options = otherOptions = undefined; + } + string = baseToString(string); + options = assignWith(baseAssign({}, otherOptions || options), settings, assignOwnDefaults); + var imports = assignWith(baseAssign({}, options.imports), settings.imports, assignOwnDefaults), importsKeys = keys(imports), importsValues = baseValues(imports, importsKeys); + var isEscaping, isEvaluating, index = 0, interpolate = options.interpolate || reNoMatch, source = "__p += '"; + var reDelimiters = RegExp((options.escape || reNoMatch).source + "|" + interpolate.source + "|" + (interpolate === reInterpolate ? reEsTemplate : reNoMatch).source + "|" + (options.evaluate || reNoMatch).source + "|$", "g"); + var sourceURL = "//# sourceURL=" + ("sourceURL" in options ? options.sourceURL : "lodash.templateSources[" + ++templateCounter + "]") + "\n"; + string.replace(reDelimiters, function(match, escapeValue, interpolateValue, esTemplateValue, evaluateValue, offset) { + interpolateValue || (interpolateValue = esTemplateValue); + source += string.slice(index, offset).replace(reUnescapedString, escapeStringChar); + if (escapeValue) { + isEscaping = true; + source += "' +\n__e(" + escapeValue + ") +\n'"; + } + if (evaluateValue) { + isEvaluating = true; + source += "';\n" + evaluateValue + ";\n__p += '"; + } + if (interpolateValue) { + source += "' +\n((__t = (" + interpolateValue + ")) == null ? '' : __t) +\n'"; + } + index = offset + match.length; + return match; + }); + source += "';\n"; + var variable = options.variable; + if (!variable) { + source = "with (obj) {\n" + source + "\n}\n"; + } + source = (isEvaluating ? source.replace(reEmptyStringLeading, "") : source).replace(reEmptyStringMiddle, "$1").replace(reEmptyStringTrailing, "$1;"); + source = "function(" + (variable || "obj") + ") {\n" + (variable ? "" : "obj || (obj = {});\n") + "var __t, __p = ''" + (isEscaping ? ", __e = _.escape" : "") + (isEvaluating ? ", __j = Array.prototype.join;\n" + "function print() { __p += __j.call(arguments, '') }\n" : ";\n") + source + "return __p\n}"; + var result = attempt(function() { + return Function(importsKeys, sourceURL + "return " + source).apply(undefined, importsValues); + }); + result.source = source; + if (isError(result)) { + throw result; + } + return result; + } + function trim(string, chars, guard) { + var value = string; + string = baseToString(string); + if (!string) { + return string; + } + if (guard ? isIterateeCall(value, chars, guard) : chars == null) { + return string.slice(trimmedLeftIndex(string), trimmedRightIndex(string) + 1); + } + chars = chars + ""; + return string.slice(charsLeftIndex(string, chars), charsRightIndex(string, chars) + 1); + } + function trimLeft(string, chars, guard) { + var value = string; + string = baseToString(string); + if (!string) { + return string; + } + if (guard ? isIterateeCall(value, chars, guard) : chars == null) { + return string.slice(trimmedLeftIndex(string)); + } + return string.slice(charsLeftIndex(string, chars + "")); + } + function trimRight(string, chars, guard) { + var value = string; + string = baseToString(string); + if (!string) { + return string; + } + if (guard ? isIterateeCall(value, chars, guard) : chars == null) { + return string.slice(0, trimmedRightIndex(string) + 1); + } + return string.slice(0, charsRightIndex(string, chars + "") + 1); + } + function trunc(string, options, guard) { + if (guard && isIterateeCall(string, options, guard)) { + options = undefined; + } + var length = DEFAULT_TRUNC_LENGTH, omission = DEFAULT_TRUNC_OMISSION; + if (options != null) { + if (isObject(options)) { + var separator = "separator" in options ? options.separator : separator; + length = "length" in options ? +options.length || 0 : length; + omission = "omission" in options ? baseToString(options.omission) : omission; + } else { + length = +options || 0; + } + } + string = baseToString(string); + if (length >= string.length) { + return string; + } + var end = length - omission.length; + if (end < 1) { + return omission; + } + var result = string.slice(0, end); + if (separator == null) { + return result + omission; + } + if (isRegExp(separator)) { + if (string.slice(end).search(separator)) { + var match, newEnd, substring = string.slice(0, end); + if (!separator.global) { + separator = RegExp(separator.source, (reFlags.exec(separator) || "") + "g"); + } + separator.lastIndex = 0; + while (match = separator.exec(substring)) { + newEnd = match.index; + } + result = result.slice(0, newEnd == null ? end : newEnd); + } + } else if (string.indexOf(separator, end) != end) { + var index = result.lastIndexOf(separator); + if (index > -1) { + result = result.slice(0, index); + } + } + return result + omission; + } + function unescape(string) { + string = baseToString(string); + return string && reHasEscapedHtml.test(string) ? string.replace(reEscapedHtml, unescapeHtmlChar) : string; + } + function words(string, pattern, guard) { + if (guard && isIterateeCall(string, pattern, guard)) { + pattern = undefined; + } + string = baseToString(string); + return string.match(pattern || reWords) || []; + } + var attempt = restParam(function(func, args) { + try { + return func.apply(undefined, args); + } catch (e) { + return isError(e) ? e : new Error(e); + } + }); + function callback(func, thisArg, guard) { + if (guard && isIterateeCall(func, thisArg, guard)) { + thisArg = undefined; + } + return isObjectLike(func) ? matches(func) : baseCallback(func, thisArg); + } + function constant(value) { + return function() { + return value; + }; + } + function identity(value) { + return value; + } + function matches(source) { + return baseMatches(baseClone(source, true)); + } + function matchesProperty(path, srcValue) { + return baseMatchesProperty(path, baseClone(srcValue, true)); + } + var method = restParam(function(path, args) { + return function(object) { + return invokePath(object, path, args); + }; + }); + var methodOf = restParam(function(object, args) { + return function(path) { + return invokePath(object, path, args); + }; + }); + function mixin(object, source, options) { + if (options == null) { + var isObj = isObject(source), props = isObj ? keys(source) : undefined, methodNames = props && props.length ? baseFunctions(source, props) : undefined; + if (!(methodNames ? methodNames.length : isObj)) { + methodNames = false; + options = source; + source = object; + object = this; + } + } + if (!methodNames) { + methodNames = baseFunctions(source, keys(source)); + } + var chain = true, index = -1, isFunc = isFunction(object), length = methodNames.length; + if (options === false) { + chain = false; + } else if (isObject(options) && "chain" in options) { + chain = options.chain; + } + while (++index < length) { + var methodName = methodNames[index], func = source[methodName]; + object[methodName] = func; + if (isFunc) { + object.prototype[methodName] = function(func) { + return function() { + var chainAll = this.__chain__; + if (chain || chainAll) { + var result = object(this.__wrapped__), actions = result.__actions__ = arrayCopy(this.__actions__); + actions.push({ + func: func, + args: arguments, + thisArg: object + }); + result.__chain__ = chainAll; + return result; + } + return func.apply(object, arrayPush([ this.value() ], arguments)); + }; + }(func); + } + } + return object; + } + function noConflict() { + root._ = oldDash; + return this; + } + function noop() {} + function property(path) { + return isKey(path) ? baseProperty(path) : basePropertyDeep(path); + } + function propertyOf(object) { + return function(path) { + return baseGet(object, toPath(path), path + ""); + }; + } + function range(start, end, step) { + if (step && isIterateeCall(start, end, step)) { + end = step = undefined; + } + start = +start || 0; + step = step == null ? 1 : +step || 0; + if (end == null) { + end = start; + start = 0; + } else { + end = +end || 0; + } + var index = -1, length = nativeMax(nativeCeil((end - start) / (step || 1)), 0), result = Array(length); + while (++index < length) { + result[index] = start; + start += step; + } + return result; + } + function times(n, iteratee, thisArg) { + n = nativeFloor(n); + if (n < 1 || !nativeIsFinite(n)) { + return []; + } + var index = -1, result = Array(nativeMin(n, MAX_ARRAY_LENGTH)); + iteratee = bindCallback(iteratee, thisArg, 1); + while (++index < n) { + if (index < MAX_ARRAY_LENGTH) { + result[index] = iteratee(index); + } else { + iteratee(index); + } + } + return result; + } + function uniqueId(prefix) { + var id = ++idCounter; + return baseToString(prefix) + id; + } + function add(augend, addend) { + return (+augend || 0) + (+addend || 0); + } + var ceil = createRound("ceil"); + var floor = createRound("floor"); + var max = createExtremum(gt, NEGATIVE_INFINITY); + var min = createExtremum(lt, POSITIVE_INFINITY); + var round = createRound("round"); + function sum(collection, iteratee, thisArg) { + if (thisArg && isIterateeCall(collection, iteratee, thisArg)) { + iteratee = undefined; + } + iteratee = getCallback(iteratee, thisArg, 3); + return iteratee.length == 1 ? arraySum(isArray(collection) ? collection : toIterable(collection), iteratee) : baseSum(collection, iteratee); + } + lodash.prototype = baseLodash.prototype; + LodashWrapper.prototype = baseCreate(baseLodash.prototype); + LodashWrapper.prototype.constructor = LodashWrapper; + LazyWrapper.prototype = baseCreate(baseLodash.prototype); + LazyWrapper.prototype.constructor = LazyWrapper; + MapCache.prototype["delete"] = mapDelete; + MapCache.prototype.get = mapGet; + MapCache.prototype.has = mapHas; + MapCache.prototype.set = mapSet; + SetCache.prototype.push = cachePush; + memoize.Cache = MapCache; + lodash.after = after; + lodash.ary = ary; + lodash.assign = assign; + lodash.at = at; + lodash.before = before; + lodash.bind = bind; + lodash.bindAll = bindAll; + lodash.bindKey = bindKey; + lodash.callback = callback; + lodash.chain = chain; + lodash.chunk = chunk; + lodash.compact = compact; + lodash.constant = constant; + lodash.countBy = countBy; + lodash.create = create; + lodash.curry = curry; + lodash.curryRight = curryRight; + lodash.debounce = debounce; + lodash.defaults = defaults; + lodash.defaultsDeep = defaultsDeep; + lodash.defer = defer; + lodash.delay = delay; + lodash.difference = difference; + lodash.drop = drop; + lodash.dropRight = dropRight; + lodash.dropRightWhile = dropRightWhile; + lodash.dropWhile = dropWhile; + lodash.fill = fill; + lodash.filter = filter; + lodash.flatten = flatten; + lodash.flattenDeep = flattenDeep; + lodash.flow = flow; + lodash.flowRight = flowRight; + lodash.forEach = forEach; + lodash.forEachRight = forEachRight; + lodash.forIn = forIn; + lodash.forInRight = forInRight; + lodash.forOwn = forOwn; + lodash.forOwnRight = forOwnRight; + lodash.functions = functions; + lodash.groupBy = groupBy; + lodash.indexBy = indexBy; + lodash.initial = initial; + lodash.intersection = intersection; + lodash.invert = invert; + lodash.invoke = invoke; + lodash.keys = keys; + lodash.keysIn = keysIn; + lodash.map = map; + lodash.mapKeys = mapKeys; + lodash.mapValues = mapValues; + lodash.matches = matches; + lodash.matchesProperty = matchesProperty; + lodash.memoize = memoize; + lodash.merge = merge; + lodash.method = method; + lodash.methodOf = methodOf; + lodash.mixin = mixin; + lodash.modArgs = modArgs; + lodash.negate = negate; + lodash.omit = omit; + lodash.once = once; + lodash.pairs = pairs; + lodash.partial = partial; + lodash.partialRight = partialRight; + lodash.partition = partition; + lodash.pick = pick; + lodash.pluck = pluck; + lodash.property = property; + lodash.propertyOf = propertyOf; + lodash.pull = pull; + lodash.pullAt = pullAt; + lodash.range = range; + lodash.rearg = rearg; + lodash.reject = reject; + lodash.remove = remove; + lodash.rest = rest; + lodash.restParam = restParam; + lodash.set = set; + lodash.shuffle = shuffle; + lodash.slice = slice; + lodash.sortBy = sortBy; + lodash.sortByAll = sortByAll; + lodash.sortByOrder = sortByOrder; + lodash.spread = spread; + lodash.take = take; + lodash.takeRight = takeRight; + lodash.takeRightWhile = takeRightWhile; + lodash.takeWhile = takeWhile; + lodash.tap = tap; + lodash.throttle = throttle; + lodash.thru = thru; + lodash.times = times; + lodash.toArray = toArray; + lodash.toPlainObject = toPlainObject; + lodash.transform = transform; + lodash.union = union; + lodash.uniq = uniq; + lodash.unzip = unzip; + lodash.unzipWith = unzipWith; + lodash.values = values; + lodash.valuesIn = valuesIn; + lodash.where = where; + lodash.without = without; + lodash.wrap = wrap; + lodash.xor = xor; + lodash.zip = zip; + lodash.zipObject = zipObject; + lodash.zipWith = zipWith; + lodash.backflow = flowRight; + lodash.collect = map; + lodash.compose = flowRight; + lodash.each = forEach; + lodash.eachRight = forEachRight; + lodash.extend = assign; + lodash.iteratee = callback; + lodash.methods = functions; + lodash.object = zipObject; + lodash.select = filter; + lodash.tail = rest; + lodash.unique = uniq; + mixin(lodash, lodash); + lodash.add = add; + lodash.attempt = attempt; + lodash.camelCase = camelCase; + lodash.capitalize = capitalize; + lodash.ceil = ceil; + lodash.clone = clone; + lodash.cloneDeep = cloneDeep; + lodash.deburr = deburr; + lodash.endsWith = endsWith; + lodash.escape = escape; + lodash.escapeRegExp = escapeRegExp; + lodash.every = every; + lodash.find = find; + lodash.findIndex = findIndex; + lodash.findKey = findKey; + lodash.findLast = findLast; + lodash.findLastIndex = findLastIndex; + lodash.findLastKey = findLastKey; + lodash.findWhere = findWhere; + lodash.first = first; + lodash.floor = floor; + lodash.get = get; + lodash.gt = gt; + lodash.gte = gte; + lodash.has = has; + lodash.identity = identity; + lodash.includes = includes; + lodash.indexOf = indexOf; + lodash.inRange = inRange; + lodash.isArguments = isArguments; + lodash.isArray = isArray; + lodash.isBoolean = isBoolean; + lodash.isDate = isDate; + lodash.isElement = isElement; + lodash.isEmpty = isEmpty; + lodash.isEqual = isEqual; + lodash.isError = isError; + lodash.isFinite = isFinite; + lodash.isFunction = isFunction; + lodash.isMatch = isMatch; + lodash.isNaN = isNaN; + lodash.isNative = isNative; + lodash.isNull = isNull; + lodash.isNumber = isNumber; + lodash.isObject = isObject; + lodash.isPlainObject = isPlainObject; + lodash.isRegExp = isRegExp; + lodash.isString = isString; + lodash.isTypedArray = isTypedArray; + lodash.isUndefined = isUndefined; + lodash.kebabCase = kebabCase; + lodash.last = last; + lodash.lastIndexOf = lastIndexOf; + lodash.lt = lt; + lodash.lte = lte; + lodash.max = max; + lodash.min = min; + lodash.noConflict = noConflict; + lodash.noop = noop; + lodash.now = now; + lodash.pad = pad; + lodash.padLeft = padLeft; + lodash.padRight = padRight; + lodash.parseInt = parseInt; + lodash.random = random; + lodash.reduce = reduce; + lodash.reduceRight = reduceRight; + lodash.repeat = repeat; + lodash.result = result; + lodash.round = round; + lodash.runInContext = runInContext; + lodash.size = size; + lodash.snakeCase = snakeCase; + lodash.some = some; + lodash.sortedIndex = sortedIndex; + lodash.sortedLastIndex = sortedLastIndex; + lodash.startCase = startCase; + lodash.startsWith = startsWith; + lodash.sum = sum; + lodash.template = template; + lodash.trim = trim; + lodash.trimLeft = trimLeft; + lodash.trimRight = trimRight; + lodash.trunc = trunc; + lodash.unescape = unescape; + lodash.uniqueId = uniqueId; + lodash.words = words; + lodash.all = every; + lodash.any = some; + lodash.contains = includes; + lodash.eq = isEqual; + lodash.detect = find; + lodash.foldl = reduce; + lodash.foldr = reduceRight; + lodash.head = first; + lodash.include = includes; + lodash.inject = reduce; + mixin(lodash, function() { + var source = {}; + baseForOwn(lodash, function(func, methodName) { + if (!lodash.prototype[methodName]) { + source[methodName] = func; + } + }); + return source; + }(), false); + lodash.sample = sample; + lodash.prototype.sample = function(n) { + if (!this.__chain__ && n == null) { + return sample(this.value()); + } + return this.thru(function(value) { + return sample(value, n); + }); }; - } - if (typeof /./ != "function" && typeof Int8Array != "object") { - _.isFunction = function(obj) { - return typeof obj == "function" || false; + lodash.VERSION = VERSION; + arrayEach([ "bind", "bindKey", "curry", "curryRight", "partial", "partialRight" ], function(methodName) { + lodash[methodName].placeholder = lodash; + }); + arrayEach([ "drop", "take" ], function(methodName, index) { + LazyWrapper.prototype[methodName] = function(n) { + var filtered = this.__filtered__; + if (filtered && !index) { + return new LazyWrapper(this); + } + n = n == null ? 1 : nativeMax(nativeFloor(n) || 0, 0); + var result = this.clone(); + if (filtered) { + result.__takeCount__ = nativeMin(result.__takeCount__, n); + } else { + result.__views__.push({ + size: n, + type: methodName + (result.__dir__ < 0 ? "Right" : "") + }); + } + return result; + }; + LazyWrapper.prototype[methodName + "Right"] = function(n) { + return this.reverse()[methodName](n).reverse(); + }; + }); + arrayEach([ "filter", "map", "takeWhile" ], function(methodName, index) { + var type = index + 1, isFilter = type != LAZY_MAP_FLAG; + LazyWrapper.prototype[methodName] = function(iteratee, thisArg) { + var result = this.clone(); + result.__iteratees__.push({ + iteratee: getCallback(iteratee, thisArg, 1), + type: type + }); + result.__filtered__ = result.__filtered__ || isFilter; + return result; + }; + }); + arrayEach([ "first", "last" ], function(methodName, index) { + var takeName = "take" + (index ? "Right" : ""); + LazyWrapper.prototype[methodName] = function() { + return this[takeName](1).value()[0]; + }; + }); + arrayEach([ "initial", "rest" ], function(methodName, index) { + var dropName = "drop" + (index ? "" : "Right"); + LazyWrapper.prototype[methodName] = function() { + return this.__filtered__ ? new LazyWrapper(this) : this[dropName](1); + }; + }); + arrayEach([ "pluck", "where" ], function(methodName, index) { + var operationName = index ? "filter" : "map", createCallback = index ? baseMatches : property; + LazyWrapper.prototype[methodName] = function(value) { + return this[operationName](createCallback(value)); + }; + }); + LazyWrapper.prototype.compact = function() { + return this.filter(identity); }; - } - _.isFinite = function(obj) { - return isFinite(obj) && !isNaN(parseFloat(obj)); - }; - _.isNaN = function(obj) { - return _.isNumber(obj) && obj !== +obj; - }; - _.isBoolean = function(obj) { - return obj === true || obj === false || toString.call(obj) === "[object Boolean]"; - }; - _.isNull = function(obj) { - return obj === null; - }; - _.isUndefined = function(obj) { - return obj === void 0; - }; - _.has = function(obj, key) { - return obj != null && hasOwnProperty.call(obj, key); - }; - _.noConflict = function() { - root._ = previousUnderscore; - return this; - }; - _.identity = function(value) { - return value; - }; - _.constant = function(value) { - return function() { - return value; + LazyWrapper.prototype.reject = function(predicate, thisArg) { + predicate = getCallback(predicate, thisArg, 1); + return this.filter(function(value) { + return !predicate(value); + }); }; - }; - _.noop = function() {}; - _.property = property; - _.propertyOf = function(obj) { - return obj == null ? function() {} : function(key) { - return obj[key]; + LazyWrapper.prototype.slice = function(start, end) { + start = start == null ? 0 : +start || 0; + var result = this; + if (result.__filtered__ && (start > 0 || end < 0)) { + return new LazyWrapper(result); + } + if (start < 0) { + result = result.takeRight(-start); + } else if (start) { + result = result.drop(start); + } + if (end !== undefined) { + end = +end || 0; + result = end < 0 ? result.dropRight(-end) : result.take(end - start); + } + return result; }; - }; - _.matcher = _.matches = function(attrs) { - attrs = _.extendOwn({}, attrs); - return function(obj) { - return _.isMatch(obj, attrs); + LazyWrapper.prototype.takeRightWhile = function(predicate, thisArg) { + return this.reverse().takeWhile(predicate, thisArg).reverse(); }; - }; - _.times = function(n, iteratee, context) { - var accum = Array(Math.max(0, n)); - iteratee = optimizeCb(iteratee, context, 1); - for (var i = 0; i < n; i++) accum[i] = iteratee(i); - return accum; - }; - _.random = function(min, max) { - if (max == null) { - max = min; - min = 0; - } - return min + Math.floor(Math.random() * (max - min + 1)); - }; - _.now = Date.now || function() { - return new Date().getTime(); - }; - var escapeMap = { - "&": "&", - "<": "<", - ">": ">", - '"': """, - "'": "'", - "`": "`" - }; - var unescapeMap = _.invert(escapeMap); - var createEscaper = function(map) { - var escaper = function(match) { - return map[match]; - }; - var source = "(?:" + _.keys(map).join("|") + ")"; - var testRegexp = RegExp(source); - var replaceRegexp = RegExp(source, "g"); - return function(string) { - string = string == null ? "" : "" + string; - return testRegexp.test(string) ? string.replace(replaceRegexp, escaper) : string; - }; - }; - _.escape = createEscaper(escapeMap); - _.unescape = createEscaper(unescapeMap); - _.result = function(object, property, fallback) { - var value = object == null ? void 0 : object[property]; - if (value === void 0) { - value = fallback; - } - return _.isFunction(value) ? value.call(object) : value; - }; - var idCounter = 0; - _.uniqueId = function(prefix) { - var id = ++idCounter + ""; - return prefix ? prefix + id : id; - }; - _.templateSettings = { - evaluate: /<%([\s\S]+?)%>/g, - interpolate: /<%=([\s\S]+?)%>/g, - escape: /<%-([\s\S]+?)%>/g - }; - var noMatch = /(.)^/; - var escapes = { - "'": "'", - "\\": "\\", - "\r": "r", - "\n": "n", - "\u2028": "u2028", - "\u2029": "u2029" - }; - var escaper = /\\|'|\r|\n|\u2028|\u2029/g; - var escapeChar = function(match) { - return "\\" + escapes[match]; - }; - _.template = function(text, settings, oldSettings) { - if (!settings && oldSettings) settings = oldSettings; - settings = _.defaults({}, settings, _.templateSettings); - var matcher = RegExp([ (settings.escape || noMatch).source, (settings.interpolate || noMatch).source, (settings.evaluate || noMatch).source ].join("|") + "|$", "g"); - var index = 0; - var source = "__p+='"; - text.replace(matcher, function(match, escape, interpolate, evaluate, offset) { - source += text.slice(index, offset).replace(escaper, escapeChar); - index = offset + match.length; - if (escape) { - source += "'+\n((__t=(" + escape + "))==null?'':_.escape(__t))+\n'"; - } else if (interpolate) { - source += "'+\n((__t=(" + interpolate + "))==null?'':__t)+\n'"; - } else if (evaluate) { - source += "';\n" + evaluate + "\n__p+='"; - } - return match; - }); - source += "';\n"; - if (!settings.variable) source = "with(obj||{}){\n" + source + "}\n"; - source = "var __t,__p='',__j=Array.prototype.join," + "print=function(){__p+=__j.call(arguments,'');};\n" + source + "return __p;\n"; - try { - var render = new Function(settings.variable || "obj", "_", source); - } catch (e) { - e.source = source; - throw e; - } - var template = function(data) { - return render.call(this, data, _); + LazyWrapper.prototype.toArray = function() { + return this.take(POSITIVE_INFINITY); }; - var argument = settings.variable || "obj"; - template.source = "function(" + argument + "){\n" + source + "}"; - return template; - }; - _.chain = function(obj) { - var instance = _(obj); - instance._chain = true; - return instance; - }; - var result = function(instance, obj) { - return instance._chain ? _(obj).chain() : obj; - }; - _.mixin = function(obj) { - _.each(_.functions(obj), function(name) { - var func = _[name] = obj[name]; - _.prototype[name] = function() { - var args = [ this._wrapped ]; - push.apply(args, arguments); - return result(this, func.apply(_, args)); + baseForOwn(LazyWrapper.prototype, function(func, methodName) { + var checkIteratee = /^(?:filter|map|reject)|While$/.test(methodName), retUnwrapped = /^(?:first|last)$/.test(methodName), lodashFunc = lodash[retUnwrapped ? "take" + (methodName == "last" ? "Right" : "") : methodName]; + if (!lodashFunc) { + return; + } + lodash.prototype[methodName] = function() { + var args = retUnwrapped ? [ 1 ] : arguments, chainAll = this.__chain__, value = this.__wrapped__, isHybrid = !!this.__actions__.length, isLazy = value instanceof LazyWrapper, iteratee = args[0], useLazy = isLazy || isArray(value); + if (useLazy && checkIteratee && typeof iteratee == "function" && iteratee.length != 1) { + isLazy = useLazy = false; + } + var interceptor = function(value) { + return retUnwrapped && chainAll ? lodashFunc(value, 1)[0] : lodashFunc.apply(undefined, arrayPush([ value ], args)); + }; + var action = { + func: thru, + args: [ interceptor ], + thisArg: undefined + }, onlyLazy = isLazy && !isHybrid; + if (retUnwrapped && !chainAll) { + if (onlyLazy) { + value = value.clone(); + value.__actions__.push(action); + return func.call(value); + } + return lodashFunc.call(undefined, this.value())[0]; + } + if (!retUnwrapped && useLazy) { + value = onlyLazy ? value : new LazyWrapper(this); + var result = func.apply(value, args); + result.__actions__.push(action); + return new LodashWrapper(result, chainAll); + } + return this.thru(interceptor); }; }); - }; - _.mixin(_); - _.each([ "pop", "push", "reverse", "shift", "sort", "splice", "unshift" ], function(name) { - var method = ArrayProto[name]; - _.prototype[name] = function() { - var obj = this._wrapped; - method.apply(obj, arguments); - if ((name === "shift" || name === "splice") && obj.length === 0) delete obj[0]; - return result(this, obj); - }; - }); - _.each([ "concat", "join", "slice" ], function(name) { - var method = ArrayProto[name]; - _.prototype[name] = function() { - return result(this, method.apply(this._wrapped, arguments)); - }; - }); - _.prototype.value = function() { - return this._wrapped; - }; - _.prototype.valueOf = _.prototype.toJSON = _.prototype.value; - _.prototype.toString = function() { - return "" + this._wrapped; - }; - if (typeof define === "function" && define.amd) { - define("underscore", [], function() { + arrayEach([ "join", "pop", "push", "replace", "shift", "sort", "splice", "split", "unshift" ], function(methodName) { + var func = (/^(?:replace|split)$/.test(methodName) ? stringProto : arrayProto)[methodName], chainName = /^(?:push|sort|unshift)$/.test(methodName) ? "tap" : "thru", retUnwrapped = /^(?:join|pop|replace|shift)$/.test(methodName); + lodash.prototype[methodName] = function() { + var args = arguments; + if (retUnwrapped && !this.__chain__) { + return func.apply(this.value(), args); + } + return this[chainName](function(value) { + return func.apply(value, args); + }); + }; + }); + baseForOwn(LazyWrapper.prototype, function(func, methodName) { + var lodashFunc = lodash[methodName]; + if (lodashFunc) { + var key = lodashFunc.name + "", names = realNames[key] || (realNames[key] = []); + names.push({ + name: methodName, + func: lodashFunc + }); + } + }); + realNames[createHybridWrapper(undefined, BIND_KEY_FLAG).name] = [ { + name: "wrapper", + func: undefined + } ]; + LazyWrapper.prototype.clone = lazyClone; + LazyWrapper.prototype.reverse = lazyReverse; + LazyWrapper.prototype.value = lazyValue; + lodash.prototype.chain = wrapperChain; + lodash.prototype.commit = wrapperCommit; + lodash.prototype.concat = wrapperConcat; + lodash.prototype.plant = wrapperPlant; + lodash.prototype.reverse = wrapperReverse; + lodash.prototype.toString = wrapperToString; + lodash.prototype.run = lodash.prototype.toJSON = lodash.prototype.valueOf = lodash.prototype.value = wrapperValue; + lodash.prototype.collect = lodash.prototype.map; + lodash.prototype.head = lodash.prototype.first; + lodash.prototype.select = lodash.prototype.filter; + lodash.prototype.tail = lodash.prototype.rest; + return lodash; + } + var _ = runInContext(); + if (typeof define == "function" && typeof define.amd == "object" && define.amd) { + root._ = _; + define(function() { return _; }); + } else if (freeExports && freeModule) { + if (moduleExports) { + (freeModule.exports = _)._ = _; + } else { + freeExports._ = _; + } + } else { + root._ = _; } }).call(this); @@ -6445,7 +9332,7 @@ } return match; }); - message += "\nhttp://errors.angularjs.org/1.4.6/" + (module ? module + "/" : "") + code; + message += "\nhttp://errors.angularjs.org/1.4.7/" + (module ? module + "/" : "") + code; for (i = SKIP_INDEXES, paramPrefix = "?"; i < templateArgs.length; i++, paramPrefix = "&") { message += paramPrefix + "p" + (i - SKIP_INDEXES) + "=" + encodeURIComponent(toDebugString(templateArgs[i])); } @@ -7264,11 +10151,11 @@ return obj; } var version = { - full: "1.4.6", + full: "1.4.7", major: 1, minor: 4, - dot: 6, - codeName: "multiplicative-elevation" + dot: 7, + codeName: "dark-luminescence" }; function publishExternalAPI(angular) { extend(angular, { @@ -7377,6 +10264,7 @@ $httpParamSerializer: $HttpParamSerializerProvider, $httpParamSerializerJQLike: $HttpParamSerializerJQLikeProvider, $httpBackend: $HttpBackendProvider, + $xhrFactory: $xhrFactoryProvider, $location: $LocationProvider, $log: $LogProvider, $parse: $ParseProvider, @@ -7422,10 +10310,10 @@ return offset ? letter.toUpperCase() : letter; }).replace(MOZ_HACK_REGEXP, "Moz$1"); } - var SINGLE_TAG_REGEXP = /^<(\w+)\s*\/?>(?:<\/\1>|)$/; + var SINGLE_TAG_REGEXP = /^<([\w-]+)\s*\/?>(?:<\/\1>|)$/; var HTML_REGEXP = /<|&#?\w+;/; - var TAG_NAME_REGEXP = /<([\w:]+)/; - var XHTML_TAG_REGEXP = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi; + var TAG_NAME_REGEXP = /<([\w:-]+)/; + var XHTML_TAG_REGEXP = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:-]+)[^>]*)\/>/gi; var wrapMap = { option: [ 1, '" ], thead: [ 1, "", "
        " ], @@ -8668,6 +11556,9 @@ } }; return function(element, options) { + if (options.cleanupStyles) { + options.from = options.to = null; + } if (options.from) { element.css(options.from); options.from = null; @@ -9933,7 +12824,7 @@ compile: function() { return { pre: function attrInterpolatePreLinkFn(scope, element, attr) { - var $$observers = attr.$$observers || (attr.$$observers = {}); + var $$observers = attr.$$observers || (attr.$$observers = createMap()); if (EVENT_HANDLER_ATTR_REGEXP.test(name)) { throw $compileMinErr("nodomevents", "Interpolations for HTML DOM event attributes are disallowed. Please use the " + "ng- versions (such as ng-click instead of onclick) instead."); } @@ -10596,12 +13487,16 @@ } } ]; } - function createXhr() { - return new window.XMLHttpRequest(); + function $xhrFactoryProvider() { + this.$get = function() { + return function createXhr() { + return new window.XMLHttpRequest(); + }; + }; } function $HttpBackendProvider() { - this.$get = [ "$browser", "$window", "$document", function($browser, $window, $document) { - return createHttpBackend($browser, createXhr, $browser.defer, $window.angular.callbacks, $document[0]); + this.$get = [ "$browser", "$window", "$document", "$xhrFactory", function($browser, $window, $document, $xhrFactory) { + return createHttpBackend($browser, $xhrFactory, $browser.defer, $window.angular.callbacks, $document[0]); } ]; } function createHttpBackend($browser, createXhr, $browserDefer, callbacks, rawDocument) { @@ -10619,7 +13514,7 @@ callbacks[callbackId] = noop; }); } else { - var xhr = createXhr(); + var xhr = createXhr(method, url); xhr.open(method, url, true); forEach(headers, function(value, key) { if (isDefined(value)) { @@ -11327,12 +14222,18 @@ } var $parseMinErr = minErr("$parse"); function ensureSafeMemberName(name, fullExpression) { - name = isObject(name) && name.toString ? name.toString() : name; if (name === "__defineGetter__" || name === "__defineSetter__" || name === "__lookupGetter__" || name === "__lookupSetter__" || name === "__proto__") { throw $parseMinErr("isecfld", "Attempting to access a disallowed field in Angular expressions! " + "Expression: {0}", fullExpression); } return name; } + function getStringValue(name, fullExpression) { + name = name + ""; + if (!isString(name)) { + throw $parseMinErr("iseccst", "Cannot convert object to primitive value! " + "Expression: {0}", fullExpression); + } + return name; + } function ensureSafeObject(obj, fullExpression) { if (obj) { if (obj.constructor === obj) { @@ -11359,6 +14260,13 @@ } } } + function ensureSafeAssignContext(obj, fullExpression) { + if (obj) { + if (obj === 0..constructor || obj === false.constructor || obj === "".constructor || obj === {}.constructor || obj === [].constructor || obj === Function.constructor) { + throw $parseMinErr("isecaf", "Assigning to a constructor is disallowed! Expression: {0}", fullExpression); + } + } + } var OPERATORS = createMap(); forEach("+ - * / % === !== == != < > <= >= && || ! = |".split(" "), function(operator) { OPERATORS[operator] = true; @@ -12107,7 +15015,7 @@ this.stage = "main"; this.recurse(ast); var fnString = '"' + this.USE + " " + this.STRICT + '";\n' + this.filterPrefix() + "var fn=" + this.generateFunction("fn", "s,l,a,i") + extra + this.watchFns() + "return fn;"; - var fn = new Function("$filter", "ensureSafeMemberName", "ensureSafeObject", "ensureSafeFunction", "ifDefined", "plus", "text", fnString)(this.$filter, ensureSafeMemberName, ensureSafeObject, ensureSafeFunction, ifDefined, plusFn, expression); + var fn = new Function("$filter", "ensureSafeMemberName", "ensureSafeObject", "ensureSafeFunction", "getStringValue", "ensureSafeAssignContext", "ifDefined", "plus", "text", fnString)(this.$filter, ensureSafeMemberName, ensureSafeObject, ensureSafeFunction, getStringValue, ensureSafeAssignContext, ifDefined, plusFn, expression); this.state = this.stage = undefined; fn.literal = isLiteral(ast); fn.constant = isConstant(ast); @@ -12244,6 +15152,7 @@ if (ast.computed) { right = self.nextId(); self.recurse(ast.property, right); + self.getStringValue(right); self.addEnsureSafeMemberName(right); if (create && create !== 1) { self.if_(self.not(self.computedMember(left, right)), self.lazyAssign(self.computedMember(left, right), "{}")); @@ -12329,6 +15238,7 @@ self.if_(self.notNull(left.context), function() { self.recurse(ast.right, right); self.addEnsureSafeObject(self.member(left.context, left.name, left.computed)); + self.addEnsureSafeAssignContext(left.context); expression = self.member(left.context, left.name, left.computed) + ast.operator + right; self.assign(intoId, expression); recursionFn(intoId || expression); @@ -12439,6 +15349,9 @@ addEnsureSafeFunction: function(item) { this.current().body.push(this.ensureSafeFunction(item), ";"); }, + addEnsureSafeAssignContext: function(item) { + this.current().body.push(this.ensureSafeAssignContext(item), ";"); + }, ensureSafeObject: function(item) { return "ensureSafeObject(" + item + ",text)"; }, @@ -12448,6 +15361,12 @@ ensureSafeFunction: function(item) { return "ensureSafeFunction(" + item + ",text)"; }, + getStringValue: function(item) { + this.assign(item, "getStringValue(" + item + ",text)"); + }, + ensureSafeAssignContext: function(item) { + return "ensureSafeAssignContext(" + item + ",text)"; + }, lazyRecurse: function(ast, intoId, nameId, recursionFn, create, skipWatchIdCheck) { var self = this; return function() { @@ -12615,6 +15534,7 @@ var lhs = left(scope, locals, assign, inputs); var rhs = right(scope, locals, assign, inputs); ensureSafeObject(lhs.value, self.expression); + ensureSafeAssignContext(lhs.context); lhs.context[lhs.name] = rhs; return context ? { value: rhs @@ -12872,6 +15792,7 @@ var value; if (lhs != null) { rhs = right(scope, locals, assign, inputs); + rhs = getStringValue(rhs); ensureSafeMemberName(rhs, expression); if (create && create !== 1 && lhs && !lhs[rhs]) { lhs[rhs] = {}; @@ -14554,6 +17475,7 @@ if (fractionSize > 0 && number < 1) { formatedText = number.toFixed(fractionSize); number = parseFloat(formatedText); + formatedText = formatedText.replace(DECIMAL_SEP, decimalSep); } } if (number === 0) { @@ -16571,11 +19493,11 @@ function updateOptionElement(option, element) { option.element = element; element.disabled = option.disabled; - if (option.value !== element.value) element.value = option.selectValue; if (option.label !== element.label) { element.label = option.label; element.textContent = option.label; } + if (option.value !== element.value) element.value = option.selectValue; } function addOrReuseElement(parent, current, type, templateElement) { var element; @@ -16603,7 +19525,7 @@ var emptyOption_ = emptyOption && emptyOption[0]; var unknownOption_ = unknownOption && unknownOption[0]; if (emptyOption_ || unknownOption_) { - while (current && (current === emptyOption_ || current === unknownOption_)) { + while (current && (current === emptyOption_ || current === unknownOption_ || emptyOption_ && emptyOption_.nodeType === NODE_TYPE_COMMENT)) { current = current.nextSibling; } } @@ -28003,6 +30925,284 @@ WaveSurfer.util.extend(WaveSurfer.Drawer.Canvas, { "use strict"; +WaveSurfer.Regions = { + init: function(a) { + this.wavesurfer = a, this.wrapper = this.wavesurfer.drawer.wrapper, this.list = {}; + }, + add: function(a) { + var b = Object.create(WaveSurfer.Region); + return b.init(a, this.wavesurfer), this.list[b.id] = b, b.on("remove", function() { + delete this.list[b.id]; + }.bind(this)), b; + }, + clear: function() { + Object.keys(this.list).forEach(function(a) { + this.list[a].remove(); + }, this); + }, + enableDragSelection: function(a) { + var b, c, d, e = this; + this.wrapper.addEventListener("mousedown", function(a) { + b = !0, c = e.wavesurfer.drawer.handleEvent(a), d = null; + }), this.wrapper.addEventListener("mouseup", function(a) { + b = !1, d && (d.fireEvent("update-end", a), e.wavesurfer.fireEvent("region-update-end", d, a)), + d = null; + }), this.wrapper.addEventListener("mousemove", function(f) { + if (b) { + d || (d = e.add(a || {})); + var g = e.wavesurfer.getDuration(), h = e.wavesurfer.drawer.handleEvent(f); + d.update({ + start: Math.min(h * g, c * g), + end: Math.max(h * g, c * g) + }); + } + }); + } +}, WaveSurfer.Region = { + style: WaveSurfer.Drawer.style, + init: function(a, b) { + this.wavesurfer = b, this.wrapper = b.drawer.wrapper, this.id = null == a.id ? WaveSurfer.util.getId() : a.id, + this.start = Number(a.start) || 0, this.end = null == a.end ? this.start + 4 / this.wrapper.scrollWidth * this.wavesurfer.getDuration() : Number(a.end), + this.resize = void 0 === a.resize ? !0 : Boolean(a.resize), this.drag = void 0 === a.drag ? !0 : Boolean(a.drag), + this.loop = Boolean(a.loop), this.color = a.color || "rgba(0, 0, 0, 0.1)", this.data = a.data || {}, + this.maxLength = a.maxLength, this.minLength = a.minLength, this.bindInOut(), this.render(), + this.wavesurfer.fireEvent("region-created", this); + }, + update: function(a) { + null != a.start && (this.start = Number(a.start)), null != a.end && (this.end = Number(a.end)), + null != a.loop && (this.loop = Boolean(a.loop)), null != a.color && (this.color = a.color), + null != a.data && (this.data = a.data), null != a.resize && (this.resize = Boolean(a.resize)), + null != a.drag && (this.drag = Boolean(a.drag)), null != a.maxLength && (this.maxLength = Number(a.maxLength)), + null != a.minLength && (this.minLength = Number(a.minLength)), this.updateRender(), + this.fireEvent("update"), this.wavesurfer.fireEvent("region-updated", this); + }, + remove: function(a) { + this.element && (this.wrapper.removeChild(this.element), this.element = null, this.fireEvent("remove"), + this.wavesurfer.fireEvent("region-removed", this)); + }, + play: function() { + this.wavesurfer.play(this.start, this.end), this.fireEvent("play"), this.wavesurfer.fireEvent("region-play", this); + }, + playLoop: function() { + this.play(), this.once("out", this.playLoop.bind(this)); + }, + render: function() { + var a = document.createElement("region"); + a.className = "wavesurfer-region", a.title = this.formatTime(this.start, this.end), + a.setAttribute("data-id", this.id); + this.wrapper.scrollWidth; + if (this.style(a, { + position: "absolute", + zIndex: 2, + height: "100%", + top: "0px" + }), this.resize) { + var b = a.appendChild(document.createElement("handle")), c = a.appendChild(document.createElement("handle")); + b.className = "wavesurfer-handle wavesurfer-handle-start", c.className = "wavesurfer-handle wavesurfer-handle-end"; + var d = { + cursor: "col-resize", + position: "absolute", + left: "0px", + top: "0px", + width: "1%", + maxWidth: "4px", + height: "100%" + }; + this.style(b, d), this.style(c, d), this.style(c, { + left: "100%" + }); + } + this.element = this.wrapper.appendChild(a), this.updateRender(), this.bindEvents(a); + }, + formatTime: function(a, b) { + return (a == b ? [ a ] : [ a, b ]).map(function(a) { + return [ Math.floor(a % 3600 / 60), ("00" + Math.floor(a % 60)).slice(-2) ].join(":"); + }).join("–"); + }, + updateRender: function() { + var a = this.wavesurfer.getDuration(), b = this.wrapper.scrollWidth; + this.start < 0 && (this.start = 0, this.end = this.end - this.start), this.end > a && (this.end = a, + this.start = a - (this.end - this.start)), null != this.minLength && (this.end = Math.max(this.start + this.minLength, this.end)), + null != this.maxLength && (this.end = Math.min(this.start + this.maxLength, this.end)), + this.style(this.element, { + left: ~~(this.start / a * b) + "px", + width: ~~((this.end - this.start) / a * b) + "px", + backgroundColor: this.color, + cursor: this.drag ? "move" : "default" + }), this.element.title = this.formatTime(this.start, this.end); + }, + bindInOut: function() { + var a = this, b = function() { + a.firedIn = !1, a.firedOut = !1; + }, c = function(b) { + !a.firedIn && a.start <= b && a.end > b && (a.firedIn = !0, a.fireEvent("in"), a.wavesurfer.fireEvent("region-in", a)), + !a.firedOut && a.firedIn && a.end <= Math.round(100 * b) / 100 && (a.firedOut = !0, + a.fireEvent("out"), a.wavesurfer.fireEvent("region-out", a)); + }; + this.wavesurfer.on("play", b), this.wavesurfer.backend.on("audioprocess", c), this.on("remove", function() { + a.wavesurfer.un("play", b), a.wavesurfer.backend.un("audioprocess", c); + }), this.on("out", function() { + a.loop && a.wavesurfer.play(a.start); + }); + }, + bindEvents: function() { + var a = this; + this.element.addEventListener("mouseenter", function(b) { + a.fireEvent("mouseenter", b), a.wavesurfer.fireEvent("region-mouseenter", a, b); + }), this.element.addEventListener("mouseleave", function(b) { + a.fireEvent("mouseleave", b), a.wavesurfer.fireEvent("region-mouseleave", a, b); + }), this.element.addEventListener("click", function(b) { + b.preventDefault(), a.fireEvent("click", b), a.wavesurfer.fireEvent("region-click", a, b); + }), this.element.addEventListener("dblclick", function(b) { + b.stopPropagation(), b.preventDefault(), a.fireEvent("dblclick", b), a.wavesurfer.fireEvent("region-dblclick", a, b); + }), (this.drag || this.resize) && function() { + var b, c, d, e = a.wavesurfer.getDuration(), f = function(f) { + f.stopPropagation(), d = a.wavesurfer.drawer.handleEvent(f) * e, "handle" == f.target.tagName.toLowerCase() ? c = f.target.classList.contains("wavesurfer-handle-start") ? "start" : "end" : b = !0; + }, g = function(d) { + (b || c) && (b = !1, c = !1, d.stopPropagation(), d.preventDefault(), a.fireEvent("update-end", d), + a.wavesurfer.fireEvent("region-update-end", a, d)); + }, h = function(f) { + if (b || c) { + var g = a.wavesurfer.drawer.handleEvent(f) * e, h = g - d; + d = g, a.drag && b && a.onDrag(h), a.resize && c && a.onResize(h, c); + } + }; + a.element.addEventListener("mousedown", f), a.wrapper.addEventListener("mousemove", h), + document.body.addEventListener("mouseup", g), a.on("remove", function() { + document.body.removeEventListener("mouseup", g), a.wrapper.removeEventListener("mousemove", h); + }), a.wavesurfer.on("destroy", function() { + document.body.removeEventListener("mouseup", g); + }); + }(); + }, + onDrag: function(a) { + this.update({ + start: this.start + a, + end: this.end + a + }); + }, + onResize: function(a, b) { + "start" == b ? this.update({ + start: Math.min(this.start + a, this.end), + end: Math.max(this.start + a, this.end) + }) : this.update({ + start: Math.min(this.end + a, this.start), + end: Math.max(this.end + a, this.start) + }); + } +}, WaveSurfer.util.extend(WaveSurfer.Region, WaveSurfer.Observer), WaveSurfer.initRegions = function() { + this.regions || (this.regions = Object.create(WaveSurfer.Regions), this.regions.init(this)); +}, WaveSurfer.addRegion = function(a) { + return this.initRegions(), this.regions.add(a); +}, WaveSurfer.clearRegions = function() { + this.regions && this.regions.clear(); +}, WaveSurfer.enableDragSelection = function(a) { + this.initRegions(), this.regions.enableDragSelection(a); +}; + +"use strict"; + +WaveSurfer.Spectrogram = { + init: function(a) { + this.params = a; + var b = this.wavesurfer = a.wavesurfer; + if (!this.wavesurfer) throw Error("No WaveSurfer instance provided"); + this.frequenciesDataUrl = a.frequenciesDataUrl; + var c = this.drawer = this.wavesurfer.drawer; + if (this.buffer = this.wavesurfer.backend.buffer, this.container = "string" == typeof a.container ? document.querySelector(a.container) : a.container, + !this.container) throw Error("No container for WaveSurfer spectrogram"); + this.width = c.width, this.pixelRatio = this.params.pixelRatio || b.params.pixelRatio, + this.fftSamples = this.params.fftSamples || b.params.fftSamples || 512, this.height = this.fftSamples / 2, + this.createWrapper(), this.createCanvas(), this.render(), b.drawer.wrapper.onscroll = this.updateScroll.bind(this), + b.on("destroy", this.destroy.bind(this)); + }, + destroy: function() { + this.unAll(), this.wrapper && (this.wrapper.parentNode.removeChild(this.wrapper), + this.wrapper = null); + }, + createWrapper: function() { + var a = this.container.querySelector("spectrogram"); + a && this.container.removeChild(a); + var b = this.wavesurfer.params; + this.wrapper = this.container.appendChild(document.createElement("spectrogram")), + this.drawer.style(this.wrapper, { + display: "block", + position: "relative", + userSelect: "none", + webkitUserSelect: "none", + height: this.height + "px" + }), (b.fillParent || b.scrollParent) && this.drawer.style(this.wrapper, { + width: "100%", + overflowX: "hidden", + overflowY: "hidden" + }); + var c = this; + this.wrapper.addEventListener("click", function(a) { + a.preventDefault(); + var b = "offsetX" in a ? a.offsetX : a.layerX; + c.fireEvent("click", b / c.scrollWidth || 0); + }); + }, + createCanvas: function() { + var a = this.canvas = this.wrapper.appendChild(document.createElement("canvas")); + this.spectrCc = a.getContext("2d"), this.wavesurfer.drawer.style(a, { + position: "absolute", + zIndex: 4 + }); + }, + render: function() { + this.updateCanvasStyle(), this.frequenciesDataUrl ? this.loadFrequenciesData(this.frequenciesDataUrl) : this.getFrequencies(this.drawSpectrogram); + }, + updateCanvasStyle: function() { + var a = Math.round(this.width / this.pixelRatio) + "px"; + this.canvas.width = this.width, this.canvas.height = this.height, this.canvas.style.width = a; + }, + drawSpectrogram: function(a, b) { + for (var c = (b.spectrCc, b.wavesurfer.backend.getDuration(), b.height), d = b.resample(a), e = 2 / b.buffer.numberOfChannels, f = 0; f < d.length; f++) for (var g = 0; g < d[f].length; g++) { + var h = 255 - d[f][g]; + b.spectrCc.fillStyle = "rgb(" + h + ", " + h + ", " + h + ")", b.spectrCc.fillRect(f, c - g * e, 1, 1 * e); + } + }, + getFrequencies: function(a) { + var b = this.fftSamples, c = this.buffer, d = [], e = new window.OfflineAudioContext(1, c.length, c.sampleRate), f = e.createBufferSource(), g = e.createScriptProcessor(0, 1, 1), h = e.createAnalyser(); + h.fftSize = b, h.smoothingTimeConstant = this.width / c.duration < 10 ? .75 : .25, + f.buffer = c, f.connect(h), h.connect(g), g.connect(e.destination), g.onaudioprocess = function() { + var a = new Uint8Array(h.frequencyBinCount); + h.getByteFrequencyData(a), d.push(a); + }, f.start(0), e.startRendering(); + var i = this; + e.oncomplete = function() { + a(d, i); + }; + }, + loadFrequenciesData: function(a) { + var b = this, c = WaveSurfer.util.ajax({ + url: a + }); + return c.on("success", function(a) { + b.drawSpectrogram(JSON.parse(a), b); + }), c.on("error", function(a) { + b.fireEvent("error", "XHR error: " + a.target.statusText); + }), c; + }, + updateScroll: function(a) { + this.wrapper.scrollLeft = a.target.scrollLeft; + }, + resample: function(a, b) { + for (var b = this.width, c = [], d = 1 / a.length, e = 1 / b, f = 0; b > f; f++) { + for (var g = new Array(a[0].length), h = 0; h < a.length; h++) { + var i = h * d, j = i + d, k = f * e, l = k + e, m = k >= j || i >= l ? 0 : Math.min(Math.max(j, k), Math.max(l, i)) - Math.max(Math.min(j, k), Math.min(l, i)); + if (m > 0) for (var n = 0; n < a[0].length; n++) null == g[n] && (g[n] = 0), g[n] += m / e * a[h][n]; + } + for (var o = new Uint8Array(a[0].length), n = 0; n < a[0].length; n++) o[n] = g[n]; + c.push(o); + } + return c; + } +}, WaveSurfer.util.extend(WaveSurfer.Spectrogram, WaveSurfer.Observer); + +"use strict"; + var model = {}; model.Value = function() { @@ -28174,8 +31374,10 @@ var elan = function() { var header = xml.querySelector("HEADER"); var inMilliseconds = header.getAttribute("TIME_UNITS") == "milliseconds"; var media = header.querySelector("MEDIA_DESCRIPTOR"); - this.mediaUrl = media.getAttribute("MEDIA_URL"); - this.mediaType = media.getAttribute("MIME_TYPE"); + if (media) { + this.mediaUrl = media.getAttribute("MEDIA_URL"); + this.mediaType = media.getAttribute("MIME_TYPE"); + } var properties = xml.querySelectorAll("PROPERTY"); _forEach.call(properties, function(prop) { var name = prop.getAttribute("NAME"); @@ -28355,6 +31557,12 @@ var cloneObject = function(oldObject) { return JSON.parse(JSON.stringify(oldObject)); }; +var enableControls = function(controls, enabled) { + _.each(controls, function(value, key) { + controls[key] = enabled; + }); +}; + var lingvodoc = {}; lingvodoc.Object = function(clientId, objectId) { @@ -28362,10 +31570,7 @@ lingvodoc.Object = function(clientId, objectId) { this.object_id = objectId; this.type = "abstract"; this.getId = function() { - return this.client_id + "" + this.object_id; - }; - this.export = function() { - return {}; + return this.client_id + "_" + this.object_id; }; }; @@ -28426,13 +31631,33 @@ lingvodoc.Perspective = function(client_id, object_id, parent_client_id, parent_ this.is_template = is_template; this.marked_for_deletion = marked_for_deletion; this.fields = []; + this.location = null; + this.blobs = []; + this.additional_metadata = {}; this.equals = function(obj) { return lingvodoc.Object.prototype.equals.call(this, obj) && this.translation == obj.translation; }; }; lingvodoc.Perspective.fromJS = function(js) { - return new lingvodoc.Perspective(js.client_id, js.object_id, js.parent_client_id, js.parent_object_id, js.translation, js.translation_string, js.status, js.is_template, js.marked_for_deletion); + var perspective = new lingvodoc.Perspective(js.client_id, js.object_id, js.parent_client_id, js.parent_object_id, js.translation, js.translation_string, js.status, js.is_template, js.marked_for_deletion); + if (_.has(js, "location") && _.has(js.location, "content")) { + perspective["location"] = { + lat: js.location.content.lat, + lng: js.location.content.lng + }; + } + if (_.has(js, "info") && js.info.type == "list") { + if (_.isArray(js.info.content)) { + perspective["blobs"] = _.map(js.info.content, function(e) { + var blob = new lingvodoc.Blob(e.info.content.client_id, e.info.content.object_id, e.info.content.name, e.info.content.data_type); + blob.url = e.info.content.content; + return blob; + }); + } + } + perspective.additional_metadata = js.additional_metadata; + return perspective; }; lingvodoc.Perspective.prototype = new lingvodoc.Object(); @@ -28457,6 +31682,25 @@ lingvodoc.User.fromJS = function(js) { return new lingvodoc.User(js.id, js.login, js.name, js.email, js.intl_name, js.about, js.signup_date, js.organizations); }; +lingvodoc.Blob = function(clientId, objectId, name, data_type) { + lingvodoc.Object.call(this, clientId, objectId); + this.type = "blob"; + this.name = name; + this.data_type = data_type; + this.url = null; + this.equals = function(obj) { + return lingvodoc.Object.prototype.equals.call(this, obj) && this.name == obj.name; + }; +}; + +lingvodoc.Blob.fromJS = function(js) { + return new lingvodoc.Blob(js.client_id, js.object_id, js.name, js.data_type); +}; + +lingvodoc.Blob.prototype = new lingvodoc.Object(); + +lingvodoc.Blob.prototype.constructor = lingvodoc.Blob; + function lingvodocAPI($http, $q) { var addUrlParameter = function(url, key, value) { return url + (url.indexOf("?") >= 0 ? "&" : "?") + encodeURIComponent(key) + "=" + encodeURIComponent(value); @@ -28530,6 +31774,21 @@ function lingvodocAPI($http, $q) { }); return deferred.promise; }; + var getPerspectiveDictionaryFieldsNew = function(perspective) { + var deferred = $q.defer(); + var url = "/dictionary/" + perspective.parent_client_id + "/" + perspective.parent_object_id + "/perspective/" + perspective.client_id + "/" + perspective.object_id + "/fields"; + $http.get(url).success(function(data, status, headers, config) { + if (_.isArray(data.fields)) { + var fields = perspectiveToDictionaryFields(data.fields); + deferred.resolve(fields); + } else { + deferred.reject("An error occurred while fetching perspective fields"); + } + }).error(function(data, status, headers, config) { + deferred.reject("An error occurred while fetching perspective fields"); + }); + return deferred.promise; + }; var removeValue = function(entry, field, fieldValue, parent) { var deferred = $q.defer(); var url; @@ -28696,8 +31955,9 @@ function lingvodocAPI($http, $q) { }); return deferred.promise; }; - var getDictionaryProperties = function(url) { + var getDictionaryProperties = function(dictionary) { var deferred = $q.defer(); + var url = "/dictionary/" + encodeURIComponent(dictionary.client_id) + "/" + encodeURIComponent(dictionary.object_id); $http.get(url).success(function(data, status, headers, config) { deferred.resolve(data); }).error(function(data, status, headers, config) { @@ -28705,8 +31965,9 @@ function lingvodocAPI($http, $q) { }); return deferred.promise; }; - var setDictionaryProperties = function(url, properties) { + var setDictionaryProperties = function(dictionary, properties) { var deferred = $q.defer(); + var url = "/dictionary/" + encodeURIComponent(dictionary.client_id) + "/" + encodeURIComponent(dictionary.object_id); $http.put(url, properties).success(function(data, status, headers, config) { deferred.resolve(data); }).error(function(data, status, headers, config) { @@ -28714,6 +31975,16 @@ function lingvodocAPI($http, $q) { }); return deferred.promise; }; + var removeDictionary = function(dictionary) { + var deferred = $q.defer(); + var url = "/dictionary/" + encodeURIComponent(dictionary.client_id) + "/" + encodeURIComponent(dictionary.object_id); + $http.delete(url).success(function(data, status, headers, config) { + deferred.resolve(); + }).error(function(data, status, headers, config) { + deferred.reject("An error occurred while trying to delete dictionary"); + }); + return deferred.promise; + }; var getLanguages = function(url) { var deferred = $q.defer(); var flatLanguages = function(languages) { @@ -28797,6 +32068,16 @@ function lingvodocAPI($http, $q) { }); return deferred.promise; }; + var removePerspective = function(perspective) { + var deferred = $q.defer(); + var url = "/dictionary/" + perspective.parent_client_id + "/" + perspective.parent_object_id + "/perspective/" + perspective.client_id + "/" + perspective.object_id; + $http.delete(url).success(function(data, status, headers, config) { + deferred.resolve(); + }).error(function(data, status, headers, config) { + deferred.reject("An error occurred while trying to delete perspective"); + }); + return deferred.promise; + }; var getUserInfo = function(userId, clientId) { var deferred = $q.defer(); var url = "/user" + "?client_id= " + encodeURIComponent(clientId) + "&user_id= " + encodeURIComponent(userId); @@ -28877,13 +32158,14 @@ function lingvodocAPI($http, $q) { }; var getDictionaries = function(query) { var deferred = $q.defer(); - var dictionaries = []; $http.post("/dictionaries", query).success(function(data, status, headers, config) { - for (var i = 0; i < data.dictionaries.length; i++) { - var dictionary = data.dictionaries[i]; - dictionaries.push(lingvodoc.Dictionary.fromJS(dictionary)); + if (_.isArray(data.dictionaries)) { + deferred.resolve(_.map(data.dictionaries, function(d) { + return lingvodoc.Dictionary.fromJS(d); + })); + } else { + deferred.reject("Failed to fetch dictionaries list. Malformed response."); } - deferred.resolve(dictionaries); }).error(function(data, status, headers, config) { deferred.reject("Failed to fetch dictionaries list"); }); @@ -29100,8 +32382,8 @@ function lingvodocAPI($http, $q) { }; $http.post("/dictionaries", req).success(function(data, status, headers, config) { var dictionaries = []; - if (angular.isArray(data.dictionaries)) { - angular.forEach(data.dictionaries, function(jsdict) { + if (_.isArray(data.dictionaries)) { + _.forEach(data.dictionaries, function(jsdict) { var dictionary = lingvodoc.Dictionary.fromJS(jsdict); if (language.client_id == dictionary.parent_client_id && language.object_id == dictionary.parent_object_id) { dictionaries.push(dictionary); @@ -29110,7 +32392,7 @@ function lingvodocAPI($http, $q) { } deferred.resolve(dictionaries); }).error(function(data, status, headers, config) { - deferred.reject("Failed to move lexical entry"); + deferred.reject("Failed to fetch list of dictionaries"); }); return deferred.promise; }; @@ -29293,10 +32575,140 @@ function lingvodocAPI($http, $q) { }); return deferred.promise; }; + var getUserBlobs = function() { + var deferred = $q.defer(); + $http.get("/blobs").success(function(data, status, headers, config) { + var blobs = _.map(data, lingvodoc.Blob.fromJS); + deferred.resolve(blobs); + }).error(function(data, status, headers, config) { + deferred.reject("Failed to fetch list of available blobs"); + }); + return deferred.promise; + }; + var checkDictionaryBlob = function(blob, parent) { + var deferred = $q.defer(); + var query = { + blob_client_id: blob.client_id, + blob_object_id: blob.object_id, + parent_client_id: parent.client_id, + parent_object_id: parent.object_id + }; + $http.post("/convert_check", query).success(function(data, status, headers, config) { + var perspectives = _.map(data, lingvodoc.Perspective.fromJS); + deferred.resolve(perspectives); + }).error(function(data, status, headers, config) { + deferred.reject("Failed to convert dictionary"); + }); + return deferred.promise; + }; + var convertDictionary = function(req) { + var deferred = $q.defer(); + $http.post("/convert", req).success(function(data, status, headers, config) { + deferred.resolve(data); + }).error(function(data, status, headers, config) { + deferred.reject("Failed to convert dictionary"); + }); + return deferred.promise; + }; + var getPerspectiveMeta = function(dictionary, perspective) { + var deferred = $q.defer(); + var url = "/dictionary/" + encodeURIComponent(dictionary.client_id) + "/" + encodeURIComponent(dictionary.object_id) + "/perspective/" + encodeURIComponent(perspective.client_id) + "/" + encodeURIComponent(perspective.object_id) + "/meta"; + $http.get(url).success(function(data, status, headers, config) { + deferred.resolve(data); + }).error(function(data, status, headers, config) { + deferred.reject("Failed to get perspective meta data!"); + }); + return deferred.promise; + }; + var setPerspectiveMeta = function(dictionary, perspective, meta) { + var deferred = $q.defer(); + var url = "/dictionary/" + encodeURIComponent(dictionary.client_id) + "/" + encodeURIComponent(dictionary.object_id) + "/perspective/" + encodeURIComponent(perspective.client_id) + "/" + encodeURIComponent(perspective.object_id) + "/meta"; + $http.put(url, meta).success(function(data, status, headers, config) { + deferred.resolve(data); + }).error(function(data, status, headers, config) { + deferred.reject("Failed to set perspective meta data!"); + }); + return deferred.promise; + }; + var removePerspectiveMeta = function(dictionary, perspective, meta) { + var deferred = $q.defer(); + var url = "/dictionary/" + encodeURIComponent(dictionary.client_id) + "/" + encodeURIComponent(dictionary.object_id) + "/perspective/" + encodeURIComponent(perspective.client_id) + "/" + encodeURIComponent(perspective.object_id) + "/meta"; + var config = { + method: "DELETE", + url: url, + data: meta, + headers: { + "Content-Type": "application/json;charset=utf-8" + } + }; + $http(config).success(function(data, status, headers, config) { + deferred.resolve(data); + }).error(function(data, status, headers, config) { + deferred.reject("Failed to remove perspective meta data!"); + }); + return deferred.promise; + }; + var advancedSearch = function(query, where, adopted, etymology) { + var deferred = $q.defer(); + var url = "/advanced_search"; + var perspectives = where.map(function(o) { + if (o.type == "perspective") { + return { + client_id: o.client_id, + object_id: o.object_id + }; + } + }).filter(function(o) { + return typeof o !== "undefined"; + }); + var req = { + searchstrings: query, + perspectives: perspectives + }; + if (_.isBoolean(adopted)) { + req.adopted = adopted; + } + if (_.isBoolean(etymology)) { + req.with_etimology = etymology; + } + $http.post(url, req).success(function(data, status, headers, config) { + var r = data.map(function(e) { + var perspective = lingvodoc.Perspective.fromJS(e); + return getPerspectiveOriginById(perspective.client_id, perspective.object_id); + }); + $q.all(r).then(function(paths) { + var out = []; + _.each(data, function(entry, i) { + entry.lexical_entry["origin"] = paths[i]; + out.push(entry.lexical_entry); + }); + deferred.resolve(out); + }, function(reason) { + deferred.reject("An error occurred while doing basic search"); + }); + }).error(function(data, status, headers, config) { + deferred.reject("An error occurred while doing advanced search"); + }); + return deferred.promise; + }; + var convertMarkup = function(object) { + var deferred = $q.defer(); + var obj = { + client_id: object.client_id, + object_id: object.object_id + }; + $http.post("/convert/markup", obj).success(function(data, status, headers, config) { + deferred.resolve(data); + }).error(function(data, status, headers, config) { + deferred.reject("Failed to convert markup!"); + }); + return deferred.promise; + }; return { getLexicalEntries: getLexicalEntries, getLexicalEntriesCount: getLexicalEntriesCount, getPerspectiveDictionaryFields: getPerspectiveDictionaryFields, + getPerspectiveDictionaryFieldsNew: getPerspectiveDictionaryFieldsNew, addNewLexicalEntry: addNewLexicalEntry, saveValue: saveValue, removeValue: removeValue, @@ -29307,6 +32719,7 @@ function lingvodocAPI($http, $q) { approveAll: approveAll, getDictionaryProperties: getDictionaryProperties, setDictionaryProperties: setDictionaryProperties, + removeDictionary: removeDictionary, getLanguages: getLanguages, setDictionaryStatus: setDictionaryStatus, setPerspectiveStatus: setPerspectiveStatus, @@ -29314,6 +32727,7 @@ function lingvodocAPI($http, $q) { getPerspectiveFields: getPerspectiveFields, setPerspectiveFields: setPerspectiveFields, getPerspectiveFieldsNew: getPerspectiveFieldsNew, + removePerspective: removePerspective, getUserInfo: getUserInfo, setUserInfo: setUserInfo, getOrganizations: getOrganizations, @@ -29340,7 +32754,15 @@ function lingvodocAPI($http, $q) { deleteDictionaryRoles: deleteDictionaryRoles, getPerspectiveRoles: getPerspectiveRoles, addPerspectiveRoles: addPerspectiveRoles, - deletePerspectiveRoles: deletePerspectiveRoles + deletePerspectiveRoles: deletePerspectiveRoles, + getUserBlobs: getUserBlobs, + checkDictionaryBlob: checkDictionaryBlob, + convertDictionary: convertDictionary, + getPerspectiveMeta: getPerspectiveMeta, + setPerspectiveMeta: setPerspectiveMeta, + removePerspectiveMeta: removePerspectiveMeta, + advancedSearch: advancedSearch, + convertMarkup: convertMarkup }; } @@ -29372,9 +32794,34 @@ function responseHandler($timeout, $modal) { function error(message) { show("error", message, 5e3); } + function yesno(status, message, callback) { + var controller = function($scope, $modalInstance) { + $scope.status = status; + $scope.message = message; + $scope.yes = function() { + $modalInstance.close(true); + }; + $scope.no = function() { + $modalInstance.close(false); + }; + }; + $modal.open({ + animation: true, + templateUrl: "responseHandlerYesNoModal.html", + controller: controller, + size: "lg", + backdrop: "static", + keyboard: false + }).result.then(function(result) { + callback(result); + }, function() { + callback(false); + }); + } return { success: success, - error: error + error: error, + yesno: yesno }; } @@ -29392,7 +32839,7 @@ angular.module("EditDictionaryModule", [ "ui.bootstrap" ]).service("dictionarySe if ($attrs.url) { wavesurfer.load($attrs.url, $attrs.data || null); } - $scope.$emit("wavesurferInit", wavesurfer); + $scope.$emit("wavesurferInit", wavesurfer, $element); } }; }).directive("onReadFile", function($parse) { @@ -29692,18 +33139,18 @@ angular.module("EditDictionaryModule", [ "ui.bootstrap" ]).service("dictionarySe }); modalInstance.result.then(function(value) {}, function() {}); }; - $scope.annotate = function(soundEntity, markupEntity) { + $scope.annotate = function(sound, markup) { var modalInstance = $modal.open({ animation: true, templateUrl: "annotationModal.html", controller: "AnnotationController", size: "lg", resolve: { - soundUrl: function() { - return soundEntity.content; - }, - annotationUrl: function() { - return markupEntity.content; + params: function() { + return { + sound: sound, + markup: markup + }; } } }); @@ -29788,7 +33235,7 @@ angular.module("EditDictionaryModule", [ "ui.bootstrap" ]).service("dictionarySe }, function(reason) { responseHandler.error(reason); }); -} ]).controller("AnnotationController", [ "$scope", "$http", "responseHandler", "soundUrl", "annotationUrl", function($scope, $http, responseHandler, soundUrl, annotationUrl) { +} ]).controller("AnnotationController", [ "$scope", "$http", "dictionaryService", "responseHandler", "params", function($scope, $http, dictionaryService, responseHandler, params) { var activeUrl = null; var createRegions = function(annotaion) { if (annotaion instanceof elan.Document) { @@ -29806,19 +33253,6 @@ angular.module("EditDictionaryModule", [ "ui.bootstrap" ]).service("dictionarySe }); } }; - var loadAnnotation = function(url) { - $http.get(url).success(function(data, status, headers, config) { - try { - var xml = new DOMParser().parseFromString(data, "application/xml"); - var annotation = new elan.Document(); - annotation.importXML(xml); - $scope.annotation = annotation; - createRegions(annotation); - } catch (e) { - alert("Failed to parse ELAN annotation: " + e); - } - }).error(function(data, status, headers, config) {}); - }; $scope.paused = true; $scope.annotation = null; $scope.playPause = function() { @@ -29857,10 +33291,22 @@ angular.module("EditDictionaryModule", [ "ui.bootstrap" ]).service("dictionarySe region.remove(region); }); $scope.wavesurfer.once("ready", function() { - loadAnnotation(annotationUrl); + dictionaryService.convertMarkup(params.markup).then(function(data) { + try { + var xml = new DOMParser().parseFromString(data.content, "application/xml"); + var annotation = new elan.Document(); + annotation.importXML(xml); + $scope.annotation = annotation; + createRegions(annotation); + } catch (e) { + responseHandler.error("Failed to parse ELAN annotation: " + e); + } + }, function(reason) { + responseHandler.error(reason); + }); $scope.$apply(); }); - $scope.wavesurfer.load(soundUrl); + $scope.wavesurfer.load(params.sound.content); }); $scope.$on("modal.closing", function(e) { $scope.wavesurfer.stop(); @@ -30247,7 +33693,7 @@ function WaveSurferController($scope) { $scope.isMediaFileAvailable = function() { return activeUrl != null; }; - $scope.$on("wavesurferInit", function(e, wavesurfer) { + $scope.$on("wavesurferInit", function(e, wavesurfer, container) { $scope.wavesurfer = wavesurfer; $scope.wavesurfer.on("play", function() { $scope.paused = false; diff --git a/lingvodoc/static/js/home.js b/lingvodoc/static/js/home.js index ef6290025..e30489da2 100644 --- a/lingvodoc/static/js/home.js +++ b/lingvodoc/static/js/home.js @@ -5377,6 +5377,3947 @@ return jQuery; }); +(function() { + var undefined; + var VERSION = "3.10.1"; + var BIND_FLAG = 1, BIND_KEY_FLAG = 2, CURRY_BOUND_FLAG = 4, CURRY_FLAG = 8, CURRY_RIGHT_FLAG = 16, PARTIAL_FLAG = 32, PARTIAL_RIGHT_FLAG = 64, ARY_FLAG = 128, REARG_FLAG = 256; + var DEFAULT_TRUNC_LENGTH = 30, DEFAULT_TRUNC_OMISSION = "..."; + var HOT_COUNT = 150, HOT_SPAN = 16; + var LARGE_ARRAY_SIZE = 200; + var LAZY_FILTER_FLAG = 1, LAZY_MAP_FLAG = 2; + var FUNC_ERROR_TEXT = "Expected a function"; + var PLACEHOLDER = "__lodash_placeholder__"; + var argsTag = "[object Arguments]", arrayTag = "[object Array]", boolTag = "[object Boolean]", dateTag = "[object Date]", errorTag = "[object Error]", funcTag = "[object Function]", mapTag = "[object Map]", numberTag = "[object Number]", objectTag = "[object Object]", regexpTag = "[object RegExp]", setTag = "[object Set]", stringTag = "[object String]", weakMapTag = "[object WeakMap]"; + var arrayBufferTag = "[object ArrayBuffer]", float32Tag = "[object Float32Array]", float64Tag = "[object Float64Array]", int8Tag = "[object Int8Array]", int16Tag = "[object Int16Array]", int32Tag = "[object Int32Array]", uint8Tag = "[object Uint8Array]", uint8ClampedTag = "[object Uint8ClampedArray]", uint16Tag = "[object Uint16Array]", uint32Tag = "[object Uint32Array]"; + var reEmptyStringLeading = /\b__p \+= '';/g, reEmptyStringMiddle = /\b(__p \+=) '' \+/g, reEmptyStringTrailing = /(__e\(.*?\)|\b__t\)) \+\n'';/g; + var reEscapedHtml = /&(?:amp|lt|gt|quot|#39|#96);/g, reUnescapedHtml = /[&<>"'`]/g, reHasEscapedHtml = RegExp(reEscapedHtml.source), reHasUnescapedHtml = RegExp(reUnescapedHtml.source); + var reEscape = /<%-([\s\S]+?)%>/g, reEvaluate = /<%([\s\S]+?)%>/g, reInterpolate = /<%=([\s\S]+?)%>/g; + var reIsDeepProp = /\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\n\\]|\\.)*?\1)\]/, reIsPlainProp = /^\w*$/, rePropName = /[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\n\\]|\\.)*?)\2)\]/g; + var reRegExpChars = /^[:!,]|[\\^$.*+?()[\]{}|\/]|(^[0-9a-fA-Fnrtuvx])|([\n\r\u2028\u2029])/g, reHasRegExpChars = RegExp(reRegExpChars.source); + var reComboMark = /[\u0300-\u036f\ufe20-\ufe23]/g; + var reEscapeChar = /\\(\\)?/g; + var reEsTemplate = /\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g; + var reFlags = /\w*$/; + var reHasHexPrefix = /^0[xX]/; + var reIsHostCtor = /^\[object .+?Constructor\]$/; + var reIsUint = /^\d+$/; + var reLatin1 = /[\xc0-\xd6\xd8-\xde\xdf-\xf6\xf8-\xff]/g; + var reNoMatch = /($^)/; + var reUnescapedString = /['\n\r\u2028\u2029\\]/g; + var reWords = function() { + var upper = "[A-Z\\xc0-\\xd6\\xd8-\\xde]", lower = "[a-z\\xdf-\\xf6\\xf8-\\xff]+"; + return RegExp(upper + "+(?=" + upper + lower + ")|" + upper + "?" + lower + "|" + upper + "+|[0-9]+", "g"); + }(); + var contextProps = [ "Array", "ArrayBuffer", "Date", "Error", "Float32Array", "Float64Array", "Function", "Int8Array", "Int16Array", "Int32Array", "Math", "Number", "Object", "RegExp", "Set", "String", "_", "clearTimeout", "isFinite", "parseFloat", "parseInt", "setTimeout", "TypeError", "Uint8Array", "Uint8ClampedArray", "Uint16Array", "Uint32Array", "WeakMap" ]; + var templateCounter = -1; + var typedArrayTags = {}; + typedArrayTags[float32Tag] = typedArrayTags[float64Tag] = typedArrayTags[int8Tag] = typedArrayTags[int16Tag] = typedArrayTags[int32Tag] = typedArrayTags[uint8Tag] = typedArrayTags[uint8ClampedTag] = typedArrayTags[uint16Tag] = typedArrayTags[uint32Tag] = true; + typedArrayTags[argsTag] = typedArrayTags[arrayTag] = typedArrayTags[arrayBufferTag] = typedArrayTags[boolTag] = typedArrayTags[dateTag] = typedArrayTags[errorTag] = typedArrayTags[funcTag] = typedArrayTags[mapTag] = typedArrayTags[numberTag] = typedArrayTags[objectTag] = typedArrayTags[regexpTag] = typedArrayTags[setTag] = typedArrayTags[stringTag] = typedArrayTags[weakMapTag] = false; + var cloneableTags = {}; + cloneableTags[argsTag] = cloneableTags[arrayTag] = cloneableTags[arrayBufferTag] = cloneableTags[boolTag] = cloneableTags[dateTag] = cloneableTags[float32Tag] = cloneableTags[float64Tag] = cloneableTags[int8Tag] = cloneableTags[int16Tag] = cloneableTags[int32Tag] = cloneableTags[numberTag] = cloneableTags[objectTag] = cloneableTags[regexpTag] = cloneableTags[stringTag] = cloneableTags[uint8Tag] = cloneableTags[uint8ClampedTag] = cloneableTags[uint16Tag] = cloneableTags[uint32Tag] = true; + cloneableTags[errorTag] = cloneableTags[funcTag] = cloneableTags[mapTag] = cloneableTags[setTag] = cloneableTags[weakMapTag] = false; + var deburredLetters = { + "À": "A", + "Á": "A", + "Â": "A", + "Ã": "A", + "Ä": "A", + "Å": "A", + "à": "a", + "á": "a", + "â": "a", + "ã": "a", + "ä": "a", + "å": "a", + "Ç": "C", + "ç": "c", + "Ð": "D", + "ð": "d", + "È": "E", + "É": "E", + "Ê": "E", + "Ë": "E", + "è": "e", + "é": "e", + "ê": "e", + "ë": "e", + "Ì": "I", + "Í": "I", + "Î": "I", + "Ï": "I", + "ì": "i", + "í": "i", + "î": "i", + "ï": "i", + "Ñ": "N", + "ñ": "n", + "Ò": "O", + "Ó": "O", + "Ô": "O", + "Õ": "O", + "Ö": "O", + "Ø": "O", + "ò": "o", + "ó": "o", + "ô": "o", + "õ": "o", + "ö": "o", + "ø": "o", + "Ù": "U", + "Ú": "U", + "Û": "U", + "Ü": "U", + "ù": "u", + "ú": "u", + "û": "u", + "ü": "u", + "Ý": "Y", + "ý": "y", + "ÿ": "y", + "Æ": "Ae", + "æ": "ae", + "Þ": "Th", + "þ": "th", + "ß": "ss" + }; + var htmlEscapes = { + "&": "&", + "<": "<", + ">": ">", + '"': """, + "'": "'", + "`": "`" + }; + var htmlUnescapes = { + "&": "&", + "<": "<", + ">": ">", + """: '"', + "'": "'", + "`": "`" + }; + var objectTypes = { + "function": true, + object: true + }; + var regexpEscapes = { + "0": "x30", + "1": "x31", + "2": "x32", + "3": "x33", + "4": "x34", + "5": "x35", + "6": "x36", + "7": "x37", + "8": "x38", + "9": "x39", + A: "x41", + B: "x42", + C: "x43", + D: "x44", + E: "x45", + F: "x46", + a: "x61", + b: "x62", + c: "x63", + d: "x64", + e: "x65", + f: "x66", + n: "x6e", + r: "x72", + t: "x74", + u: "x75", + v: "x76", + x: "x78" + }; + var stringEscapes = { + "\\": "\\", + "'": "'", + "\n": "n", + "\r": "r", + "\u2028": "u2028", + "\u2029": "u2029" + }; + var freeExports = objectTypes[typeof exports] && exports && !exports.nodeType && exports; + var freeModule = objectTypes[typeof module] && module && !module.nodeType && module; + var freeGlobal = freeExports && freeModule && typeof global == "object" && global && global.Object && global; + var freeSelf = objectTypes[typeof self] && self && self.Object && self; + var freeWindow = objectTypes[typeof window] && window && window.Object && window; + var moduleExports = freeModule && freeModule.exports === freeExports && freeExports; + var root = freeGlobal || freeWindow !== (this && this.window) && freeWindow || freeSelf || this; + function baseCompareAscending(value, other) { + if (value !== other) { + var valIsNull = value === null, valIsUndef = value === undefined, valIsReflexive = value === value; + var othIsNull = other === null, othIsUndef = other === undefined, othIsReflexive = other === other; + if (value > other && !othIsNull || !valIsReflexive || valIsNull && !othIsUndef && othIsReflexive || valIsUndef && othIsReflexive) { + return 1; + } + if (value < other && !valIsNull || !othIsReflexive || othIsNull && !valIsUndef && valIsReflexive || othIsUndef && valIsReflexive) { + return -1; + } + } + return 0; + } + function baseFindIndex(array, predicate, fromRight) { + var length = array.length, index = fromRight ? length : -1; + while (fromRight ? index-- : ++index < length) { + if (predicate(array[index], index, array)) { + return index; + } + } + return -1; + } + function baseIndexOf(array, value, fromIndex) { + if (value !== value) { + return indexOfNaN(array, fromIndex); + } + var index = fromIndex - 1, length = array.length; + while (++index < length) { + if (array[index] === value) { + return index; + } + } + return -1; + } + function baseIsFunction(value) { + return typeof value == "function" || false; + } + function baseToString(value) { + return value == null ? "" : value + ""; + } + function charsLeftIndex(string, chars) { + var index = -1, length = string.length; + while (++index < length && chars.indexOf(string.charAt(index)) > -1) {} + return index; + } + function charsRightIndex(string, chars) { + var index = string.length; + while (index-- && chars.indexOf(string.charAt(index)) > -1) {} + return index; + } + function compareAscending(object, other) { + return baseCompareAscending(object.criteria, other.criteria) || object.index - other.index; + } + function compareMultiple(object, other, orders) { + var index = -1, objCriteria = object.criteria, othCriteria = other.criteria, length = objCriteria.length, ordersLength = orders.length; + while (++index < length) { + var result = baseCompareAscending(objCriteria[index], othCriteria[index]); + if (result) { + if (index >= ordersLength) { + return result; + } + var order = orders[index]; + return result * (order === "asc" || order === true ? 1 : -1); + } + } + return object.index - other.index; + } + function deburrLetter(letter) { + return deburredLetters[letter]; + } + function escapeHtmlChar(chr) { + return htmlEscapes[chr]; + } + function escapeRegExpChar(chr, leadingChar, whitespaceChar) { + if (leadingChar) { + chr = regexpEscapes[chr]; + } else if (whitespaceChar) { + chr = stringEscapes[chr]; + } + return "\\" + chr; + } + function escapeStringChar(chr) { + return "\\" + stringEscapes[chr]; + } + function indexOfNaN(array, fromIndex, fromRight) { + var length = array.length, index = fromIndex + (fromRight ? 0 : -1); + while (fromRight ? index-- : ++index < length) { + var other = array[index]; + if (other !== other) { + return index; + } + } + return -1; + } + function isObjectLike(value) { + return !!value && typeof value == "object"; + } + function isSpace(charCode) { + return charCode <= 160 && (charCode >= 9 && charCode <= 13) || charCode == 32 || charCode == 160 || charCode == 5760 || charCode == 6158 || charCode >= 8192 && (charCode <= 8202 || charCode == 8232 || charCode == 8233 || charCode == 8239 || charCode == 8287 || charCode == 12288 || charCode == 65279); + } + function replaceHolders(array, placeholder) { + var index = -1, length = array.length, resIndex = -1, result = []; + while (++index < length) { + if (array[index] === placeholder) { + array[index] = PLACEHOLDER; + result[++resIndex] = index; + } + } + return result; + } + function sortedUniq(array, iteratee) { + var seen, index = -1, length = array.length, resIndex = -1, result = []; + while (++index < length) { + var value = array[index], computed = iteratee ? iteratee(value, index, array) : value; + if (!index || seen !== computed) { + seen = computed; + result[++resIndex] = value; + } + } + return result; + } + function trimmedLeftIndex(string) { + var index = -1, length = string.length; + while (++index < length && isSpace(string.charCodeAt(index))) {} + return index; + } + function trimmedRightIndex(string) { + var index = string.length; + while (index-- && isSpace(string.charCodeAt(index))) {} + return index; + } + function unescapeHtmlChar(chr) { + return htmlUnescapes[chr]; + } + function runInContext(context) { + context = context ? _.defaults(root.Object(), context, _.pick(root, contextProps)) : root; + var Array = context.Array, Date = context.Date, Error = context.Error, Function = context.Function, Math = context.Math, Number = context.Number, Object = context.Object, RegExp = context.RegExp, String = context.String, TypeError = context.TypeError; + var arrayProto = Array.prototype, objectProto = Object.prototype, stringProto = String.prototype; + var fnToString = Function.prototype.toString; + var hasOwnProperty = objectProto.hasOwnProperty; + var idCounter = 0; + var objToString = objectProto.toString; + var oldDash = root._; + var reIsNative = RegExp("^" + fnToString.call(hasOwnProperty).replace(/[\\^$.*+?()[\]{}|]/g, "\\$&").replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g, "$1.*?") + "$"); + var ArrayBuffer = context.ArrayBuffer, clearTimeout = context.clearTimeout, parseFloat = context.parseFloat, pow = Math.pow, propertyIsEnumerable = objectProto.propertyIsEnumerable, Set = getNative(context, "Set"), setTimeout = context.setTimeout, splice = arrayProto.splice, Uint8Array = context.Uint8Array, WeakMap = getNative(context, "WeakMap"); + var nativeCeil = Math.ceil, nativeCreate = getNative(Object, "create"), nativeFloor = Math.floor, nativeIsArray = getNative(Array, "isArray"), nativeIsFinite = context.isFinite, nativeKeys = getNative(Object, "keys"), nativeMax = Math.max, nativeMin = Math.min, nativeNow = getNative(Date, "now"), nativeParseInt = context.parseInt, nativeRandom = Math.random; + var NEGATIVE_INFINITY = Number.NEGATIVE_INFINITY, POSITIVE_INFINITY = Number.POSITIVE_INFINITY; + var MAX_ARRAY_LENGTH = 4294967295, MAX_ARRAY_INDEX = MAX_ARRAY_LENGTH - 1, HALF_MAX_ARRAY_LENGTH = MAX_ARRAY_LENGTH >>> 1; + var MAX_SAFE_INTEGER = 9007199254740991; + var metaMap = WeakMap && new WeakMap(); + var realNames = {}; + function lodash(value) { + if (isObjectLike(value) && !isArray(value) && !(value instanceof LazyWrapper)) { + if (value instanceof LodashWrapper) { + return value; + } + if (hasOwnProperty.call(value, "__chain__") && hasOwnProperty.call(value, "__wrapped__")) { + return wrapperClone(value); + } + } + return new LodashWrapper(value); + } + function baseLodash() {} + function LodashWrapper(value, chainAll, actions) { + this.__wrapped__ = value; + this.__actions__ = actions || []; + this.__chain__ = !!chainAll; + } + var support = lodash.support = {}; + lodash.templateSettings = { + escape: reEscape, + evaluate: reEvaluate, + interpolate: reInterpolate, + variable: "", + imports: { + _: lodash + } + }; + function LazyWrapper(value) { + this.__wrapped__ = value; + this.__actions__ = []; + this.__dir__ = 1; + this.__filtered__ = false; + this.__iteratees__ = []; + this.__takeCount__ = POSITIVE_INFINITY; + this.__views__ = []; + } + function lazyClone() { + var result = new LazyWrapper(this.__wrapped__); + result.__actions__ = arrayCopy(this.__actions__); + result.__dir__ = this.__dir__; + result.__filtered__ = this.__filtered__; + result.__iteratees__ = arrayCopy(this.__iteratees__); + result.__takeCount__ = this.__takeCount__; + result.__views__ = arrayCopy(this.__views__); + return result; + } + function lazyReverse() { + if (this.__filtered__) { + var result = new LazyWrapper(this); + result.__dir__ = -1; + result.__filtered__ = true; + } else { + result = this.clone(); + result.__dir__ *= -1; + } + return result; + } + function lazyValue() { + var array = this.__wrapped__.value(), dir = this.__dir__, isArr = isArray(array), isRight = dir < 0, arrLength = isArr ? array.length : 0, view = getView(0, arrLength, this.__views__), start = view.start, end = view.end, length = end - start, index = isRight ? end : start - 1, iteratees = this.__iteratees__, iterLength = iteratees.length, resIndex = 0, takeCount = nativeMin(length, this.__takeCount__); + if (!isArr || arrLength < LARGE_ARRAY_SIZE || arrLength == length && takeCount == length) { + return baseWrapperValue(array, this.__actions__); + } + var result = []; + outer: while (length-- && resIndex < takeCount) { + index += dir; + var iterIndex = -1, value = array[index]; + while (++iterIndex < iterLength) { + var data = iteratees[iterIndex], iteratee = data.iteratee, type = data.type, computed = iteratee(value); + if (type == LAZY_MAP_FLAG) { + value = computed; + } else if (!computed) { + if (type == LAZY_FILTER_FLAG) { + continue outer; + } else { + break outer; + } + } + } + result[resIndex++] = value; + } + return result; + } + function MapCache() { + this.__data__ = {}; + } + function mapDelete(key) { + return this.has(key) && delete this.__data__[key]; + } + function mapGet(key) { + return key == "__proto__" ? undefined : this.__data__[key]; + } + function mapHas(key) { + return key != "__proto__" && hasOwnProperty.call(this.__data__, key); + } + function mapSet(key, value) { + if (key != "__proto__") { + this.__data__[key] = value; + } + return this; + } + function SetCache(values) { + var length = values ? values.length : 0; + this.data = { + hash: nativeCreate(null), + set: new Set() + }; + while (length--) { + this.push(values[length]); + } + } + function cacheIndexOf(cache, value) { + var data = cache.data, result = typeof value == "string" || isObject(value) ? data.set.has(value) : data.hash[value]; + return result ? 0 : -1; + } + function cachePush(value) { + var data = this.data; + if (typeof value == "string" || isObject(value)) { + data.set.add(value); + } else { + data.hash[value] = true; + } + } + function arrayConcat(array, other) { + var index = -1, length = array.length, othIndex = -1, othLength = other.length, result = Array(length + othLength); + while (++index < length) { + result[index] = array[index]; + } + while (++othIndex < othLength) { + result[index++] = other[othIndex]; + } + return result; + } + function arrayCopy(source, array) { + var index = -1, length = source.length; + array || (array = Array(length)); + while (++index < length) { + array[index] = source[index]; + } + return array; + } + function arrayEach(array, iteratee) { + var index = -1, length = array.length; + while (++index < length) { + if (iteratee(array[index], index, array) === false) { + break; + } + } + return array; + } + function arrayEachRight(array, iteratee) { + var length = array.length; + while (length--) { + if (iteratee(array[length], length, array) === false) { + break; + } + } + return array; + } + function arrayEvery(array, predicate) { + var index = -1, length = array.length; + while (++index < length) { + if (!predicate(array[index], index, array)) { + return false; + } + } + return true; + } + function arrayExtremum(array, iteratee, comparator, exValue) { + var index = -1, length = array.length, computed = exValue, result = computed; + while (++index < length) { + var value = array[index], current = +iteratee(value); + if (comparator(current, computed)) { + computed = current; + result = value; + } + } + return result; + } + function arrayFilter(array, predicate) { + var index = -1, length = array.length, resIndex = -1, result = []; + while (++index < length) { + var value = array[index]; + if (predicate(value, index, array)) { + result[++resIndex] = value; + } + } + return result; + } + function arrayMap(array, iteratee) { + var index = -1, length = array.length, result = Array(length); + while (++index < length) { + result[index] = iteratee(array[index], index, array); + } + return result; + } + function arrayPush(array, values) { + var index = -1, length = values.length, offset = array.length; + while (++index < length) { + array[offset + index] = values[index]; + } + return array; + } + function arrayReduce(array, iteratee, accumulator, initFromArray) { + var index = -1, length = array.length; + if (initFromArray && length) { + accumulator = array[++index]; + } + while (++index < length) { + accumulator = iteratee(accumulator, array[index], index, array); + } + return accumulator; + } + function arrayReduceRight(array, iteratee, accumulator, initFromArray) { + var length = array.length; + if (initFromArray && length) { + accumulator = array[--length]; + } + while (length--) { + accumulator = iteratee(accumulator, array[length], length, array); + } + return accumulator; + } + function arraySome(array, predicate) { + var index = -1, length = array.length; + while (++index < length) { + if (predicate(array[index], index, array)) { + return true; + } + } + return false; + } + function arraySum(array, iteratee) { + var length = array.length, result = 0; + while (length--) { + result += +iteratee(array[length]) || 0; + } + return result; + } + function assignDefaults(objectValue, sourceValue) { + return objectValue === undefined ? sourceValue : objectValue; + } + function assignOwnDefaults(objectValue, sourceValue, key, object) { + return objectValue === undefined || !hasOwnProperty.call(object, key) ? sourceValue : objectValue; + } + function assignWith(object, source, customizer) { + var index = -1, props = keys(source), length = props.length; + while (++index < length) { + var key = props[index], value = object[key], result = customizer(value, source[key], key, object, source); + if ((result === result ? result !== value : value === value) || value === undefined && !(key in object)) { + object[key] = result; + } + } + return object; + } + function baseAssign(object, source) { + return source == null ? object : baseCopy(source, keys(source), object); + } + function baseAt(collection, props) { + var index = -1, isNil = collection == null, isArr = !isNil && isArrayLike(collection), length = isArr ? collection.length : 0, propsLength = props.length, result = Array(propsLength); + while (++index < propsLength) { + var key = props[index]; + if (isArr) { + result[index] = isIndex(key, length) ? collection[key] : undefined; + } else { + result[index] = isNil ? undefined : collection[key]; + } + } + return result; + } + function baseCopy(source, props, object) { + object || (object = {}); + var index = -1, length = props.length; + while (++index < length) { + var key = props[index]; + object[key] = source[key]; + } + return object; + } + function baseCallback(func, thisArg, argCount) { + var type = typeof func; + if (type == "function") { + return thisArg === undefined ? func : bindCallback(func, thisArg, argCount); + } + if (func == null) { + return identity; + } + if (type == "object") { + return baseMatches(func); + } + return thisArg === undefined ? property(func) : baseMatchesProperty(func, thisArg); + } + function baseClone(value, isDeep, customizer, key, object, stackA, stackB) { + var result; + if (customizer) { + result = object ? customizer(value, key, object) : customizer(value); + } + if (result !== undefined) { + return result; + } + if (!isObject(value)) { + return value; + } + var isArr = isArray(value); + if (isArr) { + result = initCloneArray(value); + if (!isDeep) { + return arrayCopy(value, result); + } + } else { + var tag = objToString.call(value), isFunc = tag == funcTag; + if (tag == objectTag || tag == argsTag || isFunc && !object) { + result = initCloneObject(isFunc ? {} : value); + if (!isDeep) { + return baseAssign(result, value); + } + } else { + return cloneableTags[tag] ? initCloneByTag(value, tag, isDeep) : object ? value : {}; + } + } + stackA || (stackA = []); + stackB || (stackB = []); + var length = stackA.length; + while (length--) { + if (stackA[length] == value) { + return stackB[length]; + } + } + stackA.push(value); + stackB.push(result); + (isArr ? arrayEach : baseForOwn)(value, function(subValue, key) { + result[key] = baseClone(subValue, isDeep, customizer, key, value, stackA, stackB); + }); + return result; + } + var baseCreate = function() { + function object() {} + return function(prototype) { + if (isObject(prototype)) { + object.prototype = prototype; + var result = new object(); + object.prototype = undefined; + } + return result || {}; + }; + }(); + function baseDelay(func, wait, args) { + if (typeof func != "function") { + throw new TypeError(FUNC_ERROR_TEXT); + } + return setTimeout(function() { + func.apply(undefined, args); + }, wait); + } + function baseDifference(array, values) { + var length = array ? array.length : 0, result = []; + if (!length) { + return result; + } + var index = -1, indexOf = getIndexOf(), isCommon = indexOf === baseIndexOf, cache = isCommon && values.length >= LARGE_ARRAY_SIZE ? createCache(values) : null, valuesLength = values.length; + if (cache) { + indexOf = cacheIndexOf; + isCommon = false; + values = cache; + } + outer: while (++index < length) { + var value = array[index]; + if (isCommon && value === value) { + var valuesIndex = valuesLength; + while (valuesIndex--) { + if (values[valuesIndex] === value) { + continue outer; + } + } + result.push(value); + } else if (indexOf(values, value, 0) < 0) { + result.push(value); + } + } + return result; + } + var baseEach = createBaseEach(baseForOwn); + var baseEachRight = createBaseEach(baseForOwnRight, true); + function baseEvery(collection, predicate) { + var result = true; + baseEach(collection, function(value, index, collection) { + result = !!predicate(value, index, collection); + return result; + }); + return result; + } + function baseExtremum(collection, iteratee, comparator, exValue) { + var computed = exValue, result = computed; + baseEach(collection, function(value, index, collection) { + var current = +iteratee(value, index, collection); + if (comparator(current, computed) || current === exValue && current === result) { + computed = current; + result = value; + } + }); + return result; + } + function baseFill(array, value, start, end) { + var length = array.length; + start = start == null ? 0 : +start || 0; + if (start < 0) { + start = -start > length ? 0 : length + start; + } + end = end === undefined || end > length ? length : +end || 0; + if (end < 0) { + end += length; + } + length = start > end ? 0 : end >>> 0; + start >>>= 0; + while (start < length) { + array[start++] = value; + } + return array; + } + function baseFilter(collection, predicate) { + var result = []; + baseEach(collection, function(value, index, collection) { + if (predicate(value, index, collection)) { + result.push(value); + } + }); + return result; + } + function baseFind(collection, predicate, eachFunc, retKey) { + var result; + eachFunc(collection, function(value, key, collection) { + if (predicate(value, key, collection)) { + result = retKey ? key : value; + return false; + } + }); + return result; + } + function baseFlatten(array, isDeep, isStrict, result) { + result || (result = []); + var index = -1, length = array.length; + while (++index < length) { + var value = array[index]; + if (isObjectLike(value) && isArrayLike(value) && (isStrict || isArray(value) || isArguments(value))) { + if (isDeep) { + baseFlatten(value, isDeep, isStrict, result); + } else { + arrayPush(result, value); + } + } else if (!isStrict) { + result[result.length] = value; + } + } + return result; + } + var baseFor = createBaseFor(); + var baseForRight = createBaseFor(true); + function baseForIn(object, iteratee) { + return baseFor(object, iteratee, keysIn); + } + function baseForOwn(object, iteratee) { + return baseFor(object, iteratee, keys); + } + function baseForOwnRight(object, iteratee) { + return baseForRight(object, iteratee, keys); + } + function baseFunctions(object, props) { + var index = -1, length = props.length, resIndex = -1, result = []; + while (++index < length) { + var key = props[index]; + if (isFunction(object[key])) { + result[++resIndex] = key; + } + } + return result; + } + function baseGet(object, path, pathKey) { + if (object == null) { + return; + } + if (pathKey !== undefined && pathKey in toObject(object)) { + path = [ pathKey ]; + } + var index = 0, length = path.length; + while (object != null && index < length) { + object = object[path[index++]]; + } + return index && index == length ? object : undefined; + } + function baseIsEqual(value, other, customizer, isLoose, stackA, stackB) { + if (value === other) { + return true; + } + if (value == null || other == null || !isObject(value) && !isObjectLike(other)) { + return value !== value && other !== other; + } + return baseIsEqualDeep(value, other, baseIsEqual, customizer, isLoose, stackA, stackB); + } + function baseIsEqualDeep(object, other, equalFunc, customizer, isLoose, stackA, stackB) { + var objIsArr = isArray(object), othIsArr = isArray(other), objTag = arrayTag, othTag = arrayTag; + if (!objIsArr) { + objTag = objToString.call(object); + if (objTag == argsTag) { + objTag = objectTag; + } else if (objTag != objectTag) { + objIsArr = isTypedArray(object); + } + } + if (!othIsArr) { + othTag = objToString.call(other); + if (othTag == argsTag) { + othTag = objectTag; + } else if (othTag != objectTag) { + othIsArr = isTypedArray(other); + } + } + var objIsObj = objTag == objectTag, othIsObj = othTag == objectTag, isSameTag = objTag == othTag; + if (isSameTag && !(objIsArr || objIsObj)) { + return equalByTag(object, other, objTag); + } + if (!isLoose) { + var objIsWrapped = objIsObj && hasOwnProperty.call(object, "__wrapped__"), othIsWrapped = othIsObj && hasOwnProperty.call(other, "__wrapped__"); + if (objIsWrapped || othIsWrapped) { + return equalFunc(objIsWrapped ? object.value() : object, othIsWrapped ? other.value() : other, customizer, isLoose, stackA, stackB); + } + } + if (!isSameTag) { + return false; + } + stackA || (stackA = []); + stackB || (stackB = []); + var length = stackA.length; + while (length--) { + if (stackA[length] == object) { + return stackB[length] == other; + } + } + stackA.push(object); + stackB.push(other); + var result = (objIsArr ? equalArrays : equalObjects)(object, other, equalFunc, customizer, isLoose, stackA, stackB); + stackA.pop(); + stackB.pop(); + return result; + } + function baseIsMatch(object, matchData, customizer) { + var index = matchData.length, length = index, noCustomizer = !customizer; + if (object == null) { + return !length; + } + object = toObject(object); + while (index--) { + var data = matchData[index]; + if (noCustomizer && data[2] ? data[1] !== object[data[0]] : !(data[0] in object)) { + return false; + } + } + while (++index < length) { + data = matchData[index]; + var key = data[0], objValue = object[key], srcValue = data[1]; + if (noCustomizer && data[2]) { + if (objValue === undefined && !(key in object)) { + return false; + } + } else { + var result = customizer ? customizer(objValue, srcValue, key) : undefined; + if (!(result === undefined ? baseIsEqual(srcValue, objValue, customizer, true) : result)) { + return false; + } + } + } + return true; + } + function baseMap(collection, iteratee) { + var index = -1, result = isArrayLike(collection) ? Array(collection.length) : []; + baseEach(collection, function(value, key, collection) { + result[++index] = iteratee(value, key, collection); + }); + return result; + } + function baseMatches(source) { + var matchData = getMatchData(source); + if (matchData.length == 1 && matchData[0][2]) { + var key = matchData[0][0], value = matchData[0][1]; + return function(object) { + if (object == null) { + return false; + } + return object[key] === value && (value !== undefined || key in toObject(object)); + }; + } + return function(object) { + return baseIsMatch(object, matchData); + }; + } + function baseMatchesProperty(path, srcValue) { + var isArr = isArray(path), isCommon = isKey(path) && isStrictComparable(srcValue), pathKey = path + ""; + path = toPath(path); + return function(object) { + if (object == null) { + return false; + } + var key = pathKey; + object = toObject(object); + if ((isArr || !isCommon) && !(key in object)) { + object = path.length == 1 ? object : baseGet(object, baseSlice(path, 0, -1)); + if (object == null) { + return false; + } + key = last(path); + object = toObject(object); + } + return object[key] === srcValue ? srcValue !== undefined || key in object : baseIsEqual(srcValue, object[key], undefined, true); + }; + } + function baseMerge(object, source, customizer, stackA, stackB) { + if (!isObject(object)) { + return object; + } + var isSrcArr = isArrayLike(source) && (isArray(source) || isTypedArray(source)), props = isSrcArr ? undefined : keys(source); + arrayEach(props || source, function(srcValue, key) { + if (props) { + key = srcValue; + srcValue = source[key]; + } + if (isObjectLike(srcValue)) { + stackA || (stackA = []); + stackB || (stackB = []); + baseMergeDeep(object, source, key, baseMerge, customizer, stackA, stackB); + } else { + var value = object[key], result = customizer ? customizer(value, srcValue, key, object, source) : undefined, isCommon = result === undefined; + if (isCommon) { + result = srcValue; + } + if ((result !== undefined || isSrcArr && !(key in object)) && (isCommon || (result === result ? result !== value : value === value))) { + object[key] = result; + } + } + }); + return object; + } + function baseMergeDeep(object, source, key, mergeFunc, customizer, stackA, stackB) { + var length = stackA.length, srcValue = source[key]; + while (length--) { + if (stackA[length] == srcValue) { + object[key] = stackB[length]; + return; + } + } + var value = object[key], result = customizer ? customizer(value, srcValue, key, object, source) : undefined, isCommon = result === undefined; + if (isCommon) { + result = srcValue; + if (isArrayLike(srcValue) && (isArray(srcValue) || isTypedArray(srcValue))) { + result = isArray(value) ? value : isArrayLike(value) ? arrayCopy(value) : []; + } else if (isPlainObject(srcValue) || isArguments(srcValue)) { + result = isArguments(value) ? toPlainObject(value) : isPlainObject(value) ? value : {}; + } else { + isCommon = false; + } + } + stackA.push(srcValue); + stackB.push(result); + if (isCommon) { + object[key] = mergeFunc(result, srcValue, customizer, stackA, stackB); + } else if (result === result ? result !== value : value === value) { + object[key] = result; + } + } + function baseProperty(key) { + return function(object) { + return object == null ? undefined : object[key]; + }; + } + function basePropertyDeep(path) { + var pathKey = path + ""; + path = toPath(path); + return function(object) { + return baseGet(object, path, pathKey); + }; + } + function basePullAt(array, indexes) { + var length = array ? indexes.length : 0; + while (length--) { + var index = indexes[length]; + if (index != previous && isIndex(index)) { + var previous = index; + splice.call(array, index, 1); + } + } + return array; + } + function baseRandom(min, max) { + return min + nativeFloor(nativeRandom() * (max - min + 1)); + } + function baseReduce(collection, iteratee, accumulator, initFromCollection, eachFunc) { + eachFunc(collection, function(value, index, collection) { + accumulator = initFromCollection ? (initFromCollection = false, value) : iteratee(accumulator, value, index, collection); + }); + return accumulator; + } + var baseSetData = !metaMap ? identity : function(func, data) { + metaMap.set(func, data); + return func; + }; + function baseSlice(array, start, end) { + var index = -1, length = array.length; + start = start == null ? 0 : +start || 0; + if (start < 0) { + start = -start > length ? 0 : length + start; + } + end = end === undefined || end > length ? length : +end || 0; + if (end < 0) { + end += length; + } + length = start > end ? 0 : end - start >>> 0; + start >>>= 0; + var result = Array(length); + while (++index < length) { + result[index] = array[index + start]; + } + return result; + } + function baseSome(collection, predicate) { + var result; + baseEach(collection, function(value, index, collection) { + result = predicate(value, index, collection); + return !result; + }); + return !!result; + } + function baseSortBy(array, comparer) { + var length = array.length; + array.sort(comparer); + while (length--) { + array[length] = array[length].value; + } + return array; + } + function baseSortByOrder(collection, iteratees, orders) { + var callback = getCallback(), index = -1; + iteratees = arrayMap(iteratees, function(iteratee) { + return callback(iteratee); + }); + var result = baseMap(collection, function(value) { + var criteria = arrayMap(iteratees, function(iteratee) { + return iteratee(value); + }); + return { + criteria: criteria, + index: ++index, + value: value + }; + }); + return baseSortBy(result, function(object, other) { + return compareMultiple(object, other, orders); + }); + } + function baseSum(collection, iteratee) { + var result = 0; + baseEach(collection, function(value, index, collection) { + result += +iteratee(value, index, collection) || 0; + }); + return result; + } + function baseUniq(array, iteratee) { + var index = -1, indexOf = getIndexOf(), length = array.length, isCommon = indexOf === baseIndexOf, isLarge = isCommon && length >= LARGE_ARRAY_SIZE, seen = isLarge ? createCache() : null, result = []; + if (seen) { + indexOf = cacheIndexOf; + isCommon = false; + } else { + isLarge = false; + seen = iteratee ? [] : result; + } + outer: while (++index < length) { + var value = array[index], computed = iteratee ? iteratee(value, index, array) : value; + if (isCommon && value === value) { + var seenIndex = seen.length; + while (seenIndex--) { + if (seen[seenIndex] === computed) { + continue outer; + } + } + if (iteratee) { + seen.push(computed); + } + result.push(value); + } else if (indexOf(seen, computed, 0) < 0) { + if (iteratee || isLarge) { + seen.push(computed); + } + result.push(value); + } + } + return result; + } + function baseValues(object, props) { + var index = -1, length = props.length, result = Array(length); + while (++index < length) { + result[index] = object[props[index]]; + } + return result; + } + function baseWhile(array, predicate, isDrop, fromRight) { + var length = array.length, index = fromRight ? length : -1; + while ((fromRight ? index-- : ++index < length) && predicate(array[index], index, array)) {} + return isDrop ? baseSlice(array, fromRight ? 0 : index, fromRight ? index + 1 : length) : baseSlice(array, fromRight ? index + 1 : 0, fromRight ? length : index); + } + function baseWrapperValue(value, actions) { + var result = value; + if (result instanceof LazyWrapper) { + result = result.value(); + } + var index = -1, length = actions.length; + while (++index < length) { + var action = actions[index]; + result = action.func.apply(action.thisArg, arrayPush([ result ], action.args)); + } + return result; + } + function binaryIndex(array, value, retHighest) { + var low = 0, high = array ? array.length : low; + if (typeof value == "number" && value === value && high <= HALF_MAX_ARRAY_LENGTH) { + while (low < high) { + var mid = low + high >>> 1, computed = array[mid]; + if ((retHighest ? computed <= value : computed < value) && computed !== null) { + low = mid + 1; + } else { + high = mid; + } + } + return high; + } + return binaryIndexBy(array, value, identity, retHighest); + } + function binaryIndexBy(array, value, iteratee, retHighest) { + value = iteratee(value); + var low = 0, high = array ? array.length : 0, valIsNaN = value !== value, valIsNull = value === null, valIsUndef = value === undefined; + while (low < high) { + var mid = nativeFloor((low + high) / 2), computed = iteratee(array[mid]), isDef = computed !== undefined, isReflexive = computed === computed; + if (valIsNaN) { + var setLow = isReflexive || retHighest; + } else if (valIsNull) { + setLow = isReflexive && isDef && (retHighest || computed != null); + } else if (valIsUndef) { + setLow = isReflexive && (retHighest || isDef); + } else if (computed == null) { + setLow = false; + } else { + setLow = retHighest ? computed <= value : computed < value; + } + if (setLow) { + low = mid + 1; + } else { + high = mid; + } + } + return nativeMin(high, MAX_ARRAY_INDEX); + } + function bindCallback(func, thisArg, argCount) { + if (typeof func != "function") { + return identity; + } + if (thisArg === undefined) { + return func; + } + switch (argCount) { + case 1: + return function(value) { + return func.call(thisArg, value); + }; + + case 3: + return function(value, index, collection) { + return func.call(thisArg, value, index, collection); + }; + + case 4: + return function(accumulator, value, index, collection) { + return func.call(thisArg, accumulator, value, index, collection); + }; + + case 5: + return function(value, other, key, object, source) { + return func.call(thisArg, value, other, key, object, source); + }; + } + return function() { + return func.apply(thisArg, arguments); + }; + } + function bufferClone(buffer) { + var result = new ArrayBuffer(buffer.byteLength), view = new Uint8Array(result); + view.set(new Uint8Array(buffer)); + return result; + } + function composeArgs(args, partials, holders) { + var holdersLength = holders.length, argsIndex = -1, argsLength = nativeMax(args.length - holdersLength, 0), leftIndex = -1, leftLength = partials.length, result = Array(leftLength + argsLength); + while (++leftIndex < leftLength) { + result[leftIndex] = partials[leftIndex]; + } + while (++argsIndex < holdersLength) { + result[holders[argsIndex]] = args[argsIndex]; + } + while (argsLength--) { + result[leftIndex++] = args[argsIndex++]; + } + return result; + } + function composeArgsRight(args, partials, holders) { + var holdersIndex = -1, holdersLength = holders.length, argsIndex = -1, argsLength = nativeMax(args.length - holdersLength, 0), rightIndex = -1, rightLength = partials.length, result = Array(argsLength + rightLength); + while (++argsIndex < argsLength) { + result[argsIndex] = args[argsIndex]; + } + var offset = argsIndex; + while (++rightIndex < rightLength) { + result[offset + rightIndex] = partials[rightIndex]; + } + while (++holdersIndex < holdersLength) { + result[offset + holders[holdersIndex]] = args[argsIndex++]; + } + return result; + } + function createAggregator(setter, initializer) { + return function(collection, iteratee, thisArg) { + var result = initializer ? initializer() : {}; + iteratee = getCallback(iteratee, thisArg, 3); + if (isArray(collection)) { + var index = -1, length = collection.length; + while (++index < length) { + var value = collection[index]; + setter(result, value, iteratee(value, index, collection), collection); + } + } else { + baseEach(collection, function(value, key, collection) { + setter(result, value, iteratee(value, key, collection), collection); + }); + } + return result; + }; + } + function createAssigner(assigner) { + return restParam(function(object, sources) { + var index = -1, length = object == null ? 0 : sources.length, customizer = length > 2 ? sources[length - 2] : undefined, guard = length > 2 ? sources[2] : undefined, thisArg = length > 1 ? sources[length - 1] : undefined; + if (typeof customizer == "function") { + customizer = bindCallback(customizer, thisArg, 5); + length -= 2; + } else { + customizer = typeof thisArg == "function" ? thisArg : undefined; + length -= customizer ? 1 : 0; + } + if (guard && isIterateeCall(sources[0], sources[1], guard)) { + customizer = length < 3 ? undefined : customizer; + length = 1; + } + while (++index < length) { + var source = sources[index]; + if (source) { + assigner(object, source, customizer); + } + } + return object; + }); + } + function createBaseEach(eachFunc, fromRight) { + return function(collection, iteratee) { + var length = collection ? getLength(collection) : 0; + if (!isLength(length)) { + return eachFunc(collection, iteratee); + } + var index = fromRight ? length : -1, iterable = toObject(collection); + while (fromRight ? index-- : ++index < length) { + if (iteratee(iterable[index], index, iterable) === false) { + break; + } + } + return collection; + }; + } + function createBaseFor(fromRight) { + return function(object, iteratee, keysFunc) { + var iterable = toObject(object), props = keysFunc(object), length = props.length, index = fromRight ? length : -1; + while (fromRight ? index-- : ++index < length) { + var key = props[index]; + if (iteratee(iterable[key], key, iterable) === false) { + break; + } + } + return object; + }; + } + function createBindWrapper(func, thisArg) { + var Ctor = createCtorWrapper(func); + function wrapper() { + var fn = this && this !== root && this instanceof wrapper ? Ctor : func; + return fn.apply(thisArg, arguments); + } + return wrapper; + } + function createCache(values) { + return nativeCreate && Set ? new SetCache(values) : null; + } + function createCompounder(callback) { + return function(string) { + var index = -1, array = words(deburr(string)), length = array.length, result = ""; + while (++index < length) { + result = callback(result, array[index], index); + } + return result; + }; + } + function createCtorWrapper(Ctor) { + return function() { + var args = arguments; + switch (args.length) { + case 0: + return new Ctor(); + + case 1: + return new Ctor(args[0]); + + case 2: + return new Ctor(args[0], args[1]); + + case 3: + return new Ctor(args[0], args[1], args[2]); + + case 4: + return new Ctor(args[0], args[1], args[2], args[3]); + + case 5: + return new Ctor(args[0], args[1], args[2], args[3], args[4]); + + case 6: + return new Ctor(args[0], args[1], args[2], args[3], args[4], args[5]); + + case 7: + return new Ctor(args[0], args[1], args[2], args[3], args[4], args[5], args[6]); + } + var thisBinding = baseCreate(Ctor.prototype), result = Ctor.apply(thisBinding, args); + return isObject(result) ? result : thisBinding; + }; + } + function createCurry(flag) { + function curryFunc(func, arity, guard) { + if (guard && isIterateeCall(func, arity, guard)) { + arity = undefined; + } + var result = createWrapper(func, flag, undefined, undefined, undefined, undefined, undefined, arity); + result.placeholder = curryFunc.placeholder; + return result; + } + return curryFunc; + } + function createDefaults(assigner, customizer) { + return restParam(function(args) { + var object = args[0]; + if (object == null) { + return object; + } + args.push(customizer); + return assigner.apply(undefined, args); + }); + } + function createExtremum(comparator, exValue) { + return function(collection, iteratee, thisArg) { + if (thisArg && isIterateeCall(collection, iteratee, thisArg)) { + iteratee = undefined; + } + iteratee = getCallback(iteratee, thisArg, 3); + if (iteratee.length == 1) { + collection = isArray(collection) ? collection : toIterable(collection); + var result = arrayExtremum(collection, iteratee, comparator, exValue); + if (!(collection.length && result === exValue)) { + return result; + } + } + return baseExtremum(collection, iteratee, comparator, exValue); + }; + } + function createFind(eachFunc, fromRight) { + return function(collection, predicate, thisArg) { + predicate = getCallback(predicate, thisArg, 3); + if (isArray(collection)) { + var index = baseFindIndex(collection, predicate, fromRight); + return index > -1 ? collection[index] : undefined; + } + return baseFind(collection, predicate, eachFunc); + }; + } + function createFindIndex(fromRight) { + return function(array, predicate, thisArg) { + if (!(array && array.length)) { + return -1; + } + predicate = getCallback(predicate, thisArg, 3); + return baseFindIndex(array, predicate, fromRight); + }; + } + function createFindKey(objectFunc) { + return function(object, predicate, thisArg) { + predicate = getCallback(predicate, thisArg, 3); + return baseFind(object, predicate, objectFunc, true); + }; + } + function createFlow(fromRight) { + return function() { + var wrapper, length = arguments.length, index = fromRight ? length : -1, leftIndex = 0, funcs = Array(length); + while (fromRight ? index-- : ++index < length) { + var func = funcs[leftIndex++] = arguments[index]; + if (typeof func != "function") { + throw new TypeError(FUNC_ERROR_TEXT); + } + if (!wrapper && LodashWrapper.prototype.thru && getFuncName(func) == "wrapper") { + wrapper = new LodashWrapper([], true); + } + } + index = wrapper ? -1 : length; + while (++index < length) { + func = funcs[index]; + var funcName = getFuncName(func), data = funcName == "wrapper" ? getData(func) : undefined; + if (data && isLaziable(data[0]) && data[1] == (ARY_FLAG | CURRY_FLAG | PARTIAL_FLAG | REARG_FLAG) && !data[4].length && data[9] == 1) { + wrapper = wrapper[getFuncName(data[0])].apply(wrapper, data[3]); + } else { + wrapper = func.length == 1 && isLaziable(func) ? wrapper[funcName]() : wrapper.thru(func); + } + } + return function() { + var args = arguments, value = args[0]; + if (wrapper && args.length == 1 && isArray(value) && value.length >= LARGE_ARRAY_SIZE) { + return wrapper.plant(value).value(); + } + var index = 0, result = length ? funcs[index].apply(this, args) : value; + while (++index < length) { + result = funcs[index].call(this, result); + } + return result; + }; + }; + } + function createForEach(arrayFunc, eachFunc) { + return function(collection, iteratee, thisArg) { + return typeof iteratee == "function" && thisArg === undefined && isArray(collection) ? arrayFunc(collection, iteratee) : eachFunc(collection, bindCallback(iteratee, thisArg, 3)); + }; + } + function createForIn(objectFunc) { + return function(object, iteratee, thisArg) { + if (typeof iteratee != "function" || thisArg !== undefined) { + iteratee = bindCallback(iteratee, thisArg, 3); + } + return objectFunc(object, iteratee, keysIn); + }; + } + function createForOwn(objectFunc) { + return function(object, iteratee, thisArg) { + if (typeof iteratee != "function" || thisArg !== undefined) { + iteratee = bindCallback(iteratee, thisArg, 3); + } + return objectFunc(object, iteratee); + }; + } + function createObjectMapper(isMapKeys) { + return function(object, iteratee, thisArg) { + var result = {}; + iteratee = getCallback(iteratee, thisArg, 3); + baseForOwn(object, function(value, key, object) { + var mapped = iteratee(value, key, object); + key = isMapKeys ? mapped : key; + value = isMapKeys ? value : mapped; + result[key] = value; + }); + return result; + }; + } + function createPadDir(fromRight) { + return function(string, length, chars) { + string = baseToString(string); + return (fromRight ? string : "") + createPadding(string, length, chars) + (fromRight ? "" : string); + }; + } + function createPartial(flag) { + var partialFunc = restParam(function(func, partials) { + var holders = replaceHolders(partials, partialFunc.placeholder); + return createWrapper(func, flag, undefined, partials, holders); + }); + return partialFunc; + } + function createReduce(arrayFunc, eachFunc) { + return function(collection, iteratee, accumulator, thisArg) { + var initFromArray = arguments.length < 3; + return typeof iteratee == "function" && thisArg === undefined && isArray(collection) ? arrayFunc(collection, iteratee, accumulator, initFromArray) : baseReduce(collection, getCallback(iteratee, thisArg, 4), accumulator, initFromArray, eachFunc); + }; + } + function createHybridWrapper(func, bitmask, thisArg, partials, holders, partialsRight, holdersRight, argPos, ary, arity) { + var isAry = bitmask & ARY_FLAG, isBind = bitmask & BIND_FLAG, isBindKey = bitmask & BIND_KEY_FLAG, isCurry = bitmask & CURRY_FLAG, isCurryBound = bitmask & CURRY_BOUND_FLAG, isCurryRight = bitmask & CURRY_RIGHT_FLAG, Ctor = isBindKey ? undefined : createCtorWrapper(func); + function wrapper() { + var length = arguments.length, index = length, args = Array(length); + while (index--) { + args[index] = arguments[index]; + } + if (partials) { + args = composeArgs(args, partials, holders); + } + if (partialsRight) { + args = composeArgsRight(args, partialsRight, holdersRight); + } + if (isCurry || isCurryRight) { + var placeholder = wrapper.placeholder, argsHolders = replaceHolders(args, placeholder); + length -= argsHolders.length; + if (length < arity) { + var newArgPos = argPos ? arrayCopy(argPos) : undefined, newArity = nativeMax(arity - length, 0), newsHolders = isCurry ? argsHolders : undefined, newHoldersRight = isCurry ? undefined : argsHolders, newPartials = isCurry ? args : undefined, newPartialsRight = isCurry ? undefined : args; + bitmask |= isCurry ? PARTIAL_FLAG : PARTIAL_RIGHT_FLAG; + bitmask &= ~(isCurry ? PARTIAL_RIGHT_FLAG : PARTIAL_FLAG); + if (!isCurryBound) { + bitmask &= ~(BIND_FLAG | BIND_KEY_FLAG); + } + var newData = [ func, bitmask, thisArg, newPartials, newsHolders, newPartialsRight, newHoldersRight, newArgPos, ary, newArity ], result = createHybridWrapper.apply(undefined, newData); + if (isLaziable(func)) { + setData(result, newData); + } + result.placeholder = placeholder; + return result; + } + } + var thisBinding = isBind ? thisArg : this, fn = isBindKey ? thisBinding[func] : func; + if (argPos) { + args = reorder(args, argPos); + } + if (isAry && ary < args.length) { + args.length = ary; + } + if (this && this !== root && this instanceof wrapper) { + fn = Ctor || createCtorWrapper(func); + } + return fn.apply(thisBinding, args); + } + return wrapper; + } + function createPadding(string, length, chars) { + var strLength = string.length; + length = +length; + if (strLength >= length || !nativeIsFinite(length)) { + return ""; + } + var padLength = length - strLength; + chars = chars == null ? " " : chars + ""; + return repeat(chars, nativeCeil(padLength / chars.length)).slice(0, padLength); + } + function createPartialWrapper(func, bitmask, thisArg, partials) { + var isBind = bitmask & BIND_FLAG, Ctor = createCtorWrapper(func); + function wrapper() { + var argsIndex = -1, argsLength = arguments.length, leftIndex = -1, leftLength = partials.length, args = Array(leftLength + argsLength); + while (++leftIndex < leftLength) { + args[leftIndex] = partials[leftIndex]; + } + while (argsLength--) { + args[leftIndex++] = arguments[++argsIndex]; + } + var fn = this && this !== root && this instanceof wrapper ? Ctor : func; + return fn.apply(isBind ? thisArg : this, args); + } + return wrapper; + } + function createRound(methodName) { + var func = Math[methodName]; + return function(number, precision) { + precision = precision === undefined ? 0 : +precision || 0; + if (precision) { + precision = pow(10, precision); + return func(number * precision) / precision; + } + return func(number); + }; + } + function createSortedIndex(retHighest) { + return function(array, value, iteratee, thisArg) { + var callback = getCallback(iteratee); + return iteratee == null && callback === baseCallback ? binaryIndex(array, value, retHighest) : binaryIndexBy(array, value, callback(iteratee, thisArg, 1), retHighest); + }; + } + function createWrapper(func, bitmask, thisArg, partials, holders, argPos, ary, arity) { + var isBindKey = bitmask & BIND_KEY_FLAG; + if (!isBindKey && typeof func != "function") { + throw new TypeError(FUNC_ERROR_TEXT); + } + var length = partials ? partials.length : 0; + if (!length) { + bitmask &= ~(PARTIAL_FLAG | PARTIAL_RIGHT_FLAG); + partials = holders = undefined; + } + length -= holders ? holders.length : 0; + if (bitmask & PARTIAL_RIGHT_FLAG) { + var partialsRight = partials, holdersRight = holders; + partials = holders = undefined; + } + var data = isBindKey ? undefined : getData(func), newData = [ func, bitmask, thisArg, partials, holders, partialsRight, holdersRight, argPos, ary, arity ]; + if (data) { + mergeData(newData, data); + bitmask = newData[1]; + arity = newData[9]; + } + newData[9] = arity == null ? isBindKey ? 0 : func.length : nativeMax(arity - length, 0) || 0; + if (bitmask == BIND_FLAG) { + var result = createBindWrapper(newData[0], newData[2]); + } else if ((bitmask == PARTIAL_FLAG || bitmask == (BIND_FLAG | PARTIAL_FLAG)) && !newData[4].length) { + result = createPartialWrapper.apply(undefined, newData); + } else { + result = createHybridWrapper.apply(undefined, newData); + } + var setter = data ? baseSetData : setData; + return setter(result, newData); + } + function equalArrays(array, other, equalFunc, customizer, isLoose, stackA, stackB) { + var index = -1, arrLength = array.length, othLength = other.length; + if (arrLength != othLength && !(isLoose && othLength > arrLength)) { + return false; + } + while (++index < arrLength) { + var arrValue = array[index], othValue = other[index], result = customizer ? customizer(isLoose ? othValue : arrValue, isLoose ? arrValue : othValue, index) : undefined; + if (result !== undefined) { + if (result) { + continue; + } + return false; + } + if (isLoose) { + if (!arraySome(other, function(othValue) { + return arrValue === othValue || equalFunc(arrValue, othValue, customizer, isLoose, stackA, stackB); + })) { + return false; + } + } else if (!(arrValue === othValue || equalFunc(arrValue, othValue, customizer, isLoose, stackA, stackB))) { + return false; + } + } + return true; + } + function equalByTag(object, other, tag) { + switch (tag) { + case boolTag: + case dateTag: + return +object == +other; + + case errorTag: + return object.name == other.name && object.message == other.message; + + case numberTag: + return object != +object ? other != +other : object == +other; + + case regexpTag: + case stringTag: + return object == other + ""; + } + return false; + } + function equalObjects(object, other, equalFunc, customizer, isLoose, stackA, stackB) { + var objProps = keys(object), objLength = objProps.length, othProps = keys(other), othLength = othProps.length; + if (objLength != othLength && !isLoose) { + return false; + } + var index = objLength; + while (index--) { + var key = objProps[index]; + if (!(isLoose ? key in other : hasOwnProperty.call(other, key))) { + return false; + } + } + var skipCtor = isLoose; + while (++index < objLength) { + key = objProps[index]; + var objValue = object[key], othValue = other[key], result = customizer ? customizer(isLoose ? othValue : objValue, isLoose ? objValue : othValue, key) : undefined; + if (!(result === undefined ? equalFunc(objValue, othValue, customizer, isLoose, stackA, stackB) : result)) { + return false; + } + skipCtor || (skipCtor = key == "constructor"); + } + if (!skipCtor) { + var objCtor = object.constructor, othCtor = other.constructor; + if (objCtor != othCtor && ("constructor" in object && "constructor" in other) && !(typeof objCtor == "function" && objCtor instanceof objCtor && typeof othCtor == "function" && othCtor instanceof othCtor)) { + return false; + } + } + return true; + } + function getCallback(func, thisArg, argCount) { + var result = lodash.callback || callback; + result = result === callback ? baseCallback : result; + return argCount ? result(func, thisArg, argCount) : result; + } + var getData = !metaMap ? noop : function(func) { + return metaMap.get(func); + }; + function getFuncName(func) { + var result = func.name + "", array = realNames[result], length = array ? array.length : 0; + while (length--) { + var data = array[length], otherFunc = data.func; + if (otherFunc == null || otherFunc == func) { + return data.name; + } + } + return result; + } + function getIndexOf(collection, target, fromIndex) { + var result = lodash.indexOf || indexOf; + result = result === indexOf ? baseIndexOf : result; + return collection ? result(collection, target, fromIndex) : result; + } + var getLength = baseProperty("length"); + function getMatchData(object) { + var result = pairs(object), length = result.length; + while (length--) { + result[length][2] = isStrictComparable(result[length][1]); + } + return result; + } + function getNative(object, key) { + var value = object == null ? undefined : object[key]; + return isNative(value) ? value : undefined; + } + function getView(start, end, transforms) { + var index = -1, length = transforms.length; + while (++index < length) { + var data = transforms[index], size = data.size; + switch (data.type) { + case "drop": + start += size; + break; + + case "dropRight": + end -= size; + break; + + case "take": + end = nativeMin(end, start + size); + break; + + case "takeRight": + start = nativeMax(start, end - size); + break; + } + } + return { + start: start, + end: end + }; + } + function initCloneArray(array) { + var length = array.length, result = new array.constructor(length); + if (length && typeof array[0] == "string" && hasOwnProperty.call(array, "index")) { + result.index = array.index; + result.input = array.input; + } + return result; + } + function initCloneObject(object) { + var Ctor = object.constructor; + if (!(typeof Ctor == "function" && Ctor instanceof Ctor)) { + Ctor = Object; + } + return new Ctor(); + } + function initCloneByTag(object, tag, isDeep) { + var Ctor = object.constructor; + switch (tag) { + case arrayBufferTag: + return bufferClone(object); + + case boolTag: + case dateTag: + return new Ctor(+object); + + case float32Tag: + case float64Tag: + case int8Tag: + case int16Tag: + case int32Tag: + case uint8Tag: + case uint8ClampedTag: + case uint16Tag: + case uint32Tag: + var buffer = object.buffer; + return new Ctor(isDeep ? bufferClone(buffer) : buffer, object.byteOffset, object.length); + + case numberTag: + case stringTag: + return new Ctor(object); + + case regexpTag: + var result = new Ctor(object.source, reFlags.exec(object)); + result.lastIndex = object.lastIndex; + } + return result; + } + function invokePath(object, path, args) { + if (object != null && !isKey(path, object)) { + path = toPath(path); + object = path.length == 1 ? object : baseGet(object, baseSlice(path, 0, -1)); + path = last(path); + } + var func = object == null ? object : object[path]; + return func == null ? undefined : func.apply(object, args); + } + function isArrayLike(value) { + return value != null && isLength(getLength(value)); + } + function isIndex(value, length) { + value = typeof value == "number" || reIsUint.test(value) ? +value : -1; + length = length == null ? MAX_SAFE_INTEGER : length; + return value > -1 && value % 1 == 0 && value < length; + } + function isIterateeCall(value, index, object) { + if (!isObject(object)) { + return false; + } + var type = typeof index; + if (type == "number" ? isArrayLike(object) && isIndex(index, object.length) : type == "string" && index in object) { + var other = object[index]; + return value === value ? value === other : other !== other; + } + return false; + } + function isKey(value, object) { + var type = typeof value; + if (type == "string" && reIsPlainProp.test(value) || type == "number") { + return true; + } + if (isArray(value)) { + return false; + } + var result = !reIsDeepProp.test(value); + return result || object != null && value in toObject(object); + } + function isLaziable(func) { + var funcName = getFuncName(func), other = lodash[funcName]; + if (typeof other != "function" || !(funcName in LazyWrapper.prototype)) { + return false; + } + if (func === other) { + return true; + } + var data = getData(other); + return !!data && func === data[0]; + } + function isLength(value) { + return typeof value == "number" && value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER; + } + function isStrictComparable(value) { + return value === value && !isObject(value); + } + function mergeData(data, source) { + var bitmask = data[1], srcBitmask = source[1], newBitmask = bitmask | srcBitmask, isCommon = newBitmask < ARY_FLAG; + var isCombo = srcBitmask == ARY_FLAG && bitmask == CURRY_FLAG || srcBitmask == ARY_FLAG && bitmask == REARG_FLAG && data[7].length <= source[8] || srcBitmask == (ARY_FLAG | REARG_FLAG) && bitmask == CURRY_FLAG; + if (!(isCommon || isCombo)) { + return data; + } + if (srcBitmask & BIND_FLAG) { + data[2] = source[2]; + newBitmask |= bitmask & BIND_FLAG ? 0 : CURRY_BOUND_FLAG; + } + var value = source[3]; + if (value) { + var partials = data[3]; + data[3] = partials ? composeArgs(partials, value, source[4]) : arrayCopy(value); + data[4] = partials ? replaceHolders(data[3], PLACEHOLDER) : arrayCopy(source[4]); + } + value = source[5]; + if (value) { + partials = data[5]; + data[5] = partials ? composeArgsRight(partials, value, source[6]) : arrayCopy(value); + data[6] = partials ? replaceHolders(data[5], PLACEHOLDER) : arrayCopy(source[6]); + } + value = source[7]; + if (value) { + data[7] = arrayCopy(value); + } + if (srcBitmask & ARY_FLAG) { + data[8] = data[8] == null ? source[8] : nativeMin(data[8], source[8]); + } + if (data[9] == null) { + data[9] = source[9]; + } + data[0] = source[0]; + data[1] = newBitmask; + return data; + } + function mergeDefaults(objectValue, sourceValue) { + return objectValue === undefined ? sourceValue : merge(objectValue, sourceValue, mergeDefaults); + } + function pickByArray(object, props) { + object = toObject(object); + var index = -1, length = props.length, result = {}; + while (++index < length) { + var key = props[index]; + if (key in object) { + result[key] = object[key]; + } + } + return result; + } + function pickByCallback(object, predicate) { + var result = {}; + baseForIn(object, function(value, key, object) { + if (predicate(value, key, object)) { + result[key] = value; + } + }); + return result; + } + function reorder(array, indexes) { + var arrLength = array.length, length = nativeMin(indexes.length, arrLength), oldArray = arrayCopy(array); + while (length--) { + var index = indexes[length]; + array[length] = isIndex(index, arrLength) ? oldArray[index] : undefined; + } + return array; + } + var setData = function() { + var count = 0, lastCalled = 0; + return function(key, value) { + var stamp = now(), remaining = HOT_SPAN - (stamp - lastCalled); + lastCalled = stamp; + if (remaining > 0) { + if (++count >= HOT_COUNT) { + return key; + } + } else { + count = 0; + } + return baseSetData(key, value); + }; + }(); + function shimKeys(object) { + var props = keysIn(object), propsLength = props.length, length = propsLength && object.length; + var allowIndexes = !!length && isLength(length) && (isArray(object) || isArguments(object)); + var index = -1, result = []; + while (++index < propsLength) { + var key = props[index]; + if (allowIndexes && isIndex(key, length) || hasOwnProperty.call(object, key)) { + result.push(key); + } + } + return result; + } + function toIterable(value) { + if (value == null) { + return []; + } + if (!isArrayLike(value)) { + return values(value); + } + return isObject(value) ? value : Object(value); + } + function toObject(value) { + return isObject(value) ? value : Object(value); + } + function toPath(value) { + if (isArray(value)) { + return value; + } + var result = []; + baseToString(value).replace(rePropName, function(match, number, quote, string) { + result.push(quote ? string.replace(reEscapeChar, "$1") : number || match); + }); + return result; + } + function wrapperClone(wrapper) { + return wrapper instanceof LazyWrapper ? wrapper.clone() : new LodashWrapper(wrapper.__wrapped__, wrapper.__chain__, arrayCopy(wrapper.__actions__)); + } + function chunk(array, size, guard) { + if (guard ? isIterateeCall(array, size, guard) : size == null) { + size = 1; + } else { + size = nativeMax(nativeFloor(size) || 1, 1); + } + var index = 0, length = array ? array.length : 0, resIndex = -1, result = Array(nativeCeil(length / size)); + while (index < length) { + result[++resIndex] = baseSlice(array, index, index += size); + } + return result; + } + function compact(array) { + var index = -1, length = array ? array.length : 0, resIndex = -1, result = []; + while (++index < length) { + var value = array[index]; + if (value) { + result[++resIndex] = value; + } + } + return result; + } + var difference = restParam(function(array, values) { + return isObjectLike(array) && isArrayLike(array) ? baseDifference(array, baseFlatten(values, false, true)) : []; + }); + function drop(array, n, guard) { + var length = array ? array.length : 0; + if (!length) { + return []; + } + if (guard ? isIterateeCall(array, n, guard) : n == null) { + n = 1; + } + return baseSlice(array, n < 0 ? 0 : n); + } + function dropRight(array, n, guard) { + var length = array ? array.length : 0; + if (!length) { + return []; + } + if (guard ? isIterateeCall(array, n, guard) : n == null) { + n = 1; + } + n = length - (+n || 0); + return baseSlice(array, 0, n < 0 ? 0 : n); + } + function dropRightWhile(array, predicate, thisArg) { + return array && array.length ? baseWhile(array, getCallback(predicate, thisArg, 3), true, true) : []; + } + function dropWhile(array, predicate, thisArg) { + return array && array.length ? baseWhile(array, getCallback(predicate, thisArg, 3), true) : []; + } + function fill(array, value, start, end) { + var length = array ? array.length : 0; + if (!length) { + return []; + } + if (start && typeof start != "number" && isIterateeCall(array, value, start)) { + start = 0; + end = length; + } + return baseFill(array, value, start, end); + } + var findIndex = createFindIndex(); + var findLastIndex = createFindIndex(true); + function first(array) { + return array ? array[0] : undefined; + } + function flatten(array, isDeep, guard) { + var length = array ? array.length : 0; + if (guard && isIterateeCall(array, isDeep, guard)) { + isDeep = false; + } + return length ? baseFlatten(array, isDeep) : []; + } + function flattenDeep(array) { + var length = array ? array.length : 0; + return length ? baseFlatten(array, true) : []; + } + function indexOf(array, value, fromIndex) { + var length = array ? array.length : 0; + if (!length) { + return -1; + } + if (typeof fromIndex == "number") { + fromIndex = fromIndex < 0 ? nativeMax(length + fromIndex, 0) : fromIndex; + } else if (fromIndex) { + var index = binaryIndex(array, value); + if (index < length && (value === value ? value === array[index] : array[index] !== array[index])) { + return index; + } + return -1; + } + return baseIndexOf(array, value, fromIndex || 0); + } + function initial(array) { + return dropRight(array, 1); + } + var intersection = restParam(function(arrays) { + var othLength = arrays.length, othIndex = othLength, caches = Array(length), indexOf = getIndexOf(), isCommon = indexOf === baseIndexOf, result = []; + while (othIndex--) { + var value = arrays[othIndex] = isArrayLike(value = arrays[othIndex]) ? value : []; + caches[othIndex] = isCommon && value.length >= 120 ? createCache(othIndex && value) : null; + } + var array = arrays[0], index = -1, length = array ? array.length : 0, seen = caches[0]; + outer: while (++index < length) { + value = array[index]; + if ((seen ? cacheIndexOf(seen, value) : indexOf(result, value, 0)) < 0) { + var othIndex = othLength; + while (--othIndex) { + var cache = caches[othIndex]; + if ((cache ? cacheIndexOf(cache, value) : indexOf(arrays[othIndex], value, 0)) < 0) { + continue outer; + } + } + if (seen) { + seen.push(value); + } + result.push(value); + } + } + return result; + }); + function last(array) { + var length = array ? array.length : 0; + return length ? array[length - 1] : undefined; + } + function lastIndexOf(array, value, fromIndex) { + var length = array ? array.length : 0; + if (!length) { + return -1; + } + var index = length; + if (typeof fromIndex == "number") { + index = (fromIndex < 0 ? nativeMax(length + fromIndex, 0) : nativeMin(fromIndex || 0, length - 1)) + 1; + } else if (fromIndex) { + index = binaryIndex(array, value, true) - 1; + var other = array[index]; + if (value === value ? value === other : other !== other) { + return index; + } + return -1; + } + if (value !== value) { + return indexOfNaN(array, index, true); + } + while (index--) { + if (array[index] === value) { + return index; + } + } + return -1; + } + function pull() { + var args = arguments, array = args[0]; + if (!(array && array.length)) { + return array; + } + var index = 0, indexOf = getIndexOf(), length = args.length; + while (++index < length) { + var fromIndex = 0, value = args[index]; + while ((fromIndex = indexOf(array, value, fromIndex)) > -1) { + splice.call(array, fromIndex, 1); + } + } + return array; + } + var pullAt = restParam(function(array, indexes) { + indexes = baseFlatten(indexes); + var result = baseAt(array, indexes); + basePullAt(array, indexes.sort(baseCompareAscending)); + return result; + }); + function remove(array, predicate, thisArg) { + var result = []; + if (!(array && array.length)) { + return result; + } + var index = -1, indexes = [], length = array.length; + predicate = getCallback(predicate, thisArg, 3); + while (++index < length) { + var value = array[index]; + if (predicate(value, index, array)) { + result.push(value); + indexes.push(index); + } + } + basePullAt(array, indexes); + return result; + } + function rest(array) { + return drop(array, 1); + } + function slice(array, start, end) { + var length = array ? array.length : 0; + if (!length) { + return []; + } + if (end && typeof end != "number" && isIterateeCall(array, start, end)) { + start = 0; + end = length; + } + return baseSlice(array, start, end); + } + var sortedIndex = createSortedIndex(); + var sortedLastIndex = createSortedIndex(true); + function take(array, n, guard) { + var length = array ? array.length : 0; + if (!length) { + return []; + } + if (guard ? isIterateeCall(array, n, guard) : n == null) { + n = 1; + } + return baseSlice(array, 0, n < 0 ? 0 : n); + } + function takeRight(array, n, guard) { + var length = array ? array.length : 0; + if (!length) { + return []; + } + if (guard ? isIterateeCall(array, n, guard) : n == null) { + n = 1; + } + n = length - (+n || 0); + return baseSlice(array, n < 0 ? 0 : n); + } + function takeRightWhile(array, predicate, thisArg) { + return array && array.length ? baseWhile(array, getCallback(predicate, thisArg, 3), false, true) : []; + } + function takeWhile(array, predicate, thisArg) { + return array && array.length ? baseWhile(array, getCallback(predicate, thisArg, 3)) : []; + } + var union = restParam(function(arrays) { + return baseUniq(baseFlatten(arrays, false, true)); + }); + function uniq(array, isSorted, iteratee, thisArg) { + var length = array ? array.length : 0; + if (!length) { + return []; + } + if (isSorted != null && typeof isSorted != "boolean") { + thisArg = iteratee; + iteratee = isIterateeCall(array, isSorted, thisArg) ? undefined : isSorted; + isSorted = false; + } + var callback = getCallback(); + if (!(iteratee == null && callback === baseCallback)) { + iteratee = callback(iteratee, thisArg, 3); + } + return isSorted && getIndexOf() === baseIndexOf ? sortedUniq(array, iteratee) : baseUniq(array, iteratee); + } + function unzip(array) { + if (!(array && array.length)) { + return []; + } + var index = -1, length = 0; + array = arrayFilter(array, function(group) { + if (isArrayLike(group)) { + length = nativeMax(group.length, length); + return true; + } + }); + var result = Array(length); + while (++index < length) { + result[index] = arrayMap(array, baseProperty(index)); + } + return result; + } + function unzipWith(array, iteratee, thisArg) { + var length = array ? array.length : 0; + if (!length) { + return []; + } + var result = unzip(array); + if (iteratee == null) { + return result; + } + iteratee = bindCallback(iteratee, thisArg, 4); + return arrayMap(result, function(group) { + return arrayReduce(group, iteratee, undefined, true); + }); + } + var without = restParam(function(array, values) { + return isArrayLike(array) ? baseDifference(array, values) : []; + }); + function xor() { + var index = -1, length = arguments.length; + while (++index < length) { + var array = arguments[index]; + if (isArrayLike(array)) { + var result = result ? arrayPush(baseDifference(result, array), baseDifference(array, result)) : array; + } + } + return result ? baseUniq(result) : []; + } + var zip = restParam(unzip); + function zipObject(props, values) { + var index = -1, length = props ? props.length : 0, result = {}; + if (length && !values && !isArray(props[0])) { + values = []; + } + while (++index < length) { + var key = props[index]; + if (values) { + result[key] = values[index]; + } else if (key) { + result[key[0]] = key[1]; + } + } + return result; + } + var zipWith = restParam(function(arrays) { + var length = arrays.length, iteratee = length > 2 ? arrays[length - 2] : undefined, thisArg = length > 1 ? arrays[length - 1] : undefined; + if (length > 2 && typeof iteratee == "function") { + length -= 2; + } else { + iteratee = length > 1 && typeof thisArg == "function" ? (--length, thisArg) : undefined; + thisArg = undefined; + } + arrays.length = length; + return unzipWith(arrays, iteratee, thisArg); + }); + function chain(value) { + var result = lodash(value); + result.__chain__ = true; + return result; + } + function tap(value, interceptor, thisArg) { + interceptor.call(thisArg, value); + return value; + } + function thru(value, interceptor, thisArg) { + return interceptor.call(thisArg, value); + } + function wrapperChain() { + return chain(this); + } + function wrapperCommit() { + return new LodashWrapper(this.value(), this.__chain__); + } + var wrapperConcat = restParam(function(values) { + values = baseFlatten(values); + return this.thru(function(array) { + return arrayConcat(isArray(array) ? array : [ toObject(array) ], values); + }); + }); + function wrapperPlant(value) { + var result, parent = this; + while (parent instanceof baseLodash) { + var clone = wrapperClone(parent); + if (result) { + previous.__wrapped__ = clone; + } else { + result = clone; + } + var previous = clone; + parent = parent.__wrapped__; + } + previous.__wrapped__ = value; + return result; + } + function wrapperReverse() { + var value = this.__wrapped__; + var interceptor = function(value) { + return value.reverse(); + }; + if (value instanceof LazyWrapper) { + var wrapped = value; + if (this.__actions__.length) { + wrapped = new LazyWrapper(this); + } + wrapped = wrapped.reverse(); + wrapped.__actions__.push({ + func: thru, + args: [ interceptor ], + thisArg: undefined + }); + return new LodashWrapper(wrapped, this.__chain__); + } + return this.thru(interceptor); + } + function wrapperToString() { + return this.value() + ""; + } + function wrapperValue() { + return baseWrapperValue(this.__wrapped__, this.__actions__); + } + var at = restParam(function(collection, props) { + return baseAt(collection, baseFlatten(props)); + }); + var countBy = createAggregator(function(result, value, key) { + hasOwnProperty.call(result, key) ? ++result[key] : result[key] = 1; + }); + function every(collection, predicate, thisArg) { + var func = isArray(collection) ? arrayEvery : baseEvery; + if (thisArg && isIterateeCall(collection, predicate, thisArg)) { + predicate = undefined; + } + if (typeof predicate != "function" || thisArg !== undefined) { + predicate = getCallback(predicate, thisArg, 3); + } + return func(collection, predicate); + } + function filter(collection, predicate, thisArg) { + var func = isArray(collection) ? arrayFilter : baseFilter; + predicate = getCallback(predicate, thisArg, 3); + return func(collection, predicate); + } + var find = createFind(baseEach); + var findLast = createFind(baseEachRight, true); + function findWhere(collection, source) { + return find(collection, baseMatches(source)); + } + var forEach = createForEach(arrayEach, baseEach); + var forEachRight = createForEach(arrayEachRight, baseEachRight); + var groupBy = createAggregator(function(result, value, key) { + if (hasOwnProperty.call(result, key)) { + result[key].push(value); + } else { + result[key] = [ value ]; + } + }); + function includes(collection, target, fromIndex, guard) { + var length = collection ? getLength(collection) : 0; + if (!isLength(length)) { + collection = values(collection); + length = collection.length; + } + if (typeof fromIndex != "number" || guard && isIterateeCall(target, fromIndex, guard)) { + fromIndex = 0; + } else { + fromIndex = fromIndex < 0 ? nativeMax(length + fromIndex, 0) : fromIndex || 0; + } + return typeof collection == "string" || !isArray(collection) && isString(collection) ? fromIndex <= length && collection.indexOf(target, fromIndex) > -1 : !!length && getIndexOf(collection, target, fromIndex) > -1; + } + var indexBy = createAggregator(function(result, value, key) { + result[key] = value; + }); + var invoke = restParam(function(collection, path, args) { + var index = -1, isFunc = typeof path == "function", isProp = isKey(path), result = isArrayLike(collection) ? Array(collection.length) : []; + baseEach(collection, function(value) { + var func = isFunc ? path : isProp && value != null ? value[path] : undefined; + result[++index] = func ? func.apply(value, args) : invokePath(value, path, args); + }); + return result; + }); + function map(collection, iteratee, thisArg) { + var func = isArray(collection) ? arrayMap : baseMap; + iteratee = getCallback(iteratee, thisArg, 3); + return func(collection, iteratee); + } + var partition = createAggregator(function(result, value, key) { + result[key ? 0 : 1].push(value); + }, function() { + return [ [], [] ]; + }); + function pluck(collection, path) { + return map(collection, property(path)); + } + var reduce = createReduce(arrayReduce, baseEach); + var reduceRight = createReduce(arrayReduceRight, baseEachRight); + function reject(collection, predicate, thisArg) { + var func = isArray(collection) ? arrayFilter : baseFilter; + predicate = getCallback(predicate, thisArg, 3); + return func(collection, function(value, index, collection) { + return !predicate(value, index, collection); + }); + } + function sample(collection, n, guard) { + if (guard ? isIterateeCall(collection, n, guard) : n == null) { + collection = toIterable(collection); + var length = collection.length; + return length > 0 ? collection[baseRandom(0, length - 1)] : undefined; + } + var index = -1, result = toArray(collection), length = result.length, lastIndex = length - 1; + n = nativeMin(n < 0 ? 0 : +n || 0, length); + while (++index < n) { + var rand = baseRandom(index, lastIndex), value = result[rand]; + result[rand] = result[index]; + result[index] = value; + } + result.length = n; + return result; + } + function shuffle(collection) { + return sample(collection, POSITIVE_INFINITY); + } + function size(collection) { + var length = collection ? getLength(collection) : 0; + return isLength(length) ? length : keys(collection).length; + } + function some(collection, predicate, thisArg) { + var func = isArray(collection) ? arraySome : baseSome; + if (thisArg && isIterateeCall(collection, predicate, thisArg)) { + predicate = undefined; + } + if (typeof predicate != "function" || thisArg !== undefined) { + predicate = getCallback(predicate, thisArg, 3); + } + return func(collection, predicate); + } + function sortBy(collection, iteratee, thisArg) { + if (collection == null) { + return []; + } + if (thisArg && isIterateeCall(collection, iteratee, thisArg)) { + iteratee = undefined; + } + var index = -1; + iteratee = getCallback(iteratee, thisArg, 3); + var result = baseMap(collection, function(value, key, collection) { + return { + criteria: iteratee(value, key, collection), + index: ++index, + value: value + }; + }); + return baseSortBy(result, compareAscending); + } + var sortByAll = restParam(function(collection, iteratees) { + if (collection == null) { + return []; + } + var guard = iteratees[2]; + if (guard && isIterateeCall(iteratees[0], iteratees[1], guard)) { + iteratees.length = 1; + } + return baseSortByOrder(collection, baseFlatten(iteratees), []); + }); + function sortByOrder(collection, iteratees, orders, guard) { + if (collection == null) { + return []; + } + if (guard && isIterateeCall(iteratees, orders, guard)) { + orders = undefined; + } + if (!isArray(iteratees)) { + iteratees = iteratees == null ? [] : [ iteratees ]; + } + if (!isArray(orders)) { + orders = orders == null ? [] : [ orders ]; + } + return baseSortByOrder(collection, iteratees, orders); + } + function where(collection, source) { + return filter(collection, baseMatches(source)); + } + var now = nativeNow || function() { + return new Date().getTime(); + }; + function after(n, func) { + if (typeof func != "function") { + if (typeof n == "function") { + var temp = n; + n = func; + func = temp; + } else { + throw new TypeError(FUNC_ERROR_TEXT); + } + } + n = nativeIsFinite(n = +n) ? n : 0; + return function() { + if (--n < 1) { + return func.apply(this, arguments); + } + }; + } + function ary(func, n, guard) { + if (guard && isIterateeCall(func, n, guard)) { + n = undefined; + } + n = func && n == null ? func.length : nativeMax(+n || 0, 0); + return createWrapper(func, ARY_FLAG, undefined, undefined, undefined, undefined, n); + } + function before(n, func) { + var result; + if (typeof func != "function") { + if (typeof n == "function") { + var temp = n; + n = func; + func = temp; + } else { + throw new TypeError(FUNC_ERROR_TEXT); + } + } + return function() { + if (--n > 0) { + result = func.apply(this, arguments); + } + if (n <= 1) { + func = undefined; + } + return result; + }; + } + var bind = restParam(function(func, thisArg, partials) { + var bitmask = BIND_FLAG; + if (partials.length) { + var holders = replaceHolders(partials, bind.placeholder); + bitmask |= PARTIAL_FLAG; + } + return createWrapper(func, bitmask, thisArg, partials, holders); + }); + var bindAll = restParam(function(object, methodNames) { + methodNames = methodNames.length ? baseFlatten(methodNames) : functions(object); + var index = -1, length = methodNames.length; + while (++index < length) { + var key = methodNames[index]; + object[key] = createWrapper(object[key], BIND_FLAG, object); + } + return object; + }); + var bindKey = restParam(function(object, key, partials) { + var bitmask = BIND_FLAG | BIND_KEY_FLAG; + if (partials.length) { + var holders = replaceHolders(partials, bindKey.placeholder); + bitmask |= PARTIAL_FLAG; + } + return createWrapper(key, bitmask, object, partials, holders); + }); + var curry = createCurry(CURRY_FLAG); + var curryRight = createCurry(CURRY_RIGHT_FLAG); + function debounce(func, wait, options) { + var args, maxTimeoutId, result, stamp, thisArg, timeoutId, trailingCall, lastCalled = 0, maxWait = false, trailing = true; + if (typeof func != "function") { + throw new TypeError(FUNC_ERROR_TEXT); + } + wait = wait < 0 ? 0 : +wait || 0; + if (options === true) { + var leading = true; + trailing = false; + } else if (isObject(options)) { + leading = !!options.leading; + maxWait = "maxWait" in options && nativeMax(+options.maxWait || 0, wait); + trailing = "trailing" in options ? !!options.trailing : trailing; + } + function cancel() { + if (timeoutId) { + clearTimeout(timeoutId); + } + if (maxTimeoutId) { + clearTimeout(maxTimeoutId); + } + lastCalled = 0; + maxTimeoutId = timeoutId = trailingCall = undefined; + } + function complete(isCalled, id) { + if (id) { + clearTimeout(id); + } + maxTimeoutId = timeoutId = trailingCall = undefined; + if (isCalled) { + lastCalled = now(); + result = func.apply(thisArg, args); + if (!timeoutId && !maxTimeoutId) { + args = thisArg = undefined; + } + } + } + function delayed() { + var remaining = wait - (now() - stamp); + if (remaining <= 0 || remaining > wait) { + complete(trailingCall, maxTimeoutId); + } else { + timeoutId = setTimeout(delayed, remaining); + } + } + function maxDelayed() { + complete(trailing, timeoutId); + } + function debounced() { + args = arguments; + stamp = now(); + thisArg = this; + trailingCall = trailing && (timeoutId || !leading); + if (maxWait === false) { + var leadingCall = leading && !timeoutId; + } else { + if (!maxTimeoutId && !leading) { + lastCalled = stamp; + } + var remaining = maxWait - (stamp - lastCalled), isCalled = remaining <= 0 || remaining > maxWait; + if (isCalled) { + if (maxTimeoutId) { + maxTimeoutId = clearTimeout(maxTimeoutId); + } + lastCalled = stamp; + result = func.apply(thisArg, args); + } else if (!maxTimeoutId) { + maxTimeoutId = setTimeout(maxDelayed, remaining); + } + } + if (isCalled && timeoutId) { + timeoutId = clearTimeout(timeoutId); + } else if (!timeoutId && wait !== maxWait) { + timeoutId = setTimeout(delayed, wait); + } + if (leadingCall) { + isCalled = true; + result = func.apply(thisArg, args); + } + if (isCalled && !timeoutId && !maxTimeoutId) { + args = thisArg = undefined; + } + return result; + } + debounced.cancel = cancel; + return debounced; + } + var defer = restParam(function(func, args) { + return baseDelay(func, 1, args); + }); + var delay = restParam(function(func, wait, args) { + return baseDelay(func, wait, args); + }); + var flow = createFlow(); + var flowRight = createFlow(true); + function memoize(func, resolver) { + if (typeof func != "function" || resolver && typeof resolver != "function") { + throw new TypeError(FUNC_ERROR_TEXT); + } + var memoized = function() { + var args = arguments, key = resolver ? resolver.apply(this, args) : args[0], cache = memoized.cache; + if (cache.has(key)) { + return cache.get(key); + } + var result = func.apply(this, args); + memoized.cache = cache.set(key, result); + return result; + }; + memoized.cache = new memoize.Cache(); + return memoized; + } + var modArgs = restParam(function(func, transforms) { + transforms = baseFlatten(transforms); + if (typeof func != "function" || !arrayEvery(transforms, baseIsFunction)) { + throw new TypeError(FUNC_ERROR_TEXT); + } + var length = transforms.length; + return restParam(function(args) { + var index = nativeMin(args.length, length); + while (index--) { + args[index] = transforms[index](args[index]); + } + return func.apply(this, args); + }); + }); + function negate(predicate) { + if (typeof predicate != "function") { + throw new TypeError(FUNC_ERROR_TEXT); + } + return function() { + return !predicate.apply(this, arguments); + }; + } + function once(func) { + return before(2, func); + } + var partial = createPartial(PARTIAL_FLAG); + var partialRight = createPartial(PARTIAL_RIGHT_FLAG); + var rearg = restParam(function(func, indexes) { + return createWrapper(func, REARG_FLAG, undefined, undefined, undefined, baseFlatten(indexes)); + }); + function restParam(func, start) { + if (typeof func != "function") { + throw new TypeError(FUNC_ERROR_TEXT); + } + start = nativeMax(start === undefined ? func.length - 1 : +start || 0, 0); + return function() { + var args = arguments, index = -1, length = nativeMax(args.length - start, 0), rest = Array(length); + while (++index < length) { + rest[index] = args[start + index]; + } + switch (start) { + case 0: + return func.call(this, rest); + + case 1: + return func.call(this, args[0], rest); + + case 2: + return func.call(this, args[0], args[1], rest); + } + var otherArgs = Array(start + 1); + index = -1; + while (++index < start) { + otherArgs[index] = args[index]; + } + otherArgs[start] = rest; + return func.apply(this, otherArgs); + }; + } + function spread(func) { + if (typeof func != "function") { + throw new TypeError(FUNC_ERROR_TEXT); + } + return function(array) { + return func.apply(this, array); + }; + } + function throttle(func, wait, options) { + var leading = true, trailing = true; + if (typeof func != "function") { + throw new TypeError(FUNC_ERROR_TEXT); + } + if (options === false) { + leading = false; + } else if (isObject(options)) { + leading = "leading" in options ? !!options.leading : leading; + trailing = "trailing" in options ? !!options.trailing : trailing; + } + return debounce(func, wait, { + leading: leading, + maxWait: +wait, + trailing: trailing + }); + } + function wrap(value, wrapper) { + wrapper = wrapper == null ? identity : wrapper; + return createWrapper(wrapper, PARTIAL_FLAG, undefined, [ value ], []); + } + function clone(value, isDeep, customizer, thisArg) { + if (isDeep && typeof isDeep != "boolean" && isIterateeCall(value, isDeep, customizer)) { + isDeep = false; + } else if (typeof isDeep == "function") { + thisArg = customizer; + customizer = isDeep; + isDeep = false; + } + return typeof customizer == "function" ? baseClone(value, isDeep, bindCallback(customizer, thisArg, 3)) : baseClone(value, isDeep); + } + function cloneDeep(value, customizer, thisArg) { + return typeof customizer == "function" ? baseClone(value, true, bindCallback(customizer, thisArg, 3)) : baseClone(value, true); + } + function gt(value, other) { + return value > other; + } + function gte(value, other) { + return value >= other; + } + function isArguments(value) { + return isObjectLike(value) && isArrayLike(value) && hasOwnProperty.call(value, "callee") && !propertyIsEnumerable.call(value, "callee"); + } + var isArray = nativeIsArray || function(value) { + return isObjectLike(value) && isLength(value.length) && objToString.call(value) == arrayTag; + }; + function isBoolean(value) { + return value === true || value === false || isObjectLike(value) && objToString.call(value) == boolTag; + } + function isDate(value) { + return isObjectLike(value) && objToString.call(value) == dateTag; + } + function isElement(value) { + return !!value && value.nodeType === 1 && isObjectLike(value) && !isPlainObject(value); + } + function isEmpty(value) { + if (value == null) { + return true; + } + if (isArrayLike(value) && (isArray(value) || isString(value) || isArguments(value) || isObjectLike(value) && isFunction(value.splice))) { + return !value.length; + } + return !keys(value).length; + } + function isEqual(value, other, customizer, thisArg) { + customizer = typeof customizer == "function" ? bindCallback(customizer, thisArg, 3) : undefined; + var result = customizer ? customizer(value, other) : undefined; + return result === undefined ? baseIsEqual(value, other, customizer) : !!result; + } + function isError(value) { + return isObjectLike(value) && typeof value.message == "string" && objToString.call(value) == errorTag; + } + function isFinite(value) { + return typeof value == "number" && nativeIsFinite(value); + } + function isFunction(value) { + return isObject(value) && objToString.call(value) == funcTag; + } + function isObject(value) { + var type = typeof value; + return !!value && (type == "object" || type == "function"); + } + function isMatch(object, source, customizer, thisArg) { + customizer = typeof customizer == "function" ? bindCallback(customizer, thisArg, 3) : undefined; + return baseIsMatch(object, getMatchData(source), customizer); + } + function isNaN(value) { + return isNumber(value) && value != +value; + } + function isNative(value) { + if (value == null) { + return false; + } + if (isFunction(value)) { + return reIsNative.test(fnToString.call(value)); + } + return isObjectLike(value) && reIsHostCtor.test(value); + } + function isNull(value) { + return value === null; + } + function isNumber(value) { + return typeof value == "number" || isObjectLike(value) && objToString.call(value) == numberTag; + } + function isPlainObject(value) { + var Ctor; + if (!(isObjectLike(value) && objToString.call(value) == objectTag && !isArguments(value)) || !hasOwnProperty.call(value, "constructor") && (Ctor = value.constructor, + typeof Ctor == "function" && !(Ctor instanceof Ctor))) { + return false; + } + var result; + baseForIn(value, function(subValue, key) { + result = key; + }); + return result === undefined || hasOwnProperty.call(value, result); + } + function isRegExp(value) { + return isObject(value) && objToString.call(value) == regexpTag; + } + function isString(value) { + return typeof value == "string" || isObjectLike(value) && objToString.call(value) == stringTag; + } + function isTypedArray(value) { + return isObjectLike(value) && isLength(value.length) && !!typedArrayTags[objToString.call(value)]; + } + function isUndefined(value) { + return value === undefined; + } + function lt(value, other) { + return value < other; + } + function lte(value, other) { + return value <= other; + } + function toArray(value) { + var length = value ? getLength(value) : 0; + if (!isLength(length)) { + return values(value); + } + if (!length) { + return []; + } + return arrayCopy(value); + } + function toPlainObject(value) { + return baseCopy(value, keysIn(value)); + } + var merge = createAssigner(baseMerge); + var assign = createAssigner(function(object, source, customizer) { + return customizer ? assignWith(object, source, customizer) : baseAssign(object, source); + }); + function create(prototype, properties, guard) { + var result = baseCreate(prototype); + if (guard && isIterateeCall(prototype, properties, guard)) { + properties = undefined; + } + return properties ? baseAssign(result, properties) : result; + } + var defaults = createDefaults(assign, assignDefaults); + var defaultsDeep = createDefaults(merge, mergeDefaults); + var findKey = createFindKey(baseForOwn); + var findLastKey = createFindKey(baseForOwnRight); + var forIn = createForIn(baseFor); + var forInRight = createForIn(baseForRight); + var forOwn = createForOwn(baseForOwn); + var forOwnRight = createForOwn(baseForOwnRight); + function functions(object) { + return baseFunctions(object, keysIn(object)); + } + function get(object, path, defaultValue) { + var result = object == null ? undefined : baseGet(object, toPath(path), path + ""); + return result === undefined ? defaultValue : result; + } + function has(object, path) { + if (object == null) { + return false; + } + var result = hasOwnProperty.call(object, path); + if (!result && !isKey(path)) { + path = toPath(path); + object = path.length == 1 ? object : baseGet(object, baseSlice(path, 0, -1)); + if (object == null) { + return false; + } + path = last(path); + result = hasOwnProperty.call(object, path); + } + return result || isLength(object.length) && isIndex(path, object.length) && (isArray(object) || isArguments(object)); + } + function invert(object, multiValue, guard) { + if (guard && isIterateeCall(object, multiValue, guard)) { + multiValue = undefined; + } + var index = -1, props = keys(object), length = props.length, result = {}; + while (++index < length) { + var key = props[index], value = object[key]; + if (multiValue) { + if (hasOwnProperty.call(result, value)) { + result[value].push(key); + } else { + result[value] = [ key ]; + } + } else { + result[value] = key; + } + } + return result; + } + var keys = !nativeKeys ? shimKeys : function(object) { + var Ctor = object == null ? undefined : object.constructor; + if (typeof Ctor == "function" && Ctor.prototype === object || typeof object != "function" && isArrayLike(object)) { + return shimKeys(object); + } + return isObject(object) ? nativeKeys(object) : []; + }; + function keysIn(object) { + if (object == null) { + return []; + } + if (!isObject(object)) { + object = Object(object); + } + var length = object.length; + length = length && isLength(length) && (isArray(object) || isArguments(object)) && length || 0; + var Ctor = object.constructor, index = -1, isProto = typeof Ctor == "function" && Ctor.prototype === object, result = Array(length), skipIndexes = length > 0; + while (++index < length) { + result[index] = index + ""; + } + for (var key in object) { + if (!(skipIndexes && isIndex(key, length)) && !(key == "constructor" && (isProto || !hasOwnProperty.call(object, key)))) { + result.push(key); + } + } + return result; + } + var mapKeys = createObjectMapper(true); + var mapValues = createObjectMapper(); + var omit = restParam(function(object, props) { + if (object == null) { + return {}; + } + if (typeof props[0] != "function") { + var props = arrayMap(baseFlatten(props), String); + return pickByArray(object, baseDifference(keysIn(object), props)); + } + var predicate = bindCallback(props[0], props[1], 3); + return pickByCallback(object, function(value, key, object) { + return !predicate(value, key, object); + }); + }); + function pairs(object) { + object = toObject(object); + var index = -1, props = keys(object), length = props.length, result = Array(length); + while (++index < length) { + var key = props[index]; + result[index] = [ key, object[key] ]; + } + return result; + } + var pick = restParam(function(object, props) { + if (object == null) { + return {}; + } + return typeof props[0] == "function" ? pickByCallback(object, bindCallback(props[0], props[1], 3)) : pickByArray(object, baseFlatten(props)); + }); + function result(object, path, defaultValue) { + var result = object == null ? undefined : object[path]; + if (result === undefined) { + if (object != null && !isKey(path, object)) { + path = toPath(path); + object = path.length == 1 ? object : baseGet(object, baseSlice(path, 0, -1)); + result = object == null ? undefined : object[last(path)]; + } + result = result === undefined ? defaultValue : result; + } + return isFunction(result) ? result.call(object) : result; + } + function set(object, path, value) { + if (object == null) { + return object; + } + var pathKey = path + ""; + path = object[pathKey] != null || isKey(path, object) ? [ pathKey ] : toPath(path); + var index = -1, length = path.length, lastIndex = length - 1, nested = object; + while (nested != null && ++index < length) { + var key = path[index]; + if (isObject(nested)) { + if (index == lastIndex) { + nested[key] = value; + } else if (nested[key] == null) { + nested[key] = isIndex(path[index + 1]) ? [] : {}; + } + } + nested = nested[key]; + } + return object; + } + function transform(object, iteratee, accumulator, thisArg) { + var isArr = isArray(object) || isTypedArray(object); + iteratee = getCallback(iteratee, thisArg, 4); + if (accumulator == null) { + if (isArr || isObject(object)) { + var Ctor = object.constructor; + if (isArr) { + accumulator = isArray(object) ? new Ctor() : []; + } else { + accumulator = baseCreate(isFunction(Ctor) ? Ctor.prototype : undefined); + } + } else { + accumulator = {}; + } + } + (isArr ? arrayEach : baseForOwn)(object, function(value, index, object) { + return iteratee(accumulator, value, index, object); + }); + return accumulator; + } + function values(object) { + return baseValues(object, keys(object)); + } + function valuesIn(object) { + return baseValues(object, keysIn(object)); + } + function inRange(value, start, end) { + start = +start || 0; + if (end === undefined) { + end = start; + start = 0; + } else { + end = +end || 0; + } + return value >= nativeMin(start, end) && value < nativeMax(start, end); + } + function random(min, max, floating) { + if (floating && isIterateeCall(min, max, floating)) { + max = floating = undefined; + } + var noMin = min == null, noMax = max == null; + if (floating == null) { + if (noMax && typeof min == "boolean") { + floating = min; + min = 1; + } else if (typeof max == "boolean") { + floating = max; + noMax = true; + } + } + if (noMin && noMax) { + max = 1; + noMax = false; + } + min = +min || 0; + if (noMax) { + max = min; + min = 0; + } else { + max = +max || 0; + } + if (floating || min % 1 || max % 1) { + var rand = nativeRandom(); + return nativeMin(min + rand * (max - min + parseFloat("1e-" + ((rand + "").length - 1))), max); + } + return baseRandom(min, max); + } + var camelCase = createCompounder(function(result, word, index) { + word = word.toLowerCase(); + return result + (index ? word.charAt(0).toUpperCase() + word.slice(1) : word); + }); + function capitalize(string) { + string = baseToString(string); + return string && string.charAt(0).toUpperCase() + string.slice(1); + } + function deburr(string) { + string = baseToString(string); + return string && string.replace(reLatin1, deburrLetter).replace(reComboMark, ""); + } + function endsWith(string, target, position) { + string = baseToString(string); + target = target + ""; + var length = string.length; + position = position === undefined ? length : nativeMin(position < 0 ? 0 : +position || 0, length); + position -= target.length; + return position >= 0 && string.indexOf(target, position) == position; + } + function escape(string) { + string = baseToString(string); + return string && reHasUnescapedHtml.test(string) ? string.replace(reUnescapedHtml, escapeHtmlChar) : string; + } + function escapeRegExp(string) { + string = baseToString(string); + return string && reHasRegExpChars.test(string) ? string.replace(reRegExpChars, escapeRegExpChar) : string || "(?:)"; + } + var kebabCase = createCompounder(function(result, word, index) { + return result + (index ? "-" : "") + word.toLowerCase(); + }); + function pad(string, length, chars) { + string = baseToString(string); + length = +length; + var strLength = string.length; + if (strLength >= length || !nativeIsFinite(length)) { + return string; + } + var mid = (length - strLength) / 2, leftLength = nativeFloor(mid), rightLength = nativeCeil(mid); + chars = createPadding("", rightLength, chars); + return chars.slice(0, leftLength) + string + chars; + } + var padLeft = createPadDir(); + var padRight = createPadDir(true); + function parseInt(string, radix, guard) { + if (guard ? isIterateeCall(string, radix, guard) : radix == null) { + radix = 0; + } else if (radix) { + radix = +radix; + } + string = trim(string); + return nativeParseInt(string, radix || (reHasHexPrefix.test(string) ? 16 : 10)); + } + function repeat(string, n) { + var result = ""; + string = baseToString(string); + n = +n; + if (n < 1 || !string || !nativeIsFinite(n)) { + return result; + } + do { + if (n % 2) { + result += string; + } + n = nativeFloor(n / 2); + string += string; + } while (n); + return result; + } + var snakeCase = createCompounder(function(result, word, index) { + return result + (index ? "_" : "") + word.toLowerCase(); + }); + var startCase = createCompounder(function(result, word, index) { + return result + (index ? " " : "") + (word.charAt(0).toUpperCase() + word.slice(1)); + }); + function startsWith(string, target, position) { + string = baseToString(string); + position = position == null ? 0 : nativeMin(position < 0 ? 0 : +position || 0, string.length); + return string.lastIndexOf(target, position) == position; + } + function template(string, options, otherOptions) { + var settings = lodash.templateSettings; + if (otherOptions && isIterateeCall(string, options, otherOptions)) { + options = otherOptions = undefined; + } + string = baseToString(string); + options = assignWith(baseAssign({}, otherOptions || options), settings, assignOwnDefaults); + var imports = assignWith(baseAssign({}, options.imports), settings.imports, assignOwnDefaults), importsKeys = keys(imports), importsValues = baseValues(imports, importsKeys); + var isEscaping, isEvaluating, index = 0, interpolate = options.interpolate || reNoMatch, source = "__p += '"; + var reDelimiters = RegExp((options.escape || reNoMatch).source + "|" + interpolate.source + "|" + (interpolate === reInterpolate ? reEsTemplate : reNoMatch).source + "|" + (options.evaluate || reNoMatch).source + "|$", "g"); + var sourceURL = "//# sourceURL=" + ("sourceURL" in options ? options.sourceURL : "lodash.templateSources[" + ++templateCounter + "]") + "\n"; + string.replace(reDelimiters, function(match, escapeValue, interpolateValue, esTemplateValue, evaluateValue, offset) { + interpolateValue || (interpolateValue = esTemplateValue); + source += string.slice(index, offset).replace(reUnescapedString, escapeStringChar); + if (escapeValue) { + isEscaping = true; + source += "' +\n__e(" + escapeValue + ") +\n'"; + } + if (evaluateValue) { + isEvaluating = true; + source += "';\n" + evaluateValue + ";\n__p += '"; + } + if (interpolateValue) { + source += "' +\n((__t = (" + interpolateValue + ")) == null ? '' : __t) +\n'"; + } + index = offset + match.length; + return match; + }); + source += "';\n"; + var variable = options.variable; + if (!variable) { + source = "with (obj) {\n" + source + "\n}\n"; + } + source = (isEvaluating ? source.replace(reEmptyStringLeading, "") : source).replace(reEmptyStringMiddle, "$1").replace(reEmptyStringTrailing, "$1;"); + source = "function(" + (variable || "obj") + ") {\n" + (variable ? "" : "obj || (obj = {});\n") + "var __t, __p = ''" + (isEscaping ? ", __e = _.escape" : "") + (isEvaluating ? ", __j = Array.prototype.join;\n" + "function print() { __p += __j.call(arguments, '') }\n" : ";\n") + source + "return __p\n}"; + var result = attempt(function() { + return Function(importsKeys, sourceURL + "return " + source).apply(undefined, importsValues); + }); + result.source = source; + if (isError(result)) { + throw result; + } + return result; + } + function trim(string, chars, guard) { + var value = string; + string = baseToString(string); + if (!string) { + return string; + } + if (guard ? isIterateeCall(value, chars, guard) : chars == null) { + return string.slice(trimmedLeftIndex(string), trimmedRightIndex(string) + 1); + } + chars = chars + ""; + return string.slice(charsLeftIndex(string, chars), charsRightIndex(string, chars) + 1); + } + function trimLeft(string, chars, guard) { + var value = string; + string = baseToString(string); + if (!string) { + return string; + } + if (guard ? isIterateeCall(value, chars, guard) : chars == null) { + return string.slice(trimmedLeftIndex(string)); + } + return string.slice(charsLeftIndex(string, chars + "")); + } + function trimRight(string, chars, guard) { + var value = string; + string = baseToString(string); + if (!string) { + return string; + } + if (guard ? isIterateeCall(value, chars, guard) : chars == null) { + return string.slice(0, trimmedRightIndex(string) + 1); + } + return string.slice(0, charsRightIndex(string, chars + "") + 1); + } + function trunc(string, options, guard) { + if (guard && isIterateeCall(string, options, guard)) { + options = undefined; + } + var length = DEFAULT_TRUNC_LENGTH, omission = DEFAULT_TRUNC_OMISSION; + if (options != null) { + if (isObject(options)) { + var separator = "separator" in options ? options.separator : separator; + length = "length" in options ? +options.length || 0 : length; + omission = "omission" in options ? baseToString(options.omission) : omission; + } else { + length = +options || 0; + } + } + string = baseToString(string); + if (length >= string.length) { + return string; + } + var end = length - omission.length; + if (end < 1) { + return omission; + } + var result = string.slice(0, end); + if (separator == null) { + return result + omission; + } + if (isRegExp(separator)) { + if (string.slice(end).search(separator)) { + var match, newEnd, substring = string.slice(0, end); + if (!separator.global) { + separator = RegExp(separator.source, (reFlags.exec(separator) || "") + "g"); + } + separator.lastIndex = 0; + while (match = separator.exec(substring)) { + newEnd = match.index; + } + result = result.slice(0, newEnd == null ? end : newEnd); + } + } else if (string.indexOf(separator, end) != end) { + var index = result.lastIndexOf(separator); + if (index > -1) { + result = result.slice(0, index); + } + } + return result + omission; + } + function unescape(string) { + string = baseToString(string); + return string && reHasEscapedHtml.test(string) ? string.replace(reEscapedHtml, unescapeHtmlChar) : string; + } + function words(string, pattern, guard) { + if (guard && isIterateeCall(string, pattern, guard)) { + pattern = undefined; + } + string = baseToString(string); + return string.match(pattern || reWords) || []; + } + var attempt = restParam(function(func, args) { + try { + return func.apply(undefined, args); + } catch (e) { + return isError(e) ? e : new Error(e); + } + }); + function callback(func, thisArg, guard) { + if (guard && isIterateeCall(func, thisArg, guard)) { + thisArg = undefined; + } + return isObjectLike(func) ? matches(func) : baseCallback(func, thisArg); + } + function constant(value) { + return function() { + return value; + }; + } + function identity(value) { + return value; + } + function matches(source) { + return baseMatches(baseClone(source, true)); + } + function matchesProperty(path, srcValue) { + return baseMatchesProperty(path, baseClone(srcValue, true)); + } + var method = restParam(function(path, args) { + return function(object) { + return invokePath(object, path, args); + }; + }); + var methodOf = restParam(function(object, args) { + return function(path) { + return invokePath(object, path, args); + }; + }); + function mixin(object, source, options) { + if (options == null) { + var isObj = isObject(source), props = isObj ? keys(source) : undefined, methodNames = props && props.length ? baseFunctions(source, props) : undefined; + if (!(methodNames ? methodNames.length : isObj)) { + methodNames = false; + options = source; + source = object; + object = this; + } + } + if (!methodNames) { + methodNames = baseFunctions(source, keys(source)); + } + var chain = true, index = -1, isFunc = isFunction(object), length = methodNames.length; + if (options === false) { + chain = false; + } else if (isObject(options) && "chain" in options) { + chain = options.chain; + } + while (++index < length) { + var methodName = methodNames[index], func = source[methodName]; + object[methodName] = func; + if (isFunc) { + object.prototype[methodName] = function(func) { + return function() { + var chainAll = this.__chain__; + if (chain || chainAll) { + var result = object(this.__wrapped__), actions = result.__actions__ = arrayCopy(this.__actions__); + actions.push({ + func: func, + args: arguments, + thisArg: object + }); + result.__chain__ = chainAll; + return result; + } + return func.apply(object, arrayPush([ this.value() ], arguments)); + }; + }(func); + } + } + return object; + } + function noConflict() { + root._ = oldDash; + return this; + } + function noop() {} + function property(path) { + return isKey(path) ? baseProperty(path) : basePropertyDeep(path); + } + function propertyOf(object) { + return function(path) { + return baseGet(object, toPath(path), path + ""); + }; + } + function range(start, end, step) { + if (step && isIterateeCall(start, end, step)) { + end = step = undefined; + } + start = +start || 0; + step = step == null ? 1 : +step || 0; + if (end == null) { + end = start; + start = 0; + } else { + end = +end || 0; + } + var index = -1, length = nativeMax(nativeCeil((end - start) / (step || 1)), 0), result = Array(length); + while (++index < length) { + result[index] = start; + start += step; + } + return result; + } + function times(n, iteratee, thisArg) { + n = nativeFloor(n); + if (n < 1 || !nativeIsFinite(n)) { + return []; + } + var index = -1, result = Array(nativeMin(n, MAX_ARRAY_LENGTH)); + iteratee = bindCallback(iteratee, thisArg, 1); + while (++index < n) { + if (index < MAX_ARRAY_LENGTH) { + result[index] = iteratee(index); + } else { + iteratee(index); + } + } + return result; + } + function uniqueId(prefix) { + var id = ++idCounter; + return baseToString(prefix) + id; + } + function add(augend, addend) { + return (+augend || 0) + (+addend || 0); + } + var ceil = createRound("ceil"); + var floor = createRound("floor"); + var max = createExtremum(gt, NEGATIVE_INFINITY); + var min = createExtremum(lt, POSITIVE_INFINITY); + var round = createRound("round"); + function sum(collection, iteratee, thisArg) { + if (thisArg && isIterateeCall(collection, iteratee, thisArg)) { + iteratee = undefined; + } + iteratee = getCallback(iteratee, thisArg, 3); + return iteratee.length == 1 ? arraySum(isArray(collection) ? collection : toIterable(collection), iteratee) : baseSum(collection, iteratee); + } + lodash.prototype = baseLodash.prototype; + LodashWrapper.prototype = baseCreate(baseLodash.prototype); + LodashWrapper.prototype.constructor = LodashWrapper; + LazyWrapper.prototype = baseCreate(baseLodash.prototype); + LazyWrapper.prototype.constructor = LazyWrapper; + MapCache.prototype["delete"] = mapDelete; + MapCache.prototype.get = mapGet; + MapCache.prototype.has = mapHas; + MapCache.prototype.set = mapSet; + SetCache.prototype.push = cachePush; + memoize.Cache = MapCache; + lodash.after = after; + lodash.ary = ary; + lodash.assign = assign; + lodash.at = at; + lodash.before = before; + lodash.bind = bind; + lodash.bindAll = bindAll; + lodash.bindKey = bindKey; + lodash.callback = callback; + lodash.chain = chain; + lodash.chunk = chunk; + lodash.compact = compact; + lodash.constant = constant; + lodash.countBy = countBy; + lodash.create = create; + lodash.curry = curry; + lodash.curryRight = curryRight; + lodash.debounce = debounce; + lodash.defaults = defaults; + lodash.defaultsDeep = defaultsDeep; + lodash.defer = defer; + lodash.delay = delay; + lodash.difference = difference; + lodash.drop = drop; + lodash.dropRight = dropRight; + lodash.dropRightWhile = dropRightWhile; + lodash.dropWhile = dropWhile; + lodash.fill = fill; + lodash.filter = filter; + lodash.flatten = flatten; + lodash.flattenDeep = flattenDeep; + lodash.flow = flow; + lodash.flowRight = flowRight; + lodash.forEach = forEach; + lodash.forEachRight = forEachRight; + lodash.forIn = forIn; + lodash.forInRight = forInRight; + lodash.forOwn = forOwn; + lodash.forOwnRight = forOwnRight; + lodash.functions = functions; + lodash.groupBy = groupBy; + lodash.indexBy = indexBy; + lodash.initial = initial; + lodash.intersection = intersection; + lodash.invert = invert; + lodash.invoke = invoke; + lodash.keys = keys; + lodash.keysIn = keysIn; + lodash.map = map; + lodash.mapKeys = mapKeys; + lodash.mapValues = mapValues; + lodash.matches = matches; + lodash.matchesProperty = matchesProperty; + lodash.memoize = memoize; + lodash.merge = merge; + lodash.method = method; + lodash.methodOf = methodOf; + lodash.mixin = mixin; + lodash.modArgs = modArgs; + lodash.negate = negate; + lodash.omit = omit; + lodash.once = once; + lodash.pairs = pairs; + lodash.partial = partial; + lodash.partialRight = partialRight; + lodash.partition = partition; + lodash.pick = pick; + lodash.pluck = pluck; + lodash.property = property; + lodash.propertyOf = propertyOf; + lodash.pull = pull; + lodash.pullAt = pullAt; + lodash.range = range; + lodash.rearg = rearg; + lodash.reject = reject; + lodash.remove = remove; + lodash.rest = rest; + lodash.restParam = restParam; + lodash.set = set; + lodash.shuffle = shuffle; + lodash.slice = slice; + lodash.sortBy = sortBy; + lodash.sortByAll = sortByAll; + lodash.sortByOrder = sortByOrder; + lodash.spread = spread; + lodash.take = take; + lodash.takeRight = takeRight; + lodash.takeRightWhile = takeRightWhile; + lodash.takeWhile = takeWhile; + lodash.tap = tap; + lodash.throttle = throttle; + lodash.thru = thru; + lodash.times = times; + lodash.toArray = toArray; + lodash.toPlainObject = toPlainObject; + lodash.transform = transform; + lodash.union = union; + lodash.uniq = uniq; + lodash.unzip = unzip; + lodash.unzipWith = unzipWith; + lodash.values = values; + lodash.valuesIn = valuesIn; + lodash.where = where; + lodash.without = without; + lodash.wrap = wrap; + lodash.xor = xor; + lodash.zip = zip; + lodash.zipObject = zipObject; + lodash.zipWith = zipWith; + lodash.backflow = flowRight; + lodash.collect = map; + lodash.compose = flowRight; + lodash.each = forEach; + lodash.eachRight = forEachRight; + lodash.extend = assign; + lodash.iteratee = callback; + lodash.methods = functions; + lodash.object = zipObject; + lodash.select = filter; + lodash.tail = rest; + lodash.unique = uniq; + mixin(lodash, lodash); + lodash.add = add; + lodash.attempt = attempt; + lodash.camelCase = camelCase; + lodash.capitalize = capitalize; + lodash.ceil = ceil; + lodash.clone = clone; + lodash.cloneDeep = cloneDeep; + lodash.deburr = deburr; + lodash.endsWith = endsWith; + lodash.escape = escape; + lodash.escapeRegExp = escapeRegExp; + lodash.every = every; + lodash.find = find; + lodash.findIndex = findIndex; + lodash.findKey = findKey; + lodash.findLast = findLast; + lodash.findLastIndex = findLastIndex; + lodash.findLastKey = findLastKey; + lodash.findWhere = findWhere; + lodash.first = first; + lodash.floor = floor; + lodash.get = get; + lodash.gt = gt; + lodash.gte = gte; + lodash.has = has; + lodash.identity = identity; + lodash.includes = includes; + lodash.indexOf = indexOf; + lodash.inRange = inRange; + lodash.isArguments = isArguments; + lodash.isArray = isArray; + lodash.isBoolean = isBoolean; + lodash.isDate = isDate; + lodash.isElement = isElement; + lodash.isEmpty = isEmpty; + lodash.isEqual = isEqual; + lodash.isError = isError; + lodash.isFinite = isFinite; + lodash.isFunction = isFunction; + lodash.isMatch = isMatch; + lodash.isNaN = isNaN; + lodash.isNative = isNative; + lodash.isNull = isNull; + lodash.isNumber = isNumber; + lodash.isObject = isObject; + lodash.isPlainObject = isPlainObject; + lodash.isRegExp = isRegExp; + lodash.isString = isString; + lodash.isTypedArray = isTypedArray; + lodash.isUndefined = isUndefined; + lodash.kebabCase = kebabCase; + lodash.last = last; + lodash.lastIndexOf = lastIndexOf; + lodash.lt = lt; + lodash.lte = lte; + lodash.max = max; + lodash.min = min; + lodash.noConflict = noConflict; + lodash.noop = noop; + lodash.now = now; + lodash.pad = pad; + lodash.padLeft = padLeft; + lodash.padRight = padRight; + lodash.parseInt = parseInt; + lodash.random = random; + lodash.reduce = reduce; + lodash.reduceRight = reduceRight; + lodash.repeat = repeat; + lodash.result = result; + lodash.round = round; + lodash.runInContext = runInContext; + lodash.size = size; + lodash.snakeCase = snakeCase; + lodash.some = some; + lodash.sortedIndex = sortedIndex; + lodash.sortedLastIndex = sortedLastIndex; + lodash.startCase = startCase; + lodash.startsWith = startsWith; + lodash.sum = sum; + lodash.template = template; + lodash.trim = trim; + lodash.trimLeft = trimLeft; + lodash.trimRight = trimRight; + lodash.trunc = trunc; + lodash.unescape = unescape; + lodash.uniqueId = uniqueId; + lodash.words = words; + lodash.all = every; + lodash.any = some; + lodash.contains = includes; + lodash.eq = isEqual; + lodash.detect = find; + lodash.foldl = reduce; + lodash.foldr = reduceRight; + lodash.head = first; + lodash.include = includes; + lodash.inject = reduce; + mixin(lodash, function() { + var source = {}; + baseForOwn(lodash, function(func, methodName) { + if (!lodash.prototype[methodName]) { + source[methodName] = func; + } + }); + return source; + }(), false); + lodash.sample = sample; + lodash.prototype.sample = function(n) { + if (!this.__chain__ && n == null) { + return sample(this.value()); + } + return this.thru(function(value) { + return sample(value, n); + }); + }; + lodash.VERSION = VERSION; + arrayEach([ "bind", "bindKey", "curry", "curryRight", "partial", "partialRight" ], function(methodName) { + lodash[methodName].placeholder = lodash; + }); + arrayEach([ "drop", "take" ], function(methodName, index) { + LazyWrapper.prototype[methodName] = function(n) { + var filtered = this.__filtered__; + if (filtered && !index) { + return new LazyWrapper(this); + } + n = n == null ? 1 : nativeMax(nativeFloor(n) || 0, 0); + var result = this.clone(); + if (filtered) { + result.__takeCount__ = nativeMin(result.__takeCount__, n); + } else { + result.__views__.push({ + size: n, + type: methodName + (result.__dir__ < 0 ? "Right" : "") + }); + } + return result; + }; + LazyWrapper.prototype[methodName + "Right"] = function(n) { + return this.reverse()[methodName](n).reverse(); + }; + }); + arrayEach([ "filter", "map", "takeWhile" ], function(methodName, index) { + var type = index + 1, isFilter = type != LAZY_MAP_FLAG; + LazyWrapper.prototype[methodName] = function(iteratee, thisArg) { + var result = this.clone(); + result.__iteratees__.push({ + iteratee: getCallback(iteratee, thisArg, 1), + type: type + }); + result.__filtered__ = result.__filtered__ || isFilter; + return result; + }; + }); + arrayEach([ "first", "last" ], function(methodName, index) { + var takeName = "take" + (index ? "Right" : ""); + LazyWrapper.prototype[methodName] = function() { + return this[takeName](1).value()[0]; + }; + }); + arrayEach([ "initial", "rest" ], function(methodName, index) { + var dropName = "drop" + (index ? "" : "Right"); + LazyWrapper.prototype[methodName] = function() { + return this.__filtered__ ? new LazyWrapper(this) : this[dropName](1); + }; + }); + arrayEach([ "pluck", "where" ], function(methodName, index) { + var operationName = index ? "filter" : "map", createCallback = index ? baseMatches : property; + LazyWrapper.prototype[methodName] = function(value) { + return this[operationName](createCallback(value)); + }; + }); + LazyWrapper.prototype.compact = function() { + return this.filter(identity); + }; + LazyWrapper.prototype.reject = function(predicate, thisArg) { + predicate = getCallback(predicate, thisArg, 1); + return this.filter(function(value) { + return !predicate(value); + }); + }; + LazyWrapper.prototype.slice = function(start, end) { + start = start == null ? 0 : +start || 0; + var result = this; + if (result.__filtered__ && (start > 0 || end < 0)) { + return new LazyWrapper(result); + } + if (start < 0) { + result = result.takeRight(-start); + } else if (start) { + result = result.drop(start); + } + if (end !== undefined) { + end = +end || 0; + result = end < 0 ? result.dropRight(-end) : result.take(end - start); + } + return result; + }; + LazyWrapper.prototype.takeRightWhile = function(predicate, thisArg) { + return this.reverse().takeWhile(predicate, thisArg).reverse(); + }; + LazyWrapper.prototype.toArray = function() { + return this.take(POSITIVE_INFINITY); + }; + baseForOwn(LazyWrapper.prototype, function(func, methodName) { + var checkIteratee = /^(?:filter|map|reject)|While$/.test(methodName), retUnwrapped = /^(?:first|last)$/.test(methodName), lodashFunc = lodash[retUnwrapped ? "take" + (methodName == "last" ? "Right" : "") : methodName]; + if (!lodashFunc) { + return; + } + lodash.prototype[methodName] = function() { + var args = retUnwrapped ? [ 1 ] : arguments, chainAll = this.__chain__, value = this.__wrapped__, isHybrid = !!this.__actions__.length, isLazy = value instanceof LazyWrapper, iteratee = args[0], useLazy = isLazy || isArray(value); + if (useLazy && checkIteratee && typeof iteratee == "function" && iteratee.length != 1) { + isLazy = useLazy = false; + } + var interceptor = function(value) { + return retUnwrapped && chainAll ? lodashFunc(value, 1)[0] : lodashFunc.apply(undefined, arrayPush([ value ], args)); + }; + var action = { + func: thru, + args: [ interceptor ], + thisArg: undefined + }, onlyLazy = isLazy && !isHybrid; + if (retUnwrapped && !chainAll) { + if (onlyLazy) { + value = value.clone(); + value.__actions__.push(action); + return func.call(value); + } + return lodashFunc.call(undefined, this.value())[0]; + } + if (!retUnwrapped && useLazy) { + value = onlyLazy ? value : new LazyWrapper(this); + var result = func.apply(value, args); + result.__actions__.push(action); + return new LodashWrapper(result, chainAll); + } + return this.thru(interceptor); + }; + }); + arrayEach([ "join", "pop", "push", "replace", "shift", "sort", "splice", "split", "unshift" ], function(methodName) { + var func = (/^(?:replace|split)$/.test(methodName) ? stringProto : arrayProto)[methodName], chainName = /^(?:push|sort|unshift)$/.test(methodName) ? "tap" : "thru", retUnwrapped = /^(?:join|pop|replace|shift)$/.test(methodName); + lodash.prototype[methodName] = function() { + var args = arguments; + if (retUnwrapped && !this.__chain__) { + return func.apply(this.value(), args); + } + return this[chainName](function(value) { + return func.apply(value, args); + }); + }; + }); + baseForOwn(LazyWrapper.prototype, function(func, methodName) { + var lodashFunc = lodash[methodName]; + if (lodashFunc) { + var key = lodashFunc.name + "", names = realNames[key] || (realNames[key] = []); + names.push({ + name: methodName, + func: lodashFunc + }); + } + }); + realNames[createHybridWrapper(undefined, BIND_KEY_FLAG).name] = [ { + name: "wrapper", + func: undefined + } ]; + LazyWrapper.prototype.clone = lazyClone; + LazyWrapper.prototype.reverse = lazyReverse; + LazyWrapper.prototype.value = lazyValue; + lodash.prototype.chain = wrapperChain; + lodash.prototype.commit = wrapperCommit; + lodash.prototype.concat = wrapperConcat; + lodash.prototype.plant = wrapperPlant; + lodash.prototype.reverse = wrapperReverse; + lodash.prototype.toString = wrapperToString; + lodash.prototype.run = lodash.prototype.toJSON = lodash.prototype.valueOf = lodash.prototype.value = wrapperValue; + lodash.prototype.collect = lodash.prototype.map; + lodash.prototype.head = lodash.prototype.first; + lodash.prototype.select = lodash.prototype.filter; + lodash.prototype.tail = lodash.prototype.rest; + return lodash; + } + var _ = runInContext(); + if (typeof define == "function" && typeof define.amd == "object" && define.amd) { + root._ = _; + define(function() { + return _; + }); + } else if (freeExports && freeModule) { + if (moduleExports) { + (freeModule.exports = _)._ = _; + } else { + freeExports._ = _; + } + } else { + root._ = _; + } +}).call(this); + (function(window, document, undefined) { "use strict"; function minErr(module, ErrorConstructor) { @@ -5391,7 +9332,7 @@ } return match; }); - message += "\nhttp://errors.angularjs.org/1.4.6/" + (module ? module + "/" : "") + code; + message += "\nhttp://errors.angularjs.org/1.4.7/" + (module ? module + "/" : "") + code; for (i = SKIP_INDEXES, paramPrefix = "?"; i < templateArgs.length; i++, paramPrefix = "&") { message += paramPrefix + "p" + (i - SKIP_INDEXES) + "=" + encodeURIComponent(toDebugString(templateArgs[i])); } @@ -6210,11 +10151,11 @@ return obj; } var version = { - full: "1.4.6", + full: "1.4.7", major: 1, minor: 4, - dot: 6, - codeName: "multiplicative-elevation" + dot: 7, + codeName: "dark-luminescence" }; function publishExternalAPI(angular) { extend(angular, { @@ -6323,6 +10264,7 @@ $httpParamSerializer: $HttpParamSerializerProvider, $httpParamSerializerJQLike: $HttpParamSerializerJQLikeProvider, $httpBackend: $HttpBackendProvider, + $xhrFactory: $xhrFactoryProvider, $location: $LocationProvider, $log: $LogProvider, $parse: $ParseProvider, @@ -6368,10 +10310,10 @@ return offset ? letter.toUpperCase() : letter; }).replace(MOZ_HACK_REGEXP, "Moz$1"); } - var SINGLE_TAG_REGEXP = /^<(\w+)\s*\/?>(?:<\/\1>|)$/; + var SINGLE_TAG_REGEXP = /^<([\w-]+)\s*\/?>(?:<\/\1>|)$/; var HTML_REGEXP = /<|&#?\w+;/; - var TAG_NAME_REGEXP = /<([\w:]+)/; - var XHTML_TAG_REGEXP = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi; + var TAG_NAME_REGEXP = /<([\w:-]+)/; + var XHTML_TAG_REGEXP = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:-]+)[^>]*)\/>/gi; var wrapMap = { option: [ 1, '" ], thead: [ 1, "", "
        " ], @@ -7614,6 +11556,9 @@ } }; return function(element, options) { + if (options.cleanupStyles) { + options.from = options.to = null; + } if (options.from) { element.css(options.from); options.from = null; @@ -8879,7 +12824,7 @@ compile: function() { return { pre: function attrInterpolatePreLinkFn(scope, element, attr) { - var $$observers = attr.$$observers || (attr.$$observers = {}); + var $$observers = attr.$$observers || (attr.$$observers = createMap()); if (EVENT_HANDLER_ATTR_REGEXP.test(name)) { throw $compileMinErr("nodomevents", "Interpolations for HTML DOM event attributes are disallowed. Please use the " + "ng- versions (such as ng-click instead of onclick) instead."); } @@ -9542,12 +13487,16 @@ } } ]; } - function createXhr() { - return new window.XMLHttpRequest(); + function $xhrFactoryProvider() { + this.$get = function() { + return function createXhr() { + return new window.XMLHttpRequest(); + }; + }; } function $HttpBackendProvider() { - this.$get = [ "$browser", "$window", "$document", function($browser, $window, $document) { - return createHttpBackend($browser, createXhr, $browser.defer, $window.angular.callbacks, $document[0]); + this.$get = [ "$browser", "$window", "$document", "$xhrFactory", function($browser, $window, $document, $xhrFactory) { + return createHttpBackend($browser, $xhrFactory, $browser.defer, $window.angular.callbacks, $document[0]); } ]; } function createHttpBackend($browser, createXhr, $browserDefer, callbacks, rawDocument) { @@ -9565,7 +13514,7 @@ callbacks[callbackId] = noop; }); } else { - var xhr = createXhr(); + var xhr = createXhr(method, url); xhr.open(method, url, true); forEach(headers, function(value, key) { if (isDefined(value)) { @@ -10273,12 +14222,18 @@ } var $parseMinErr = minErr("$parse"); function ensureSafeMemberName(name, fullExpression) { - name = isObject(name) && name.toString ? name.toString() : name; if (name === "__defineGetter__" || name === "__defineSetter__" || name === "__lookupGetter__" || name === "__lookupSetter__" || name === "__proto__") { throw $parseMinErr("isecfld", "Attempting to access a disallowed field in Angular expressions! " + "Expression: {0}", fullExpression); } return name; } + function getStringValue(name, fullExpression) { + name = name + ""; + if (!isString(name)) { + throw $parseMinErr("iseccst", "Cannot convert object to primitive value! " + "Expression: {0}", fullExpression); + } + return name; + } function ensureSafeObject(obj, fullExpression) { if (obj) { if (obj.constructor === obj) { @@ -10305,6 +14260,13 @@ } } } + function ensureSafeAssignContext(obj, fullExpression) { + if (obj) { + if (obj === 0..constructor || obj === false.constructor || obj === "".constructor || obj === {}.constructor || obj === [].constructor || obj === Function.constructor) { + throw $parseMinErr("isecaf", "Assigning to a constructor is disallowed! Expression: {0}", fullExpression); + } + } + } var OPERATORS = createMap(); forEach("+ - * / % === !== == != < > <= >= && || ! = |".split(" "), function(operator) { OPERATORS[operator] = true; @@ -11053,7 +15015,7 @@ this.stage = "main"; this.recurse(ast); var fnString = '"' + this.USE + " " + this.STRICT + '";\n' + this.filterPrefix() + "var fn=" + this.generateFunction("fn", "s,l,a,i") + extra + this.watchFns() + "return fn;"; - var fn = new Function("$filter", "ensureSafeMemberName", "ensureSafeObject", "ensureSafeFunction", "ifDefined", "plus", "text", fnString)(this.$filter, ensureSafeMemberName, ensureSafeObject, ensureSafeFunction, ifDefined, plusFn, expression); + var fn = new Function("$filter", "ensureSafeMemberName", "ensureSafeObject", "ensureSafeFunction", "getStringValue", "ensureSafeAssignContext", "ifDefined", "plus", "text", fnString)(this.$filter, ensureSafeMemberName, ensureSafeObject, ensureSafeFunction, getStringValue, ensureSafeAssignContext, ifDefined, plusFn, expression); this.state = this.stage = undefined; fn.literal = isLiteral(ast); fn.constant = isConstant(ast); @@ -11190,6 +15152,7 @@ if (ast.computed) { right = self.nextId(); self.recurse(ast.property, right); + self.getStringValue(right); self.addEnsureSafeMemberName(right); if (create && create !== 1) { self.if_(self.not(self.computedMember(left, right)), self.lazyAssign(self.computedMember(left, right), "{}")); @@ -11275,6 +15238,7 @@ self.if_(self.notNull(left.context), function() { self.recurse(ast.right, right); self.addEnsureSafeObject(self.member(left.context, left.name, left.computed)); + self.addEnsureSafeAssignContext(left.context); expression = self.member(left.context, left.name, left.computed) + ast.operator + right; self.assign(intoId, expression); recursionFn(intoId || expression); @@ -11385,6 +15349,9 @@ addEnsureSafeFunction: function(item) { this.current().body.push(this.ensureSafeFunction(item), ";"); }, + addEnsureSafeAssignContext: function(item) { + this.current().body.push(this.ensureSafeAssignContext(item), ";"); + }, ensureSafeObject: function(item) { return "ensureSafeObject(" + item + ",text)"; }, @@ -11394,6 +15361,12 @@ ensureSafeFunction: function(item) { return "ensureSafeFunction(" + item + ",text)"; }, + getStringValue: function(item) { + this.assign(item, "getStringValue(" + item + ",text)"); + }, + ensureSafeAssignContext: function(item) { + return "ensureSafeAssignContext(" + item + ",text)"; + }, lazyRecurse: function(ast, intoId, nameId, recursionFn, create, skipWatchIdCheck) { var self = this; return function() { @@ -11561,6 +15534,7 @@ var lhs = left(scope, locals, assign, inputs); var rhs = right(scope, locals, assign, inputs); ensureSafeObject(lhs.value, self.expression); + ensureSafeAssignContext(lhs.context); lhs.context[lhs.name] = rhs; return context ? { value: rhs @@ -11818,6 +15792,7 @@ var value; if (lhs != null) { rhs = right(scope, locals, assign, inputs); + rhs = getStringValue(rhs); ensureSafeMemberName(rhs, expression); if (create && create !== 1 && lhs && !lhs[rhs]) { lhs[rhs] = {}; @@ -13500,6 +17475,7 @@ if (fractionSize > 0 && number < 1) { formatedText = number.toFixed(fractionSize); number = parseFloat(formatedText); + formatedText = formatedText.replace(DECIMAL_SEP, decimalSep); } } if (number === 0) { @@ -15517,11 +19493,11 @@ function updateOptionElement(option, element) { option.element = element; element.disabled = option.disabled; - if (option.value !== element.value) element.value = option.selectValue; if (option.label !== element.label) { element.label = option.label; element.textContent = option.label; } + if (option.value !== element.value) element.value = option.selectValue; } function addOrReuseElement(parent, current, type, templateElement) { var element; @@ -15549,7 +19525,7 @@ var emptyOption_ = emptyOption && emptyOption[0]; var unknownOption_ = unknownOption && unknownOption[0]; if (emptyOption_ || unknownOption_) { - while (current && (current === emptyOption_ || current === unknownOption_)) { + while (current && (current === emptyOption_ || current === unknownOption_ || emptyOption_ && emptyOption_.nodeType === NODE_TYPE_COMMENT)) { current = current.nextSibling; } } @@ -26287,6 +30263,12 @@ var cloneObject = function(oldObject) { return JSON.parse(JSON.stringify(oldObject)); }; +var enableControls = function(controls, enabled) { + _.each(controls, function(value, key) { + controls[key] = enabled; + }); +}; + var lingvodoc = {}; lingvodoc.Object = function(clientId, objectId) { @@ -26294,10 +30276,7 @@ lingvodoc.Object = function(clientId, objectId) { this.object_id = objectId; this.type = "abstract"; this.getId = function() { - return this.client_id + "" + this.object_id; - }; - this.export = function() { - return {}; + return this.client_id + "_" + this.object_id; }; }; @@ -26358,13 +30337,33 @@ lingvodoc.Perspective = function(client_id, object_id, parent_client_id, parent_ this.is_template = is_template; this.marked_for_deletion = marked_for_deletion; this.fields = []; + this.location = null; + this.blobs = []; + this.additional_metadata = {}; this.equals = function(obj) { return lingvodoc.Object.prototype.equals.call(this, obj) && this.translation == obj.translation; }; }; lingvodoc.Perspective.fromJS = function(js) { - return new lingvodoc.Perspective(js.client_id, js.object_id, js.parent_client_id, js.parent_object_id, js.translation, js.translation_string, js.status, js.is_template, js.marked_for_deletion); + var perspective = new lingvodoc.Perspective(js.client_id, js.object_id, js.parent_client_id, js.parent_object_id, js.translation, js.translation_string, js.status, js.is_template, js.marked_for_deletion); + if (_.has(js, "location") && _.has(js.location, "content")) { + perspective["location"] = { + lat: js.location.content.lat, + lng: js.location.content.lng + }; + } + if (_.has(js, "info") && js.info.type == "list") { + if (_.isArray(js.info.content)) { + perspective["blobs"] = _.map(js.info.content, function(e) { + var blob = new lingvodoc.Blob(e.info.content.client_id, e.info.content.object_id, e.info.content.name, e.info.content.data_type); + blob.url = e.info.content.content; + return blob; + }); + } + } + perspective.additional_metadata = js.additional_metadata; + return perspective; }; lingvodoc.Perspective.prototype = new lingvodoc.Object(); @@ -26389,6 +30388,25 @@ lingvodoc.User.fromJS = function(js) { return new lingvodoc.User(js.id, js.login, js.name, js.email, js.intl_name, js.about, js.signup_date, js.organizations); }; +lingvodoc.Blob = function(clientId, objectId, name, data_type) { + lingvodoc.Object.call(this, clientId, objectId); + this.type = "blob"; + this.name = name; + this.data_type = data_type; + this.url = null; + this.equals = function(obj) { + return lingvodoc.Object.prototype.equals.call(this, obj) && this.name == obj.name; + }; +}; + +lingvodoc.Blob.fromJS = function(js) { + return new lingvodoc.Blob(js.client_id, js.object_id, js.name, js.data_type); +}; + +lingvodoc.Blob.prototype = new lingvodoc.Object(); + +lingvodoc.Blob.prototype.constructor = lingvodoc.Blob; + function lingvodocAPI($http, $q) { var addUrlParameter = function(url, key, value) { return url + (url.indexOf("?") >= 0 ? "&" : "?") + encodeURIComponent(key) + "=" + encodeURIComponent(value); @@ -26462,6 +30480,21 @@ function lingvodocAPI($http, $q) { }); return deferred.promise; }; + var getPerspectiveDictionaryFieldsNew = function(perspective) { + var deferred = $q.defer(); + var url = "/dictionary/" + perspective.parent_client_id + "/" + perspective.parent_object_id + "/perspective/" + perspective.client_id + "/" + perspective.object_id + "/fields"; + $http.get(url).success(function(data, status, headers, config) { + if (_.isArray(data.fields)) { + var fields = perspectiveToDictionaryFields(data.fields); + deferred.resolve(fields); + } else { + deferred.reject("An error occurred while fetching perspective fields"); + } + }).error(function(data, status, headers, config) { + deferred.reject("An error occurred while fetching perspective fields"); + }); + return deferred.promise; + }; var removeValue = function(entry, field, fieldValue, parent) { var deferred = $q.defer(); var url; @@ -26628,8 +30661,9 @@ function lingvodocAPI($http, $q) { }); return deferred.promise; }; - var getDictionaryProperties = function(url) { + var getDictionaryProperties = function(dictionary) { var deferred = $q.defer(); + var url = "/dictionary/" + encodeURIComponent(dictionary.client_id) + "/" + encodeURIComponent(dictionary.object_id); $http.get(url).success(function(data, status, headers, config) { deferred.resolve(data); }).error(function(data, status, headers, config) { @@ -26637,8 +30671,9 @@ function lingvodocAPI($http, $q) { }); return deferred.promise; }; - var setDictionaryProperties = function(url, properties) { + var setDictionaryProperties = function(dictionary, properties) { var deferred = $q.defer(); + var url = "/dictionary/" + encodeURIComponent(dictionary.client_id) + "/" + encodeURIComponent(dictionary.object_id); $http.put(url, properties).success(function(data, status, headers, config) { deferred.resolve(data); }).error(function(data, status, headers, config) { @@ -26646,6 +30681,16 @@ function lingvodocAPI($http, $q) { }); return deferred.promise; }; + var removeDictionary = function(dictionary) { + var deferred = $q.defer(); + var url = "/dictionary/" + encodeURIComponent(dictionary.client_id) + "/" + encodeURIComponent(dictionary.object_id); + $http.delete(url).success(function(data, status, headers, config) { + deferred.resolve(); + }).error(function(data, status, headers, config) { + deferred.reject("An error occurred while trying to delete dictionary"); + }); + return deferred.promise; + }; var getLanguages = function(url) { var deferred = $q.defer(); var flatLanguages = function(languages) { @@ -26729,6 +30774,16 @@ function lingvodocAPI($http, $q) { }); return deferred.promise; }; + var removePerspective = function(perspective) { + var deferred = $q.defer(); + var url = "/dictionary/" + perspective.parent_client_id + "/" + perspective.parent_object_id + "/perspective/" + perspective.client_id + "/" + perspective.object_id; + $http.delete(url).success(function(data, status, headers, config) { + deferred.resolve(); + }).error(function(data, status, headers, config) { + deferred.reject("An error occurred while trying to delete perspective"); + }); + return deferred.promise; + }; var getUserInfo = function(userId, clientId) { var deferred = $q.defer(); var url = "/user" + "?client_id= " + encodeURIComponent(clientId) + "&user_id= " + encodeURIComponent(userId); @@ -26809,13 +30864,14 @@ function lingvodocAPI($http, $q) { }; var getDictionaries = function(query) { var deferred = $q.defer(); - var dictionaries = []; $http.post("/dictionaries", query).success(function(data, status, headers, config) { - for (var i = 0; i < data.dictionaries.length; i++) { - var dictionary = data.dictionaries[i]; - dictionaries.push(lingvodoc.Dictionary.fromJS(dictionary)); + if (_.isArray(data.dictionaries)) { + deferred.resolve(_.map(data.dictionaries, function(d) { + return lingvodoc.Dictionary.fromJS(d); + })); + } else { + deferred.reject("Failed to fetch dictionaries list. Malformed response."); } - deferred.resolve(dictionaries); }).error(function(data, status, headers, config) { deferred.reject("Failed to fetch dictionaries list"); }); @@ -27032,8 +31088,8 @@ function lingvodocAPI($http, $q) { }; $http.post("/dictionaries", req).success(function(data, status, headers, config) { var dictionaries = []; - if (angular.isArray(data.dictionaries)) { - angular.forEach(data.dictionaries, function(jsdict) { + if (_.isArray(data.dictionaries)) { + _.forEach(data.dictionaries, function(jsdict) { var dictionary = lingvodoc.Dictionary.fromJS(jsdict); if (language.client_id == dictionary.parent_client_id && language.object_id == dictionary.parent_object_id) { dictionaries.push(dictionary); @@ -27042,7 +31098,7 @@ function lingvodocAPI($http, $q) { } deferred.resolve(dictionaries); }).error(function(data, status, headers, config) { - deferred.reject("Failed to move lexical entry"); + deferred.reject("Failed to fetch list of dictionaries"); }); return deferred.promise; }; @@ -27225,10 +31281,140 @@ function lingvodocAPI($http, $q) { }); return deferred.promise; }; + var getUserBlobs = function() { + var deferred = $q.defer(); + $http.get("/blobs").success(function(data, status, headers, config) { + var blobs = _.map(data, lingvodoc.Blob.fromJS); + deferred.resolve(blobs); + }).error(function(data, status, headers, config) { + deferred.reject("Failed to fetch list of available blobs"); + }); + return deferred.promise; + }; + var checkDictionaryBlob = function(blob, parent) { + var deferred = $q.defer(); + var query = { + blob_client_id: blob.client_id, + blob_object_id: blob.object_id, + parent_client_id: parent.client_id, + parent_object_id: parent.object_id + }; + $http.post("/convert_check", query).success(function(data, status, headers, config) { + var perspectives = _.map(data, lingvodoc.Perspective.fromJS); + deferred.resolve(perspectives); + }).error(function(data, status, headers, config) { + deferred.reject("Failed to convert dictionary"); + }); + return deferred.promise; + }; + var convertDictionary = function(req) { + var deferred = $q.defer(); + $http.post("/convert", req).success(function(data, status, headers, config) { + deferred.resolve(data); + }).error(function(data, status, headers, config) { + deferred.reject("Failed to convert dictionary"); + }); + return deferred.promise; + }; + var getPerspectiveMeta = function(dictionary, perspective) { + var deferred = $q.defer(); + var url = "/dictionary/" + encodeURIComponent(dictionary.client_id) + "/" + encodeURIComponent(dictionary.object_id) + "/perspective/" + encodeURIComponent(perspective.client_id) + "/" + encodeURIComponent(perspective.object_id) + "/meta"; + $http.get(url).success(function(data, status, headers, config) { + deferred.resolve(data); + }).error(function(data, status, headers, config) { + deferred.reject("Failed to get perspective meta data!"); + }); + return deferred.promise; + }; + var setPerspectiveMeta = function(dictionary, perspective, meta) { + var deferred = $q.defer(); + var url = "/dictionary/" + encodeURIComponent(dictionary.client_id) + "/" + encodeURIComponent(dictionary.object_id) + "/perspective/" + encodeURIComponent(perspective.client_id) + "/" + encodeURIComponent(perspective.object_id) + "/meta"; + $http.put(url, meta).success(function(data, status, headers, config) { + deferred.resolve(data); + }).error(function(data, status, headers, config) { + deferred.reject("Failed to set perspective meta data!"); + }); + return deferred.promise; + }; + var removePerspectiveMeta = function(dictionary, perspective, meta) { + var deferred = $q.defer(); + var url = "/dictionary/" + encodeURIComponent(dictionary.client_id) + "/" + encodeURIComponent(dictionary.object_id) + "/perspective/" + encodeURIComponent(perspective.client_id) + "/" + encodeURIComponent(perspective.object_id) + "/meta"; + var config = { + method: "DELETE", + url: url, + data: meta, + headers: { + "Content-Type": "application/json;charset=utf-8" + } + }; + $http(config).success(function(data, status, headers, config) { + deferred.resolve(data); + }).error(function(data, status, headers, config) { + deferred.reject("Failed to remove perspective meta data!"); + }); + return deferred.promise; + }; + var advancedSearch = function(query, where, adopted, etymology) { + var deferred = $q.defer(); + var url = "/advanced_search"; + var perspectives = where.map(function(o) { + if (o.type == "perspective") { + return { + client_id: o.client_id, + object_id: o.object_id + }; + } + }).filter(function(o) { + return typeof o !== "undefined"; + }); + var req = { + searchstrings: query, + perspectives: perspectives + }; + if (_.isBoolean(adopted)) { + req.adopted = adopted; + } + if (_.isBoolean(etymology)) { + req.with_etimology = etymology; + } + $http.post(url, req).success(function(data, status, headers, config) { + var r = data.map(function(e) { + var perspective = lingvodoc.Perspective.fromJS(e); + return getPerspectiveOriginById(perspective.client_id, perspective.object_id); + }); + $q.all(r).then(function(paths) { + var out = []; + _.each(data, function(entry, i) { + entry.lexical_entry["origin"] = paths[i]; + out.push(entry.lexical_entry); + }); + deferred.resolve(out); + }, function(reason) { + deferred.reject("An error occurred while doing basic search"); + }); + }).error(function(data, status, headers, config) { + deferred.reject("An error occurred while doing advanced search"); + }); + return deferred.promise; + }; + var convertMarkup = function(object) { + var deferred = $q.defer(); + var obj = { + client_id: object.client_id, + object_id: object.object_id + }; + $http.post("/convert/markup", obj).success(function(data, status, headers, config) { + deferred.resolve(data); + }).error(function(data, status, headers, config) { + deferred.reject("Failed to convert markup!"); + }); + return deferred.promise; + }; return { getLexicalEntries: getLexicalEntries, getLexicalEntriesCount: getLexicalEntriesCount, getPerspectiveDictionaryFields: getPerspectiveDictionaryFields, + getPerspectiveDictionaryFieldsNew: getPerspectiveDictionaryFieldsNew, addNewLexicalEntry: addNewLexicalEntry, saveValue: saveValue, removeValue: removeValue, @@ -27239,6 +31425,7 @@ function lingvodocAPI($http, $q) { approveAll: approveAll, getDictionaryProperties: getDictionaryProperties, setDictionaryProperties: setDictionaryProperties, + removeDictionary: removeDictionary, getLanguages: getLanguages, setDictionaryStatus: setDictionaryStatus, setPerspectiveStatus: setPerspectiveStatus, @@ -27246,6 +31433,7 @@ function lingvodocAPI($http, $q) { getPerspectiveFields: getPerspectiveFields, setPerspectiveFields: setPerspectiveFields, getPerspectiveFieldsNew: getPerspectiveFieldsNew, + removePerspective: removePerspective, getUserInfo: getUserInfo, setUserInfo: setUserInfo, getOrganizations: getOrganizations, @@ -27272,7 +31460,15 @@ function lingvodocAPI($http, $q) { deleteDictionaryRoles: deleteDictionaryRoles, getPerspectiveRoles: getPerspectiveRoles, addPerspectiveRoles: addPerspectiveRoles, - deletePerspectiveRoles: deletePerspectiveRoles + deletePerspectiveRoles: deletePerspectiveRoles, + getUserBlobs: getUserBlobs, + checkDictionaryBlob: checkDictionaryBlob, + convertDictionary: convertDictionary, + getPerspectiveMeta: getPerspectiveMeta, + setPerspectiveMeta: setPerspectiveMeta, + removePerspectiveMeta: removePerspectiveMeta, + advancedSearch: advancedSearch, + convertMarkup: convertMarkup }; } @@ -27304,9 +31500,34 @@ function responseHandler($timeout, $modal) { function error(message) { show("error", message, 5e3); } + function yesno(status, message, callback) { + var controller = function($scope, $modalInstance) { + $scope.status = status; + $scope.message = message; + $scope.yes = function() { + $modalInstance.close(true); + }; + $scope.no = function() { + $modalInstance.close(false); + }; + }; + $modal.open({ + animation: true, + templateUrl: "responseHandlerYesNoModal.html", + controller: controller, + size: "lg", + backdrop: "static", + keyboard: false + }).result.then(function(result) { + callback(result); + }, function() { + callback(false); + }); + } return { success: success, - error: error + error: error, + yesno: yesno }; } @@ -27314,18 +31535,21 @@ function responseHandler($timeout, $modal) { angular.module("HomeModule", [ "ui.bootstrap" ], function($rootScopeProvider) { $rootScopeProvider.digestTtl(1e3); -}).service("dictionaryService", lingvodocAPI).factory("responseHandler", [ "$timeout", "$modal", responseHandler ]).controller("HomeController", [ "$scope", "$http", "$modal", "$q", "$log", "dictionaryService", "responseHandler", function($scope, $http, $modal, $q, $log, dictionaryService, responseHandler) { - var languagesUrl = $("#languagesUrl").data("lingvodoc"); - var dictionariesUrl = $("#dictionariesUrl").data("lingvodoc"); - var getUserInfoUrl = $("#getUserInfoUrl").data("lingvodoc"); +}).factory("dictionaryService", [ "$http", "$q", lingvodocAPI ]).factory("responseHandler", [ "$timeout", "$modal", responseHandler ]).controller("HomeController", [ "$scope", "$http", "$log", "dictionaryService", "responseHandler", function($scope, $http, $log, dictionaryService, responseHandler) { $scope.languages = []; $scope.getPerspectiveLink = function(dictionary, perspective) { return "/dictionary/" + encodeURIComponent(dictionary.client_id) + "/" + encodeURIComponent(dictionary.object_id) + "/perspective/" + encodeURIComponent(perspective.client_id) + "/" + encodeURIComponent(perspective.object_id) + "/view"; }; + $scope.getPerspectiveAuthors = function(perspective) { + var meta = JSON.parse(perspective.additional_metadata); + if (_.has(meta, "authors") && _.has(meta.authors, "content") && _.isString(meta.authors.content)) { + return meta.authors.content; + } + }; var getPublishedPerspectives = function(dictionary) { dictionaryService.getDictionaryPerspectives(dictionary).then(function(perspectives) { var published = []; - angular.forEach(perspectives, function(perspective) { + _.forEach(perspectives, function(perspective) { if (perspective.status.toUpperCase() == "published".toUpperCase()) { published.push(perspective); } @@ -27336,10 +31560,10 @@ angular.module("HomeModule", [ "ui.bootstrap" ], function($rootScopeProvider) { var setPerspectives = function(languages) { for (var i = 0; i < languages.length; ++i) { var lang = languages[i]; - angular.forEach(lang.dicts, function(dict) { + _.forEach(lang.dicts, function(dict) { getPublishedPerspectives(dict); }); - if (angular.isArray(lang.contains)) { + if (_.isArray(lang.contains)) { setPerspectives(lang.contains); } } diff --git a/lingvodoc/static/js/languages.js b/lingvodoc/static/js/languages.js index cd5b3c344..8a8c6ed5e 100644 --- a/lingvodoc/static/js/languages.js +++ b/lingvodoc/static/js/languages.js @@ -5377,6 +5377,3947 @@ return jQuery; }); +(function() { + var undefined; + var VERSION = "3.10.1"; + var BIND_FLAG = 1, BIND_KEY_FLAG = 2, CURRY_BOUND_FLAG = 4, CURRY_FLAG = 8, CURRY_RIGHT_FLAG = 16, PARTIAL_FLAG = 32, PARTIAL_RIGHT_FLAG = 64, ARY_FLAG = 128, REARG_FLAG = 256; + var DEFAULT_TRUNC_LENGTH = 30, DEFAULT_TRUNC_OMISSION = "..."; + var HOT_COUNT = 150, HOT_SPAN = 16; + var LARGE_ARRAY_SIZE = 200; + var LAZY_FILTER_FLAG = 1, LAZY_MAP_FLAG = 2; + var FUNC_ERROR_TEXT = "Expected a function"; + var PLACEHOLDER = "__lodash_placeholder__"; + var argsTag = "[object Arguments]", arrayTag = "[object Array]", boolTag = "[object Boolean]", dateTag = "[object Date]", errorTag = "[object Error]", funcTag = "[object Function]", mapTag = "[object Map]", numberTag = "[object Number]", objectTag = "[object Object]", regexpTag = "[object RegExp]", setTag = "[object Set]", stringTag = "[object String]", weakMapTag = "[object WeakMap]"; + var arrayBufferTag = "[object ArrayBuffer]", float32Tag = "[object Float32Array]", float64Tag = "[object Float64Array]", int8Tag = "[object Int8Array]", int16Tag = "[object Int16Array]", int32Tag = "[object Int32Array]", uint8Tag = "[object Uint8Array]", uint8ClampedTag = "[object Uint8ClampedArray]", uint16Tag = "[object Uint16Array]", uint32Tag = "[object Uint32Array]"; + var reEmptyStringLeading = /\b__p \+= '';/g, reEmptyStringMiddle = /\b(__p \+=) '' \+/g, reEmptyStringTrailing = /(__e\(.*?\)|\b__t\)) \+\n'';/g; + var reEscapedHtml = /&(?:amp|lt|gt|quot|#39|#96);/g, reUnescapedHtml = /[&<>"'`]/g, reHasEscapedHtml = RegExp(reEscapedHtml.source), reHasUnescapedHtml = RegExp(reUnescapedHtml.source); + var reEscape = /<%-([\s\S]+?)%>/g, reEvaluate = /<%([\s\S]+?)%>/g, reInterpolate = /<%=([\s\S]+?)%>/g; + var reIsDeepProp = /\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\n\\]|\\.)*?\1)\]/, reIsPlainProp = /^\w*$/, rePropName = /[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\n\\]|\\.)*?)\2)\]/g; + var reRegExpChars = /^[:!,]|[\\^$.*+?()[\]{}|\/]|(^[0-9a-fA-Fnrtuvx])|([\n\r\u2028\u2029])/g, reHasRegExpChars = RegExp(reRegExpChars.source); + var reComboMark = /[\u0300-\u036f\ufe20-\ufe23]/g; + var reEscapeChar = /\\(\\)?/g; + var reEsTemplate = /\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g; + var reFlags = /\w*$/; + var reHasHexPrefix = /^0[xX]/; + var reIsHostCtor = /^\[object .+?Constructor\]$/; + var reIsUint = /^\d+$/; + var reLatin1 = /[\xc0-\xd6\xd8-\xde\xdf-\xf6\xf8-\xff]/g; + var reNoMatch = /($^)/; + var reUnescapedString = /['\n\r\u2028\u2029\\]/g; + var reWords = function() { + var upper = "[A-Z\\xc0-\\xd6\\xd8-\\xde]", lower = "[a-z\\xdf-\\xf6\\xf8-\\xff]+"; + return RegExp(upper + "+(?=" + upper + lower + ")|" + upper + "?" + lower + "|" + upper + "+|[0-9]+", "g"); + }(); + var contextProps = [ "Array", "ArrayBuffer", "Date", "Error", "Float32Array", "Float64Array", "Function", "Int8Array", "Int16Array", "Int32Array", "Math", "Number", "Object", "RegExp", "Set", "String", "_", "clearTimeout", "isFinite", "parseFloat", "parseInt", "setTimeout", "TypeError", "Uint8Array", "Uint8ClampedArray", "Uint16Array", "Uint32Array", "WeakMap" ]; + var templateCounter = -1; + var typedArrayTags = {}; + typedArrayTags[float32Tag] = typedArrayTags[float64Tag] = typedArrayTags[int8Tag] = typedArrayTags[int16Tag] = typedArrayTags[int32Tag] = typedArrayTags[uint8Tag] = typedArrayTags[uint8ClampedTag] = typedArrayTags[uint16Tag] = typedArrayTags[uint32Tag] = true; + typedArrayTags[argsTag] = typedArrayTags[arrayTag] = typedArrayTags[arrayBufferTag] = typedArrayTags[boolTag] = typedArrayTags[dateTag] = typedArrayTags[errorTag] = typedArrayTags[funcTag] = typedArrayTags[mapTag] = typedArrayTags[numberTag] = typedArrayTags[objectTag] = typedArrayTags[regexpTag] = typedArrayTags[setTag] = typedArrayTags[stringTag] = typedArrayTags[weakMapTag] = false; + var cloneableTags = {}; + cloneableTags[argsTag] = cloneableTags[arrayTag] = cloneableTags[arrayBufferTag] = cloneableTags[boolTag] = cloneableTags[dateTag] = cloneableTags[float32Tag] = cloneableTags[float64Tag] = cloneableTags[int8Tag] = cloneableTags[int16Tag] = cloneableTags[int32Tag] = cloneableTags[numberTag] = cloneableTags[objectTag] = cloneableTags[regexpTag] = cloneableTags[stringTag] = cloneableTags[uint8Tag] = cloneableTags[uint8ClampedTag] = cloneableTags[uint16Tag] = cloneableTags[uint32Tag] = true; + cloneableTags[errorTag] = cloneableTags[funcTag] = cloneableTags[mapTag] = cloneableTags[setTag] = cloneableTags[weakMapTag] = false; + var deburredLetters = { + "À": "A", + "Á": "A", + "Â": "A", + "Ã": "A", + "Ä": "A", + "Å": "A", + "à": "a", + "á": "a", + "â": "a", + "ã": "a", + "ä": "a", + "å": "a", + "Ç": "C", + "ç": "c", + "Ð": "D", + "ð": "d", + "È": "E", + "É": "E", + "Ê": "E", + "Ë": "E", + "è": "e", + "é": "e", + "ê": "e", + "ë": "e", + "Ì": "I", + "Í": "I", + "Î": "I", + "Ï": "I", + "ì": "i", + "í": "i", + "î": "i", + "ï": "i", + "Ñ": "N", + "ñ": "n", + "Ò": "O", + "Ó": "O", + "Ô": "O", + "Õ": "O", + "Ö": "O", + "Ø": "O", + "ò": "o", + "ó": "o", + "ô": "o", + "õ": "o", + "ö": "o", + "ø": "o", + "Ù": "U", + "Ú": "U", + "Û": "U", + "Ü": "U", + "ù": "u", + "ú": "u", + "û": "u", + "ü": "u", + "Ý": "Y", + "ý": "y", + "ÿ": "y", + "Æ": "Ae", + "æ": "ae", + "Þ": "Th", + "þ": "th", + "ß": "ss" + }; + var htmlEscapes = { + "&": "&", + "<": "<", + ">": ">", + '"': """, + "'": "'", + "`": "`" + }; + var htmlUnescapes = { + "&": "&", + "<": "<", + ">": ">", + """: '"', + "'": "'", + "`": "`" + }; + var objectTypes = { + "function": true, + object: true + }; + var regexpEscapes = { + "0": "x30", + "1": "x31", + "2": "x32", + "3": "x33", + "4": "x34", + "5": "x35", + "6": "x36", + "7": "x37", + "8": "x38", + "9": "x39", + A: "x41", + B: "x42", + C: "x43", + D: "x44", + E: "x45", + F: "x46", + a: "x61", + b: "x62", + c: "x63", + d: "x64", + e: "x65", + f: "x66", + n: "x6e", + r: "x72", + t: "x74", + u: "x75", + v: "x76", + x: "x78" + }; + var stringEscapes = { + "\\": "\\", + "'": "'", + "\n": "n", + "\r": "r", + "\u2028": "u2028", + "\u2029": "u2029" + }; + var freeExports = objectTypes[typeof exports] && exports && !exports.nodeType && exports; + var freeModule = objectTypes[typeof module] && module && !module.nodeType && module; + var freeGlobal = freeExports && freeModule && typeof global == "object" && global && global.Object && global; + var freeSelf = objectTypes[typeof self] && self && self.Object && self; + var freeWindow = objectTypes[typeof window] && window && window.Object && window; + var moduleExports = freeModule && freeModule.exports === freeExports && freeExports; + var root = freeGlobal || freeWindow !== (this && this.window) && freeWindow || freeSelf || this; + function baseCompareAscending(value, other) { + if (value !== other) { + var valIsNull = value === null, valIsUndef = value === undefined, valIsReflexive = value === value; + var othIsNull = other === null, othIsUndef = other === undefined, othIsReflexive = other === other; + if (value > other && !othIsNull || !valIsReflexive || valIsNull && !othIsUndef && othIsReflexive || valIsUndef && othIsReflexive) { + return 1; + } + if (value < other && !valIsNull || !othIsReflexive || othIsNull && !valIsUndef && valIsReflexive || othIsUndef && valIsReflexive) { + return -1; + } + } + return 0; + } + function baseFindIndex(array, predicate, fromRight) { + var length = array.length, index = fromRight ? length : -1; + while (fromRight ? index-- : ++index < length) { + if (predicate(array[index], index, array)) { + return index; + } + } + return -1; + } + function baseIndexOf(array, value, fromIndex) { + if (value !== value) { + return indexOfNaN(array, fromIndex); + } + var index = fromIndex - 1, length = array.length; + while (++index < length) { + if (array[index] === value) { + return index; + } + } + return -1; + } + function baseIsFunction(value) { + return typeof value == "function" || false; + } + function baseToString(value) { + return value == null ? "" : value + ""; + } + function charsLeftIndex(string, chars) { + var index = -1, length = string.length; + while (++index < length && chars.indexOf(string.charAt(index)) > -1) {} + return index; + } + function charsRightIndex(string, chars) { + var index = string.length; + while (index-- && chars.indexOf(string.charAt(index)) > -1) {} + return index; + } + function compareAscending(object, other) { + return baseCompareAscending(object.criteria, other.criteria) || object.index - other.index; + } + function compareMultiple(object, other, orders) { + var index = -1, objCriteria = object.criteria, othCriteria = other.criteria, length = objCriteria.length, ordersLength = orders.length; + while (++index < length) { + var result = baseCompareAscending(objCriteria[index], othCriteria[index]); + if (result) { + if (index >= ordersLength) { + return result; + } + var order = orders[index]; + return result * (order === "asc" || order === true ? 1 : -1); + } + } + return object.index - other.index; + } + function deburrLetter(letter) { + return deburredLetters[letter]; + } + function escapeHtmlChar(chr) { + return htmlEscapes[chr]; + } + function escapeRegExpChar(chr, leadingChar, whitespaceChar) { + if (leadingChar) { + chr = regexpEscapes[chr]; + } else if (whitespaceChar) { + chr = stringEscapes[chr]; + } + return "\\" + chr; + } + function escapeStringChar(chr) { + return "\\" + stringEscapes[chr]; + } + function indexOfNaN(array, fromIndex, fromRight) { + var length = array.length, index = fromIndex + (fromRight ? 0 : -1); + while (fromRight ? index-- : ++index < length) { + var other = array[index]; + if (other !== other) { + return index; + } + } + return -1; + } + function isObjectLike(value) { + return !!value && typeof value == "object"; + } + function isSpace(charCode) { + return charCode <= 160 && (charCode >= 9 && charCode <= 13) || charCode == 32 || charCode == 160 || charCode == 5760 || charCode == 6158 || charCode >= 8192 && (charCode <= 8202 || charCode == 8232 || charCode == 8233 || charCode == 8239 || charCode == 8287 || charCode == 12288 || charCode == 65279); + } + function replaceHolders(array, placeholder) { + var index = -1, length = array.length, resIndex = -1, result = []; + while (++index < length) { + if (array[index] === placeholder) { + array[index] = PLACEHOLDER; + result[++resIndex] = index; + } + } + return result; + } + function sortedUniq(array, iteratee) { + var seen, index = -1, length = array.length, resIndex = -1, result = []; + while (++index < length) { + var value = array[index], computed = iteratee ? iteratee(value, index, array) : value; + if (!index || seen !== computed) { + seen = computed; + result[++resIndex] = value; + } + } + return result; + } + function trimmedLeftIndex(string) { + var index = -1, length = string.length; + while (++index < length && isSpace(string.charCodeAt(index))) {} + return index; + } + function trimmedRightIndex(string) { + var index = string.length; + while (index-- && isSpace(string.charCodeAt(index))) {} + return index; + } + function unescapeHtmlChar(chr) { + return htmlUnescapes[chr]; + } + function runInContext(context) { + context = context ? _.defaults(root.Object(), context, _.pick(root, contextProps)) : root; + var Array = context.Array, Date = context.Date, Error = context.Error, Function = context.Function, Math = context.Math, Number = context.Number, Object = context.Object, RegExp = context.RegExp, String = context.String, TypeError = context.TypeError; + var arrayProto = Array.prototype, objectProto = Object.prototype, stringProto = String.prototype; + var fnToString = Function.prototype.toString; + var hasOwnProperty = objectProto.hasOwnProperty; + var idCounter = 0; + var objToString = objectProto.toString; + var oldDash = root._; + var reIsNative = RegExp("^" + fnToString.call(hasOwnProperty).replace(/[\\^$.*+?()[\]{}|]/g, "\\$&").replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g, "$1.*?") + "$"); + var ArrayBuffer = context.ArrayBuffer, clearTimeout = context.clearTimeout, parseFloat = context.parseFloat, pow = Math.pow, propertyIsEnumerable = objectProto.propertyIsEnumerable, Set = getNative(context, "Set"), setTimeout = context.setTimeout, splice = arrayProto.splice, Uint8Array = context.Uint8Array, WeakMap = getNative(context, "WeakMap"); + var nativeCeil = Math.ceil, nativeCreate = getNative(Object, "create"), nativeFloor = Math.floor, nativeIsArray = getNative(Array, "isArray"), nativeIsFinite = context.isFinite, nativeKeys = getNative(Object, "keys"), nativeMax = Math.max, nativeMin = Math.min, nativeNow = getNative(Date, "now"), nativeParseInt = context.parseInt, nativeRandom = Math.random; + var NEGATIVE_INFINITY = Number.NEGATIVE_INFINITY, POSITIVE_INFINITY = Number.POSITIVE_INFINITY; + var MAX_ARRAY_LENGTH = 4294967295, MAX_ARRAY_INDEX = MAX_ARRAY_LENGTH - 1, HALF_MAX_ARRAY_LENGTH = MAX_ARRAY_LENGTH >>> 1; + var MAX_SAFE_INTEGER = 9007199254740991; + var metaMap = WeakMap && new WeakMap(); + var realNames = {}; + function lodash(value) { + if (isObjectLike(value) && !isArray(value) && !(value instanceof LazyWrapper)) { + if (value instanceof LodashWrapper) { + return value; + } + if (hasOwnProperty.call(value, "__chain__") && hasOwnProperty.call(value, "__wrapped__")) { + return wrapperClone(value); + } + } + return new LodashWrapper(value); + } + function baseLodash() {} + function LodashWrapper(value, chainAll, actions) { + this.__wrapped__ = value; + this.__actions__ = actions || []; + this.__chain__ = !!chainAll; + } + var support = lodash.support = {}; + lodash.templateSettings = { + escape: reEscape, + evaluate: reEvaluate, + interpolate: reInterpolate, + variable: "", + imports: { + _: lodash + } + }; + function LazyWrapper(value) { + this.__wrapped__ = value; + this.__actions__ = []; + this.__dir__ = 1; + this.__filtered__ = false; + this.__iteratees__ = []; + this.__takeCount__ = POSITIVE_INFINITY; + this.__views__ = []; + } + function lazyClone() { + var result = new LazyWrapper(this.__wrapped__); + result.__actions__ = arrayCopy(this.__actions__); + result.__dir__ = this.__dir__; + result.__filtered__ = this.__filtered__; + result.__iteratees__ = arrayCopy(this.__iteratees__); + result.__takeCount__ = this.__takeCount__; + result.__views__ = arrayCopy(this.__views__); + return result; + } + function lazyReverse() { + if (this.__filtered__) { + var result = new LazyWrapper(this); + result.__dir__ = -1; + result.__filtered__ = true; + } else { + result = this.clone(); + result.__dir__ *= -1; + } + return result; + } + function lazyValue() { + var array = this.__wrapped__.value(), dir = this.__dir__, isArr = isArray(array), isRight = dir < 0, arrLength = isArr ? array.length : 0, view = getView(0, arrLength, this.__views__), start = view.start, end = view.end, length = end - start, index = isRight ? end : start - 1, iteratees = this.__iteratees__, iterLength = iteratees.length, resIndex = 0, takeCount = nativeMin(length, this.__takeCount__); + if (!isArr || arrLength < LARGE_ARRAY_SIZE || arrLength == length && takeCount == length) { + return baseWrapperValue(array, this.__actions__); + } + var result = []; + outer: while (length-- && resIndex < takeCount) { + index += dir; + var iterIndex = -1, value = array[index]; + while (++iterIndex < iterLength) { + var data = iteratees[iterIndex], iteratee = data.iteratee, type = data.type, computed = iteratee(value); + if (type == LAZY_MAP_FLAG) { + value = computed; + } else if (!computed) { + if (type == LAZY_FILTER_FLAG) { + continue outer; + } else { + break outer; + } + } + } + result[resIndex++] = value; + } + return result; + } + function MapCache() { + this.__data__ = {}; + } + function mapDelete(key) { + return this.has(key) && delete this.__data__[key]; + } + function mapGet(key) { + return key == "__proto__" ? undefined : this.__data__[key]; + } + function mapHas(key) { + return key != "__proto__" && hasOwnProperty.call(this.__data__, key); + } + function mapSet(key, value) { + if (key != "__proto__") { + this.__data__[key] = value; + } + return this; + } + function SetCache(values) { + var length = values ? values.length : 0; + this.data = { + hash: nativeCreate(null), + set: new Set() + }; + while (length--) { + this.push(values[length]); + } + } + function cacheIndexOf(cache, value) { + var data = cache.data, result = typeof value == "string" || isObject(value) ? data.set.has(value) : data.hash[value]; + return result ? 0 : -1; + } + function cachePush(value) { + var data = this.data; + if (typeof value == "string" || isObject(value)) { + data.set.add(value); + } else { + data.hash[value] = true; + } + } + function arrayConcat(array, other) { + var index = -1, length = array.length, othIndex = -1, othLength = other.length, result = Array(length + othLength); + while (++index < length) { + result[index] = array[index]; + } + while (++othIndex < othLength) { + result[index++] = other[othIndex]; + } + return result; + } + function arrayCopy(source, array) { + var index = -1, length = source.length; + array || (array = Array(length)); + while (++index < length) { + array[index] = source[index]; + } + return array; + } + function arrayEach(array, iteratee) { + var index = -1, length = array.length; + while (++index < length) { + if (iteratee(array[index], index, array) === false) { + break; + } + } + return array; + } + function arrayEachRight(array, iteratee) { + var length = array.length; + while (length--) { + if (iteratee(array[length], length, array) === false) { + break; + } + } + return array; + } + function arrayEvery(array, predicate) { + var index = -1, length = array.length; + while (++index < length) { + if (!predicate(array[index], index, array)) { + return false; + } + } + return true; + } + function arrayExtremum(array, iteratee, comparator, exValue) { + var index = -1, length = array.length, computed = exValue, result = computed; + while (++index < length) { + var value = array[index], current = +iteratee(value); + if (comparator(current, computed)) { + computed = current; + result = value; + } + } + return result; + } + function arrayFilter(array, predicate) { + var index = -1, length = array.length, resIndex = -1, result = []; + while (++index < length) { + var value = array[index]; + if (predicate(value, index, array)) { + result[++resIndex] = value; + } + } + return result; + } + function arrayMap(array, iteratee) { + var index = -1, length = array.length, result = Array(length); + while (++index < length) { + result[index] = iteratee(array[index], index, array); + } + return result; + } + function arrayPush(array, values) { + var index = -1, length = values.length, offset = array.length; + while (++index < length) { + array[offset + index] = values[index]; + } + return array; + } + function arrayReduce(array, iteratee, accumulator, initFromArray) { + var index = -1, length = array.length; + if (initFromArray && length) { + accumulator = array[++index]; + } + while (++index < length) { + accumulator = iteratee(accumulator, array[index], index, array); + } + return accumulator; + } + function arrayReduceRight(array, iteratee, accumulator, initFromArray) { + var length = array.length; + if (initFromArray && length) { + accumulator = array[--length]; + } + while (length--) { + accumulator = iteratee(accumulator, array[length], length, array); + } + return accumulator; + } + function arraySome(array, predicate) { + var index = -1, length = array.length; + while (++index < length) { + if (predicate(array[index], index, array)) { + return true; + } + } + return false; + } + function arraySum(array, iteratee) { + var length = array.length, result = 0; + while (length--) { + result += +iteratee(array[length]) || 0; + } + return result; + } + function assignDefaults(objectValue, sourceValue) { + return objectValue === undefined ? sourceValue : objectValue; + } + function assignOwnDefaults(objectValue, sourceValue, key, object) { + return objectValue === undefined || !hasOwnProperty.call(object, key) ? sourceValue : objectValue; + } + function assignWith(object, source, customizer) { + var index = -1, props = keys(source), length = props.length; + while (++index < length) { + var key = props[index], value = object[key], result = customizer(value, source[key], key, object, source); + if ((result === result ? result !== value : value === value) || value === undefined && !(key in object)) { + object[key] = result; + } + } + return object; + } + function baseAssign(object, source) { + return source == null ? object : baseCopy(source, keys(source), object); + } + function baseAt(collection, props) { + var index = -1, isNil = collection == null, isArr = !isNil && isArrayLike(collection), length = isArr ? collection.length : 0, propsLength = props.length, result = Array(propsLength); + while (++index < propsLength) { + var key = props[index]; + if (isArr) { + result[index] = isIndex(key, length) ? collection[key] : undefined; + } else { + result[index] = isNil ? undefined : collection[key]; + } + } + return result; + } + function baseCopy(source, props, object) { + object || (object = {}); + var index = -1, length = props.length; + while (++index < length) { + var key = props[index]; + object[key] = source[key]; + } + return object; + } + function baseCallback(func, thisArg, argCount) { + var type = typeof func; + if (type == "function") { + return thisArg === undefined ? func : bindCallback(func, thisArg, argCount); + } + if (func == null) { + return identity; + } + if (type == "object") { + return baseMatches(func); + } + return thisArg === undefined ? property(func) : baseMatchesProperty(func, thisArg); + } + function baseClone(value, isDeep, customizer, key, object, stackA, stackB) { + var result; + if (customizer) { + result = object ? customizer(value, key, object) : customizer(value); + } + if (result !== undefined) { + return result; + } + if (!isObject(value)) { + return value; + } + var isArr = isArray(value); + if (isArr) { + result = initCloneArray(value); + if (!isDeep) { + return arrayCopy(value, result); + } + } else { + var tag = objToString.call(value), isFunc = tag == funcTag; + if (tag == objectTag || tag == argsTag || isFunc && !object) { + result = initCloneObject(isFunc ? {} : value); + if (!isDeep) { + return baseAssign(result, value); + } + } else { + return cloneableTags[tag] ? initCloneByTag(value, tag, isDeep) : object ? value : {}; + } + } + stackA || (stackA = []); + stackB || (stackB = []); + var length = stackA.length; + while (length--) { + if (stackA[length] == value) { + return stackB[length]; + } + } + stackA.push(value); + stackB.push(result); + (isArr ? arrayEach : baseForOwn)(value, function(subValue, key) { + result[key] = baseClone(subValue, isDeep, customizer, key, value, stackA, stackB); + }); + return result; + } + var baseCreate = function() { + function object() {} + return function(prototype) { + if (isObject(prototype)) { + object.prototype = prototype; + var result = new object(); + object.prototype = undefined; + } + return result || {}; + }; + }(); + function baseDelay(func, wait, args) { + if (typeof func != "function") { + throw new TypeError(FUNC_ERROR_TEXT); + } + return setTimeout(function() { + func.apply(undefined, args); + }, wait); + } + function baseDifference(array, values) { + var length = array ? array.length : 0, result = []; + if (!length) { + return result; + } + var index = -1, indexOf = getIndexOf(), isCommon = indexOf === baseIndexOf, cache = isCommon && values.length >= LARGE_ARRAY_SIZE ? createCache(values) : null, valuesLength = values.length; + if (cache) { + indexOf = cacheIndexOf; + isCommon = false; + values = cache; + } + outer: while (++index < length) { + var value = array[index]; + if (isCommon && value === value) { + var valuesIndex = valuesLength; + while (valuesIndex--) { + if (values[valuesIndex] === value) { + continue outer; + } + } + result.push(value); + } else if (indexOf(values, value, 0) < 0) { + result.push(value); + } + } + return result; + } + var baseEach = createBaseEach(baseForOwn); + var baseEachRight = createBaseEach(baseForOwnRight, true); + function baseEvery(collection, predicate) { + var result = true; + baseEach(collection, function(value, index, collection) { + result = !!predicate(value, index, collection); + return result; + }); + return result; + } + function baseExtremum(collection, iteratee, comparator, exValue) { + var computed = exValue, result = computed; + baseEach(collection, function(value, index, collection) { + var current = +iteratee(value, index, collection); + if (comparator(current, computed) || current === exValue && current === result) { + computed = current; + result = value; + } + }); + return result; + } + function baseFill(array, value, start, end) { + var length = array.length; + start = start == null ? 0 : +start || 0; + if (start < 0) { + start = -start > length ? 0 : length + start; + } + end = end === undefined || end > length ? length : +end || 0; + if (end < 0) { + end += length; + } + length = start > end ? 0 : end >>> 0; + start >>>= 0; + while (start < length) { + array[start++] = value; + } + return array; + } + function baseFilter(collection, predicate) { + var result = []; + baseEach(collection, function(value, index, collection) { + if (predicate(value, index, collection)) { + result.push(value); + } + }); + return result; + } + function baseFind(collection, predicate, eachFunc, retKey) { + var result; + eachFunc(collection, function(value, key, collection) { + if (predicate(value, key, collection)) { + result = retKey ? key : value; + return false; + } + }); + return result; + } + function baseFlatten(array, isDeep, isStrict, result) { + result || (result = []); + var index = -1, length = array.length; + while (++index < length) { + var value = array[index]; + if (isObjectLike(value) && isArrayLike(value) && (isStrict || isArray(value) || isArguments(value))) { + if (isDeep) { + baseFlatten(value, isDeep, isStrict, result); + } else { + arrayPush(result, value); + } + } else if (!isStrict) { + result[result.length] = value; + } + } + return result; + } + var baseFor = createBaseFor(); + var baseForRight = createBaseFor(true); + function baseForIn(object, iteratee) { + return baseFor(object, iteratee, keysIn); + } + function baseForOwn(object, iteratee) { + return baseFor(object, iteratee, keys); + } + function baseForOwnRight(object, iteratee) { + return baseForRight(object, iteratee, keys); + } + function baseFunctions(object, props) { + var index = -1, length = props.length, resIndex = -1, result = []; + while (++index < length) { + var key = props[index]; + if (isFunction(object[key])) { + result[++resIndex] = key; + } + } + return result; + } + function baseGet(object, path, pathKey) { + if (object == null) { + return; + } + if (pathKey !== undefined && pathKey in toObject(object)) { + path = [ pathKey ]; + } + var index = 0, length = path.length; + while (object != null && index < length) { + object = object[path[index++]]; + } + return index && index == length ? object : undefined; + } + function baseIsEqual(value, other, customizer, isLoose, stackA, stackB) { + if (value === other) { + return true; + } + if (value == null || other == null || !isObject(value) && !isObjectLike(other)) { + return value !== value && other !== other; + } + return baseIsEqualDeep(value, other, baseIsEqual, customizer, isLoose, stackA, stackB); + } + function baseIsEqualDeep(object, other, equalFunc, customizer, isLoose, stackA, stackB) { + var objIsArr = isArray(object), othIsArr = isArray(other), objTag = arrayTag, othTag = arrayTag; + if (!objIsArr) { + objTag = objToString.call(object); + if (objTag == argsTag) { + objTag = objectTag; + } else if (objTag != objectTag) { + objIsArr = isTypedArray(object); + } + } + if (!othIsArr) { + othTag = objToString.call(other); + if (othTag == argsTag) { + othTag = objectTag; + } else if (othTag != objectTag) { + othIsArr = isTypedArray(other); + } + } + var objIsObj = objTag == objectTag, othIsObj = othTag == objectTag, isSameTag = objTag == othTag; + if (isSameTag && !(objIsArr || objIsObj)) { + return equalByTag(object, other, objTag); + } + if (!isLoose) { + var objIsWrapped = objIsObj && hasOwnProperty.call(object, "__wrapped__"), othIsWrapped = othIsObj && hasOwnProperty.call(other, "__wrapped__"); + if (objIsWrapped || othIsWrapped) { + return equalFunc(objIsWrapped ? object.value() : object, othIsWrapped ? other.value() : other, customizer, isLoose, stackA, stackB); + } + } + if (!isSameTag) { + return false; + } + stackA || (stackA = []); + stackB || (stackB = []); + var length = stackA.length; + while (length--) { + if (stackA[length] == object) { + return stackB[length] == other; + } + } + stackA.push(object); + stackB.push(other); + var result = (objIsArr ? equalArrays : equalObjects)(object, other, equalFunc, customizer, isLoose, stackA, stackB); + stackA.pop(); + stackB.pop(); + return result; + } + function baseIsMatch(object, matchData, customizer) { + var index = matchData.length, length = index, noCustomizer = !customizer; + if (object == null) { + return !length; + } + object = toObject(object); + while (index--) { + var data = matchData[index]; + if (noCustomizer && data[2] ? data[1] !== object[data[0]] : !(data[0] in object)) { + return false; + } + } + while (++index < length) { + data = matchData[index]; + var key = data[0], objValue = object[key], srcValue = data[1]; + if (noCustomizer && data[2]) { + if (objValue === undefined && !(key in object)) { + return false; + } + } else { + var result = customizer ? customizer(objValue, srcValue, key) : undefined; + if (!(result === undefined ? baseIsEqual(srcValue, objValue, customizer, true) : result)) { + return false; + } + } + } + return true; + } + function baseMap(collection, iteratee) { + var index = -1, result = isArrayLike(collection) ? Array(collection.length) : []; + baseEach(collection, function(value, key, collection) { + result[++index] = iteratee(value, key, collection); + }); + return result; + } + function baseMatches(source) { + var matchData = getMatchData(source); + if (matchData.length == 1 && matchData[0][2]) { + var key = matchData[0][0], value = matchData[0][1]; + return function(object) { + if (object == null) { + return false; + } + return object[key] === value && (value !== undefined || key in toObject(object)); + }; + } + return function(object) { + return baseIsMatch(object, matchData); + }; + } + function baseMatchesProperty(path, srcValue) { + var isArr = isArray(path), isCommon = isKey(path) && isStrictComparable(srcValue), pathKey = path + ""; + path = toPath(path); + return function(object) { + if (object == null) { + return false; + } + var key = pathKey; + object = toObject(object); + if ((isArr || !isCommon) && !(key in object)) { + object = path.length == 1 ? object : baseGet(object, baseSlice(path, 0, -1)); + if (object == null) { + return false; + } + key = last(path); + object = toObject(object); + } + return object[key] === srcValue ? srcValue !== undefined || key in object : baseIsEqual(srcValue, object[key], undefined, true); + }; + } + function baseMerge(object, source, customizer, stackA, stackB) { + if (!isObject(object)) { + return object; + } + var isSrcArr = isArrayLike(source) && (isArray(source) || isTypedArray(source)), props = isSrcArr ? undefined : keys(source); + arrayEach(props || source, function(srcValue, key) { + if (props) { + key = srcValue; + srcValue = source[key]; + } + if (isObjectLike(srcValue)) { + stackA || (stackA = []); + stackB || (stackB = []); + baseMergeDeep(object, source, key, baseMerge, customizer, stackA, stackB); + } else { + var value = object[key], result = customizer ? customizer(value, srcValue, key, object, source) : undefined, isCommon = result === undefined; + if (isCommon) { + result = srcValue; + } + if ((result !== undefined || isSrcArr && !(key in object)) && (isCommon || (result === result ? result !== value : value === value))) { + object[key] = result; + } + } + }); + return object; + } + function baseMergeDeep(object, source, key, mergeFunc, customizer, stackA, stackB) { + var length = stackA.length, srcValue = source[key]; + while (length--) { + if (stackA[length] == srcValue) { + object[key] = stackB[length]; + return; + } + } + var value = object[key], result = customizer ? customizer(value, srcValue, key, object, source) : undefined, isCommon = result === undefined; + if (isCommon) { + result = srcValue; + if (isArrayLike(srcValue) && (isArray(srcValue) || isTypedArray(srcValue))) { + result = isArray(value) ? value : isArrayLike(value) ? arrayCopy(value) : []; + } else if (isPlainObject(srcValue) || isArguments(srcValue)) { + result = isArguments(value) ? toPlainObject(value) : isPlainObject(value) ? value : {}; + } else { + isCommon = false; + } + } + stackA.push(srcValue); + stackB.push(result); + if (isCommon) { + object[key] = mergeFunc(result, srcValue, customizer, stackA, stackB); + } else if (result === result ? result !== value : value === value) { + object[key] = result; + } + } + function baseProperty(key) { + return function(object) { + return object == null ? undefined : object[key]; + }; + } + function basePropertyDeep(path) { + var pathKey = path + ""; + path = toPath(path); + return function(object) { + return baseGet(object, path, pathKey); + }; + } + function basePullAt(array, indexes) { + var length = array ? indexes.length : 0; + while (length--) { + var index = indexes[length]; + if (index != previous && isIndex(index)) { + var previous = index; + splice.call(array, index, 1); + } + } + return array; + } + function baseRandom(min, max) { + return min + nativeFloor(nativeRandom() * (max - min + 1)); + } + function baseReduce(collection, iteratee, accumulator, initFromCollection, eachFunc) { + eachFunc(collection, function(value, index, collection) { + accumulator = initFromCollection ? (initFromCollection = false, value) : iteratee(accumulator, value, index, collection); + }); + return accumulator; + } + var baseSetData = !metaMap ? identity : function(func, data) { + metaMap.set(func, data); + return func; + }; + function baseSlice(array, start, end) { + var index = -1, length = array.length; + start = start == null ? 0 : +start || 0; + if (start < 0) { + start = -start > length ? 0 : length + start; + } + end = end === undefined || end > length ? length : +end || 0; + if (end < 0) { + end += length; + } + length = start > end ? 0 : end - start >>> 0; + start >>>= 0; + var result = Array(length); + while (++index < length) { + result[index] = array[index + start]; + } + return result; + } + function baseSome(collection, predicate) { + var result; + baseEach(collection, function(value, index, collection) { + result = predicate(value, index, collection); + return !result; + }); + return !!result; + } + function baseSortBy(array, comparer) { + var length = array.length; + array.sort(comparer); + while (length--) { + array[length] = array[length].value; + } + return array; + } + function baseSortByOrder(collection, iteratees, orders) { + var callback = getCallback(), index = -1; + iteratees = arrayMap(iteratees, function(iteratee) { + return callback(iteratee); + }); + var result = baseMap(collection, function(value) { + var criteria = arrayMap(iteratees, function(iteratee) { + return iteratee(value); + }); + return { + criteria: criteria, + index: ++index, + value: value + }; + }); + return baseSortBy(result, function(object, other) { + return compareMultiple(object, other, orders); + }); + } + function baseSum(collection, iteratee) { + var result = 0; + baseEach(collection, function(value, index, collection) { + result += +iteratee(value, index, collection) || 0; + }); + return result; + } + function baseUniq(array, iteratee) { + var index = -1, indexOf = getIndexOf(), length = array.length, isCommon = indexOf === baseIndexOf, isLarge = isCommon && length >= LARGE_ARRAY_SIZE, seen = isLarge ? createCache() : null, result = []; + if (seen) { + indexOf = cacheIndexOf; + isCommon = false; + } else { + isLarge = false; + seen = iteratee ? [] : result; + } + outer: while (++index < length) { + var value = array[index], computed = iteratee ? iteratee(value, index, array) : value; + if (isCommon && value === value) { + var seenIndex = seen.length; + while (seenIndex--) { + if (seen[seenIndex] === computed) { + continue outer; + } + } + if (iteratee) { + seen.push(computed); + } + result.push(value); + } else if (indexOf(seen, computed, 0) < 0) { + if (iteratee || isLarge) { + seen.push(computed); + } + result.push(value); + } + } + return result; + } + function baseValues(object, props) { + var index = -1, length = props.length, result = Array(length); + while (++index < length) { + result[index] = object[props[index]]; + } + return result; + } + function baseWhile(array, predicate, isDrop, fromRight) { + var length = array.length, index = fromRight ? length : -1; + while ((fromRight ? index-- : ++index < length) && predicate(array[index], index, array)) {} + return isDrop ? baseSlice(array, fromRight ? 0 : index, fromRight ? index + 1 : length) : baseSlice(array, fromRight ? index + 1 : 0, fromRight ? length : index); + } + function baseWrapperValue(value, actions) { + var result = value; + if (result instanceof LazyWrapper) { + result = result.value(); + } + var index = -1, length = actions.length; + while (++index < length) { + var action = actions[index]; + result = action.func.apply(action.thisArg, arrayPush([ result ], action.args)); + } + return result; + } + function binaryIndex(array, value, retHighest) { + var low = 0, high = array ? array.length : low; + if (typeof value == "number" && value === value && high <= HALF_MAX_ARRAY_LENGTH) { + while (low < high) { + var mid = low + high >>> 1, computed = array[mid]; + if ((retHighest ? computed <= value : computed < value) && computed !== null) { + low = mid + 1; + } else { + high = mid; + } + } + return high; + } + return binaryIndexBy(array, value, identity, retHighest); + } + function binaryIndexBy(array, value, iteratee, retHighest) { + value = iteratee(value); + var low = 0, high = array ? array.length : 0, valIsNaN = value !== value, valIsNull = value === null, valIsUndef = value === undefined; + while (low < high) { + var mid = nativeFloor((low + high) / 2), computed = iteratee(array[mid]), isDef = computed !== undefined, isReflexive = computed === computed; + if (valIsNaN) { + var setLow = isReflexive || retHighest; + } else if (valIsNull) { + setLow = isReflexive && isDef && (retHighest || computed != null); + } else if (valIsUndef) { + setLow = isReflexive && (retHighest || isDef); + } else if (computed == null) { + setLow = false; + } else { + setLow = retHighest ? computed <= value : computed < value; + } + if (setLow) { + low = mid + 1; + } else { + high = mid; + } + } + return nativeMin(high, MAX_ARRAY_INDEX); + } + function bindCallback(func, thisArg, argCount) { + if (typeof func != "function") { + return identity; + } + if (thisArg === undefined) { + return func; + } + switch (argCount) { + case 1: + return function(value) { + return func.call(thisArg, value); + }; + + case 3: + return function(value, index, collection) { + return func.call(thisArg, value, index, collection); + }; + + case 4: + return function(accumulator, value, index, collection) { + return func.call(thisArg, accumulator, value, index, collection); + }; + + case 5: + return function(value, other, key, object, source) { + return func.call(thisArg, value, other, key, object, source); + }; + } + return function() { + return func.apply(thisArg, arguments); + }; + } + function bufferClone(buffer) { + var result = new ArrayBuffer(buffer.byteLength), view = new Uint8Array(result); + view.set(new Uint8Array(buffer)); + return result; + } + function composeArgs(args, partials, holders) { + var holdersLength = holders.length, argsIndex = -1, argsLength = nativeMax(args.length - holdersLength, 0), leftIndex = -1, leftLength = partials.length, result = Array(leftLength + argsLength); + while (++leftIndex < leftLength) { + result[leftIndex] = partials[leftIndex]; + } + while (++argsIndex < holdersLength) { + result[holders[argsIndex]] = args[argsIndex]; + } + while (argsLength--) { + result[leftIndex++] = args[argsIndex++]; + } + return result; + } + function composeArgsRight(args, partials, holders) { + var holdersIndex = -1, holdersLength = holders.length, argsIndex = -1, argsLength = nativeMax(args.length - holdersLength, 0), rightIndex = -1, rightLength = partials.length, result = Array(argsLength + rightLength); + while (++argsIndex < argsLength) { + result[argsIndex] = args[argsIndex]; + } + var offset = argsIndex; + while (++rightIndex < rightLength) { + result[offset + rightIndex] = partials[rightIndex]; + } + while (++holdersIndex < holdersLength) { + result[offset + holders[holdersIndex]] = args[argsIndex++]; + } + return result; + } + function createAggregator(setter, initializer) { + return function(collection, iteratee, thisArg) { + var result = initializer ? initializer() : {}; + iteratee = getCallback(iteratee, thisArg, 3); + if (isArray(collection)) { + var index = -1, length = collection.length; + while (++index < length) { + var value = collection[index]; + setter(result, value, iteratee(value, index, collection), collection); + } + } else { + baseEach(collection, function(value, key, collection) { + setter(result, value, iteratee(value, key, collection), collection); + }); + } + return result; + }; + } + function createAssigner(assigner) { + return restParam(function(object, sources) { + var index = -1, length = object == null ? 0 : sources.length, customizer = length > 2 ? sources[length - 2] : undefined, guard = length > 2 ? sources[2] : undefined, thisArg = length > 1 ? sources[length - 1] : undefined; + if (typeof customizer == "function") { + customizer = bindCallback(customizer, thisArg, 5); + length -= 2; + } else { + customizer = typeof thisArg == "function" ? thisArg : undefined; + length -= customizer ? 1 : 0; + } + if (guard && isIterateeCall(sources[0], sources[1], guard)) { + customizer = length < 3 ? undefined : customizer; + length = 1; + } + while (++index < length) { + var source = sources[index]; + if (source) { + assigner(object, source, customizer); + } + } + return object; + }); + } + function createBaseEach(eachFunc, fromRight) { + return function(collection, iteratee) { + var length = collection ? getLength(collection) : 0; + if (!isLength(length)) { + return eachFunc(collection, iteratee); + } + var index = fromRight ? length : -1, iterable = toObject(collection); + while (fromRight ? index-- : ++index < length) { + if (iteratee(iterable[index], index, iterable) === false) { + break; + } + } + return collection; + }; + } + function createBaseFor(fromRight) { + return function(object, iteratee, keysFunc) { + var iterable = toObject(object), props = keysFunc(object), length = props.length, index = fromRight ? length : -1; + while (fromRight ? index-- : ++index < length) { + var key = props[index]; + if (iteratee(iterable[key], key, iterable) === false) { + break; + } + } + return object; + }; + } + function createBindWrapper(func, thisArg) { + var Ctor = createCtorWrapper(func); + function wrapper() { + var fn = this && this !== root && this instanceof wrapper ? Ctor : func; + return fn.apply(thisArg, arguments); + } + return wrapper; + } + function createCache(values) { + return nativeCreate && Set ? new SetCache(values) : null; + } + function createCompounder(callback) { + return function(string) { + var index = -1, array = words(deburr(string)), length = array.length, result = ""; + while (++index < length) { + result = callback(result, array[index], index); + } + return result; + }; + } + function createCtorWrapper(Ctor) { + return function() { + var args = arguments; + switch (args.length) { + case 0: + return new Ctor(); + + case 1: + return new Ctor(args[0]); + + case 2: + return new Ctor(args[0], args[1]); + + case 3: + return new Ctor(args[0], args[1], args[2]); + + case 4: + return new Ctor(args[0], args[1], args[2], args[3]); + + case 5: + return new Ctor(args[0], args[1], args[2], args[3], args[4]); + + case 6: + return new Ctor(args[0], args[1], args[2], args[3], args[4], args[5]); + + case 7: + return new Ctor(args[0], args[1], args[2], args[3], args[4], args[5], args[6]); + } + var thisBinding = baseCreate(Ctor.prototype), result = Ctor.apply(thisBinding, args); + return isObject(result) ? result : thisBinding; + }; + } + function createCurry(flag) { + function curryFunc(func, arity, guard) { + if (guard && isIterateeCall(func, arity, guard)) { + arity = undefined; + } + var result = createWrapper(func, flag, undefined, undefined, undefined, undefined, undefined, arity); + result.placeholder = curryFunc.placeholder; + return result; + } + return curryFunc; + } + function createDefaults(assigner, customizer) { + return restParam(function(args) { + var object = args[0]; + if (object == null) { + return object; + } + args.push(customizer); + return assigner.apply(undefined, args); + }); + } + function createExtremum(comparator, exValue) { + return function(collection, iteratee, thisArg) { + if (thisArg && isIterateeCall(collection, iteratee, thisArg)) { + iteratee = undefined; + } + iteratee = getCallback(iteratee, thisArg, 3); + if (iteratee.length == 1) { + collection = isArray(collection) ? collection : toIterable(collection); + var result = arrayExtremum(collection, iteratee, comparator, exValue); + if (!(collection.length && result === exValue)) { + return result; + } + } + return baseExtremum(collection, iteratee, comparator, exValue); + }; + } + function createFind(eachFunc, fromRight) { + return function(collection, predicate, thisArg) { + predicate = getCallback(predicate, thisArg, 3); + if (isArray(collection)) { + var index = baseFindIndex(collection, predicate, fromRight); + return index > -1 ? collection[index] : undefined; + } + return baseFind(collection, predicate, eachFunc); + }; + } + function createFindIndex(fromRight) { + return function(array, predicate, thisArg) { + if (!(array && array.length)) { + return -1; + } + predicate = getCallback(predicate, thisArg, 3); + return baseFindIndex(array, predicate, fromRight); + }; + } + function createFindKey(objectFunc) { + return function(object, predicate, thisArg) { + predicate = getCallback(predicate, thisArg, 3); + return baseFind(object, predicate, objectFunc, true); + }; + } + function createFlow(fromRight) { + return function() { + var wrapper, length = arguments.length, index = fromRight ? length : -1, leftIndex = 0, funcs = Array(length); + while (fromRight ? index-- : ++index < length) { + var func = funcs[leftIndex++] = arguments[index]; + if (typeof func != "function") { + throw new TypeError(FUNC_ERROR_TEXT); + } + if (!wrapper && LodashWrapper.prototype.thru && getFuncName(func) == "wrapper") { + wrapper = new LodashWrapper([], true); + } + } + index = wrapper ? -1 : length; + while (++index < length) { + func = funcs[index]; + var funcName = getFuncName(func), data = funcName == "wrapper" ? getData(func) : undefined; + if (data && isLaziable(data[0]) && data[1] == (ARY_FLAG | CURRY_FLAG | PARTIAL_FLAG | REARG_FLAG) && !data[4].length && data[9] == 1) { + wrapper = wrapper[getFuncName(data[0])].apply(wrapper, data[3]); + } else { + wrapper = func.length == 1 && isLaziable(func) ? wrapper[funcName]() : wrapper.thru(func); + } + } + return function() { + var args = arguments, value = args[0]; + if (wrapper && args.length == 1 && isArray(value) && value.length >= LARGE_ARRAY_SIZE) { + return wrapper.plant(value).value(); + } + var index = 0, result = length ? funcs[index].apply(this, args) : value; + while (++index < length) { + result = funcs[index].call(this, result); + } + return result; + }; + }; + } + function createForEach(arrayFunc, eachFunc) { + return function(collection, iteratee, thisArg) { + return typeof iteratee == "function" && thisArg === undefined && isArray(collection) ? arrayFunc(collection, iteratee) : eachFunc(collection, bindCallback(iteratee, thisArg, 3)); + }; + } + function createForIn(objectFunc) { + return function(object, iteratee, thisArg) { + if (typeof iteratee != "function" || thisArg !== undefined) { + iteratee = bindCallback(iteratee, thisArg, 3); + } + return objectFunc(object, iteratee, keysIn); + }; + } + function createForOwn(objectFunc) { + return function(object, iteratee, thisArg) { + if (typeof iteratee != "function" || thisArg !== undefined) { + iteratee = bindCallback(iteratee, thisArg, 3); + } + return objectFunc(object, iteratee); + }; + } + function createObjectMapper(isMapKeys) { + return function(object, iteratee, thisArg) { + var result = {}; + iteratee = getCallback(iteratee, thisArg, 3); + baseForOwn(object, function(value, key, object) { + var mapped = iteratee(value, key, object); + key = isMapKeys ? mapped : key; + value = isMapKeys ? value : mapped; + result[key] = value; + }); + return result; + }; + } + function createPadDir(fromRight) { + return function(string, length, chars) { + string = baseToString(string); + return (fromRight ? string : "") + createPadding(string, length, chars) + (fromRight ? "" : string); + }; + } + function createPartial(flag) { + var partialFunc = restParam(function(func, partials) { + var holders = replaceHolders(partials, partialFunc.placeholder); + return createWrapper(func, flag, undefined, partials, holders); + }); + return partialFunc; + } + function createReduce(arrayFunc, eachFunc) { + return function(collection, iteratee, accumulator, thisArg) { + var initFromArray = arguments.length < 3; + return typeof iteratee == "function" && thisArg === undefined && isArray(collection) ? arrayFunc(collection, iteratee, accumulator, initFromArray) : baseReduce(collection, getCallback(iteratee, thisArg, 4), accumulator, initFromArray, eachFunc); + }; + } + function createHybridWrapper(func, bitmask, thisArg, partials, holders, partialsRight, holdersRight, argPos, ary, arity) { + var isAry = bitmask & ARY_FLAG, isBind = bitmask & BIND_FLAG, isBindKey = bitmask & BIND_KEY_FLAG, isCurry = bitmask & CURRY_FLAG, isCurryBound = bitmask & CURRY_BOUND_FLAG, isCurryRight = bitmask & CURRY_RIGHT_FLAG, Ctor = isBindKey ? undefined : createCtorWrapper(func); + function wrapper() { + var length = arguments.length, index = length, args = Array(length); + while (index--) { + args[index] = arguments[index]; + } + if (partials) { + args = composeArgs(args, partials, holders); + } + if (partialsRight) { + args = composeArgsRight(args, partialsRight, holdersRight); + } + if (isCurry || isCurryRight) { + var placeholder = wrapper.placeholder, argsHolders = replaceHolders(args, placeholder); + length -= argsHolders.length; + if (length < arity) { + var newArgPos = argPos ? arrayCopy(argPos) : undefined, newArity = nativeMax(arity - length, 0), newsHolders = isCurry ? argsHolders : undefined, newHoldersRight = isCurry ? undefined : argsHolders, newPartials = isCurry ? args : undefined, newPartialsRight = isCurry ? undefined : args; + bitmask |= isCurry ? PARTIAL_FLAG : PARTIAL_RIGHT_FLAG; + bitmask &= ~(isCurry ? PARTIAL_RIGHT_FLAG : PARTIAL_FLAG); + if (!isCurryBound) { + bitmask &= ~(BIND_FLAG | BIND_KEY_FLAG); + } + var newData = [ func, bitmask, thisArg, newPartials, newsHolders, newPartialsRight, newHoldersRight, newArgPos, ary, newArity ], result = createHybridWrapper.apply(undefined, newData); + if (isLaziable(func)) { + setData(result, newData); + } + result.placeholder = placeholder; + return result; + } + } + var thisBinding = isBind ? thisArg : this, fn = isBindKey ? thisBinding[func] : func; + if (argPos) { + args = reorder(args, argPos); + } + if (isAry && ary < args.length) { + args.length = ary; + } + if (this && this !== root && this instanceof wrapper) { + fn = Ctor || createCtorWrapper(func); + } + return fn.apply(thisBinding, args); + } + return wrapper; + } + function createPadding(string, length, chars) { + var strLength = string.length; + length = +length; + if (strLength >= length || !nativeIsFinite(length)) { + return ""; + } + var padLength = length - strLength; + chars = chars == null ? " " : chars + ""; + return repeat(chars, nativeCeil(padLength / chars.length)).slice(0, padLength); + } + function createPartialWrapper(func, bitmask, thisArg, partials) { + var isBind = bitmask & BIND_FLAG, Ctor = createCtorWrapper(func); + function wrapper() { + var argsIndex = -1, argsLength = arguments.length, leftIndex = -1, leftLength = partials.length, args = Array(leftLength + argsLength); + while (++leftIndex < leftLength) { + args[leftIndex] = partials[leftIndex]; + } + while (argsLength--) { + args[leftIndex++] = arguments[++argsIndex]; + } + var fn = this && this !== root && this instanceof wrapper ? Ctor : func; + return fn.apply(isBind ? thisArg : this, args); + } + return wrapper; + } + function createRound(methodName) { + var func = Math[methodName]; + return function(number, precision) { + precision = precision === undefined ? 0 : +precision || 0; + if (precision) { + precision = pow(10, precision); + return func(number * precision) / precision; + } + return func(number); + }; + } + function createSortedIndex(retHighest) { + return function(array, value, iteratee, thisArg) { + var callback = getCallback(iteratee); + return iteratee == null && callback === baseCallback ? binaryIndex(array, value, retHighest) : binaryIndexBy(array, value, callback(iteratee, thisArg, 1), retHighest); + }; + } + function createWrapper(func, bitmask, thisArg, partials, holders, argPos, ary, arity) { + var isBindKey = bitmask & BIND_KEY_FLAG; + if (!isBindKey && typeof func != "function") { + throw new TypeError(FUNC_ERROR_TEXT); + } + var length = partials ? partials.length : 0; + if (!length) { + bitmask &= ~(PARTIAL_FLAG | PARTIAL_RIGHT_FLAG); + partials = holders = undefined; + } + length -= holders ? holders.length : 0; + if (bitmask & PARTIAL_RIGHT_FLAG) { + var partialsRight = partials, holdersRight = holders; + partials = holders = undefined; + } + var data = isBindKey ? undefined : getData(func), newData = [ func, bitmask, thisArg, partials, holders, partialsRight, holdersRight, argPos, ary, arity ]; + if (data) { + mergeData(newData, data); + bitmask = newData[1]; + arity = newData[9]; + } + newData[9] = arity == null ? isBindKey ? 0 : func.length : nativeMax(arity - length, 0) || 0; + if (bitmask == BIND_FLAG) { + var result = createBindWrapper(newData[0], newData[2]); + } else if ((bitmask == PARTIAL_FLAG || bitmask == (BIND_FLAG | PARTIAL_FLAG)) && !newData[4].length) { + result = createPartialWrapper.apply(undefined, newData); + } else { + result = createHybridWrapper.apply(undefined, newData); + } + var setter = data ? baseSetData : setData; + return setter(result, newData); + } + function equalArrays(array, other, equalFunc, customizer, isLoose, stackA, stackB) { + var index = -1, arrLength = array.length, othLength = other.length; + if (arrLength != othLength && !(isLoose && othLength > arrLength)) { + return false; + } + while (++index < arrLength) { + var arrValue = array[index], othValue = other[index], result = customizer ? customizer(isLoose ? othValue : arrValue, isLoose ? arrValue : othValue, index) : undefined; + if (result !== undefined) { + if (result) { + continue; + } + return false; + } + if (isLoose) { + if (!arraySome(other, function(othValue) { + return arrValue === othValue || equalFunc(arrValue, othValue, customizer, isLoose, stackA, stackB); + })) { + return false; + } + } else if (!(arrValue === othValue || equalFunc(arrValue, othValue, customizer, isLoose, stackA, stackB))) { + return false; + } + } + return true; + } + function equalByTag(object, other, tag) { + switch (tag) { + case boolTag: + case dateTag: + return +object == +other; + + case errorTag: + return object.name == other.name && object.message == other.message; + + case numberTag: + return object != +object ? other != +other : object == +other; + + case regexpTag: + case stringTag: + return object == other + ""; + } + return false; + } + function equalObjects(object, other, equalFunc, customizer, isLoose, stackA, stackB) { + var objProps = keys(object), objLength = objProps.length, othProps = keys(other), othLength = othProps.length; + if (objLength != othLength && !isLoose) { + return false; + } + var index = objLength; + while (index--) { + var key = objProps[index]; + if (!(isLoose ? key in other : hasOwnProperty.call(other, key))) { + return false; + } + } + var skipCtor = isLoose; + while (++index < objLength) { + key = objProps[index]; + var objValue = object[key], othValue = other[key], result = customizer ? customizer(isLoose ? othValue : objValue, isLoose ? objValue : othValue, key) : undefined; + if (!(result === undefined ? equalFunc(objValue, othValue, customizer, isLoose, stackA, stackB) : result)) { + return false; + } + skipCtor || (skipCtor = key == "constructor"); + } + if (!skipCtor) { + var objCtor = object.constructor, othCtor = other.constructor; + if (objCtor != othCtor && ("constructor" in object && "constructor" in other) && !(typeof objCtor == "function" && objCtor instanceof objCtor && typeof othCtor == "function" && othCtor instanceof othCtor)) { + return false; + } + } + return true; + } + function getCallback(func, thisArg, argCount) { + var result = lodash.callback || callback; + result = result === callback ? baseCallback : result; + return argCount ? result(func, thisArg, argCount) : result; + } + var getData = !metaMap ? noop : function(func) { + return metaMap.get(func); + }; + function getFuncName(func) { + var result = func.name + "", array = realNames[result], length = array ? array.length : 0; + while (length--) { + var data = array[length], otherFunc = data.func; + if (otherFunc == null || otherFunc == func) { + return data.name; + } + } + return result; + } + function getIndexOf(collection, target, fromIndex) { + var result = lodash.indexOf || indexOf; + result = result === indexOf ? baseIndexOf : result; + return collection ? result(collection, target, fromIndex) : result; + } + var getLength = baseProperty("length"); + function getMatchData(object) { + var result = pairs(object), length = result.length; + while (length--) { + result[length][2] = isStrictComparable(result[length][1]); + } + return result; + } + function getNative(object, key) { + var value = object == null ? undefined : object[key]; + return isNative(value) ? value : undefined; + } + function getView(start, end, transforms) { + var index = -1, length = transforms.length; + while (++index < length) { + var data = transforms[index], size = data.size; + switch (data.type) { + case "drop": + start += size; + break; + + case "dropRight": + end -= size; + break; + + case "take": + end = nativeMin(end, start + size); + break; + + case "takeRight": + start = nativeMax(start, end - size); + break; + } + } + return { + start: start, + end: end + }; + } + function initCloneArray(array) { + var length = array.length, result = new array.constructor(length); + if (length && typeof array[0] == "string" && hasOwnProperty.call(array, "index")) { + result.index = array.index; + result.input = array.input; + } + return result; + } + function initCloneObject(object) { + var Ctor = object.constructor; + if (!(typeof Ctor == "function" && Ctor instanceof Ctor)) { + Ctor = Object; + } + return new Ctor(); + } + function initCloneByTag(object, tag, isDeep) { + var Ctor = object.constructor; + switch (tag) { + case arrayBufferTag: + return bufferClone(object); + + case boolTag: + case dateTag: + return new Ctor(+object); + + case float32Tag: + case float64Tag: + case int8Tag: + case int16Tag: + case int32Tag: + case uint8Tag: + case uint8ClampedTag: + case uint16Tag: + case uint32Tag: + var buffer = object.buffer; + return new Ctor(isDeep ? bufferClone(buffer) : buffer, object.byteOffset, object.length); + + case numberTag: + case stringTag: + return new Ctor(object); + + case regexpTag: + var result = new Ctor(object.source, reFlags.exec(object)); + result.lastIndex = object.lastIndex; + } + return result; + } + function invokePath(object, path, args) { + if (object != null && !isKey(path, object)) { + path = toPath(path); + object = path.length == 1 ? object : baseGet(object, baseSlice(path, 0, -1)); + path = last(path); + } + var func = object == null ? object : object[path]; + return func == null ? undefined : func.apply(object, args); + } + function isArrayLike(value) { + return value != null && isLength(getLength(value)); + } + function isIndex(value, length) { + value = typeof value == "number" || reIsUint.test(value) ? +value : -1; + length = length == null ? MAX_SAFE_INTEGER : length; + return value > -1 && value % 1 == 0 && value < length; + } + function isIterateeCall(value, index, object) { + if (!isObject(object)) { + return false; + } + var type = typeof index; + if (type == "number" ? isArrayLike(object) && isIndex(index, object.length) : type == "string" && index in object) { + var other = object[index]; + return value === value ? value === other : other !== other; + } + return false; + } + function isKey(value, object) { + var type = typeof value; + if (type == "string" && reIsPlainProp.test(value) || type == "number") { + return true; + } + if (isArray(value)) { + return false; + } + var result = !reIsDeepProp.test(value); + return result || object != null && value in toObject(object); + } + function isLaziable(func) { + var funcName = getFuncName(func), other = lodash[funcName]; + if (typeof other != "function" || !(funcName in LazyWrapper.prototype)) { + return false; + } + if (func === other) { + return true; + } + var data = getData(other); + return !!data && func === data[0]; + } + function isLength(value) { + return typeof value == "number" && value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER; + } + function isStrictComparable(value) { + return value === value && !isObject(value); + } + function mergeData(data, source) { + var bitmask = data[1], srcBitmask = source[1], newBitmask = bitmask | srcBitmask, isCommon = newBitmask < ARY_FLAG; + var isCombo = srcBitmask == ARY_FLAG && bitmask == CURRY_FLAG || srcBitmask == ARY_FLAG && bitmask == REARG_FLAG && data[7].length <= source[8] || srcBitmask == (ARY_FLAG | REARG_FLAG) && bitmask == CURRY_FLAG; + if (!(isCommon || isCombo)) { + return data; + } + if (srcBitmask & BIND_FLAG) { + data[2] = source[2]; + newBitmask |= bitmask & BIND_FLAG ? 0 : CURRY_BOUND_FLAG; + } + var value = source[3]; + if (value) { + var partials = data[3]; + data[3] = partials ? composeArgs(partials, value, source[4]) : arrayCopy(value); + data[4] = partials ? replaceHolders(data[3], PLACEHOLDER) : arrayCopy(source[4]); + } + value = source[5]; + if (value) { + partials = data[5]; + data[5] = partials ? composeArgsRight(partials, value, source[6]) : arrayCopy(value); + data[6] = partials ? replaceHolders(data[5], PLACEHOLDER) : arrayCopy(source[6]); + } + value = source[7]; + if (value) { + data[7] = arrayCopy(value); + } + if (srcBitmask & ARY_FLAG) { + data[8] = data[8] == null ? source[8] : nativeMin(data[8], source[8]); + } + if (data[9] == null) { + data[9] = source[9]; + } + data[0] = source[0]; + data[1] = newBitmask; + return data; + } + function mergeDefaults(objectValue, sourceValue) { + return objectValue === undefined ? sourceValue : merge(objectValue, sourceValue, mergeDefaults); + } + function pickByArray(object, props) { + object = toObject(object); + var index = -1, length = props.length, result = {}; + while (++index < length) { + var key = props[index]; + if (key in object) { + result[key] = object[key]; + } + } + return result; + } + function pickByCallback(object, predicate) { + var result = {}; + baseForIn(object, function(value, key, object) { + if (predicate(value, key, object)) { + result[key] = value; + } + }); + return result; + } + function reorder(array, indexes) { + var arrLength = array.length, length = nativeMin(indexes.length, arrLength), oldArray = arrayCopy(array); + while (length--) { + var index = indexes[length]; + array[length] = isIndex(index, arrLength) ? oldArray[index] : undefined; + } + return array; + } + var setData = function() { + var count = 0, lastCalled = 0; + return function(key, value) { + var stamp = now(), remaining = HOT_SPAN - (stamp - lastCalled); + lastCalled = stamp; + if (remaining > 0) { + if (++count >= HOT_COUNT) { + return key; + } + } else { + count = 0; + } + return baseSetData(key, value); + }; + }(); + function shimKeys(object) { + var props = keysIn(object), propsLength = props.length, length = propsLength && object.length; + var allowIndexes = !!length && isLength(length) && (isArray(object) || isArguments(object)); + var index = -1, result = []; + while (++index < propsLength) { + var key = props[index]; + if (allowIndexes && isIndex(key, length) || hasOwnProperty.call(object, key)) { + result.push(key); + } + } + return result; + } + function toIterable(value) { + if (value == null) { + return []; + } + if (!isArrayLike(value)) { + return values(value); + } + return isObject(value) ? value : Object(value); + } + function toObject(value) { + return isObject(value) ? value : Object(value); + } + function toPath(value) { + if (isArray(value)) { + return value; + } + var result = []; + baseToString(value).replace(rePropName, function(match, number, quote, string) { + result.push(quote ? string.replace(reEscapeChar, "$1") : number || match); + }); + return result; + } + function wrapperClone(wrapper) { + return wrapper instanceof LazyWrapper ? wrapper.clone() : new LodashWrapper(wrapper.__wrapped__, wrapper.__chain__, arrayCopy(wrapper.__actions__)); + } + function chunk(array, size, guard) { + if (guard ? isIterateeCall(array, size, guard) : size == null) { + size = 1; + } else { + size = nativeMax(nativeFloor(size) || 1, 1); + } + var index = 0, length = array ? array.length : 0, resIndex = -1, result = Array(nativeCeil(length / size)); + while (index < length) { + result[++resIndex] = baseSlice(array, index, index += size); + } + return result; + } + function compact(array) { + var index = -1, length = array ? array.length : 0, resIndex = -1, result = []; + while (++index < length) { + var value = array[index]; + if (value) { + result[++resIndex] = value; + } + } + return result; + } + var difference = restParam(function(array, values) { + return isObjectLike(array) && isArrayLike(array) ? baseDifference(array, baseFlatten(values, false, true)) : []; + }); + function drop(array, n, guard) { + var length = array ? array.length : 0; + if (!length) { + return []; + } + if (guard ? isIterateeCall(array, n, guard) : n == null) { + n = 1; + } + return baseSlice(array, n < 0 ? 0 : n); + } + function dropRight(array, n, guard) { + var length = array ? array.length : 0; + if (!length) { + return []; + } + if (guard ? isIterateeCall(array, n, guard) : n == null) { + n = 1; + } + n = length - (+n || 0); + return baseSlice(array, 0, n < 0 ? 0 : n); + } + function dropRightWhile(array, predicate, thisArg) { + return array && array.length ? baseWhile(array, getCallback(predicate, thisArg, 3), true, true) : []; + } + function dropWhile(array, predicate, thisArg) { + return array && array.length ? baseWhile(array, getCallback(predicate, thisArg, 3), true) : []; + } + function fill(array, value, start, end) { + var length = array ? array.length : 0; + if (!length) { + return []; + } + if (start && typeof start != "number" && isIterateeCall(array, value, start)) { + start = 0; + end = length; + } + return baseFill(array, value, start, end); + } + var findIndex = createFindIndex(); + var findLastIndex = createFindIndex(true); + function first(array) { + return array ? array[0] : undefined; + } + function flatten(array, isDeep, guard) { + var length = array ? array.length : 0; + if (guard && isIterateeCall(array, isDeep, guard)) { + isDeep = false; + } + return length ? baseFlatten(array, isDeep) : []; + } + function flattenDeep(array) { + var length = array ? array.length : 0; + return length ? baseFlatten(array, true) : []; + } + function indexOf(array, value, fromIndex) { + var length = array ? array.length : 0; + if (!length) { + return -1; + } + if (typeof fromIndex == "number") { + fromIndex = fromIndex < 0 ? nativeMax(length + fromIndex, 0) : fromIndex; + } else if (fromIndex) { + var index = binaryIndex(array, value); + if (index < length && (value === value ? value === array[index] : array[index] !== array[index])) { + return index; + } + return -1; + } + return baseIndexOf(array, value, fromIndex || 0); + } + function initial(array) { + return dropRight(array, 1); + } + var intersection = restParam(function(arrays) { + var othLength = arrays.length, othIndex = othLength, caches = Array(length), indexOf = getIndexOf(), isCommon = indexOf === baseIndexOf, result = []; + while (othIndex--) { + var value = arrays[othIndex] = isArrayLike(value = arrays[othIndex]) ? value : []; + caches[othIndex] = isCommon && value.length >= 120 ? createCache(othIndex && value) : null; + } + var array = arrays[0], index = -1, length = array ? array.length : 0, seen = caches[0]; + outer: while (++index < length) { + value = array[index]; + if ((seen ? cacheIndexOf(seen, value) : indexOf(result, value, 0)) < 0) { + var othIndex = othLength; + while (--othIndex) { + var cache = caches[othIndex]; + if ((cache ? cacheIndexOf(cache, value) : indexOf(arrays[othIndex], value, 0)) < 0) { + continue outer; + } + } + if (seen) { + seen.push(value); + } + result.push(value); + } + } + return result; + }); + function last(array) { + var length = array ? array.length : 0; + return length ? array[length - 1] : undefined; + } + function lastIndexOf(array, value, fromIndex) { + var length = array ? array.length : 0; + if (!length) { + return -1; + } + var index = length; + if (typeof fromIndex == "number") { + index = (fromIndex < 0 ? nativeMax(length + fromIndex, 0) : nativeMin(fromIndex || 0, length - 1)) + 1; + } else if (fromIndex) { + index = binaryIndex(array, value, true) - 1; + var other = array[index]; + if (value === value ? value === other : other !== other) { + return index; + } + return -1; + } + if (value !== value) { + return indexOfNaN(array, index, true); + } + while (index--) { + if (array[index] === value) { + return index; + } + } + return -1; + } + function pull() { + var args = arguments, array = args[0]; + if (!(array && array.length)) { + return array; + } + var index = 0, indexOf = getIndexOf(), length = args.length; + while (++index < length) { + var fromIndex = 0, value = args[index]; + while ((fromIndex = indexOf(array, value, fromIndex)) > -1) { + splice.call(array, fromIndex, 1); + } + } + return array; + } + var pullAt = restParam(function(array, indexes) { + indexes = baseFlatten(indexes); + var result = baseAt(array, indexes); + basePullAt(array, indexes.sort(baseCompareAscending)); + return result; + }); + function remove(array, predicate, thisArg) { + var result = []; + if (!(array && array.length)) { + return result; + } + var index = -1, indexes = [], length = array.length; + predicate = getCallback(predicate, thisArg, 3); + while (++index < length) { + var value = array[index]; + if (predicate(value, index, array)) { + result.push(value); + indexes.push(index); + } + } + basePullAt(array, indexes); + return result; + } + function rest(array) { + return drop(array, 1); + } + function slice(array, start, end) { + var length = array ? array.length : 0; + if (!length) { + return []; + } + if (end && typeof end != "number" && isIterateeCall(array, start, end)) { + start = 0; + end = length; + } + return baseSlice(array, start, end); + } + var sortedIndex = createSortedIndex(); + var sortedLastIndex = createSortedIndex(true); + function take(array, n, guard) { + var length = array ? array.length : 0; + if (!length) { + return []; + } + if (guard ? isIterateeCall(array, n, guard) : n == null) { + n = 1; + } + return baseSlice(array, 0, n < 0 ? 0 : n); + } + function takeRight(array, n, guard) { + var length = array ? array.length : 0; + if (!length) { + return []; + } + if (guard ? isIterateeCall(array, n, guard) : n == null) { + n = 1; + } + n = length - (+n || 0); + return baseSlice(array, n < 0 ? 0 : n); + } + function takeRightWhile(array, predicate, thisArg) { + return array && array.length ? baseWhile(array, getCallback(predicate, thisArg, 3), false, true) : []; + } + function takeWhile(array, predicate, thisArg) { + return array && array.length ? baseWhile(array, getCallback(predicate, thisArg, 3)) : []; + } + var union = restParam(function(arrays) { + return baseUniq(baseFlatten(arrays, false, true)); + }); + function uniq(array, isSorted, iteratee, thisArg) { + var length = array ? array.length : 0; + if (!length) { + return []; + } + if (isSorted != null && typeof isSorted != "boolean") { + thisArg = iteratee; + iteratee = isIterateeCall(array, isSorted, thisArg) ? undefined : isSorted; + isSorted = false; + } + var callback = getCallback(); + if (!(iteratee == null && callback === baseCallback)) { + iteratee = callback(iteratee, thisArg, 3); + } + return isSorted && getIndexOf() === baseIndexOf ? sortedUniq(array, iteratee) : baseUniq(array, iteratee); + } + function unzip(array) { + if (!(array && array.length)) { + return []; + } + var index = -1, length = 0; + array = arrayFilter(array, function(group) { + if (isArrayLike(group)) { + length = nativeMax(group.length, length); + return true; + } + }); + var result = Array(length); + while (++index < length) { + result[index] = arrayMap(array, baseProperty(index)); + } + return result; + } + function unzipWith(array, iteratee, thisArg) { + var length = array ? array.length : 0; + if (!length) { + return []; + } + var result = unzip(array); + if (iteratee == null) { + return result; + } + iteratee = bindCallback(iteratee, thisArg, 4); + return arrayMap(result, function(group) { + return arrayReduce(group, iteratee, undefined, true); + }); + } + var without = restParam(function(array, values) { + return isArrayLike(array) ? baseDifference(array, values) : []; + }); + function xor() { + var index = -1, length = arguments.length; + while (++index < length) { + var array = arguments[index]; + if (isArrayLike(array)) { + var result = result ? arrayPush(baseDifference(result, array), baseDifference(array, result)) : array; + } + } + return result ? baseUniq(result) : []; + } + var zip = restParam(unzip); + function zipObject(props, values) { + var index = -1, length = props ? props.length : 0, result = {}; + if (length && !values && !isArray(props[0])) { + values = []; + } + while (++index < length) { + var key = props[index]; + if (values) { + result[key] = values[index]; + } else if (key) { + result[key[0]] = key[1]; + } + } + return result; + } + var zipWith = restParam(function(arrays) { + var length = arrays.length, iteratee = length > 2 ? arrays[length - 2] : undefined, thisArg = length > 1 ? arrays[length - 1] : undefined; + if (length > 2 && typeof iteratee == "function") { + length -= 2; + } else { + iteratee = length > 1 && typeof thisArg == "function" ? (--length, thisArg) : undefined; + thisArg = undefined; + } + arrays.length = length; + return unzipWith(arrays, iteratee, thisArg); + }); + function chain(value) { + var result = lodash(value); + result.__chain__ = true; + return result; + } + function tap(value, interceptor, thisArg) { + interceptor.call(thisArg, value); + return value; + } + function thru(value, interceptor, thisArg) { + return interceptor.call(thisArg, value); + } + function wrapperChain() { + return chain(this); + } + function wrapperCommit() { + return new LodashWrapper(this.value(), this.__chain__); + } + var wrapperConcat = restParam(function(values) { + values = baseFlatten(values); + return this.thru(function(array) { + return arrayConcat(isArray(array) ? array : [ toObject(array) ], values); + }); + }); + function wrapperPlant(value) { + var result, parent = this; + while (parent instanceof baseLodash) { + var clone = wrapperClone(parent); + if (result) { + previous.__wrapped__ = clone; + } else { + result = clone; + } + var previous = clone; + parent = parent.__wrapped__; + } + previous.__wrapped__ = value; + return result; + } + function wrapperReverse() { + var value = this.__wrapped__; + var interceptor = function(value) { + return value.reverse(); + }; + if (value instanceof LazyWrapper) { + var wrapped = value; + if (this.__actions__.length) { + wrapped = new LazyWrapper(this); + } + wrapped = wrapped.reverse(); + wrapped.__actions__.push({ + func: thru, + args: [ interceptor ], + thisArg: undefined + }); + return new LodashWrapper(wrapped, this.__chain__); + } + return this.thru(interceptor); + } + function wrapperToString() { + return this.value() + ""; + } + function wrapperValue() { + return baseWrapperValue(this.__wrapped__, this.__actions__); + } + var at = restParam(function(collection, props) { + return baseAt(collection, baseFlatten(props)); + }); + var countBy = createAggregator(function(result, value, key) { + hasOwnProperty.call(result, key) ? ++result[key] : result[key] = 1; + }); + function every(collection, predicate, thisArg) { + var func = isArray(collection) ? arrayEvery : baseEvery; + if (thisArg && isIterateeCall(collection, predicate, thisArg)) { + predicate = undefined; + } + if (typeof predicate != "function" || thisArg !== undefined) { + predicate = getCallback(predicate, thisArg, 3); + } + return func(collection, predicate); + } + function filter(collection, predicate, thisArg) { + var func = isArray(collection) ? arrayFilter : baseFilter; + predicate = getCallback(predicate, thisArg, 3); + return func(collection, predicate); + } + var find = createFind(baseEach); + var findLast = createFind(baseEachRight, true); + function findWhere(collection, source) { + return find(collection, baseMatches(source)); + } + var forEach = createForEach(arrayEach, baseEach); + var forEachRight = createForEach(arrayEachRight, baseEachRight); + var groupBy = createAggregator(function(result, value, key) { + if (hasOwnProperty.call(result, key)) { + result[key].push(value); + } else { + result[key] = [ value ]; + } + }); + function includes(collection, target, fromIndex, guard) { + var length = collection ? getLength(collection) : 0; + if (!isLength(length)) { + collection = values(collection); + length = collection.length; + } + if (typeof fromIndex != "number" || guard && isIterateeCall(target, fromIndex, guard)) { + fromIndex = 0; + } else { + fromIndex = fromIndex < 0 ? nativeMax(length + fromIndex, 0) : fromIndex || 0; + } + return typeof collection == "string" || !isArray(collection) && isString(collection) ? fromIndex <= length && collection.indexOf(target, fromIndex) > -1 : !!length && getIndexOf(collection, target, fromIndex) > -1; + } + var indexBy = createAggregator(function(result, value, key) { + result[key] = value; + }); + var invoke = restParam(function(collection, path, args) { + var index = -1, isFunc = typeof path == "function", isProp = isKey(path), result = isArrayLike(collection) ? Array(collection.length) : []; + baseEach(collection, function(value) { + var func = isFunc ? path : isProp && value != null ? value[path] : undefined; + result[++index] = func ? func.apply(value, args) : invokePath(value, path, args); + }); + return result; + }); + function map(collection, iteratee, thisArg) { + var func = isArray(collection) ? arrayMap : baseMap; + iteratee = getCallback(iteratee, thisArg, 3); + return func(collection, iteratee); + } + var partition = createAggregator(function(result, value, key) { + result[key ? 0 : 1].push(value); + }, function() { + return [ [], [] ]; + }); + function pluck(collection, path) { + return map(collection, property(path)); + } + var reduce = createReduce(arrayReduce, baseEach); + var reduceRight = createReduce(arrayReduceRight, baseEachRight); + function reject(collection, predicate, thisArg) { + var func = isArray(collection) ? arrayFilter : baseFilter; + predicate = getCallback(predicate, thisArg, 3); + return func(collection, function(value, index, collection) { + return !predicate(value, index, collection); + }); + } + function sample(collection, n, guard) { + if (guard ? isIterateeCall(collection, n, guard) : n == null) { + collection = toIterable(collection); + var length = collection.length; + return length > 0 ? collection[baseRandom(0, length - 1)] : undefined; + } + var index = -1, result = toArray(collection), length = result.length, lastIndex = length - 1; + n = nativeMin(n < 0 ? 0 : +n || 0, length); + while (++index < n) { + var rand = baseRandom(index, lastIndex), value = result[rand]; + result[rand] = result[index]; + result[index] = value; + } + result.length = n; + return result; + } + function shuffle(collection) { + return sample(collection, POSITIVE_INFINITY); + } + function size(collection) { + var length = collection ? getLength(collection) : 0; + return isLength(length) ? length : keys(collection).length; + } + function some(collection, predicate, thisArg) { + var func = isArray(collection) ? arraySome : baseSome; + if (thisArg && isIterateeCall(collection, predicate, thisArg)) { + predicate = undefined; + } + if (typeof predicate != "function" || thisArg !== undefined) { + predicate = getCallback(predicate, thisArg, 3); + } + return func(collection, predicate); + } + function sortBy(collection, iteratee, thisArg) { + if (collection == null) { + return []; + } + if (thisArg && isIterateeCall(collection, iteratee, thisArg)) { + iteratee = undefined; + } + var index = -1; + iteratee = getCallback(iteratee, thisArg, 3); + var result = baseMap(collection, function(value, key, collection) { + return { + criteria: iteratee(value, key, collection), + index: ++index, + value: value + }; + }); + return baseSortBy(result, compareAscending); + } + var sortByAll = restParam(function(collection, iteratees) { + if (collection == null) { + return []; + } + var guard = iteratees[2]; + if (guard && isIterateeCall(iteratees[0], iteratees[1], guard)) { + iteratees.length = 1; + } + return baseSortByOrder(collection, baseFlatten(iteratees), []); + }); + function sortByOrder(collection, iteratees, orders, guard) { + if (collection == null) { + return []; + } + if (guard && isIterateeCall(iteratees, orders, guard)) { + orders = undefined; + } + if (!isArray(iteratees)) { + iteratees = iteratees == null ? [] : [ iteratees ]; + } + if (!isArray(orders)) { + orders = orders == null ? [] : [ orders ]; + } + return baseSortByOrder(collection, iteratees, orders); + } + function where(collection, source) { + return filter(collection, baseMatches(source)); + } + var now = nativeNow || function() { + return new Date().getTime(); + }; + function after(n, func) { + if (typeof func != "function") { + if (typeof n == "function") { + var temp = n; + n = func; + func = temp; + } else { + throw new TypeError(FUNC_ERROR_TEXT); + } + } + n = nativeIsFinite(n = +n) ? n : 0; + return function() { + if (--n < 1) { + return func.apply(this, arguments); + } + }; + } + function ary(func, n, guard) { + if (guard && isIterateeCall(func, n, guard)) { + n = undefined; + } + n = func && n == null ? func.length : nativeMax(+n || 0, 0); + return createWrapper(func, ARY_FLAG, undefined, undefined, undefined, undefined, n); + } + function before(n, func) { + var result; + if (typeof func != "function") { + if (typeof n == "function") { + var temp = n; + n = func; + func = temp; + } else { + throw new TypeError(FUNC_ERROR_TEXT); + } + } + return function() { + if (--n > 0) { + result = func.apply(this, arguments); + } + if (n <= 1) { + func = undefined; + } + return result; + }; + } + var bind = restParam(function(func, thisArg, partials) { + var bitmask = BIND_FLAG; + if (partials.length) { + var holders = replaceHolders(partials, bind.placeholder); + bitmask |= PARTIAL_FLAG; + } + return createWrapper(func, bitmask, thisArg, partials, holders); + }); + var bindAll = restParam(function(object, methodNames) { + methodNames = methodNames.length ? baseFlatten(methodNames) : functions(object); + var index = -1, length = methodNames.length; + while (++index < length) { + var key = methodNames[index]; + object[key] = createWrapper(object[key], BIND_FLAG, object); + } + return object; + }); + var bindKey = restParam(function(object, key, partials) { + var bitmask = BIND_FLAG | BIND_KEY_FLAG; + if (partials.length) { + var holders = replaceHolders(partials, bindKey.placeholder); + bitmask |= PARTIAL_FLAG; + } + return createWrapper(key, bitmask, object, partials, holders); + }); + var curry = createCurry(CURRY_FLAG); + var curryRight = createCurry(CURRY_RIGHT_FLAG); + function debounce(func, wait, options) { + var args, maxTimeoutId, result, stamp, thisArg, timeoutId, trailingCall, lastCalled = 0, maxWait = false, trailing = true; + if (typeof func != "function") { + throw new TypeError(FUNC_ERROR_TEXT); + } + wait = wait < 0 ? 0 : +wait || 0; + if (options === true) { + var leading = true; + trailing = false; + } else if (isObject(options)) { + leading = !!options.leading; + maxWait = "maxWait" in options && nativeMax(+options.maxWait || 0, wait); + trailing = "trailing" in options ? !!options.trailing : trailing; + } + function cancel() { + if (timeoutId) { + clearTimeout(timeoutId); + } + if (maxTimeoutId) { + clearTimeout(maxTimeoutId); + } + lastCalled = 0; + maxTimeoutId = timeoutId = trailingCall = undefined; + } + function complete(isCalled, id) { + if (id) { + clearTimeout(id); + } + maxTimeoutId = timeoutId = trailingCall = undefined; + if (isCalled) { + lastCalled = now(); + result = func.apply(thisArg, args); + if (!timeoutId && !maxTimeoutId) { + args = thisArg = undefined; + } + } + } + function delayed() { + var remaining = wait - (now() - stamp); + if (remaining <= 0 || remaining > wait) { + complete(trailingCall, maxTimeoutId); + } else { + timeoutId = setTimeout(delayed, remaining); + } + } + function maxDelayed() { + complete(trailing, timeoutId); + } + function debounced() { + args = arguments; + stamp = now(); + thisArg = this; + trailingCall = trailing && (timeoutId || !leading); + if (maxWait === false) { + var leadingCall = leading && !timeoutId; + } else { + if (!maxTimeoutId && !leading) { + lastCalled = stamp; + } + var remaining = maxWait - (stamp - lastCalled), isCalled = remaining <= 0 || remaining > maxWait; + if (isCalled) { + if (maxTimeoutId) { + maxTimeoutId = clearTimeout(maxTimeoutId); + } + lastCalled = stamp; + result = func.apply(thisArg, args); + } else if (!maxTimeoutId) { + maxTimeoutId = setTimeout(maxDelayed, remaining); + } + } + if (isCalled && timeoutId) { + timeoutId = clearTimeout(timeoutId); + } else if (!timeoutId && wait !== maxWait) { + timeoutId = setTimeout(delayed, wait); + } + if (leadingCall) { + isCalled = true; + result = func.apply(thisArg, args); + } + if (isCalled && !timeoutId && !maxTimeoutId) { + args = thisArg = undefined; + } + return result; + } + debounced.cancel = cancel; + return debounced; + } + var defer = restParam(function(func, args) { + return baseDelay(func, 1, args); + }); + var delay = restParam(function(func, wait, args) { + return baseDelay(func, wait, args); + }); + var flow = createFlow(); + var flowRight = createFlow(true); + function memoize(func, resolver) { + if (typeof func != "function" || resolver && typeof resolver != "function") { + throw new TypeError(FUNC_ERROR_TEXT); + } + var memoized = function() { + var args = arguments, key = resolver ? resolver.apply(this, args) : args[0], cache = memoized.cache; + if (cache.has(key)) { + return cache.get(key); + } + var result = func.apply(this, args); + memoized.cache = cache.set(key, result); + return result; + }; + memoized.cache = new memoize.Cache(); + return memoized; + } + var modArgs = restParam(function(func, transforms) { + transforms = baseFlatten(transforms); + if (typeof func != "function" || !arrayEvery(transforms, baseIsFunction)) { + throw new TypeError(FUNC_ERROR_TEXT); + } + var length = transforms.length; + return restParam(function(args) { + var index = nativeMin(args.length, length); + while (index--) { + args[index] = transforms[index](args[index]); + } + return func.apply(this, args); + }); + }); + function negate(predicate) { + if (typeof predicate != "function") { + throw new TypeError(FUNC_ERROR_TEXT); + } + return function() { + return !predicate.apply(this, arguments); + }; + } + function once(func) { + return before(2, func); + } + var partial = createPartial(PARTIAL_FLAG); + var partialRight = createPartial(PARTIAL_RIGHT_FLAG); + var rearg = restParam(function(func, indexes) { + return createWrapper(func, REARG_FLAG, undefined, undefined, undefined, baseFlatten(indexes)); + }); + function restParam(func, start) { + if (typeof func != "function") { + throw new TypeError(FUNC_ERROR_TEXT); + } + start = nativeMax(start === undefined ? func.length - 1 : +start || 0, 0); + return function() { + var args = arguments, index = -1, length = nativeMax(args.length - start, 0), rest = Array(length); + while (++index < length) { + rest[index] = args[start + index]; + } + switch (start) { + case 0: + return func.call(this, rest); + + case 1: + return func.call(this, args[0], rest); + + case 2: + return func.call(this, args[0], args[1], rest); + } + var otherArgs = Array(start + 1); + index = -1; + while (++index < start) { + otherArgs[index] = args[index]; + } + otherArgs[start] = rest; + return func.apply(this, otherArgs); + }; + } + function spread(func) { + if (typeof func != "function") { + throw new TypeError(FUNC_ERROR_TEXT); + } + return function(array) { + return func.apply(this, array); + }; + } + function throttle(func, wait, options) { + var leading = true, trailing = true; + if (typeof func != "function") { + throw new TypeError(FUNC_ERROR_TEXT); + } + if (options === false) { + leading = false; + } else if (isObject(options)) { + leading = "leading" in options ? !!options.leading : leading; + trailing = "trailing" in options ? !!options.trailing : trailing; + } + return debounce(func, wait, { + leading: leading, + maxWait: +wait, + trailing: trailing + }); + } + function wrap(value, wrapper) { + wrapper = wrapper == null ? identity : wrapper; + return createWrapper(wrapper, PARTIAL_FLAG, undefined, [ value ], []); + } + function clone(value, isDeep, customizer, thisArg) { + if (isDeep && typeof isDeep != "boolean" && isIterateeCall(value, isDeep, customizer)) { + isDeep = false; + } else if (typeof isDeep == "function") { + thisArg = customizer; + customizer = isDeep; + isDeep = false; + } + return typeof customizer == "function" ? baseClone(value, isDeep, bindCallback(customizer, thisArg, 3)) : baseClone(value, isDeep); + } + function cloneDeep(value, customizer, thisArg) { + return typeof customizer == "function" ? baseClone(value, true, bindCallback(customizer, thisArg, 3)) : baseClone(value, true); + } + function gt(value, other) { + return value > other; + } + function gte(value, other) { + return value >= other; + } + function isArguments(value) { + return isObjectLike(value) && isArrayLike(value) && hasOwnProperty.call(value, "callee") && !propertyIsEnumerable.call(value, "callee"); + } + var isArray = nativeIsArray || function(value) { + return isObjectLike(value) && isLength(value.length) && objToString.call(value) == arrayTag; + }; + function isBoolean(value) { + return value === true || value === false || isObjectLike(value) && objToString.call(value) == boolTag; + } + function isDate(value) { + return isObjectLike(value) && objToString.call(value) == dateTag; + } + function isElement(value) { + return !!value && value.nodeType === 1 && isObjectLike(value) && !isPlainObject(value); + } + function isEmpty(value) { + if (value == null) { + return true; + } + if (isArrayLike(value) && (isArray(value) || isString(value) || isArguments(value) || isObjectLike(value) && isFunction(value.splice))) { + return !value.length; + } + return !keys(value).length; + } + function isEqual(value, other, customizer, thisArg) { + customizer = typeof customizer == "function" ? bindCallback(customizer, thisArg, 3) : undefined; + var result = customizer ? customizer(value, other) : undefined; + return result === undefined ? baseIsEqual(value, other, customizer) : !!result; + } + function isError(value) { + return isObjectLike(value) && typeof value.message == "string" && objToString.call(value) == errorTag; + } + function isFinite(value) { + return typeof value == "number" && nativeIsFinite(value); + } + function isFunction(value) { + return isObject(value) && objToString.call(value) == funcTag; + } + function isObject(value) { + var type = typeof value; + return !!value && (type == "object" || type == "function"); + } + function isMatch(object, source, customizer, thisArg) { + customizer = typeof customizer == "function" ? bindCallback(customizer, thisArg, 3) : undefined; + return baseIsMatch(object, getMatchData(source), customizer); + } + function isNaN(value) { + return isNumber(value) && value != +value; + } + function isNative(value) { + if (value == null) { + return false; + } + if (isFunction(value)) { + return reIsNative.test(fnToString.call(value)); + } + return isObjectLike(value) && reIsHostCtor.test(value); + } + function isNull(value) { + return value === null; + } + function isNumber(value) { + return typeof value == "number" || isObjectLike(value) && objToString.call(value) == numberTag; + } + function isPlainObject(value) { + var Ctor; + if (!(isObjectLike(value) && objToString.call(value) == objectTag && !isArguments(value)) || !hasOwnProperty.call(value, "constructor") && (Ctor = value.constructor, + typeof Ctor == "function" && !(Ctor instanceof Ctor))) { + return false; + } + var result; + baseForIn(value, function(subValue, key) { + result = key; + }); + return result === undefined || hasOwnProperty.call(value, result); + } + function isRegExp(value) { + return isObject(value) && objToString.call(value) == regexpTag; + } + function isString(value) { + return typeof value == "string" || isObjectLike(value) && objToString.call(value) == stringTag; + } + function isTypedArray(value) { + return isObjectLike(value) && isLength(value.length) && !!typedArrayTags[objToString.call(value)]; + } + function isUndefined(value) { + return value === undefined; + } + function lt(value, other) { + return value < other; + } + function lte(value, other) { + return value <= other; + } + function toArray(value) { + var length = value ? getLength(value) : 0; + if (!isLength(length)) { + return values(value); + } + if (!length) { + return []; + } + return arrayCopy(value); + } + function toPlainObject(value) { + return baseCopy(value, keysIn(value)); + } + var merge = createAssigner(baseMerge); + var assign = createAssigner(function(object, source, customizer) { + return customizer ? assignWith(object, source, customizer) : baseAssign(object, source); + }); + function create(prototype, properties, guard) { + var result = baseCreate(prototype); + if (guard && isIterateeCall(prototype, properties, guard)) { + properties = undefined; + } + return properties ? baseAssign(result, properties) : result; + } + var defaults = createDefaults(assign, assignDefaults); + var defaultsDeep = createDefaults(merge, mergeDefaults); + var findKey = createFindKey(baseForOwn); + var findLastKey = createFindKey(baseForOwnRight); + var forIn = createForIn(baseFor); + var forInRight = createForIn(baseForRight); + var forOwn = createForOwn(baseForOwn); + var forOwnRight = createForOwn(baseForOwnRight); + function functions(object) { + return baseFunctions(object, keysIn(object)); + } + function get(object, path, defaultValue) { + var result = object == null ? undefined : baseGet(object, toPath(path), path + ""); + return result === undefined ? defaultValue : result; + } + function has(object, path) { + if (object == null) { + return false; + } + var result = hasOwnProperty.call(object, path); + if (!result && !isKey(path)) { + path = toPath(path); + object = path.length == 1 ? object : baseGet(object, baseSlice(path, 0, -1)); + if (object == null) { + return false; + } + path = last(path); + result = hasOwnProperty.call(object, path); + } + return result || isLength(object.length) && isIndex(path, object.length) && (isArray(object) || isArguments(object)); + } + function invert(object, multiValue, guard) { + if (guard && isIterateeCall(object, multiValue, guard)) { + multiValue = undefined; + } + var index = -1, props = keys(object), length = props.length, result = {}; + while (++index < length) { + var key = props[index], value = object[key]; + if (multiValue) { + if (hasOwnProperty.call(result, value)) { + result[value].push(key); + } else { + result[value] = [ key ]; + } + } else { + result[value] = key; + } + } + return result; + } + var keys = !nativeKeys ? shimKeys : function(object) { + var Ctor = object == null ? undefined : object.constructor; + if (typeof Ctor == "function" && Ctor.prototype === object || typeof object != "function" && isArrayLike(object)) { + return shimKeys(object); + } + return isObject(object) ? nativeKeys(object) : []; + }; + function keysIn(object) { + if (object == null) { + return []; + } + if (!isObject(object)) { + object = Object(object); + } + var length = object.length; + length = length && isLength(length) && (isArray(object) || isArguments(object)) && length || 0; + var Ctor = object.constructor, index = -1, isProto = typeof Ctor == "function" && Ctor.prototype === object, result = Array(length), skipIndexes = length > 0; + while (++index < length) { + result[index] = index + ""; + } + for (var key in object) { + if (!(skipIndexes && isIndex(key, length)) && !(key == "constructor" && (isProto || !hasOwnProperty.call(object, key)))) { + result.push(key); + } + } + return result; + } + var mapKeys = createObjectMapper(true); + var mapValues = createObjectMapper(); + var omit = restParam(function(object, props) { + if (object == null) { + return {}; + } + if (typeof props[0] != "function") { + var props = arrayMap(baseFlatten(props), String); + return pickByArray(object, baseDifference(keysIn(object), props)); + } + var predicate = bindCallback(props[0], props[1], 3); + return pickByCallback(object, function(value, key, object) { + return !predicate(value, key, object); + }); + }); + function pairs(object) { + object = toObject(object); + var index = -1, props = keys(object), length = props.length, result = Array(length); + while (++index < length) { + var key = props[index]; + result[index] = [ key, object[key] ]; + } + return result; + } + var pick = restParam(function(object, props) { + if (object == null) { + return {}; + } + return typeof props[0] == "function" ? pickByCallback(object, bindCallback(props[0], props[1], 3)) : pickByArray(object, baseFlatten(props)); + }); + function result(object, path, defaultValue) { + var result = object == null ? undefined : object[path]; + if (result === undefined) { + if (object != null && !isKey(path, object)) { + path = toPath(path); + object = path.length == 1 ? object : baseGet(object, baseSlice(path, 0, -1)); + result = object == null ? undefined : object[last(path)]; + } + result = result === undefined ? defaultValue : result; + } + return isFunction(result) ? result.call(object) : result; + } + function set(object, path, value) { + if (object == null) { + return object; + } + var pathKey = path + ""; + path = object[pathKey] != null || isKey(path, object) ? [ pathKey ] : toPath(path); + var index = -1, length = path.length, lastIndex = length - 1, nested = object; + while (nested != null && ++index < length) { + var key = path[index]; + if (isObject(nested)) { + if (index == lastIndex) { + nested[key] = value; + } else if (nested[key] == null) { + nested[key] = isIndex(path[index + 1]) ? [] : {}; + } + } + nested = nested[key]; + } + return object; + } + function transform(object, iteratee, accumulator, thisArg) { + var isArr = isArray(object) || isTypedArray(object); + iteratee = getCallback(iteratee, thisArg, 4); + if (accumulator == null) { + if (isArr || isObject(object)) { + var Ctor = object.constructor; + if (isArr) { + accumulator = isArray(object) ? new Ctor() : []; + } else { + accumulator = baseCreate(isFunction(Ctor) ? Ctor.prototype : undefined); + } + } else { + accumulator = {}; + } + } + (isArr ? arrayEach : baseForOwn)(object, function(value, index, object) { + return iteratee(accumulator, value, index, object); + }); + return accumulator; + } + function values(object) { + return baseValues(object, keys(object)); + } + function valuesIn(object) { + return baseValues(object, keysIn(object)); + } + function inRange(value, start, end) { + start = +start || 0; + if (end === undefined) { + end = start; + start = 0; + } else { + end = +end || 0; + } + return value >= nativeMin(start, end) && value < nativeMax(start, end); + } + function random(min, max, floating) { + if (floating && isIterateeCall(min, max, floating)) { + max = floating = undefined; + } + var noMin = min == null, noMax = max == null; + if (floating == null) { + if (noMax && typeof min == "boolean") { + floating = min; + min = 1; + } else if (typeof max == "boolean") { + floating = max; + noMax = true; + } + } + if (noMin && noMax) { + max = 1; + noMax = false; + } + min = +min || 0; + if (noMax) { + max = min; + min = 0; + } else { + max = +max || 0; + } + if (floating || min % 1 || max % 1) { + var rand = nativeRandom(); + return nativeMin(min + rand * (max - min + parseFloat("1e-" + ((rand + "").length - 1))), max); + } + return baseRandom(min, max); + } + var camelCase = createCompounder(function(result, word, index) { + word = word.toLowerCase(); + return result + (index ? word.charAt(0).toUpperCase() + word.slice(1) : word); + }); + function capitalize(string) { + string = baseToString(string); + return string && string.charAt(0).toUpperCase() + string.slice(1); + } + function deburr(string) { + string = baseToString(string); + return string && string.replace(reLatin1, deburrLetter).replace(reComboMark, ""); + } + function endsWith(string, target, position) { + string = baseToString(string); + target = target + ""; + var length = string.length; + position = position === undefined ? length : nativeMin(position < 0 ? 0 : +position || 0, length); + position -= target.length; + return position >= 0 && string.indexOf(target, position) == position; + } + function escape(string) { + string = baseToString(string); + return string && reHasUnescapedHtml.test(string) ? string.replace(reUnescapedHtml, escapeHtmlChar) : string; + } + function escapeRegExp(string) { + string = baseToString(string); + return string && reHasRegExpChars.test(string) ? string.replace(reRegExpChars, escapeRegExpChar) : string || "(?:)"; + } + var kebabCase = createCompounder(function(result, word, index) { + return result + (index ? "-" : "") + word.toLowerCase(); + }); + function pad(string, length, chars) { + string = baseToString(string); + length = +length; + var strLength = string.length; + if (strLength >= length || !nativeIsFinite(length)) { + return string; + } + var mid = (length - strLength) / 2, leftLength = nativeFloor(mid), rightLength = nativeCeil(mid); + chars = createPadding("", rightLength, chars); + return chars.slice(0, leftLength) + string + chars; + } + var padLeft = createPadDir(); + var padRight = createPadDir(true); + function parseInt(string, radix, guard) { + if (guard ? isIterateeCall(string, radix, guard) : radix == null) { + radix = 0; + } else if (radix) { + radix = +radix; + } + string = trim(string); + return nativeParseInt(string, radix || (reHasHexPrefix.test(string) ? 16 : 10)); + } + function repeat(string, n) { + var result = ""; + string = baseToString(string); + n = +n; + if (n < 1 || !string || !nativeIsFinite(n)) { + return result; + } + do { + if (n % 2) { + result += string; + } + n = nativeFloor(n / 2); + string += string; + } while (n); + return result; + } + var snakeCase = createCompounder(function(result, word, index) { + return result + (index ? "_" : "") + word.toLowerCase(); + }); + var startCase = createCompounder(function(result, word, index) { + return result + (index ? " " : "") + (word.charAt(0).toUpperCase() + word.slice(1)); + }); + function startsWith(string, target, position) { + string = baseToString(string); + position = position == null ? 0 : nativeMin(position < 0 ? 0 : +position || 0, string.length); + return string.lastIndexOf(target, position) == position; + } + function template(string, options, otherOptions) { + var settings = lodash.templateSettings; + if (otherOptions && isIterateeCall(string, options, otherOptions)) { + options = otherOptions = undefined; + } + string = baseToString(string); + options = assignWith(baseAssign({}, otherOptions || options), settings, assignOwnDefaults); + var imports = assignWith(baseAssign({}, options.imports), settings.imports, assignOwnDefaults), importsKeys = keys(imports), importsValues = baseValues(imports, importsKeys); + var isEscaping, isEvaluating, index = 0, interpolate = options.interpolate || reNoMatch, source = "__p += '"; + var reDelimiters = RegExp((options.escape || reNoMatch).source + "|" + interpolate.source + "|" + (interpolate === reInterpolate ? reEsTemplate : reNoMatch).source + "|" + (options.evaluate || reNoMatch).source + "|$", "g"); + var sourceURL = "//# sourceURL=" + ("sourceURL" in options ? options.sourceURL : "lodash.templateSources[" + ++templateCounter + "]") + "\n"; + string.replace(reDelimiters, function(match, escapeValue, interpolateValue, esTemplateValue, evaluateValue, offset) { + interpolateValue || (interpolateValue = esTemplateValue); + source += string.slice(index, offset).replace(reUnescapedString, escapeStringChar); + if (escapeValue) { + isEscaping = true; + source += "' +\n__e(" + escapeValue + ") +\n'"; + } + if (evaluateValue) { + isEvaluating = true; + source += "';\n" + evaluateValue + ";\n__p += '"; + } + if (interpolateValue) { + source += "' +\n((__t = (" + interpolateValue + ")) == null ? '' : __t) +\n'"; + } + index = offset + match.length; + return match; + }); + source += "';\n"; + var variable = options.variable; + if (!variable) { + source = "with (obj) {\n" + source + "\n}\n"; + } + source = (isEvaluating ? source.replace(reEmptyStringLeading, "") : source).replace(reEmptyStringMiddle, "$1").replace(reEmptyStringTrailing, "$1;"); + source = "function(" + (variable || "obj") + ") {\n" + (variable ? "" : "obj || (obj = {});\n") + "var __t, __p = ''" + (isEscaping ? ", __e = _.escape" : "") + (isEvaluating ? ", __j = Array.prototype.join;\n" + "function print() { __p += __j.call(arguments, '') }\n" : ";\n") + source + "return __p\n}"; + var result = attempt(function() { + return Function(importsKeys, sourceURL + "return " + source).apply(undefined, importsValues); + }); + result.source = source; + if (isError(result)) { + throw result; + } + return result; + } + function trim(string, chars, guard) { + var value = string; + string = baseToString(string); + if (!string) { + return string; + } + if (guard ? isIterateeCall(value, chars, guard) : chars == null) { + return string.slice(trimmedLeftIndex(string), trimmedRightIndex(string) + 1); + } + chars = chars + ""; + return string.slice(charsLeftIndex(string, chars), charsRightIndex(string, chars) + 1); + } + function trimLeft(string, chars, guard) { + var value = string; + string = baseToString(string); + if (!string) { + return string; + } + if (guard ? isIterateeCall(value, chars, guard) : chars == null) { + return string.slice(trimmedLeftIndex(string)); + } + return string.slice(charsLeftIndex(string, chars + "")); + } + function trimRight(string, chars, guard) { + var value = string; + string = baseToString(string); + if (!string) { + return string; + } + if (guard ? isIterateeCall(value, chars, guard) : chars == null) { + return string.slice(0, trimmedRightIndex(string) + 1); + } + return string.slice(0, charsRightIndex(string, chars + "") + 1); + } + function trunc(string, options, guard) { + if (guard && isIterateeCall(string, options, guard)) { + options = undefined; + } + var length = DEFAULT_TRUNC_LENGTH, omission = DEFAULT_TRUNC_OMISSION; + if (options != null) { + if (isObject(options)) { + var separator = "separator" in options ? options.separator : separator; + length = "length" in options ? +options.length || 0 : length; + omission = "omission" in options ? baseToString(options.omission) : omission; + } else { + length = +options || 0; + } + } + string = baseToString(string); + if (length >= string.length) { + return string; + } + var end = length - omission.length; + if (end < 1) { + return omission; + } + var result = string.slice(0, end); + if (separator == null) { + return result + omission; + } + if (isRegExp(separator)) { + if (string.slice(end).search(separator)) { + var match, newEnd, substring = string.slice(0, end); + if (!separator.global) { + separator = RegExp(separator.source, (reFlags.exec(separator) || "") + "g"); + } + separator.lastIndex = 0; + while (match = separator.exec(substring)) { + newEnd = match.index; + } + result = result.slice(0, newEnd == null ? end : newEnd); + } + } else if (string.indexOf(separator, end) != end) { + var index = result.lastIndexOf(separator); + if (index > -1) { + result = result.slice(0, index); + } + } + return result + omission; + } + function unescape(string) { + string = baseToString(string); + return string && reHasEscapedHtml.test(string) ? string.replace(reEscapedHtml, unescapeHtmlChar) : string; + } + function words(string, pattern, guard) { + if (guard && isIterateeCall(string, pattern, guard)) { + pattern = undefined; + } + string = baseToString(string); + return string.match(pattern || reWords) || []; + } + var attempt = restParam(function(func, args) { + try { + return func.apply(undefined, args); + } catch (e) { + return isError(e) ? e : new Error(e); + } + }); + function callback(func, thisArg, guard) { + if (guard && isIterateeCall(func, thisArg, guard)) { + thisArg = undefined; + } + return isObjectLike(func) ? matches(func) : baseCallback(func, thisArg); + } + function constant(value) { + return function() { + return value; + }; + } + function identity(value) { + return value; + } + function matches(source) { + return baseMatches(baseClone(source, true)); + } + function matchesProperty(path, srcValue) { + return baseMatchesProperty(path, baseClone(srcValue, true)); + } + var method = restParam(function(path, args) { + return function(object) { + return invokePath(object, path, args); + }; + }); + var methodOf = restParam(function(object, args) { + return function(path) { + return invokePath(object, path, args); + }; + }); + function mixin(object, source, options) { + if (options == null) { + var isObj = isObject(source), props = isObj ? keys(source) : undefined, methodNames = props && props.length ? baseFunctions(source, props) : undefined; + if (!(methodNames ? methodNames.length : isObj)) { + methodNames = false; + options = source; + source = object; + object = this; + } + } + if (!methodNames) { + methodNames = baseFunctions(source, keys(source)); + } + var chain = true, index = -1, isFunc = isFunction(object), length = methodNames.length; + if (options === false) { + chain = false; + } else if (isObject(options) && "chain" in options) { + chain = options.chain; + } + while (++index < length) { + var methodName = methodNames[index], func = source[methodName]; + object[methodName] = func; + if (isFunc) { + object.prototype[methodName] = function(func) { + return function() { + var chainAll = this.__chain__; + if (chain || chainAll) { + var result = object(this.__wrapped__), actions = result.__actions__ = arrayCopy(this.__actions__); + actions.push({ + func: func, + args: arguments, + thisArg: object + }); + result.__chain__ = chainAll; + return result; + } + return func.apply(object, arrayPush([ this.value() ], arguments)); + }; + }(func); + } + } + return object; + } + function noConflict() { + root._ = oldDash; + return this; + } + function noop() {} + function property(path) { + return isKey(path) ? baseProperty(path) : basePropertyDeep(path); + } + function propertyOf(object) { + return function(path) { + return baseGet(object, toPath(path), path + ""); + }; + } + function range(start, end, step) { + if (step && isIterateeCall(start, end, step)) { + end = step = undefined; + } + start = +start || 0; + step = step == null ? 1 : +step || 0; + if (end == null) { + end = start; + start = 0; + } else { + end = +end || 0; + } + var index = -1, length = nativeMax(nativeCeil((end - start) / (step || 1)), 0), result = Array(length); + while (++index < length) { + result[index] = start; + start += step; + } + return result; + } + function times(n, iteratee, thisArg) { + n = nativeFloor(n); + if (n < 1 || !nativeIsFinite(n)) { + return []; + } + var index = -1, result = Array(nativeMin(n, MAX_ARRAY_LENGTH)); + iteratee = bindCallback(iteratee, thisArg, 1); + while (++index < n) { + if (index < MAX_ARRAY_LENGTH) { + result[index] = iteratee(index); + } else { + iteratee(index); + } + } + return result; + } + function uniqueId(prefix) { + var id = ++idCounter; + return baseToString(prefix) + id; + } + function add(augend, addend) { + return (+augend || 0) + (+addend || 0); + } + var ceil = createRound("ceil"); + var floor = createRound("floor"); + var max = createExtremum(gt, NEGATIVE_INFINITY); + var min = createExtremum(lt, POSITIVE_INFINITY); + var round = createRound("round"); + function sum(collection, iteratee, thisArg) { + if (thisArg && isIterateeCall(collection, iteratee, thisArg)) { + iteratee = undefined; + } + iteratee = getCallback(iteratee, thisArg, 3); + return iteratee.length == 1 ? arraySum(isArray(collection) ? collection : toIterable(collection), iteratee) : baseSum(collection, iteratee); + } + lodash.prototype = baseLodash.prototype; + LodashWrapper.prototype = baseCreate(baseLodash.prototype); + LodashWrapper.prototype.constructor = LodashWrapper; + LazyWrapper.prototype = baseCreate(baseLodash.prototype); + LazyWrapper.prototype.constructor = LazyWrapper; + MapCache.prototype["delete"] = mapDelete; + MapCache.prototype.get = mapGet; + MapCache.prototype.has = mapHas; + MapCache.prototype.set = mapSet; + SetCache.prototype.push = cachePush; + memoize.Cache = MapCache; + lodash.after = after; + lodash.ary = ary; + lodash.assign = assign; + lodash.at = at; + lodash.before = before; + lodash.bind = bind; + lodash.bindAll = bindAll; + lodash.bindKey = bindKey; + lodash.callback = callback; + lodash.chain = chain; + lodash.chunk = chunk; + lodash.compact = compact; + lodash.constant = constant; + lodash.countBy = countBy; + lodash.create = create; + lodash.curry = curry; + lodash.curryRight = curryRight; + lodash.debounce = debounce; + lodash.defaults = defaults; + lodash.defaultsDeep = defaultsDeep; + lodash.defer = defer; + lodash.delay = delay; + lodash.difference = difference; + lodash.drop = drop; + lodash.dropRight = dropRight; + lodash.dropRightWhile = dropRightWhile; + lodash.dropWhile = dropWhile; + lodash.fill = fill; + lodash.filter = filter; + lodash.flatten = flatten; + lodash.flattenDeep = flattenDeep; + lodash.flow = flow; + lodash.flowRight = flowRight; + lodash.forEach = forEach; + lodash.forEachRight = forEachRight; + lodash.forIn = forIn; + lodash.forInRight = forInRight; + lodash.forOwn = forOwn; + lodash.forOwnRight = forOwnRight; + lodash.functions = functions; + lodash.groupBy = groupBy; + lodash.indexBy = indexBy; + lodash.initial = initial; + lodash.intersection = intersection; + lodash.invert = invert; + lodash.invoke = invoke; + lodash.keys = keys; + lodash.keysIn = keysIn; + lodash.map = map; + lodash.mapKeys = mapKeys; + lodash.mapValues = mapValues; + lodash.matches = matches; + lodash.matchesProperty = matchesProperty; + lodash.memoize = memoize; + lodash.merge = merge; + lodash.method = method; + lodash.methodOf = methodOf; + lodash.mixin = mixin; + lodash.modArgs = modArgs; + lodash.negate = negate; + lodash.omit = omit; + lodash.once = once; + lodash.pairs = pairs; + lodash.partial = partial; + lodash.partialRight = partialRight; + lodash.partition = partition; + lodash.pick = pick; + lodash.pluck = pluck; + lodash.property = property; + lodash.propertyOf = propertyOf; + lodash.pull = pull; + lodash.pullAt = pullAt; + lodash.range = range; + lodash.rearg = rearg; + lodash.reject = reject; + lodash.remove = remove; + lodash.rest = rest; + lodash.restParam = restParam; + lodash.set = set; + lodash.shuffle = shuffle; + lodash.slice = slice; + lodash.sortBy = sortBy; + lodash.sortByAll = sortByAll; + lodash.sortByOrder = sortByOrder; + lodash.spread = spread; + lodash.take = take; + lodash.takeRight = takeRight; + lodash.takeRightWhile = takeRightWhile; + lodash.takeWhile = takeWhile; + lodash.tap = tap; + lodash.throttle = throttle; + lodash.thru = thru; + lodash.times = times; + lodash.toArray = toArray; + lodash.toPlainObject = toPlainObject; + lodash.transform = transform; + lodash.union = union; + lodash.uniq = uniq; + lodash.unzip = unzip; + lodash.unzipWith = unzipWith; + lodash.values = values; + lodash.valuesIn = valuesIn; + lodash.where = where; + lodash.without = without; + lodash.wrap = wrap; + lodash.xor = xor; + lodash.zip = zip; + lodash.zipObject = zipObject; + lodash.zipWith = zipWith; + lodash.backflow = flowRight; + lodash.collect = map; + lodash.compose = flowRight; + lodash.each = forEach; + lodash.eachRight = forEachRight; + lodash.extend = assign; + lodash.iteratee = callback; + lodash.methods = functions; + lodash.object = zipObject; + lodash.select = filter; + lodash.tail = rest; + lodash.unique = uniq; + mixin(lodash, lodash); + lodash.add = add; + lodash.attempt = attempt; + lodash.camelCase = camelCase; + lodash.capitalize = capitalize; + lodash.ceil = ceil; + lodash.clone = clone; + lodash.cloneDeep = cloneDeep; + lodash.deburr = deburr; + lodash.endsWith = endsWith; + lodash.escape = escape; + lodash.escapeRegExp = escapeRegExp; + lodash.every = every; + lodash.find = find; + lodash.findIndex = findIndex; + lodash.findKey = findKey; + lodash.findLast = findLast; + lodash.findLastIndex = findLastIndex; + lodash.findLastKey = findLastKey; + lodash.findWhere = findWhere; + lodash.first = first; + lodash.floor = floor; + lodash.get = get; + lodash.gt = gt; + lodash.gte = gte; + lodash.has = has; + lodash.identity = identity; + lodash.includes = includes; + lodash.indexOf = indexOf; + lodash.inRange = inRange; + lodash.isArguments = isArguments; + lodash.isArray = isArray; + lodash.isBoolean = isBoolean; + lodash.isDate = isDate; + lodash.isElement = isElement; + lodash.isEmpty = isEmpty; + lodash.isEqual = isEqual; + lodash.isError = isError; + lodash.isFinite = isFinite; + lodash.isFunction = isFunction; + lodash.isMatch = isMatch; + lodash.isNaN = isNaN; + lodash.isNative = isNative; + lodash.isNull = isNull; + lodash.isNumber = isNumber; + lodash.isObject = isObject; + lodash.isPlainObject = isPlainObject; + lodash.isRegExp = isRegExp; + lodash.isString = isString; + lodash.isTypedArray = isTypedArray; + lodash.isUndefined = isUndefined; + lodash.kebabCase = kebabCase; + lodash.last = last; + lodash.lastIndexOf = lastIndexOf; + lodash.lt = lt; + lodash.lte = lte; + lodash.max = max; + lodash.min = min; + lodash.noConflict = noConflict; + lodash.noop = noop; + lodash.now = now; + lodash.pad = pad; + lodash.padLeft = padLeft; + lodash.padRight = padRight; + lodash.parseInt = parseInt; + lodash.random = random; + lodash.reduce = reduce; + lodash.reduceRight = reduceRight; + lodash.repeat = repeat; + lodash.result = result; + lodash.round = round; + lodash.runInContext = runInContext; + lodash.size = size; + lodash.snakeCase = snakeCase; + lodash.some = some; + lodash.sortedIndex = sortedIndex; + lodash.sortedLastIndex = sortedLastIndex; + lodash.startCase = startCase; + lodash.startsWith = startsWith; + lodash.sum = sum; + lodash.template = template; + lodash.trim = trim; + lodash.trimLeft = trimLeft; + lodash.trimRight = trimRight; + lodash.trunc = trunc; + lodash.unescape = unescape; + lodash.uniqueId = uniqueId; + lodash.words = words; + lodash.all = every; + lodash.any = some; + lodash.contains = includes; + lodash.eq = isEqual; + lodash.detect = find; + lodash.foldl = reduce; + lodash.foldr = reduceRight; + lodash.head = first; + lodash.include = includes; + lodash.inject = reduce; + mixin(lodash, function() { + var source = {}; + baseForOwn(lodash, function(func, methodName) { + if (!lodash.prototype[methodName]) { + source[methodName] = func; + } + }); + return source; + }(), false); + lodash.sample = sample; + lodash.prototype.sample = function(n) { + if (!this.__chain__ && n == null) { + return sample(this.value()); + } + return this.thru(function(value) { + return sample(value, n); + }); + }; + lodash.VERSION = VERSION; + arrayEach([ "bind", "bindKey", "curry", "curryRight", "partial", "partialRight" ], function(methodName) { + lodash[methodName].placeholder = lodash; + }); + arrayEach([ "drop", "take" ], function(methodName, index) { + LazyWrapper.prototype[methodName] = function(n) { + var filtered = this.__filtered__; + if (filtered && !index) { + return new LazyWrapper(this); + } + n = n == null ? 1 : nativeMax(nativeFloor(n) || 0, 0); + var result = this.clone(); + if (filtered) { + result.__takeCount__ = nativeMin(result.__takeCount__, n); + } else { + result.__views__.push({ + size: n, + type: methodName + (result.__dir__ < 0 ? "Right" : "") + }); + } + return result; + }; + LazyWrapper.prototype[methodName + "Right"] = function(n) { + return this.reverse()[methodName](n).reverse(); + }; + }); + arrayEach([ "filter", "map", "takeWhile" ], function(methodName, index) { + var type = index + 1, isFilter = type != LAZY_MAP_FLAG; + LazyWrapper.prototype[methodName] = function(iteratee, thisArg) { + var result = this.clone(); + result.__iteratees__.push({ + iteratee: getCallback(iteratee, thisArg, 1), + type: type + }); + result.__filtered__ = result.__filtered__ || isFilter; + return result; + }; + }); + arrayEach([ "first", "last" ], function(methodName, index) { + var takeName = "take" + (index ? "Right" : ""); + LazyWrapper.prototype[methodName] = function() { + return this[takeName](1).value()[0]; + }; + }); + arrayEach([ "initial", "rest" ], function(methodName, index) { + var dropName = "drop" + (index ? "" : "Right"); + LazyWrapper.prototype[methodName] = function() { + return this.__filtered__ ? new LazyWrapper(this) : this[dropName](1); + }; + }); + arrayEach([ "pluck", "where" ], function(methodName, index) { + var operationName = index ? "filter" : "map", createCallback = index ? baseMatches : property; + LazyWrapper.prototype[methodName] = function(value) { + return this[operationName](createCallback(value)); + }; + }); + LazyWrapper.prototype.compact = function() { + return this.filter(identity); + }; + LazyWrapper.prototype.reject = function(predicate, thisArg) { + predicate = getCallback(predicate, thisArg, 1); + return this.filter(function(value) { + return !predicate(value); + }); + }; + LazyWrapper.prototype.slice = function(start, end) { + start = start == null ? 0 : +start || 0; + var result = this; + if (result.__filtered__ && (start > 0 || end < 0)) { + return new LazyWrapper(result); + } + if (start < 0) { + result = result.takeRight(-start); + } else if (start) { + result = result.drop(start); + } + if (end !== undefined) { + end = +end || 0; + result = end < 0 ? result.dropRight(-end) : result.take(end - start); + } + return result; + }; + LazyWrapper.prototype.takeRightWhile = function(predicate, thisArg) { + return this.reverse().takeWhile(predicate, thisArg).reverse(); + }; + LazyWrapper.prototype.toArray = function() { + return this.take(POSITIVE_INFINITY); + }; + baseForOwn(LazyWrapper.prototype, function(func, methodName) { + var checkIteratee = /^(?:filter|map|reject)|While$/.test(methodName), retUnwrapped = /^(?:first|last)$/.test(methodName), lodashFunc = lodash[retUnwrapped ? "take" + (methodName == "last" ? "Right" : "") : methodName]; + if (!lodashFunc) { + return; + } + lodash.prototype[methodName] = function() { + var args = retUnwrapped ? [ 1 ] : arguments, chainAll = this.__chain__, value = this.__wrapped__, isHybrid = !!this.__actions__.length, isLazy = value instanceof LazyWrapper, iteratee = args[0], useLazy = isLazy || isArray(value); + if (useLazy && checkIteratee && typeof iteratee == "function" && iteratee.length != 1) { + isLazy = useLazy = false; + } + var interceptor = function(value) { + return retUnwrapped && chainAll ? lodashFunc(value, 1)[0] : lodashFunc.apply(undefined, arrayPush([ value ], args)); + }; + var action = { + func: thru, + args: [ interceptor ], + thisArg: undefined + }, onlyLazy = isLazy && !isHybrid; + if (retUnwrapped && !chainAll) { + if (onlyLazy) { + value = value.clone(); + value.__actions__.push(action); + return func.call(value); + } + return lodashFunc.call(undefined, this.value())[0]; + } + if (!retUnwrapped && useLazy) { + value = onlyLazy ? value : new LazyWrapper(this); + var result = func.apply(value, args); + result.__actions__.push(action); + return new LodashWrapper(result, chainAll); + } + return this.thru(interceptor); + }; + }); + arrayEach([ "join", "pop", "push", "replace", "shift", "sort", "splice", "split", "unshift" ], function(methodName) { + var func = (/^(?:replace|split)$/.test(methodName) ? stringProto : arrayProto)[methodName], chainName = /^(?:push|sort|unshift)$/.test(methodName) ? "tap" : "thru", retUnwrapped = /^(?:join|pop|replace|shift)$/.test(methodName); + lodash.prototype[methodName] = function() { + var args = arguments; + if (retUnwrapped && !this.__chain__) { + return func.apply(this.value(), args); + } + return this[chainName](function(value) { + return func.apply(value, args); + }); + }; + }); + baseForOwn(LazyWrapper.prototype, function(func, methodName) { + var lodashFunc = lodash[methodName]; + if (lodashFunc) { + var key = lodashFunc.name + "", names = realNames[key] || (realNames[key] = []); + names.push({ + name: methodName, + func: lodashFunc + }); + } + }); + realNames[createHybridWrapper(undefined, BIND_KEY_FLAG).name] = [ { + name: "wrapper", + func: undefined + } ]; + LazyWrapper.prototype.clone = lazyClone; + LazyWrapper.prototype.reverse = lazyReverse; + LazyWrapper.prototype.value = lazyValue; + lodash.prototype.chain = wrapperChain; + lodash.prototype.commit = wrapperCommit; + lodash.prototype.concat = wrapperConcat; + lodash.prototype.plant = wrapperPlant; + lodash.prototype.reverse = wrapperReverse; + lodash.prototype.toString = wrapperToString; + lodash.prototype.run = lodash.prototype.toJSON = lodash.prototype.valueOf = lodash.prototype.value = wrapperValue; + lodash.prototype.collect = lodash.prototype.map; + lodash.prototype.head = lodash.prototype.first; + lodash.prototype.select = lodash.prototype.filter; + lodash.prototype.tail = lodash.prototype.rest; + return lodash; + } + var _ = runInContext(); + if (typeof define == "function" && typeof define.amd == "object" && define.amd) { + root._ = _; + define(function() { + return _; + }); + } else if (freeExports && freeModule) { + if (moduleExports) { + (freeModule.exports = _)._ = _; + } else { + freeExports._ = _; + } + } else { + root._ = _; + } +}).call(this); + (function(window, document, undefined) { "use strict"; function minErr(module, ErrorConstructor) { @@ -5391,7 +9332,7 @@ } return match; }); - message += "\nhttp://errors.angularjs.org/1.4.6/" + (module ? module + "/" : "") + code; + message += "\nhttp://errors.angularjs.org/1.4.7/" + (module ? module + "/" : "") + code; for (i = SKIP_INDEXES, paramPrefix = "?"; i < templateArgs.length; i++, paramPrefix = "&") { message += paramPrefix + "p" + (i - SKIP_INDEXES) + "=" + encodeURIComponent(toDebugString(templateArgs[i])); } @@ -6210,11 +10151,11 @@ return obj; } var version = { - full: "1.4.6", + full: "1.4.7", major: 1, minor: 4, - dot: 6, - codeName: "multiplicative-elevation" + dot: 7, + codeName: "dark-luminescence" }; function publishExternalAPI(angular) { extend(angular, { @@ -6323,6 +10264,7 @@ $httpParamSerializer: $HttpParamSerializerProvider, $httpParamSerializerJQLike: $HttpParamSerializerJQLikeProvider, $httpBackend: $HttpBackendProvider, + $xhrFactory: $xhrFactoryProvider, $location: $LocationProvider, $log: $LogProvider, $parse: $ParseProvider, @@ -6368,10 +10310,10 @@ return offset ? letter.toUpperCase() : letter; }).replace(MOZ_HACK_REGEXP, "Moz$1"); } - var SINGLE_TAG_REGEXP = /^<(\w+)\s*\/?>(?:<\/\1>|)$/; + var SINGLE_TAG_REGEXP = /^<([\w-]+)\s*\/?>(?:<\/\1>|)$/; var HTML_REGEXP = /<|&#?\w+;/; - var TAG_NAME_REGEXP = /<([\w:]+)/; - var XHTML_TAG_REGEXP = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi; + var TAG_NAME_REGEXP = /<([\w:-]+)/; + var XHTML_TAG_REGEXP = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:-]+)[^>]*)\/>/gi; var wrapMap = { option: [ 1, '" ], thead: [ 1, "", "
        " ], @@ -7614,6 +11556,9 @@ } }; return function(element, options) { + if (options.cleanupStyles) { + options.from = options.to = null; + } if (options.from) { element.css(options.from); options.from = null; @@ -8879,7 +12824,7 @@ compile: function() { return { pre: function attrInterpolatePreLinkFn(scope, element, attr) { - var $$observers = attr.$$observers || (attr.$$observers = {}); + var $$observers = attr.$$observers || (attr.$$observers = createMap()); if (EVENT_HANDLER_ATTR_REGEXP.test(name)) { throw $compileMinErr("nodomevents", "Interpolations for HTML DOM event attributes are disallowed. Please use the " + "ng- versions (such as ng-click instead of onclick) instead."); } @@ -9542,12 +13487,16 @@ } } ]; } - function createXhr() { - return new window.XMLHttpRequest(); + function $xhrFactoryProvider() { + this.$get = function() { + return function createXhr() { + return new window.XMLHttpRequest(); + }; + }; } function $HttpBackendProvider() { - this.$get = [ "$browser", "$window", "$document", function($browser, $window, $document) { - return createHttpBackend($browser, createXhr, $browser.defer, $window.angular.callbacks, $document[0]); + this.$get = [ "$browser", "$window", "$document", "$xhrFactory", function($browser, $window, $document, $xhrFactory) { + return createHttpBackend($browser, $xhrFactory, $browser.defer, $window.angular.callbacks, $document[0]); } ]; } function createHttpBackend($browser, createXhr, $browserDefer, callbacks, rawDocument) { @@ -9565,7 +13514,7 @@ callbacks[callbackId] = noop; }); } else { - var xhr = createXhr(); + var xhr = createXhr(method, url); xhr.open(method, url, true); forEach(headers, function(value, key) { if (isDefined(value)) { @@ -10273,12 +14222,18 @@ } var $parseMinErr = minErr("$parse"); function ensureSafeMemberName(name, fullExpression) { - name = isObject(name) && name.toString ? name.toString() : name; if (name === "__defineGetter__" || name === "__defineSetter__" || name === "__lookupGetter__" || name === "__lookupSetter__" || name === "__proto__") { throw $parseMinErr("isecfld", "Attempting to access a disallowed field in Angular expressions! " + "Expression: {0}", fullExpression); } return name; } + function getStringValue(name, fullExpression) { + name = name + ""; + if (!isString(name)) { + throw $parseMinErr("iseccst", "Cannot convert object to primitive value! " + "Expression: {0}", fullExpression); + } + return name; + } function ensureSafeObject(obj, fullExpression) { if (obj) { if (obj.constructor === obj) { @@ -10305,6 +14260,13 @@ } } } + function ensureSafeAssignContext(obj, fullExpression) { + if (obj) { + if (obj === 0..constructor || obj === false.constructor || obj === "".constructor || obj === {}.constructor || obj === [].constructor || obj === Function.constructor) { + throw $parseMinErr("isecaf", "Assigning to a constructor is disallowed! Expression: {0}", fullExpression); + } + } + } var OPERATORS = createMap(); forEach("+ - * / % === !== == != < > <= >= && || ! = |".split(" "), function(operator) { OPERATORS[operator] = true; @@ -11053,7 +15015,7 @@ this.stage = "main"; this.recurse(ast); var fnString = '"' + this.USE + " " + this.STRICT + '";\n' + this.filterPrefix() + "var fn=" + this.generateFunction("fn", "s,l,a,i") + extra + this.watchFns() + "return fn;"; - var fn = new Function("$filter", "ensureSafeMemberName", "ensureSafeObject", "ensureSafeFunction", "ifDefined", "plus", "text", fnString)(this.$filter, ensureSafeMemberName, ensureSafeObject, ensureSafeFunction, ifDefined, plusFn, expression); + var fn = new Function("$filter", "ensureSafeMemberName", "ensureSafeObject", "ensureSafeFunction", "getStringValue", "ensureSafeAssignContext", "ifDefined", "plus", "text", fnString)(this.$filter, ensureSafeMemberName, ensureSafeObject, ensureSafeFunction, getStringValue, ensureSafeAssignContext, ifDefined, plusFn, expression); this.state = this.stage = undefined; fn.literal = isLiteral(ast); fn.constant = isConstant(ast); @@ -11190,6 +15152,7 @@ if (ast.computed) { right = self.nextId(); self.recurse(ast.property, right); + self.getStringValue(right); self.addEnsureSafeMemberName(right); if (create && create !== 1) { self.if_(self.not(self.computedMember(left, right)), self.lazyAssign(self.computedMember(left, right), "{}")); @@ -11275,6 +15238,7 @@ self.if_(self.notNull(left.context), function() { self.recurse(ast.right, right); self.addEnsureSafeObject(self.member(left.context, left.name, left.computed)); + self.addEnsureSafeAssignContext(left.context); expression = self.member(left.context, left.name, left.computed) + ast.operator + right; self.assign(intoId, expression); recursionFn(intoId || expression); @@ -11385,6 +15349,9 @@ addEnsureSafeFunction: function(item) { this.current().body.push(this.ensureSafeFunction(item), ";"); }, + addEnsureSafeAssignContext: function(item) { + this.current().body.push(this.ensureSafeAssignContext(item), ";"); + }, ensureSafeObject: function(item) { return "ensureSafeObject(" + item + ",text)"; }, @@ -11394,6 +15361,12 @@ ensureSafeFunction: function(item) { return "ensureSafeFunction(" + item + ",text)"; }, + getStringValue: function(item) { + this.assign(item, "getStringValue(" + item + ",text)"); + }, + ensureSafeAssignContext: function(item) { + return "ensureSafeAssignContext(" + item + ",text)"; + }, lazyRecurse: function(ast, intoId, nameId, recursionFn, create, skipWatchIdCheck) { var self = this; return function() { @@ -11561,6 +15534,7 @@ var lhs = left(scope, locals, assign, inputs); var rhs = right(scope, locals, assign, inputs); ensureSafeObject(lhs.value, self.expression); + ensureSafeAssignContext(lhs.context); lhs.context[lhs.name] = rhs; return context ? { value: rhs @@ -11818,6 +15792,7 @@ var value; if (lhs != null) { rhs = right(scope, locals, assign, inputs); + rhs = getStringValue(rhs); ensureSafeMemberName(rhs, expression); if (create && create !== 1 && lhs && !lhs[rhs]) { lhs[rhs] = {}; @@ -13500,6 +17475,7 @@ if (fractionSize > 0 && number < 1) { formatedText = number.toFixed(fractionSize); number = parseFloat(formatedText); + formatedText = formatedText.replace(DECIMAL_SEP, decimalSep); } } if (number === 0) { @@ -15517,11 +19493,11 @@ function updateOptionElement(option, element) { option.element = element; element.disabled = option.disabled; - if (option.value !== element.value) element.value = option.selectValue; if (option.label !== element.label) { element.label = option.label; element.textContent = option.label; } + if (option.value !== element.value) element.value = option.selectValue; } function addOrReuseElement(parent, current, type, templateElement) { var element; @@ -15549,7 +19525,7 @@ var emptyOption_ = emptyOption && emptyOption[0]; var unknownOption_ = unknownOption && unknownOption[0]; if (emptyOption_ || unknownOption_) { - while (current && (current === emptyOption_ || current === unknownOption_)) { + while (current && (current === emptyOption_ || current === unknownOption_ || emptyOption_ && emptyOption_.nodeType === NODE_TYPE_COMMENT)) { current = current.nextSibling; } } @@ -26227,947 +30203,6 @@ angular.module("template/typeahead/typeahead-popup.html", []).run([ "$templateCa "use strict"; -var WaveSurfer = { - defaultParams: { - height: 128, - waveColor: "#999", - progressColor: "#555", - cursorColor: "#333", - cursorWidth: 1, - skipLength: 2, - minPxPerSec: 20, - pixelRatio: window.devicePixelRatio, - fillParent: !0, - scrollParent: !1, - hideScrollbar: !1, - normalize: !1, - audioContext: null, - container: null, - dragSelection: !0, - loopSelection: !0, - audioRate: 1, - interact: !0, - splitChannels: !1, - renderer: "Canvas", - backend: "WebAudio", - mediaType: "audio" - }, - init: function(a) { - if (this.params = WaveSurfer.util.extend({}, this.defaultParams, a), this.container = "string" == typeof a.container ? document.querySelector(this.params.container) : this.params.container, - !this.container) throw new Error("Container element not found"); - if ("undefined" == typeof this.params.mediaContainer ? this.mediaContainer = this.container : "string" == typeof this.params.mediaContainer ? this.mediaContainer = document.querySelector(this.params.mediaContainer) : this.mediaContainer = this.params.mediaContainer, - !this.mediaContainer) throw new Error("Media Container element not found"); - this.savedVolume = 0, this.isMuted = !1, this.tmpEvents = [], this.createDrawer(), - this.createBackend(); - }, - createDrawer: function() { - var a = this; - this.drawer = Object.create(WaveSurfer.Drawer[this.params.renderer]), this.drawer.init(this.container, this.params), - this.drawer.on("redraw", function() { - a.drawBuffer(), a.drawer.progress(a.backend.getPlayedPercents()); - }), this.drawer.on("click", function(b, c) { - setTimeout(function() { - a.seekTo(c); - }, 0); - }), this.drawer.on("scroll", function(b) { - a.fireEvent("scroll", b); - }); - }, - createBackend: function() { - var a = this; - this.backend && this.backend.destroy(), "AudioElement" == this.params.backend && (this.params.backend = "MediaElement"), - "WebAudio" != this.params.backend || WaveSurfer.WebAudio.supportsWebAudio() || (this.params.backend = "MediaElement"), - this.backend = Object.create(WaveSurfer[this.params.backend]), this.backend.init(this.params), - this.backend.on("finish", function() { - a.fireEvent("finish"); - }), this.backend.on("play", function() { - a.fireEvent("play"); - }), this.backend.on("pause", function() { - a.fireEvent("pause"); - }), this.backend.on("audioprocess", function(b) { - a.drawer.progress(a.backend.getPlayedPercents()), a.fireEvent("audioprocess", b); - }); - }, - getDuration: function() { - return this.backend.getDuration(); - }, - getCurrentTime: function() { - return this.backend.getCurrentTime(); - }, - play: function(a, b) { - this.backend.play(a, b); - }, - pause: function() { - this.backend.pause(); - }, - playPause: function() { - this.backend.isPaused() ? this.play() : this.pause(); - }, - isPlaying: function() { - return !this.backend.isPaused(); - }, - skipBackward: function(a) { - this.skip(-a || -this.params.skipLength); - }, - skipForward: function(a) { - this.skip(a || this.params.skipLength); - }, - skip: function(a) { - var b = this.getCurrentTime() || 0, c = this.getDuration() || 1; - b = Math.max(0, Math.min(c, b + (a || 0))), this.seekAndCenter(b / c); - }, - seekAndCenter: function(a) { - this.seekTo(a), this.drawer.recenter(a); - }, - seekTo: function(a) { - var b = this.backend.isPaused(), c = this.params.scrollParent; - b && (this.params.scrollParent = !1), this.backend.seekTo(a * this.getDuration()), - this.drawer.progress(this.backend.getPlayedPercents()), b || (this.backend.pause(), - this.backend.play()), this.params.scrollParent = c, this.fireEvent("seek", a); - }, - stop: function() { - this.pause(), this.seekTo(0), this.drawer.progress(0); - }, - setVolume: function(a) { - this.backend.setVolume(a); - }, - setPlaybackRate: function(a) { - this.backend.setPlaybackRate(a); - }, - toggleMute: function() { - this.isMuted ? (this.backend.setVolume(this.savedVolume), this.isMuted = !1) : (this.savedVolume = this.backend.getVolume(), - this.backend.setVolume(0), this.isMuted = !0); - }, - toggleScroll: function() { - this.params.scrollParent = !this.params.scrollParent, this.drawBuffer(); - }, - toggleInteraction: function() { - this.params.interact = !this.params.interact; - }, - drawBuffer: function() { - var a = Math.round(this.getDuration() * this.params.minPxPerSec * this.params.pixelRatio), b = this.drawer.getWidth(), c = a; - this.params.fillParent && (!this.params.scrollParent || b > a) && (c = b); - var d = this.backend.getPeaks(c); - this.drawer.drawPeaks(d, c), this.fireEvent("redraw", d, c); - }, - zoom: function(a) { - this.params.minPxPerSec = a, this.params.scrollParent = !0, this.drawBuffer(), this.seekAndCenter(this.getCurrentTime() / this.getDuration()); - }, - loadArrayBuffer: function(a) { - this.decodeArrayBuffer(a, function(a) { - this.loadDecodedBuffer(a); - }.bind(this)); - }, - loadDecodedBuffer: function(a) { - this.backend.load(a), this.drawBuffer(), this.fireEvent("ready"); - }, - loadBlob: function(a) { - var b = this, c = new FileReader(); - c.addEventListener("progress", function(a) { - b.onProgress(a); - }), c.addEventListener("load", function(a) { - b.loadArrayBuffer(a.target.result); - }), c.addEventListener("error", function() { - b.fireEvent("error", "Error reading file"); - }), c.readAsArrayBuffer(a), this.empty(); - }, - load: function(a, b) { - switch (this.params.backend) { - case "WebAudio": - return this.loadBuffer(a); - - case "MediaElement": - return this.loadMediaElement(a, b); - } - }, - loadBuffer: function(a) { - return this.empty(), this.getArrayBuffer(a, this.loadArrayBuffer.bind(this)); - }, - loadMediaElement: function(a, b) { - this.empty(), this.backend.load(a, this.mediaContainer, b), this.tmpEvents.push(this.backend.once("canplay", function() { - this.drawBuffer(), this.fireEvent("ready"); - }.bind(this)), this.backend.once("error", function(a) { - this.fireEvent("error", a); - }.bind(this))), !b && this.backend.supportsWebAudio() && this.getArrayBuffer(a, function(a) { - this.decodeArrayBuffer(a, function(a) { - this.backend.buffer = a, this.drawBuffer(); - }.bind(this)); - }.bind(this)); - }, - decodeArrayBuffer: function(a, b) { - this.backend.decodeArrayBuffer(a, this.fireEvent.bind(this, "decoded"), this.fireEvent.bind(this, "error", "Error decoding audiobuffer")), - this.tmpEvents.push(this.once("decoded", b)); - }, - getArrayBuffer: function(a, b) { - var c = this, d = WaveSurfer.util.ajax({ - url: a, - responseType: "arraybuffer" - }); - return this.tmpEvents.push(d.on("progress", function(a) { - c.onProgress(a); - }), d.on("success", b), d.on("error", function(a) { - c.fireEvent("error", "XHR error: " + a.target.statusText); - })), d; - }, - onProgress: function(a) { - if (a.lengthComputable) var b = a.loaded / a.total; else b = a.loaded / (a.loaded + 1e6); - this.fireEvent("loading", Math.round(100 * b), a.target); - }, - exportPCM: function(a, b, c) { - a = a || 1024, b = b || 1e4, c = c || !1; - var d = this.backend.getPeaks(a, b), e = [].map.call(d, function(a) { - return Math.round(a * b) / b; - }), f = JSON.stringify(e); - return c || window.open("data:application/json;charset=utf-8," + encodeURIComponent(f)), - f; - }, - clearTmpEvents: function() { - this.tmpEvents.forEach(function(a) { - a.un(); - }); - }, - empty: function() { - this.backend.isPaused() || (this.stop(), this.backend.disconnectSource()), this.clearTmpEvents(), - this.drawer.progress(0), this.drawer.setWidth(0), this.drawer.drawPeaks({ - length: this.drawer.getWidth() - }, 0); - }, - destroy: function() { - this.fireEvent("destroy"), this.clearTmpEvents(), this.unAll(), this.backend.destroy(), - this.drawer.destroy(); - } -}; - -WaveSurfer.create = function(a) { - var b = Object.create(WaveSurfer); - return b.init(a), b; -}, WaveSurfer.util = { - extend: function(a) { - var b = Array.prototype.slice.call(arguments, 1); - return b.forEach(function(b) { - Object.keys(b).forEach(function(c) { - a[c] = b[c]; - }); - }), a; - }, - getId: function() { - return "wavesurfer_" + Math.random().toString(32).substring(2); - }, - ajax: function(a) { - var b = Object.create(WaveSurfer.Observer), c = new XMLHttpRequest(), d = !1; - return c.open(a.method || "GET", a.url, !0), c.responseType = a.responseType || "json", - c.addEventListener("progress", function(a) { - b.fireEvent("progress", a), a.lengthComputable && a.loaded == a.total && (d = !0); - }), c.addEventListener("load", function(a) { - d || b.fireEvent("progress", a), b.fireEvent("load", a), 200 == c.status || 206 == c.status ? b.fireEvent("success", c.response, a) : b.fireEvent("error", a); - }), c.addEventListener("error", function(a) { - b.fireEvent("error", a); - }), c.send(), b.xhr = c, b; - } -}, WaveSurfer.Observer = { - on: function(a, b) { - this.handlers || (this.handlers = {}); - var c = this.handlers[a]; - return c || (c = this.handlers[a] = []), c.push(b), { - name: a, - callback: b, - un: this.un.bind(this, a, b) - }; - }, - un: function(a, b) { - if (this.handlers) { - var c = this.handlers[a]; - if (c) if (b) for (var d = c.length - 1; d >= 0; d--) c[d] == b && c.splice(d, 1); else c.length = 0; - } - }, - unAll: function() { - this.handlers = null; - }, - once: function(a, b) { - var c = this, d = function() { - b.apply(this, arguments), setTimeout(function() { - c.un(a, d); - }, 0); - }; - return this.on(a, d); - }, - fireEvent: function(a) { - if (this.handlers) { - var b = this.handlers[a], c = Array.prototype.slice.call(arguments, 1); - b && b.forEach(function(a) { - a.apply(null, c); - }); - } - } -}, WaveSurfer.util.extend(WaveSurfer, WaveSurfer.Observer), WaveSurfer.WebAudio = { - scriptBufferSize: 256, - PLAYING_STATE: 0, - PAUSED_STATE: 1, - FINISHED_STATE: 2, - supportsWebAudio: function() { - return !(!window.AudioContext && !window.webkitAudioContext); - }, - getAudioContext: function() { - return WaveSurfer.WebAudio.audioContext || (WaveSurfer.WebAudio.audioContext = new (window.AudioContext || window.webkitAudioContext)()), - WaveSurfer.WebAudio.audioContext; - }, - getOfflineAudioContext: function(a) { - return WaveSurfer.WebAudio.offlineAudioContext || (WaveSurfer.WebAudio.offlineAudioContext = new (window.OfflineAudioContext || window.webkitOfflineAudioContext)(1, 2, a)), - WaveSurfer.WebAudio.offlineAudioContext; - }, - init: function(a) { - this.params = a, this.ac = a.audioContext || this.getAudioContext(), this.lastPlay = this.ac.currentTime, - this.startPosition = 0, this.scheduledPause = null, this.states = [ Object.create(WaveSurfer.WebAudio.state.playing), Object.create(WaveSurfer.WebAudio.state.paused), Object.create(WaveSurfer.WebAudio.state.finished) ], - this.createVolumeNode(), this.createScriptNode(), this.createAnalyserNode(), this.setState(this.PAUSED_STATE), - this.setPlaybackRate(this.params.audioRate); - }, - disconnectFilters: function() { - this.filters && (this.filters.forEach(function(a) { - a && a.disconnect(); - }), this.filters = null, this.analyser.connect(this.gainNode)); - }, - setState: function(a) { - this.state !== this.states[a] && (this.state = this.states[a], this.state.init.call(this)); - }, - setFilter: function() { - this.setFilters([].slice.call(arguments)); - }, - setFilters: function(a) { - this.disconnectFilters(), a && a.length && (this.filters = a, this.analyser.disconnect(), - a.reduce(function(a, b) { - return a.connect(b), b; - }, this.analyser).connect(this.gainNode)); - }, - createScriptNode: function() { - this.ac.createScriptProcessor ? this.scriptNode = this.ac.createScriptProcessor(this.scriptBufferSize) : this.scriptNode = this.ac.createJavaScriptNode(this.scriptBufferSize), - this.scriptNode.connect(this.ac.destination); - }, - addOnAudioProcess: function() { - var a = this; - this.scriptNode.onaudioprocess = function() { - var b = a.getCurrentTime(); - b >= a.getDuration() ? (a.setState(a.FINISHED_STATE), a.fireEvent("pause")) : b >= a.scheduledPause ? (a.setState(a.PAUSED_STATE), - a.fireEvent("pause")) : a.state === a.states[a.PLAYING_STATE] && a.fireEvent("audioprocess", b); - }; - }, - removeOnAudioProcess: function() { - this.scriptNode.onaudioprocess = null; - }, - createAnalyserNode: function() { - this.analyser = this.ac.createAnalyser(), this.analyser.connect(this.gainNode); - }, - createVolumeNode: function() { - this.ac.createGain ? this.gainNode = this.ac.createGain() : this.gainNode = this.ac.createGainNode(), - this.gainNode.connect(this.ac.destination); - }, - setVolume: function(a) { - this.gainNode.gain.value = a; - }, - getVolume: function() { - return this.gainNode.gain.value; - }, - decodeArrayBuffer: function(a, b, c) { - this.offlineAc || (this.offlineAc = this.getOfflineAudioContext(this.ac ? this.ac.sampleRate : 44100)), - this.offlineAc.decodeAudioData(a, function(a) { - b(a); - }.bind(this), c); - }, - getPeaks: function(a) { - for (var b = this.buffer.length / a, c = ~~(b / 10) || 1, d = this.buffer.numberOfChannels, e = [], f = [], g = 0; d > g; g++) for (var h = e[g] = [], i = this.buffer.getChannelData(g), j = 0; a > j; j++) { - for (var k = ~~(j * b), l = ~~(k + b), m = i[0], n = i[0], o = k; l > o; o += c) { - var p = i[o]; - p > n && (n = p), m > p && (m = p); - } - h[2 * j] = n, h[2 * j + 1] = m, (0 == g || n > f[2 * j]) && (f[2 * j] = n), (0 == g || m < f[2 * j + 1]) && (f[2 * j + 1] = m); - } - return this.params.splitChannels ? e : f; - }, - getPlayedPercents: function() { - return this.state.getPlayedPercents.call(this); - }, - disconnectSource: function() { - this.source && this.source.disconnect(); - }, - destroy: function() { - this.isPaused() || this.pause(), this.unAll(), this.buffer = null, this.disconnectFilters(), - this.disconnectSource(), this.gainNode.disconnect(), this.scriptNode.disconnect(), - this.analyser.disconnect(); - }, - load: function(a) { - this.startPosition = 0, this.lastPlay = this.ac.currentTime, this.buffer = a, this.createSource(); - }, - createSource: function() { - this.disconnectSource(), this.source = this.ac.createBufferSource(), this.source.start = this.source.start || this.source.noteGrainOn, - this.source.stop = this.source.stop || this.source.noteOff, this.source.playbackRate.value = this.playbackRate, - this.source.buffer = this.buffer, this.source.connect(this.analyser); - }, - isPaused: function() { - return this.state !== this.states[this.PLAYING_STATE]; - }, - getDuration: function() { - return this.buffer ? this.buffer.duration : 0; - }, - seekTo: function(a, b) { - return this.scheduledPause = null, null == a && (a = this.getCurrentTime(), a >= this.getDuration() && (a = 0)), - null == b && (b = this.getDuration()), this.startPosition = a, this.lastPlay = this.ac.currentTime, - this.state === this.states[this.FINISHED_STATE] && this.setState(this.PAUSED_STATE), - { - start: a, - end: b - }; - }, - getPlayedTime: function() { - return (this.ac.currentTime - this.lastPlay) * this.playbackRate; - }, - play: function(a, b) { - this.createSource(); - var c = this.seekTo(a, b); - a = c.start, b = c.end, this.scheduledPause = b, this.source.start(0, a, b - a), - this.setState(this.PLAYING_STATE), this.fireEvent("play"); - }, - pause: function() { - this.scheduledPause = null, this.startPosition += this.getPlayedTime(), this.source && this.source.stop(0), - this.setState(this.PAUSED_STATE), this.fireEvent("pause"); - }, - getCurrentTime: function() { - return this.state.getCurrentTime.call(this); - }, - setPlaybackRate: function(a) { - a = a || 1, this.isPaused() ? this.playbackRate = a : (this.pause(), this.playbackRate = a, - this.play()); - } -}, WaveSurfer.WebAudio.state = {}, WaveSurfer.WebAudio.state.playing = { - init: function() { - this.addOnAudioProcess(); - }, - getPlayedPercents: function() { - var a = this.getDuration(); - return this.getCurrentTime() / a || 0; - }, - getCurrentTime: function() { - return this.startPosition + this.getPlayedTime(); - } -}, WaveSurfer.WebAudio.state.paused = { - init: function() { - this.removeOnAudioProcess(); - }, - getPlayedPercents: function() { - var a = this.getDuration(); - return this.getCurrentTime() / a || 0; - }, - getCurrentTime: function() { - return this.startPosition; - } -}, WaveSurfer.WebAudio.state.finished = { - init: function() { - this.removeOnAudioProcess(), this.fireEvent("finish"); - }, - getPlayedPercents: function() { - return 1; - }, - getCurrentTime: function() { - return this.getDuration(); - } -}, WaveSurfer.util.extend(WaveSurfer.WebAudio, WaveSurfer.Observer), WaveSurfer.MediaElement = Object.create(WaveSurfer.WebAudio), -WaveSurfer.util.extend(WaveSurfer.MediaElement, { - init: function(a) { - this.params = a, this.media = { - currentTime: 0, - duration: 0, - paused: !0, - playbackRate: 1, - play: function() {}, - pause: function() {} - }, this.mediaType = a.mediaType.toLowerCase(), this.elementPosition = a.elementPosition; - }, - load: function(a, b, c) { - var d = this, e = document.createElement(this.mediaType); - e.controls = !1, e.autoplay = !1, e.preload = "auto", e.src = a, e.addEventListener("error", function() { - d.fireEvent("error", "Error loading media element"); - }), e.addEventListener("canplay", function() { - d.fireEvent("canplay"); - }), e.addEventListener("ended", function() { - d.fireEvent("finish"); - }), e.addEventListener("timeupdate", function() { - d.fireEvent("audioprocess", d.getCurrentTime()); - }); - var f = b.querySelector(this.mediaType); - f && b.removeChild(f), b.appendChild(e), this.media = e, this.peaks = c, this.onPlayEnd = null, - this.buffer = null, this.setPlaybackRate(this.playbackRate); - }, - isPaused: function() { - return !this.media || this.media.paused; - }, - getDuration: function() { - var a = this.media.duration; - return a >= 1 / 0 && (a = this.media.seekable.end()), a; - }, - getCurrentTime: function() { - return this.media && this.media.currentTime; - }, - getPlayedPercents: function() { - return this.getCurrentTime() / this.getDuration() || 0; - }, - setPlaybackRate: function(a) { - this.playbackRate = a || 1, this.media.playbackRate = this.playbackRate; - }, - seekTo: function(a) { - null != a && (this.media.currentTime = a), this.clearPlayEnd(); - }, - play: function(a, b) { - this.seekTo(a), this.media.play(), b && this.setPlayEnd(b), this.fireEvent("play"); - }, - pause: function() { - this.media && this.media.pause(), this.clearPlayEnd(), this.fireEvent("pause"); - }, - setPlayEnd: function(a) { - var b = this; - this.onPlayEnd = function(c) { - c >= a && (b.pause(), b.seekTo(a)); - }, this.on("audioprocess", this.onPlayEnd); - }, - clearPlayEnd: function() { - this.onPlayEnd && (this.un("audioprocess", this.onPlayEnd), this.onPlayEnd = null); - }, - getPeaks: function(a) { - return this.buffer ? WaveSurfer.WebAudio.getPeaks.call(this, a) : this.peaks || []; - }, - getVolume: function() { - return this.media.volume; - }, - setVolume: function(a) { - this.media.volume = a; - }, - destroy: function() { - this.pause(), this.unAll(), this.media && this.media.parentNode && this.media.parentNode.removeChild(this.media), - this.media = null; - } -}), WaveSurfer.AudioElement = WaveSurfer.MediaElement, WaveSurfer.Drawer = { - init: function(a, b) { - this.container = a, this.params = b, this.width = 0, this.height = b.height * this.params.pixelRatio, - this.lastPos = 0, this.createWrapper(), this.createElements(); - }, - createWrapper: function() { - this.wrapper = this.container.appendChild(document.createElement("wave")), this.style(this.wrapper, { - display: "block", - position: "relative", - userSelect: "none", - webkitUserSelect: "none", - height: this.params.height + "px" - }), (this.params.fillParent || this.params.scrollParent) && this.style(this.wrapper, { - width: "100%", - overflowX: this.params.hideScrollbar ? "hidden" : "auto", - overflowY: "hidden" - }), this.setupWrapperEvents(); - }, - handleEvent: function(a) { - a.preventDefault(); - var b = this.wrapper.getBoundingClientRect(); - return (a.clientX - b.left + this.wrapper.scrollLeft) / this.wrapper.scrollWidth || 0; - }, - setupWrapperEvents: function() { - var a = this; - this.wrapper.addEventListener("click", function(b) { - var c = a.wrapper.offsetHeight - a.wrapper.clientHeight; - if (0 != c) { - var d = a.wrapper.getBoundingClientRect(); - if (b.clientY >= d.bottom - c) return; - } - a.params.interact && a.fireEvent("click", b, a.handleEvent(b)); - }), this.wrapper.addEventListener("scroll", function(b) { - a.fireEvent("scroll", b); - }); - }, - drawPeaks: function(a, b) { - this.resetScroll(), this.setWidth(b), this.params.barWidth ? this.drawBars(a) : this.drawWave(a); - }, - style: function(a, b) { - return Object.keys(b).forEach(function(c) { - a.style[c] !== b[c] && (a.style[c] = b[c]); - }), a; - }, - resetScroll: function() { - null !== this.wrapper && (this.wrapper.scrollLeft = 0); - }, - recenter: function(a) { - var b = this.wrapper.scrollWidth * a; - this.recenterOnPosition(b, !0); - }, - recenterOnPosition: function(a, b) { - var c = this.wrapper.scrollLeft, d = ~~(this.wrapper.clientWidth / 2), e = a - d, f = e - c, g = this.wrapper.scrollWidth - this.wrapper.clientWidth; - if (0 != g) { - if (!b && f >= -d && d > f) { - var h = 5; - f = Math.max(-h, Math.min(h, f)), e = c + f; - } - e = Math.max(0, Math.min(g, e)), e != c && (this.wrapper.scrollLeft = e); - } - }, - getWidth: function() { - return Math.round(this.container.clientWidth * this.params.pixelRatio); - }, - setWidth: function(a) { - a != this.width && (this.width = a, this.params.fillParent || this.params.scrollParent ? this.style(this.wrapper, { - width: "" - }) : this.style(this.wrapper, { - width: ~~(this.width / this.params.pixelRatio) + "px" - }), this.updateSize()); - }, - setHeight: function(a) { - a != this.height && (this.height = a, this.style(this.wrapper, { - height: ~~(this.height / this.params.pixelRatio) + "px" - }), this.updateSize()); - }, - progress: function(a) { - var b = 1 / this.params.pixelRatio, c = Math.round(a * this.width) * b; - if (c < this.lastPos || c - this.lastPos >= b) { - if (this.lastPos = c, this.params.scrollParent) { - var d = ~~(this.wrapper.scrollWidth * a); - this.recenterOnPosition(d); - } - this.updateProgress(a); - } - }, - destroy: function() { - this.unAll(), this.wrapper && (this.container.removeChild(this.wrapper), this.wrapper = null); - }, - createElements: function() {}, - updateSize: function() {}, - drawWave: function(a, b) {}, - clearWave: function() {}, - updateProgress: function(a) {} -}, WaveSurfer.util.extend(WaveSurfer.Drawer, WaveSurfer.Observer), WaveSurfer.Drawer.Canvas = Object.create(WaveSurfer.Drawer), -WaveSurfer.util.extend(WaveSurfer.Drawer.Canvas, { - createElements: function() { - var a = this.wrapper.appendChild(this.style(document.createElement("canvas"), { - position: "absolute", - zIndex: 1, - left: 0, - top: 0, - bottom: 0 - })); - if (this.waveCc = a.getContext("2d"), this.progressWave = this.wrapper.appendChild(this.style(document.createElement("wave"), { - position: "absolute", - zIndex: 2, - left: 0, - top: 0, - bottom: 0, - overflow: "hidden", - width: "0", - display: "none", - boxSizing: "border-box", - borderRightStyle: "solid", - borderRightWidth: this.params.cursorWidth + "px", - borderRightColor: this.params.cursorColor - })), this.params.waveColor != this.params.progressColor) { - var b = this.progressWave.appendChild(document.createElement("canvas")); - this.progressCc = b.getContext("2d"); - } - }, - updateSize: function() { - var a = Math.round(this.width / this.params.pixelRatio); - this.waveCc.canvas.width = this.width, this.waveCc.canvas.height = this.height, - this.style(this.waveCc.canvas, { - width: a + "px" - }), this.style(this.progressWave, { - display: "block" - }), this.progressCc && (this.progressCc.canvas.width = this.width, this.progressCc.canvas.height = this.height, - this.style(this.progressCc.canvas, { - width: a + "px" - })), this.clearWave(); - }, - clearWave: function() { - this.waveCc.clearRect(0, 0, this.width, this.height), this.progressCc && this.progressCc.clearRect(0, 0, this.width, this.height); - }, - drawBars: function(a, b) { - if (a[0] instanceof Array) { - var c = a; - if (this.params.splitChannels) return this.setHeight(c.length * this.params.height * this.params.pixelRatio), - void c.forEach(this.drawBars, this); - a = c[0]; - } - var d = .5 / this.params.pixelRatio, e = this.width, f = this.params.height * this.params.pixelRatio, g = f * b || 0, h = f / 2, i = ~~(a.length / 2), j = this.params.barWidth * this.params.pixelRatio, k = Math.max(this.params.pixelRatio, ~~(j / 2)), l = j + k, m = 1; - if (this.params.normalize) { - var n, o; - o = Math.max.apply(Math, a), n = Math.min.apply(Math, a), m = o, -n > m && (m = -n); - } - var p = i / e; - this.waveCc.fillStyle = this.params.waveColor, this.progressCc && (this.progressCc.fillStyle = this.params.progressColor), - [ this.waveCc, this.progressCc ].forEach(function(b) { - if (b) if (this.params.reflection) for (var c = 0; e > c; c += l) { - var f = Math.round(a[2 * c * p] / m * h); - b.fillRect(c + d, h - f + g, j + d, 2 * f); - } else { - for (var c = 0; e > c; c += l) { - var f = Math.round(a[2 * c * p] / m * h); - b.fillRect(c + d, h - f + g, j + d, f); - } - for (var c = 0; e > c; c += l) { - var f = Math.round(a[2 * c * p + 1] / m * h); - b.fillRect(c + d, h - f + g, j + d, f); - } - } - }, this); - }, - drawWave: function(a, b) { - if (a[0] instanceof Array) { - var c = a; - if (this.params.splitChannels) return this.setHeight(c.length * this.params.height * this.params.pixelRatio), - void c.forEach(this.drawWave, this); - a = c[0]; - } - var d = .5 / this.params.pixelRatio, e = this.params.height * this.params.pixelRatio, f = e * b || 0, g = e / 2, h = ~~(a.length / 2), i = 1; - this.params.fillParent && this.width != h && (i = this.width / h); - var j = 1; - if (this.params.normalize) { - var k, l; - l = Math.max.apply(Math, a), k = Math.min.apply(Math, a), j = l, -k > j && (j = -k); - } - this.waveCc.fillStyle = this.params.waveColor, this.progressCc && (this.progressCc.fillStyle = this.params.progressColor), - [ this.waveCc, this.progressCc ].forEach(function(b) { - if (b) { - b.beginPath(), b.moveTo(d, g + f); - for (var c = 0; h > c; c++) { - var e = Math.round(a[2 * c] / j * g); - b.lineTo(c * i + d, g - e + f); - } - for (var c = h - 1; c >= 0; c--) { - var e = Math.round(a[2 * c + 1] / j * g); - b.lineTo(c * i + d, g - e + f); - } - b.closePath(), b.fill(), b.fillRect(0, g + f - d, this.width, d); - } - }, this); - }, - updateProgress: function(a) { - var b = Math.round(this.width * a) / this.params.pixelRatio; - this.style(this.progressWave, { - width: b + "px" - }); - } -}); - -var app = angular.module("autocomplete", []); - -app.directive("autocomplete", function() { - var index = -1; - return { - restrict: "E", - scope: { - searchParam: "=ngModel", - suggestions: "=data", - onType: "=onType", - onSelect: "=onSelect", - autocompleteRequired: "=" - }, - controller: [ "$scope", function($scope) { - $scope.selectedIndex = -1; - $scope.initLock = true; - $scope.setIndex = function(i) { - $scope.selectedIndex = parseInt(i); - }; - this.setIndex = function(i) { - $scope.setIndex(i); - $scope.$apply(); - }; - $scope.getIndex = function(i) { - return $scope.selectedIndex; - }; - var watching = true; - $scope.completing = false; - $scope.$watch("searchParam", function(newValue, oldValue) { - if (oldValue === newValue || !oldValue && $scope.initLock) { - return; - } - if (watching && typeof $scope.searchParam !== "undefined" && $scope.searchParam !== null) { - $scope.completing = true; - $scope.searchFilter = $scope.searchParam; - $scope.selectedIndex = -1; - } - if ($scope.onType) $scope.onType($scope.searchParam); - }); - this.preSelect = function(suggestion) { - watching = false; - $scope.$apply(); - watching = true; - }; - $scope.preSelect = this.preSelect; - this.preSelectOff = function() { - watching = true; - }; - $scope.preSelectOff = this.preSelectOff; - $scope.select = function(suggestion) { - if (suggestion) { - $scope.searchParam = suggestion; - $scope.searchFilter = suggestion; - if ($scope.onSelect) $scope.onSelect(suggestion); - } - watching = false; - $scope.completing = false; - setTimeout(function() { - watching = true; - }, 1e3); - $scope.setIndex(-1); - }; - } ], - link: function(scope, element, attrs) { - setTimeout(function() { - scope.initLock = false; - scope.$apply(); - }, 250); - var attr = ""; - scope.attrs = { - placeholder: "start typing...", - "class": "", - id: "", - inputclass: "", - inputid: "" - }; - for (var a in attrs) { - attr = a.replace("attr", "").toLowerCase(); - if (a.indexOf("attr") === 0) { - scope.attrs[attr] = attrs[a]; - } - } - if (attrs.clickActivation) { - element[0].onclick = function(e) { - if (!scope.searchParam) { - setTimeout(function() { - scope.completing = true; - scope.$apply(); - }, 200); - } - }; - } - var key = { - left: 37, - up: 38, - right: 39, - down: 40, - enter: 13, - esc: 27, - tab: 9 - }; - document.addEventListener("keydown", function(e) { - var keycode = e.keyCode || e.which; - switch (keycode) { - case key.esc: - scope.select(); - scope.setIndex(-1); - scope.$apply(); - e.preventDefault(); - } - }, true); - document.addEventListener("blur", function(e) { - setTimeout(function() { - scope.select(); - scope.setIndex(-1); - scope.$apply(); - }, 150); - }, true); - element[0].addEventListener("keydown", function(e) { - var keycode = e.keyCode || e.which; - var l = angular.element(this).find("li").length; - if (!scope.completing || l == 0) return; - switch (keycode) { - case key.up: - index = scope.getIndex() - 1; - if (index < -1) { - index = l - 1; - } else if (index >= l) { - index = -1; - scope.setIndex(index); - scope.preSelectOff(); - break; - } - scope.setIndex(index); - if (index !== -1) scope.preSelect(angular.element(angular.element(this).find("li")[index]).text()); - scope.$apply(); - break; - - case key.down: - index = scope.getIndex() + 1; - if (index < -1) { - index = l - 1; - } else if (index >= l) { - index = -1; - scope.setIndex(index); - scope.preSelectOff(); - scope.$apply(); - break; - } - scope.setIndex(index); - if (index !== -1) scope.preSelect(angular.element(angular.element(this).find("li")[index]).text()); - break; - - case key.left: - break; - - case key.right: - case key.enter: - case key.tab: - index = scope.getIndex(); - if (index !== -1) { - scope.select(angular.element(angular.element(this).find("li")[index]).text()); - if (keycode == key.enter) { - e.preventDefault(); - } - } else { - if (keycode == key.enter) { - scope.select(); - } - } - scope.setIndex(-1); - scope.$apply(); - break; - - case key.esc: - scope.select(); - scope.setIndex(-1); - scope.$apply(); - e.preventDefault(); - break; - - default: - return; - } - }); - }, - template: '
        ' - }; -}); - -app.filter("highlight", [ "$sce", function($sce) { - return function(input, searchParam) { - if (typeof input === "function") return ""; - if (searchParam) { - var words = "(" + searchParam.split(/\ /).join(" |") + "|" + searchParam.split(/\ /).join("|") + ")", exp = new RegExp(words, "gi"); - if (words.length) { - input = input.replace(exp, '$1'); - } - } - return $sce.trustAsHtml(input); - }; -} ]); - -app.directive("suggestion", function() { - return { - restrict: "A", - require: "^autocomplete", - link: function(scope, element, attrs, autoCtrl) { - element.bind("mouseenter", function() { - autoCtrl.preSelect(attrs.val); - autoCtrl.setIndex(attrs.index); - }); - element.bind("mouseleave", function() { - autoCtrl.preSelectOff(); - }); - } - }; -}); - -"use strict"; - var app = angular.module("LanguagesModule", [ "ui.bootstrap" ]); app.factory("responseHandler", [ "$timeout", "$modal", responseHandler ]); @@ -27311,8 +30346,33 @@ function responseHandler($timeout, $modal) { function error(message) { show("error", message, 5e3); } + function yesno(status, message, callback) { + var controller = function($scope, $modalInstance) { + $scope.status = status; + $scope.message = message; + $scope.yes = function() { + $modalInstance.close(true); + }; + $scope.no = function() { + $modalInstance.close(false); + }; + }; + $modal.open({ + animation: true, + templateUrl: "responseHandlerYesNoModal.html", + controller: controller, + size: "lg", + backdrop: "static", + keyboard: false + }).result.then(function(result) { + callback(result); + }, function() { + callback(false); + }); + } return { success: success, - error: error + error: error, + yesno: yesno }; } \ No newline at end of file diff --git a/lingvodoc/static/js/login.js b/lingvodoc/static/js/login.js index c61971896..ea61bfc18 100644 --- a/lingvodoc/static/js/login.js +++ b/lingvodoc/static/js/login.js @@ -5377,6 +5377,3947 @@ return jQuery; }); +(function() { + var undefined; + var VERSION = "3.10.1"; + var BIND_FLAG = 1, BIND_KEY_FLAG = 2, CURRY_BOUND_FLAG = 4, CURRY_FLAG = 8, CURRY_RIGHT_FLAG = 16, PARTIAL_FLAG = 32, PARTIAL_RIGHT_FLAG = 64, ARY_FLAG = 128, REARG_FLAG = 256; + var DEFAULT_TRUNC_LENGTH = 30, DEFAULT_TRUNC_OMISSION = "..."; + var HOT_COUNT = 150, HOT_SPAN = 16; + var LARGE_ARRAY_SIZE = 200; + var LAZY_FILTER_FLAG = 1, LAZY_MAP_FLAG = 2; + var FUNC_ERROR_TEXT = "Expected a function"; + var PLACEHOLDER = "__lodash_placeholder__"; + var argsTag = "[object Arguments]", arrayTag = "[object Array]", boolTag = "[object Boolean]", dateTag = "[object Date]", errorTag = "[object Error]", funcTag = "[object Function]", mapTag = "[object Map]", numberTag = "[object Number]", objectTag = "[object Object]", regexpTag = "[object RegExp]", setTag = "[object Set]", stringTag = "[object String]", weakMapTag = "[object WeakMap]"; + var arrayBufferTag = "[object ArrayBuffer]", float32Tag = "[object Float32Array]", float64Tag = "[object Float64Array]", int8Tag = "[object Int8Array]", int16Tag = "[object Int16Array]", int32Tag = "[object Int32Array]", uint8Tag = "[object Uint8Array]", uint8ClampedTag = "[object Uint8ClampedArray]", uint16Tag = "[object Uint16Array]", uint32Tag = "[object Uint32Array]"; + var reEmptyStringLeading = /\b__p \+= '';/g, reEmptyStringMiddle = /\b(__p \+=) '' \+/g, reEmptyStringTrailing = /(__e\(.*?\)|\b__t\)) \+\n'';/g; + var reEscapedHtml = /&(?:amp|lt|gt|quot|#39|#96);/g, reUnescapedHtml = /[&<>"'`]/g, reHasEscapedHtml = RegExp(reEscapedHtml.source), reHasUnescapedHtml = RegExp(reUnescapedHtml.source); + var reEscape = /<%-([\s\S]+?)%>/g, reEvaluate = /<%([\s\S]+?)%>/g, reInterpolate = /<%=([\s\S]+?)%>/g; + var reIsDeepProp = /\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\n\\]|\\.)*?\1)\]/, reIsPlainProp = /^\w*$/, rePropName = /[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\n\\]|\\.)*?)\2)\]/g; + var reRegExpChars = /^[:!,]|[\\^$.*+?()[\]{}|\/]|(^[0-9a-fA-Fnrtuvx])|([\n\r\u2028\u2029])/g, reHasRegExpChars = RegExp(reRegExpChars.source); + var reComboMark = /[\u0300-\u036f\ufe20-\ufe23]/g; + var reEscapeChar = /\\(\\)?/g; + var reEsTemplate = /\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g; + var reFlags = /\w*$/; + var reHasHexPrefix = /^0[xX]/; + var reIsHostCtor = /^\[object .+?Constructor\]$/; + var reIsUint = /^\d+$/; + var reLatin1 = /[\xc0-\xd6\xd8-\xde\xdf-\xf6\xf8-\xff]/g; + var reNoMatch = /($^)/; + var reUnescapedString = /['\n\r\u2028\u2029\\]/g; + var reWords = function() { + var upper = "[A-Z\\xc0-\\xd6\\xd8-\\xde]", lower = "[a-z\\xdf-\\xf6\\xf8-\\xff]+"; + return RegExp(upper + "+(?=" + upper + lower + ")|" + upper + "?" + lower + "|" + upper + "+|[0-9]+", "g"); + }(); + var contextProps = [ "Array", "ArrayBuffer", "Date", "Error", "Float32Array", "Float64Array", "Function", "Int8Array", "Int16Array", "Int32Array", "Math", "Number", "Object", "RegExp", "Set", "String", "_", "clearTimeout", "isFinite", "parseFloat", "parseInt", "setTimeout", "TypeError", "Uint8Array", "Uint8ClampedArray", "Uint16Array", "Uint32Array", "WeakMap" ]; + var templateCounter = -1; + var typedArrayTags = {}; + typedArrayTags[float32Tag] = typedArrayTags[float64Tag] = typedArrayTags[int8Tag] = typedArrayTags[int16Tag] = typedArrayTags[int32Tag] = typedArrayTags[uint8Tag] = typedArrayTags[uint8ClampedTag] = typedArrayTags[uint16Tag] = typedArrayTags[uint32Tag] = true; + typedArrayTags[argsTag] = typedArrayTags[arrayTag] = typedArrayTags[arrayBufferTag] = typedArrayTags[boolTag] = typedArrayTags[dateTag] = typedArrayTags[errorTag] = typedArrayTags[funcTag] = typedArrayTags[mapTag] = typedArrayTags[numberTag] = typedArrayTags[objectTag] = typedArrayTags[regexpTag] = typedArrayTags[setTag] = typedArrayTags[stringTag] = typedArrayTags[weakMapTag] = false; + var cloneableTags = {}; + cloneableTags[argsTag] = cloneableTags[arrayTag] = cloneableTags[arrayBufferTag] = cloneableTags[boolTag] = cloneableTags[dateTag] = cloneableTags[float32Tag] = cloneableTags[float64Tag] = cloneableTags[int8Tag] = cloneableTags[int16Tag] = cloneableTags[int32Tag] = cloneableTags[numberTag] = cloneableTags[objectTag] = cloneableTags[regexpTag] = cloneableTags[stringTag] = cloneableTags[uint8Tag] = cloneableTags[uint8ClampedTag] = cloneableTags[uint16Tag] = cloneableTags[uint32Tag] = true; + cloneableTags[errorTag] = cloneableTags[funcTag] = cloneableTags[mapTag] = cloneableTags[setTag] = cloneableTags[weakMapTag] = false; + var deburredLetters = { + "À": "A", + "Á": "A", + "Â": "A", + "Ã": "A", + "Ä": "A", + "Å": "A", + "à": "a", + "á": "a", + "â": "a", + "ã": "a", + "ä": "a", + "å": "a", + "Ç": "C", + "ç": "c", + "Ð": "D", + "ð": "d", + "È": "E", + "É": "E", + "Ê": "E", + "Ë": "E", + "è": "e", + "é": "e", + "ê": "e", + "ë": "e", + "Ì": "I", + "Í": "I", + "Î": "I", + "Ï": "I", + "ì": "i", + "í": "i", + "î": "i", + "ï": "i", + "Ñ": "N", + "ñ": "n", + "Ò": "O", + "Ó": "O", + "Ô": "O", + "Õ": "O", + "Ö": "O", + "Ø": "O", + "ò": "o", + "ó": "o", + "ô": "o", + "õ": "o", + "ö": "o", + "ø": "o", + "Ù": "U", + "Ú": "U", + "Û": "U", + "Ü": "U", + "ù": "u", + "ú": "u", + "û": "u", + "ü": "u", + "Ý": "Y", + "ý": "y", + "ÿ": "y", + "Æ": "Ae", + "æ": "ae", + "Þ": "Th", + "þ": "th", + "ß": "ss" + }; + var htmlEscapes = { + "&": "&", + "<": "<", + ">": ">", + '"': """, + "'": "'", + "`": "`" + }; + var htmlUnescapes = { + "&": "&", + "<": "<", + ">": ">", + """: '"', + "'": "'", + "`": "`" + }; + var objectTypes = { + "function": true, + object: true + }; + var regexpEscapes = { + "0": "x30", + "1": "x31", + "2": "x32", + "3": "x33", + "4": "x34", + "5": "x35", + "6": "x36", + "7": "x37", + "8": "x38", + "9": "x39", + A: "x41", + B: "x42", + C: "x43", + D: "x44", + E: "x45", + F: "x46", + a: "x61", + b: "x62", + c: "x63", + d: "x64", + e: "x65", + f: "x66", + n: "x6e", + r: "x72", + t: "x74", + u: "x75", + v: "x76", + x: "x78" + }; + var stringEscapes = { + "\\": "\\", + "'": "'", + "\n": "n", + "\r": "r", + "\u2028": "u2028", + "\u2029": "u2029" + }; + var freeExports = objectTypes[typeof exports] && exports && !exports.nodeType && exports; + var freeModule = objectTypes[typeof module] && module && !module.nodeType && module; + var freeGlobal = freeExports && freeModule && typeof global == "object" && global && global.Object && global; + var freeSelf = objectTypes[typeof self] && self && self.Object && self; + var freeWindow = objectTypes[typeof window] && window && window.Object && window; + var moduleExports = freeModule && freeModule.exports === freeExports && freeExports; + var root = freeGlobal || freeWindow !== (this && this.window) && freeWindow || freeSelf || this; + function baseCompareAscending(value, other) { + if (value !== other) { + var valIsNull = value === null, valIsUndef = value === undefined, valIsReflexive = value === value; + var othIsNull = other === null, othIsUndef = other === undefined, othIsReflexive = other === other; + if (value > other && !othIsNull || !valIsReflexive || valIsNull && !othIsUndef && othIsReflexive || valIsUndef && othIsReflexive) { + return 1; + } + if (value < other && !valIsNull || !othIsReflexive || othIsNull && !valIsUndef && valIsReflexive || othIsUndef && valIsReflexive) { + return -1; + } + } + return 0; + } + function baseFindIndex(array, predicate, fromRight) { + var length = array.length, index = fromRight ? length : -1; + while (fromRight ? index-- : ++index < length) { + if (predicate(array[index], index, array)) { + return index; + } + } + return -1; + } + function baseIndexOf(array, value, fromIndex) { + if (value !== value) { + return indexOfNaN(array, fromIndex); + } + var index = fromIndex - 1, length = array.length; + while (++index < length) { + if (array[index] === value) { + return index; + } + } + return -1; + } + function baseIsFunction(value) { + return typeof value == "function" || false; + } + function baseToString(value) { + return value == null ? "" : value + ""; + } + function charsLeftIndex(string, chars) { + var index = -1, length = string.length; + while (++index < length && chars.indexOf(string.charAt(index)) > -1) {} + return index; + } + function charsRightIndex(string, chars) { + var index = string.length; + while (index-- && chars.indexOf(string.charAt(index)) > -1) {} + return index; + } + function compareAscending(object, other) { + return baseCompareAscending(object.criteria, other.criteria) || object.index - other.index; + } + function compareMultiple(object, other, orders) { + var index = -1, objCriteria = object.criteria, othCriteria = other.criteria, length = objCriteria.length, ordersLength = orders.length; + while (++index < length) { + var result = baseCompareAscending(objCriteria[index], othCriteria[index]); + if (result) { + if (index >= ordersLength) { + return result; + } + var order = orders[index]; + return result * (order === "asc" || order === true ? 1 : -1); + } + } + return object.index - other.index; + } + function deburrLetter(letter) { + return deburredLetters[letter]; + } + function escapeHtmlChar(chr) { + return htmlEscapes[chr]; + } + function escapeRegExpChar(chr, leadingChar, whitespaceChar) { + if (leadingChar) { + chr = regexpEscapes[chr]; + } else if (whitespaceChar) { + chr = stringEscapes[chr]; + } + return "\\" + chr; + } + function escapeStringChar(chr) { + return "\\" + stringEscapes[chr]; + } + function indexOfNaN(array, fromIndex, fromRight) { + var length = array.length, index = fromIndex + (fromRight ? 0 : -1); + while (fromRight ? index-- : ++index < length) { + var other = array[index]; + if (other !== other) { + return index; + } + } + return -1; + } + function isObjectLike(value) { + return !!value && typeof value == "object"; + } + function isSpace(charCode) { + return charCode <= 160 && (charCode >= 9 && charCode <= 13) || charCode == 32 || charCode == 160 || charCode == 5760 || charCode == 6158 || charCode >= 8192 && (charCode <= 8202 || charCode == 8232 || charCode == 8233 || charCode == 8239 || charCode == 8287 || charCode == 12288 || charCode == 65279); + } + function replaceHolders(array, placeholder) { + var index = -1, length = array.length, resIndex = -1, result = []; + while (++index < length) { + if (array[index] === placeholder) { + array[index] = PLACEHOLDER; + result[++resIndex] = index; + } + } + return result; + } + function sortedUniq(array, iteratee) { + var seen, index = -1, length = array.length, resIndex = -1, result = []; + while (++index < length) { + var value = array[index], computed = iteratee ? iteratee(value, index, array) : value; + if (!index || seen !== computed) { + seen = computed; + result[++resIndex] = value; + } + } + return result; + } + function trimmedLeftIndex(string) { + var index = -1, length = string.length; + while (++index < length && isSpace(string.charCodeAt(index))) {} + return index; + } + function trimmedRightIndex(string) { + var index = string.length; + while (index-- && isSpace(string.charCodeAt(index))) {} + return index; + } + function unescapeHtmlChar(chr) { + return htmlUnescapes[chr]; + } + function runInContext(context) { + context = context ? _.defaults(root.Object(), context, _.pick(root, contextProps)) : root; + var Array = context.Array, Date = context.Date, Error = context.Error, Function = context.Function, Math = context.Math, Number = context.Number, Object = context.Object, RegExp = context.RegExp, String = context.String, TypeError = context.TypeError; + var arrayProto = Array.prototype, objectProto = Object.prototype, stringProto = String.prototype; + var fnToString = Function.prototype.toString; + var hasOwnProperty = objectProto.hasOwnProperty; + var idCounter = 0; + var objToString = objectProto.toString; + var oldDash = root._; + var reIsNative = RegExp("^" + fnToString.call(hasOwnProperty).replace(/[\\^$.*+?()[\]{}|]/g, "\\$&").replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g, "$1.*?") + "$"); + var ArrayBuffer = context.ArrayBuffer, clearTimeout = context.clearTimeout, parseFloat = context.parseFloat, pow = Math.pow, propertyIsEnumerable = objectProto.propertyIsEnumerable, Set = getNative(context, "Set"), setTimeout = context.setTimeout, splice = arrayProto.splice, Uint8Array = context.Uint8Array, WeakMap = getNative(context, "WeakMap"); + var nativeCeil = Math.ceil, nativeCreate = getNative(Object, "create"), nativeFloor = Math.floor, nativeIsArray = getNative(Array, "isArray"), nativeIsFinite = context.isFinite, nativeKeys = getNative(Object, "keys"), nativeMax = Math.max, nativeMin = Math.min, nativeNow = getNative(Date, "now"), nativeParseInt = context.parseInt, nativeRandom = Math.random; + var NEGATIVE_INFINITY = Number.NEGATIVE_INFINITY, POSITIVE_INFINITY = Number.POSITIVE_INFINITY; + var MAX_ARRAY_LENGTH = 4294967295, MAX_ARRAY_INDEX = MAX_ARRAY_LENGTH - 1, HALF_MAX_ARRAY_LENGTH = MAX_ARRAY_LENGTH >>> 1; + var MAX_SAFE_INTEGER = 9007199254740991; + var metaMap = WeakMap && new WeakMap(); + var realNames = {}; + function lodash(value) { + if (isObjectLike(value) && !isArray(value) && !(value instanceof LazyWrapper)) { + if (value instanceof LodashWrapper) { + return value; + } + if (hasOwnProperty.call(value, "__chain__") && hasOwnProperty.call(value, "__wrapped__")) { + return wrapperClone(value); + } + } + return new LodashWrapper(value); + } + function baseLodash() {} + function LodashWrapper(value, chainAll, actions) { + this.__wrapped__ = value; + this.__actions__ = actions || []; + this.__chain__ = !!chainAll; + } + var support = lodash.support = {}; + lodash.templateSettings = { + escape: reEscape, + evaluate: reEvaluate, + interpolate: reInterpolate, + variable: "", + imports: { + _: lodash + } + }; + function LazyWrapper(value) { + this.__wrapped__ = value; + this.__actions__ = []; + this.__dir__ = 1; + this.__filtered__ = false; + this.__iteratees__ = []; + this.__takeCount__ = POSITIVE_INFINITY; + this.__views__ = []; + } + function lazyClone() { + var result = new LazyWrapper(this.__wrapped__); + result.__actions__ = arrayCopy(this.__actions__); + result.__dir__ = this.__dir__; + result.__filtered__ = this.__filtered__; + result.__iteratees__ = arrayCopy(this.__iteratees__); + result.__takeCount__ = this.__takeCount__; + result.__views__ = arrayCopy(this.__views__); + return result; + } + function lazyReverse() { + if (this.__filtered__) { + var result = new LazyWrapper(this); + result.__dir__ = -1; + result.__filtered__ = true; + } else { + result = this.clone(); + result.__dir__ *= -1; + } + return result; + } + function lazyValue() { + var array = this.__wrapped__.value(), dir = this.__dir__, isArr = isArray(array), isRight = dir < 0, arrLength = isArr ? array.length : 0, view = getView(0, arrLength, this.__views__), start = view.start, end = view.end, length = end - start, index = isRight ? end : start - 1, iteratees = this.__iteratees__, iterLength = iteratees.length, resIndex = 0, takeCount = nativeMin(length, this.__takeCount__); + if (!isArr || arrLength < LARGE_ARRAY_SIZE || arrLength == length && takeCount == length) { + return baseWrapperValue(array, this.__actions__); + } + var result = []; + outer: while (length-- && resIndex < takeCount) { + index += dir; + var iterIndex = -1, value = array[index]; + while (++iterIndex < iterLength) { + var data = iteratees[iterIndex], iteratee = data.iteratee, type = data.type, computed = iteratee(value); + if (type == LAZY_MAP_FLAG) { + value = computed; + } else if (!computed) { + if (type == LAZY_FILTER_FLAG) { + continue outer; + } else { + break outer; + } + } + } + result[resIndex++] = value; + } + return result; + } + function MapCache() { + this.__data__ = {}; + } + function mapDelete(key) { + return this.has(key) && delete this.__data__[key]; + } + function mapGet(key) { + return key == "__proto__" ? undefined : this.__data__[key]; + } + function mapHas(key) { + return key != "__proto__" && hasOwnProperty.call(this.__data__, key); + } + function mapSet(key, value) { + if (key != "__proto__") { + this.__data__[key] = value; + } + return this; + } + function SetCache(values) { + var length = values ? values.length : 0; + this.data = { + hash: nativeCreate(null), + set: new Set() + }; + while (length--) { + this.push(values[length]); + } + } + function cacheIndexOf(cache, value) { + var data = cache.data, result = typeof value == "string" || isObject(value) ? data.set.has(value) : data.hash[value]; + return result ? 0 : -1; + } + function cachePush(value) { + var data = this.data; + if (typeof value == "string" || isObject(value)) { + data.set.add(value); + } else { + data.hash[value] = true; + } + } + function arrayConcat(array, other) { + var index = -1, length = array.length, othIndex = -1, othLength = other.length, result = Array(length + othLength); + while (++index < length) { + result[index] = array[index]; + } + while (++othIndex < othLength) { + result[index++] = other[othIndex]; + } + return result; + } + function arrayCopy(source, array) { + var index = -1, length = source.length; + array || (array = Array(length)); + while (++index < length) { + array[index] = source[index]; + } + return array; + } + function arrayEach(array, iteratee) { + var index = -1, length = array.length; + while (++index < length) { + if (iteratee(array[index], index, array) === false) { + break; + } + } + return array; + } + function arrayEachRight(array, iteratee) { + var length = array.length; + while (length--) { + if (iteratee(array[length], length, array) === false) { + break; + } + } + return array; + } + function arrayEvery(array, predicate) { + var index = -1, length = array.length; + while (++index < length) { + if (!predicate(array[index], index, array)) { + return false; + } + } + return true; + } + function arrayExtremum(array, iteratee, comparator, exValue) { + var index = -1, length = array.length, computed = exValue, result = computed; + while (++index < length) { + var value = array[index], current = +iteratee(value); + if (comparator(current, computed)) { + computed = current; + result = value; + } + } + return result; + } + function arrayFilter(array, predicate) { + var index = -1, length = array.length, resIndex = -1, result = []; + while (++index < length) { + var value = array[index]; + if (predicate(value, index, array)) { + result[++resIndex] = value; + } + } + return result; + } + function arrayMap(array, iteratee) { + var index = -1, length = array.length, result = Array(length); + while (++index < length) { + result[index] = iteratee(array[index], index, array); + } + return result; + } + function arrayPush(array, values) { + var index = -1, length = values.length, offset = array.length; + while (++index < length) { + array[offset + index] = values[index]; + } + return array; + } + function arrayReduce(array, iteratee, accumulator, initFromArray) { + var index = -1, length = array.length; + if (initFromArray && length) { + accumulator = array[++index]; + } + while (++index < length) { + accumulator = iteratee(accumulator, array[index], index, array); + } + return accumulator; + } + function arrayReduceRight(array, iteratee, accumulator, initFromArray) { + var length = array.length; + if (initFromArray && length) { + accumulator = array[--length]; + } + while (length--) { + accumulator = iteratee(accumulator, array[length], length, array); + } + return accumulator; + } + function arraySome(array, predicate) { + var index = -1, length = array.length; + while (++index < length) { + if (predicate(array[index], index, array)) { + return true; + } + } + return false; + } + function arraySum(array, iteratee) { + var length = array.length, result = 0; + while (length--) { + result += +iteratee(array[length]) || 0; + } + return result; + } + function assignDefaults(objectValue, sourceValue) { + return objectValue === undefined ? sourceValue : objectValue; + } + function assignOwnDefaults(objectValue, sourceValue, key, object) { + return objectValue === undefined || !hasOwnProperty.call(object, key) ? sourceValue : objectValue; + } + function assignWith(object, source, customizer) { + var index = -1, props = keys(source), length = props.length; + while (++index < length) { + var key = props[index], value = object[key], result = customizer(value, source[key], key, object, source); + if ((result === result ? result !== value : value === value) || value === undefined && !(key in object)) { + object[key] = result; + } + } + return object; + } + function baseAssign(object, source) { + return source == null ? object : baseCopy(source, keys(source), object); + } + function baseAt(collection, props) { + var index = -1, isNil = collection == null, isArr = !isNil && isArrayLike(collection), length = isArr ? collection.length : 0, propsLength = props.length, result = Array(propsLength); + while (++index < propsLength) { + var key = props[index]; + if (isArr) { + result[index] = isIndex(key, length) ? collection[key] : undefined; + } else { + result[index] = isNil ? undefined : collection[key]; + } + } + return result; + } + function baseCopy(source, props, object) { + object || (object = {}); + var index = -1, length = props.length; + while (++index < length) { + var key = props[index]; + object[key] = source[key]; + } + return object; + } + function baseCallback(func, thisArg, argCount) { + var type = typeof func; + if (type == "function") { + return thisArg === undefined ? func : bindCallback(func, thisArg, argCount); + } + if (func == null) { + return identity; + } + if (type == "object") { + return baseMatches(func); + } + return thisArg === undefined ? property(func) : baseMatchesProperty(func, thisArg); + } + function baseClone(value, isDeep, customizer, key, object, stackA, stackB) { + var result; + if (customizer) { + result = object ? customizer(value, key, object) : customizer(value); + } + if (result !== undefined) { + return result; + } + if (!isObject(value)) { + return value; + } + var isArr = isArray(value); + if (isArr) { + result = initCloneArray(value); + if (!isDeep) { + return arrayCopy(value, result); + } + } else { + var tag = objToString.call(value), isFunc = tag == funcTag; + if (tag == objectTag || tag == argsTag || isFunc && !object) { + result = initCloneObject(isFunc ? {} : value); + if (!isDeep) { + return baseAssign(result, value); + } + } else { + return cloneableTags[tag] ? initCloneByTag(value, tag, isDeep) : object ? value : {}; + } + } + stackA || (stackA = []); + stackB || (stackB = []); + var length = stackA.length; + while (length--) { + if (stackA[length] == value) { + return stackB[length]; + } + } + stackA.push(value); + stackB.push(result); + (isArr ? arrayEach : baseForOwn)(value, function(subValue, key) { + result[key] = baseClone(subValue, isDeep, customizer, key, value, stackA, stackB); + }); + return result; + } + var baseCreate = function() { + function object() {} + return function(prototype) { + if (isObject(prototype)) { + object.prototype = prototype; + var result = new object(); + object.prototype = undefined; + } + return result || {}; + }; + }(); + function baseDelay(func, wait, args) { + if (typeof func != "function") { + throw new TypeError(FUNC_ERROR_TEXT); + } + return setTimeout(function() { + func.apply(undefined, args); + }, wait); + } + function baseDifference(array, values) { + var length = array ? array.length : 0, result = []; + if (!length) { + return result; + } + var index = -1, indexOf = getIndexOf(), isCommon = indexOf === baseIndexOf, cache = isCommon && values.length >= LARGE_ARRAY_SIZE ? createCache(values) : null, valuesLength = values.length; + if (cache) { + indexOf = cacheIndexOf; + isCommon = false; + values = cache; + } + outer: while (++index < length) { + var value = array[index]; + if (isCommon && value === value) { + var valuesIndex = valuesLength; + while (valuesIndex--) { + if (values[valuesIndex] === value) { + continue outer; + } + } + result.push(value); + } else if (indexOf(values, value, 0) < 0) { + result.push(value); + } + } + return result; + } + var baseEach = createBaseEach(baseForOwn); + var baseEachRight = createBaseEach(baseForOwnRight, true); + function baseEvery(collection, predicate) { + var result = true; + baseEach(collection, function(value, index, collection) { + result = !!predicate(value, index, collection); + return result; + }); + return result; + } + function baseExtremum(collection, iteratee, comparator, exValue) { + var computed = exValue, result = computed; + baseEach(collection, function(value, index, collection) { + var current = +iteratee(value, index, collection); + if (comparator(current, computed) || current === exValue && current === result) { + computed = current; + result = value; + } + }); + return result; + } + function baseFill(array, value, start, end) { + var length = array.length; + start = start == null ? 0 : +start || 0; + if (start < 0) { + start = -start > length ? 0 : length + start; + } + end = end === undefined || end > length ? length : +end || 0; + if (end < 0) { + end += length; + } + length = start > end ? 0 : end >>> 0; + start >>>= 0; + while (start < length) { + array[start++] = value; + } + return array; + } + function baseFilter(collection, predicate) { + var result = []; + baseEach(collection, function(value, index, collection) { + if (predicate(value, index, collection)) { + result.push(value); + } + }); + return result; + } + function baseFind(collection, predicate, eachFunc, retKey) { + var result; + eachFunc(collection, function(value, key, collection) { + if (predicate(value, key, collection)) { + result = retKey ? key : value; + return false; + } + }); + return result; + } + function baseFlatten(array, isDeep, isStrict, result) { + result || (result = []); + var index = -1, length = array.length; + while (++index < length) { + var value = array[index]; + if (isObjectLike(value) && isArrayLike(value) && (isStrict || isArray(value) || isArguments(value))) { + if (isDeep) { + baseFlatten(value, isDeep, isStrict, result); + } else { + arrayPush(result, value); + } + } else if (!isStrict) { + result[result.length] = value; + } + } + return result; + } + var baseFor = createBaseFor(); + var baseForRight = createBaseFor(true); + function baseForIn(object, iteratee) { + return baseFor(object, iteratee, keysIn); + } + function baseForOwn(object, iteratee) { + return baseFor(object, iteratee, keys); + } + function baseForOwnRight(object, iteratee) { + return baseForRight(object, iteratee, keys); + } + function baseFunctions(object, props) { + var index = -1, length = props.length, resIndex = -1, result = []; + while (++index < length) { + var key = props[index]; + if (isFunction(object[key])) { + result[++resIndex] = key; + } + } + return result; + } + function baseGet(object, path, pathKey) { + if (object == null) { + return; + } + if (pathKey !== undefined && pathKey in toObject(object)) { + path = [ pathKey ]; + } + var index = 0, length = path.length; + while (object != null && index < length) { + object = object[path[index++]]; + } + return index && index == length ? object : undefined; + } + function baseIsEqual(value, other, customizer, isLoose, stackA, stackB) { + if (value === other) { + return true; + } + if (value == null || other == null || !isObject(value) && !isObjectLike(other)) { + return value !== value && other !== other; + } + return baseIsEqualDeep(value, other, baseIsEqual, customizer, isLoose, stackA, stackB); + } + function baseIsEqualDeep(object, other, equalFunc, customizer, isLoose, stackA, stackB) { + var objIsArr = isArray(object), othIsArr = isArray(other), objTag = arrayTag, othTag = arrayTag; + if (!objIsArr) { + objTag = objToString.call(object); + if (objTag == argsTag) { + objTag = objectTag; + } else if (objTag != objectTag) { + objIsArr = isTypedArray(object); + } + } + if (!othIsArr) { + othTag = objToString.call(other); + if (othTag == argsTag) { + othTag = objectTag; + } else if (othTag != objectTag) { + othIsArr = isTypedArray(other); + } + } + var objIsObj = objTag == objectTag, othIsObj = othTag == objectTag, isSameTag = objTag == othTag; + if (isSameTag && !(objIsArr || objIsObj)) { + return equalByTag(object, other, objTag); + } + if (!isLoose) { + var objIsWrapped = objIsObj && hasOwnProperty.call(object, "__wrapped__"), othIsWrapped = othIsObj && hasOwnProperty.call(other, "__wrapped__"); + if (objIsWrapped || othIsWrapped) { + return equalFunc(objIsWrapped ? object.value() : object, othIsWrapped ? other.value() : other, customizer, isLoose, stackA, stackB); + } + } + if (!isSameTag) { + return false; + } + stackA || (stackA = []); + stackB || (stackB = []); + var length = stackA.length; + while (length--) { + if (stackA[length] == object) { + return stackB[length] == other; + } + } + stackA.push(object); + stackB.push(other); + var result = (objIsArr ? equalArrays : equalObjects)(object, other, equalFunc, customizer, isLoose, stackA, stackB); + stackA.pop(); + stackB.pop(); + return result; + } + function baseIsMatch(object, matchData, customizer) { + var index = matchData.length, length = index, noCustomizer = !customizer; + if (object == null) { + return !length; + } + object = toObject(object); + while (index--) { + var data = matchData[index]; + if (noCustomizer && data[2] ? data[1] !== object[data[0]] : !(data[0] in object)) { + return false; + } + } + while (++index < length) { + data = matchData[index]; + var key = data[0], objValue = object[key], srcValue = data[1]; + if (noCustomizer && data[2]) { + if (objValue === undefined && !(key in object)) { + return false; + } + } else { + var result = customizer ? customizer(objValue, srcValue, key) : undefined; + if (!(result === undefined ? baseIsEqual(srcValue, objValue, customizer, true) : result)) { + return false; + } + } + } + return true; + } + function baseMap(collection, iteratee) { + var index = -1, result = isArrayLike(collection) ? Array(collection.length) : []; + baseEach(collection, function(value, key, collection) { + result[++index] = iteratee(value, key, collection); + }); + return result; + } + function baseMatches(source) { + var matchData = getMatchData(source); + if (matchData.length == 1 && matchData[0][2]) { + var key = matchData[0][0], value = matchData[0][1]; + return function(object) { + if (object == null) { + return false; + } + return object[key] === value && (value !== undefined || key in toObject(object)); + }; + } + return function(object) { + return baseIsMatch(object, matchData); + }; + } + function baseMatchesProperty(path, srcValue) { + var isArr = isArray(path), isCommon = isKey(path) && isStrictComparable(srcValue), pathKey = path + ""; + path = toPath(path); + return function(object) { + if (object == null) { + return false; + } + var key = pathKey; + object = toObject(object); + if ((isArr || !isCommon) && !(key in object)) { + object = path.length == 1 ? object : baseGet(object, baseSlice(path, 0, -1)); + if (object == null) { + return false; + } + key = last(path); + object = toObject(object); + } + return object[key] === srcValue ? srcValue !== undefined || key in object : baseIsEqual(srcValue, object[key], undefined, true); + }; + } + function baseMerge(object, source, customizer, stackA, stackB) { + if (!isObject(object)) { + return object; + } + var isSrcArr = isArrayLike(source) && (isArray(source) || isTypedArray(source)), props = isSrcArr ? undefined : keys(source); + arrayEach(props || source, function(srcValue, key) { + if (props) { + key = srcValue; + srcValue = source[key]; + } + if (isObjectLike(srcValue)) { + stackA || (stackA = []); + stackB || (stackB = []); + baseMergeDeep(object, source, key, baseMerge, customizer, stackA, stackB); + } else { + var value = object[key], result = customizer ? customizer(value, srcValue, key, object, source) : undefined, isCommon = result === undefined; + if (isCommon) { + result = srcValue; + } + if ((result !== undefined || isSrcArr && !(key in object)) && (isCommon || (result === result ? result !== value : value === value))) { + object[key] = result; + } + } + }); + return object; + } + function baseMergeDeep(object, source, key, mergeFunc, customizer, stackA, stackB) { + var length = stackA.length, srcValue = source[key]; + while (length--) { + if (stackA[length] == srcValue) { + object[key] = stackB[length]; + return; + } + } + var value = object[key], result = customizer ? customizer(value, srcValue, key, object, source) : undefined, isCommon = result === undefined; + if (isCommon) { + result = srcValue; + if (isArrayLike(srcValue) && (isArray(srcValue) || isTypedArray(srcValue))) { + result = isArray(value) ? value : isArrayLike(value) ? arrayCopy(value) : []; + } else if (isPlainObject(srcValue) || isArguments(srcValue)) { + result = isArguments(value) ? toPlainObject(value) : isPlainObject(value) ? value : {}; + } else { + isCommon = false; + } + } + stackA.push(srcValue); + stackB.push(result); + if (isCommon) { + object[key] = mergeFunc(result, srcValue, customizer, stackA, stackB); + } else if (result === result ? result !== value : value === value) { + object[key] = result; + } + } + function baseProperty(key) { + return function(object) { + return object == null ? undefined : object[key]; + }; + } + function basePropertyDeep(path) { + var pathKey = path + ""; + path = toPath(path); + return function(object) { + return baseGet(object, path, pathKey); + }; + } + function basePullAt(array, indexes) { + var length = array ? indexes.length : 0; + while (length--) { + var index = indexes[length]; + if (index != previous && isIndex(index)) { + var previous = index; + splice.call(array, index, 1); + } + } + return array; + } + function baseRandom(min, max) { + return min + nativeFloor(nativeRandom() * (max - min + 1)); + } + function baseReduce(collection, iteratee, accumulator, initFromCollection, eachFunc) { + eachFunc(collection, function(value, index, collection) { + accumulator = initFromCollection ? (initFromCollection = false, value) : iteratee(accumulator, value, index, collection); + }); + return accumulator; + } + var baseSetData = !metaMap ? identity : function(func, data) { + metaMap.set(func, data); + return func; + }; + function baseSlice(array, start, end) { + var index = -1, length = array.length; + start = start == null ? 0 : +start || 0; + if (start < 0) { + start = -start > length ? 0 : length + start; + } + end = end === undefined || end > length ? length : +end || 0; + if (end < 0) { + end += length; + } + length = start > end ? 0 : end - start >>> 0; + start >>>= 0; + var result = Array(length); + while (++index < length) { + result[index] = array[index + start]; + } + return result; + } + function baseSome(collection, predicate) { + var result; + baseEach(collection, function(value, index, collection) { + result = predicate(value, index, collection); + return !result; + }); + return !!result; + } + function baseSortBy(array, comparer) { + var length = array.length; + array.sort(comparer); + while (length--) { + array[length] = array[length].value; + } + return array; + } + function baseSortByOrder(collection, iteratees, orders) { + var callback = getCallback(), index = -1; + iteratees = arrayMap(iteratees, function(iteratee) { + return callback(iteratee); + }); + var result = baseMap(collection, function(value) { + var criteria = arrayMap(iteratees, function(iteratee) { + return iteratee(value); + }); + return { + criteria: criteria, + index: ++index, + value: value + }; + }); + return baseSortBy(result, function(object, other) { + return compareMultiple(object, other, orders); + }); + } + function baseSum(collection, iteratee) { + var result = 0; + baseEach(collection, function(value, index, collection) { + result += +iteratee(value, index, collection) || 0; + }); + return result; + } + function baseUniq(array, iteratee) { + var index = -1, indexOf = getIndexOf(), length = array.length, isCommon = indexOf === baseIndexOf, isLarge = isCommon && length >= LARGE_ARRAY_SIZE, seen = isLarge ? createCache() : null, result = []; + if (seen) { + indexOf = cacheIndexOf; + isCommon = false; + } else { + isLarge = false; + seen = iteratee ? [] : result; + } + outer: while (++index < length) { + var value = array[index], computed = iteratee ? iteratee(value, index, array) : value; + if (isCommon && value === value) { + var seenIndex = seen.length; + while (seenIndex--) { + if (seen[seenIndex] === computed) { + continue outer; + } + } + if (iteratee) { + seen.push(computed); + } + result.push(value); + } else if (indexOf(seen, computed, 0) < 0) { + if (iteratee || isLarge) { + seen.push(computed); + } + result.push(value); + } + } + return result; + } + function baseValues(object, props) { + var index = -1, length = props.length, result = Array(length); + while (++index < length) { + result[index] = object[props[index]]; + } + return result; + } + function baseWhile(array, predicate, isDrop, fromRight) { + var length = array.length, index = fromRight ? length : -1; + while ((fromRight ? index-- : ++index < length) && predicate(array[index], index, array)) {} + return isDrop ? baseSlice(array, fromRight ? 0 : index, fromRight ? index + 1 : length) : baseSlice(array, fromRight ? index + 1 : 0, fromRight ? length : index); + } + function baseWrapperValue(value, actions) { + var result = value; + if (result instanceof LazyWrapper) { + result = result.value(); + } + var index = -1, length = actions.length; + while (++index < length) { + var action = actions[index]; + result = action.func.apply(action.thisArg, arrayPush([ result ], action.args)); + } + return result; + } + function binaryIndex(array, value, retHighest) { + var low = 0, high = array ? array.length : low; + if (typeof value == "number" && value === value && high <= HALF_MAX_ARRAY_LENGTH) { + while (low < high) { + var mid = low + high >>> 1, computed = array[mid]; + if ((retHighest ? computed <= value : computed < value) && computed !== null) { + low = mid + 1; + } else { + high = mid; + } + } + return high; + } + return binaryIndexBy(array, value, identity, retHighest); + } + function binaryIndexBy(array, value, iteratee, retHighest) { + value = iteratee(value); + var low = 0, high = array ? array.length : 0, valIsNaN = value !== value, valIsNull = value === null, valIsUndef = value === undefined; + while (low < high) { + var mid = nativeFloor((low + high) / 2), computed = iteratee(array[mid]), isDef = computed !== undefined, isReflexive = computed === computed; + if (valIsNaN) { + var setLow = isReflexive || retHighest; + } else if (valIsNull) { + setLow = isReflexive && isDef && (retHighest || computed != null); + } else if (valIsUndef) { + setLow = isReflexive && (retHighest || isDef); + } else if (computed == null) { + setLow = false; + } else { + setLow = retHighest ? computed <= value : computed < value; + } + if (setLow) { + low = mid + 1; + } else { + high = mid; + } + } + return nativeMin(high, MAX_ARRAY_INDEX); + } + function bindCallback(func, thisArg, argCount) { + if (typeof func != "function") { + return identity; + } + if (thisArg === undefined) { + return func; + } + switch (argCount) { + case 1: + return function(value) { + return func.call(thisArg, value); + }; + + case 3: + return function(value, index, collection) { + return func.call(thisArg, value, index, collection); + }; + + case 4: + return function(accumulator, value, index, collection) { + return func.call(thisArg, accumulator, value, index, collection); + }; + + case 5: + return function(value, other, key, object, source) { + return func.call(thisArg, value, other, key, object, source); + }; + } + return function() { + return func.apply(thisArg, arguments); + }; + } + function bufferClone(buffer) { + var result = new ArrayBuffer(buffer.byteLength), view = new Uint8Array(result); + view.set(new Uint8Array(buffer)); + return result; + } + function composeArgs(args, partials, holders) { + var holdersLength = holders.length, argsIndex = -1, argsLength = nativeMax(args.length - holdersLength, 0), leftIndex = -1, leftLength = partials.length, result = Array(leftLength + argsLength); + while (++leftIndex < leftLength) { + result[leftIndex] = partials[leftIndex]; + } + while (++argsIndex < holdersLength) { + result[holders[argsIndex]] = args[argsIndex]; + } + while (argsLength--) { + result[leftIndex++] = args[argsIndex++]; + } + return result; + } + function composeArgsRight(args, partials, holders) { + var holdersIndex = -1, holdersLength = holders.length, argsIndex = -1, argsLength = nativeMax(args.length - holdersLength, 0), rightIndex = -1, rightLength = partials.length, result = Array(argsLength + rightLength); + while (++argsIndex < argsLength) { + result[argsIndex] = args[argsIndex]; + } + var offset = argsIndex; + while (++rightIndex < rightLength) { + result[offset + rightIndex] = partials[rightIndex]; + } + while (++holdersIndex < holdersLength) { + result[offset + holders[holdersIndex]] = args[argsIndex++]; + } + return result; + } + function createAggregator(setter, initializer) { + return function(collection, iteratee, thisArg) { + var result = initializer ? initializer() : {}; + iteratee = getCallback(iteratee, thisArg, 3); + if (isArray(collection)) { + var index = -1, length = collection.length; + while (++index < length) { + var value = collection[index]; + setter(result, value, iteratee(value, index, collection), collection); + } + } else { + baseEach(collection, function(value, key, collection) { + setter(result, value, iteratee(value, key, collection), collection); + }); + } + return result; + }; + } + function createAssigner(assigner) { + return restParam(function(object, sources) { + var index = -1, length = object == null ? 0 : sources.length, customizer = length > 2 ? sources[length - 2] : undefined, guard = length > 2 ? sources[2] : undefined, thisArg = length > 1 ? sources[length - 1] : undefined; + if (typeof customizer == "function") { + customizer = bindCallback(customizer, thisArg, 5); + length -= 2; + } else { + customizer = typeof thisArg == "function" ? thisArg : undefined; + length -= customizer ? 1 : 0; + } + if (guard && isIterateeCall(sources[0], sources[1], guard)) { + customizer = length < 3 ? undefined : customizer; + length = 1; + } + while (++index < length) { + var source = sources[index]; + if (source) { + assigner(object, source, customizer); + } + } + return object; + }); + } + function createBaseEach(eachFunc, fromRight) { + return function(collection, iteratee) { + var length = collection ? getLength(collection) : 0; + if (!isLength(length)) { + return eachFunc(collection, iteratee); + } + var index = fromRight ? length : -1, iterable = toObject(collection); + while (fromRight ? index-- : ++index < length) { + if (iteratee(iterable[index], index, iterable) === false) { + break; + } + } + return collection; + }; + } + function createBaseFor(fromRight) { + return function(object, iteratee, keysFunc) { + var iterable = toObject(object), props = keysFunc(object), length = props.length, index = fromRight ? length : -1; + while (fromRight ? index-- : ++index < length) { + var key = props[index]; + if (iteratee(iterable[key], key, iterable) === false) { + break; + } + } + return object; + }; + } + function createBindWrapper(func, thisArg) { + var Ctor = createCtorWrapper(func); + function wrapper() { + var fn = this && this !== root && this instanceof wrapper ? Ctor : func; + return fn.apply(thisArg, arguments); + } + return wrapper; + } + function createCache(values) { + return nativeCreate && Set ? new SetCache(values) : null; + } + function createCompounder(callback) { + return function(string) { + var index = -1, array = words(deburr(string)), length = array.length, result = ""; + while (++index < length) { + result = callback(result, array[index], index); + } + return result; + }; + } + function createCtorWrapper(Ctor) { + return function() { + var args = arguments; + switch (args.length) { + case 0: + return new Ctor(); + + case 1: + return new Ctor(args[0]); + + case 2: + return new Ctor(args[0], args[1]); + + case 3: + return new Ctor(args[0], args[1], args[2]); + + case 4: + return new Ctor(args[0], args[1], args[2], args[3]); + + case 5: + return new Ctor(args[0], args[1], args[2], args[3], args[4]); + + case 6: + return new Ctor(args[0], args[1], args[2], args[3], args[4], args[5]); + + case 7: + return new Ctor(args[0], args[1], args[2], args[3], args[4], args[5], args[6]); + } + var thisBinding = baseCreate(Ctor.prototype), result = Ctor.apply(thisBinding, args); + return isObject(result) ? result : thisBinding; + }; + } + function createCurry(flag) { + function curryFunc(func, arity, guard) { + if (guard && isIterateeCall(func, arity, guard)) { + arity = undefined; + } + var result = createWrapper(func, flag, undefined, undefined, undefined, undefined, undefined, arity); + result.placeholder = curryFunc.placeholder; + return result; + } + return curryFunc; + } + function createDefaults(assigner, customizer) { + return restParam(function(args) { + var object = args[0]; + if (object == null) { + return object; + } + args.push(customizer); + return assigner.apply(undefined, args); + }); + } + function createExtremum(comparator, exValue) { + return function(collection, iteratee, thisArg) { + if (thisArg && isIterateeCall(collection, iteratee, thisArg)) { + iteratee = undefined; + } + iteratee = getCallback(iteratee, thisArg, 3); + if (iteratee.length == 1) { + collection = isArray(collection) ? collection : toIterable(collection); + var result = arrayExtremum(collection, iteratee, comparator, exValue); + if (!(collection.length && result === exValue)) { + return result; + } + } + return baseExtremum(collection, iteratee, comparator, exValue); + }; + } + function createFind(eachFunc, fromRight) { + return function(collection, predicate, thisArg) { + predicate = getCallback(predicate, thisArg, 3); + if (isArray(collection)) { + var index = baseFindIndex(collection, predicate, fromRight); + return index > -1 ? collection[index] : undefined; + } + return baseFind(collection, predicate, eachFunc); + }; + } + function createFindIndex(fromRight) { + return function(array, predicate, thisArg) { + if (!(array && array.length)) { + return -1; + } + predicate = getCallback(predicate, thisArg, 3); + return baseFindIndex(array, predicate, fromRight); + }; + } + function createFindKey(objectFunc) { + return function(object, predicate, thisArg) { + predicate = getCallback(predicate, thisArg, 3); + return baseFind(object, predicate, objectFunc, true); + }; + } + function createFlow(fromRight) { + return function() { + var wrapper, length = arguments.length, index = fromRight ? length : -1, leftIndex = 0, funcs = Array(length); + while (fromRight ? index-- : ++index < length) { + var func = funcs[leftIndex++] = arguments[index]; + if (typeof func != "function") { + throw new TypeError(FUNC_ERROR_TEXT); + } + if (!wrapper && LodashWrapper.prototype.thru && getFuncName(func) == "wrapper") { + wrapper = new LodashWrapper([], true); + } + } + index = wrapper ? -1 : length; + while (++index < length) { + func = funcs[index]; + var funcName = getFuncName(func), data = funcName == "wrapper" ? getData(func) : undefined; + if (data && isLaziable(data[0]) && data[1] == (ARY_FLAG | CURRY_FLAG | PARTIAL_FLAG | REARG_FLAG) && !data[4].length && data[9] == 1) { + wrapper = wrapper[getFuncName(data[0])].apply(wrapper, data[3]); + } else { + wrapper = func.length == 1 && isLaziable(func) ? wrapper[funcName]() : wrapper.thru(func); + } + } + return function() { + var args = arguments, value = args[0]; + if (wrapper && args.length == 1 && isArray(value) && value.length >= LARGE_ARRAY_SIZE) { + return wrapper.plant(value).value(); + } + var index = 0, result = length ? funcs[index].apply(this, args) : value; + while (++index < length) { + result = funcs[index].call(this, result); + } + return result; + }; + }; + } + function createForEach(arrayFunc, eachFunc) { + return function(collection, iteratee, thisArg) { + return typeof iteratee == "function" && thisArg === undefined && isArray(collection) ? arrayFunc(collection, iteratee) : eachFunc(collection, bindCallback(iteratee, thisArg, 3)); + }; + } + function createForIn(objectFunc) { + return function(object, iteratee, thisArg) { + if (typeof iteratee != "function" || thisArg !== undefined) { + iteratee = bindCallback(iteratee, thisArg, 3); + } + return objectFunc(object, iteratee, keysIn); + }; + } + function createForOwn(objectFunc) { + return function(object, iteratee, thisArg) { + if (typeof iteratee != "function" || thisArg !== undefined) { + iteratee = bindCallback(iteratee, thisArg, 3); + } + return objectFunc(object, iteratee); + }; + } + function createObjectMapper(isMapKeys) { + return function(object, iteratee, thisArg) { + var result = {}; + iteratee = getCallback(iteratee, thisArg, 3); + baseForOwn(object, function(value, key, object) { + var mapped = iteratee(value, key, object); + key = isMapKeys ? mapped : key; + value = isMapKeys ? value : mapped; + result[key] = value; + }); + return result; + }; + } + function createPadDir(fromRight) { + return function(string, length, chars) { + string = baseToString(string); + return (fromRight ? string : "") + createPadding(string, length, chars) + (fromRight ? "" : string); + }; + } + function createPartial(flag) { + var partialFunc = restParam(function(func, partials) { + var holders = replaceHolders(partials, partialFunc.placeholder); + return createWrapper(func, flag, undefined, partials, holders); + }); + return partialFunc; + } + function createReduce(arrayFunc, eachFunc) { + return function(collection, iteratee, accumulator, thisArg) { + var initFromArray = arguments.length < 3; + return typeof iteratee == "function" && thisArg === undefined && isArray(collection) ? arrayFunc(collection, iteratee, accumulator, initFromArray) : baseReduce(collection, getCallback(iteratee, thisArg, 4), accumulator, initFromArray, eachFunc); + }; + } + function createHybridWrapper(func, bitmask, thisArg, partials, holders, partialsRight, holdersRight, argPos, ary, arity) { + var isAry = bitmask & ARY_FLAG, isBind = bitmask & BIND_FLAG, isBindKey = bitmask & BIND_KEY_FLAG, isCurry = bitmask & CURRY_FLAG, isCurryBound = bitmask & CURRY_BOUND_FLAG, isCurryRight = bitmask & CURRY_RIGHT_FLAG, Ctor = isBindKey ? undefined : createCtorWrapper(func); + function wrapper() { + var length = arguments.length, index = length, args = Array(length); + while (index--) { + args[index] = arguments[index]; + } + if (partials) { + args = composeArgs(args, partials, holders); + } + if (partialsRight) { + args = composeArgsRight(args, partialsRight, holdersRight); + } + if (isCurry || isCurryRight) { + var placeholder = wrapper.placeholder, argsHolders = replaceHolders(args, placeholder); + length -= argsHolders.length; + if (length < arity) { + var newArgPos = argPos ? arrayCopy(argPos) : undefined, newArity = nativeMax(arity - length, 0), newsHolders = isCurry ? argsHolders : undefined, newHoldersRight = isCurry ? undefined : argsHolders, newPartials = isCurry ? args : undefined, newPartialsRight = isCurry ? undefined : args; + bitmask |= isCurry ? PARTIAL_FLAG : PARTIAL_RIGHT_FLAG; + bitmask &= ~(isCurry ? PARTIAL_RIGHT_FLAG : PARTIAL_FLAG); + if (!isCurryBound) { + bitmask &= ~(BIND_FLAG | BIND_KEY_FLAG); + } + var newData = [ func, bitmask, thisArg, newPartials, newsHolders, newPartialsRight, newHoldersRight, newArgPos, ary, newArity ], result = createHybridWrapper.apply(undefined, newData); + if (isLaziable(func)) { + setData(result, newData); + } + result.placeholder = placeholder; + return result; + } + } + var thisBinding = isBind ? thisArg : this, fn = isBindKey ? thisBinding[func] : func; + if (argPos) { + args = reorder(args, argPos); + } + if (isAry && ary < args.length) { + args.length = ary; + } + if (this && this !== root && this instanceof wrapper) { + fn = Ctor || createCtorWrapper(func); + } + return fn.apply(thisBinding, args); + } + return wrapper; + } + function createPadding(string, length, chars) { + var strLength = string.length; + length = +length; + if (strLength >= length || !nativeIsFinite(length)) { + return ""; + } + var padLength = length - strLength; + chars = chars == null ? " " : chars + ""; + return repeat(chars, nativeCeil(padLength / chars.length)).slice(0, padLength); + } + function createPartialWrapper(func, bitmask, thisArg, partials) { + var isBind = bitmask & BIND_FLAG, Ctor = createCtorWrapper(func); + function wrapper() { + var argsIndex = -1, argsLength = arguments.length, leftIndex = -1, leftLength = partials.length, args = Array(leftLength + argsLength); + while (++leftIndex < leftLength) { + args[leftIndex] = partials[leftIndex]; + } + while (argsLength--) { + args[leftIndex++] = arguments[++argsIndex]; + } + var fn = this && this !== root && this instanceof wrapper ? Ctor : func; + return fn.apply(isBind ? thisArg : this, args); + } + return wrapper; + } + function createRound(methodName) { + var func = Math[methodName]; + return function(number, precision) { + precision = precision === undefined ? 0 : +precision || 0; + if (precision) { + precision = pow(10, precision); + return func(number * precision) / precision; + } + return func(number); + }; + } + function createSortedIndex(retHighest) { + return function(array, value, iteratee, thisArg) { + var callback = getCallback(iteratee); + return iteratee == null && callback === baseCallback ? binaryIndex(array, value, retHighest) : binaryIndexBy(array, value, callback(iteratee, thisArg, 1), retHighest); + }; + } + function createWrapper(func, bitmask, thisArg, partials, holders, argPos, ary, arity) { + var isBindKey = bitmask & BIND_KEY_FLAG; + if (!isBindKey && typeof func != "function") { + throw new TypeError(FUNC_ERROR_TEXT); + } + var length = partials ? partials.length : 0; + if (!length) { + bitmask &= ~(PARTIAL_FLAG | PARTIAL_RIGHT_FLAG); + partials = holders = undefined; + } + length -= holders ? holders.length : 0; + if (bitmask & PARTIAL_RIGHT_FLAG) { + var partialsRight = partials, holdersRight = holders; + partials = holders = undefined; + } + var data = isBindKey ? undefined : getData(func), newData = [ func, bitmask, thisArg, partials, holders, partialsRight, holdersRight, argPos, ary, arity ]; + if (data) { + mergeData(newData, data); + bitmask = newData[1]; + arity = newData[9]; + } + newData[9] = arity == null ? isBindKey ? 0 : func.length : nativeMax(arity - length, 0) || 0; + if (bitmask == BIND_FLAG) { + var result = createBindWrapper(newData[0], newData[2]); + } else if ((bitmask == PARTIAL_FLAG || bitmask == (BIND_FLAG | PARTIAL_FLAG)) && !newData[4].length) { + result = createPartialWrapper.apply(undefined, newData); + } else { + result = createHybridWrapper.apply(undefined, newData); + } + var setter = data ? baseSetData : setData; + return setter(result, newData); + } + function equalArrays(array, other, equalFunc, customizer, isLoose, stackA, stackB) { + var index = -1, arrLength = array.length, othLength = other.length; + if (arrLength != othLength && !(isLoose && othLength > arrLength)) { + return false; + } + while (++index < arrLength) { + var arrValue = array[index], othValue = other[index], result = customizer ? customizer(isLoose ? othValue : arrValue, isLoose ? arrValue : othValue, index) : undefined; + if (result !== undefined) { + if (result) { + continue; + } + return false; + } + if (isLoose) { + if (!arraySome(other, function(othValue) { + return arrValue === othValue || equalFunc(arrValue, othValue, customizer, isLoose, stackA, stackB); + })) { + return false; + } + } else if (!(arrValue === othValue || equalFunc(arrValue, othValue, customizer, isLoose, stackA, stackB))) { + return false; + } + } + return true; + } + function equalByTag(object, other, tag) { + switch (tag) { + case boolTag: + case dateTag: + return +object == +other; + + case errorTag: + return object.name == other.name && object.message == other.message; + + case numberTag: + return object != +object ? other != +other : object == +other; + + case regexpTag: + case stringTag: + return object == other + ""; + } + return false; + } + function equalObjects(object, other, equalFunc, customizer, isLoose, stackA, stackB) { + var objProps = keys(object), objLength = objProps.length, othProps = keys(other), othLength = othProps.length; + if (objLength != othLength && !isLoose) { + return false; + } + var index = objLength; + while (index--) { + var key = objProps[index]; + if (!(isLoose ? key in other : hasOwnProperty.call(other, key))) { + return false; + } + } + var skipCtor = isLoose; + while (++index < objLength) { + key = objProps[index]; + var objValue = object[key], othValue = other[key], result = customizer ? customizer(isLoose ? othValue : objValue, isLoose ? objValue : othValue, key) : undefined; + if (!(result === undefined ? equalFunc(objValue, othValue, customizer, isLoose, stackA, stackB) : result)) { + return false; + } + skipCtor || (skipCtor = key == "constructor"); + } + if (!skipCtor) { + var objCtor = object.constructor, othCtor = other.constructor; + if (objCtor != othCtor && ("constructor" in object && "constructor" in other) && !(typeof objCtor == "function" && objCtor instanceof objCtor && typeof othCtor == "function" && othCtor instanceof othCtor)) { + return false; + } + } + return true; + } + function getCallback(func, thisArg, argCount) { + var result = lodash.callback || callback; + result = result === callback ? baseCallback : result; + return argCount ? result(func, thisArg, argCount) : result; + } + var getData = !metaMap ? noop : function(func) { + return metaMap.get(func); + }; + function getFuncName(func) { + var result = func.name + "", array = realNames[result], length = array ? array.length : 0; + while (length--) { + var data = array[length], otherFunc = data.func; + if (otherFunc == null || otherFunc == func) { + return data.name; + } + } + return result; + } + function getIndexOf(collection, target, fromIndex) { + var result = lodash.indexOf || indexOf; + result = result === indexOf ? baseIndexOf : result; + return collection ? result(collection, target, fromIndex) : result; + } + var getLength = baseProperty("length"); + function getMatchData(object) { + var result = pairs(object), length = result.length; + while (length--) { + result[length][2] = isStrictComparable(result[length][1]); + } + return result; + } + function getNative(object, key) { + var value = object == null ? undefined : object[key]; + return isNative(value) ? value : undefined; + } + function getView(start, end, transforms) { + var index = -1, length = transforms.length; + while (++index < length) { + var data = transforms[index], size = data.size; + switch (data.type) { + case "drop": + start += size; + break; + + case "dropRight": + end -= size; + break; + + case "take": + end = nativeMin(end, start + size); + break; + + case "takeRight": + start = nativeMax(start, end - size); + break; + } + } + return { + start: start, + end: end + }; + } + function initCloneArray(array) { + var length = array.length, result = new array.constructor(length); + if (length && typeof array[0] == "string" && hasOwnProperty.call(array, "index")) { + result.index = array.index; + result.input = array.input; + } + return result; + } + function initCloneObject(object) { + var Ctor = object.constructor; + if (!(typeof Ctor == "function" && Ctor instanceof Ctor)) { + Ctor = Object; + } + return new Ctor(); + } + function initCloneByTag(object, tag, isDeep) { + var Ctor = object.constructor; + switch (tag) { + case arrayBufferTag: + return bufferClone(object); + + case boolTag: + case dateTag: + return new Ctor(+object); + + case float32Tag: + case float64Tag: + case int8Tag: + case int16Tag: + case int32Tag: + case uint8Tag: + case uint8ClampedTag: + case uint16Tag: + case uint32Tag: + var buffer = object.buffer; + return new Ctor(isDeep ? bufferClone(buffer) : buffer, object.byteOffset, object.length); + + case numberTag: + case stringTag: + return new Ctor(object); + + case regexpTag: + var result = new Ctor(object.source, reFlags.exec(object)); + result.lastIndex = object.lastIndex; + } + return result; + } + function invokePath(object, path, args) { + if (object != null && !isKey(path, object)) { + path = toPath(path); + object = path.length == 1 ? object : baseGet(object, baseSlice(path, 0, -1)); + path = last(path); + } + var func = object == null ? object : object[path]; + return func == null ? undefined : func.apply(object, args); + } + function isArrayLike(value) { + return value != null && isLength(getLength(value)); + } + function isIndex(value, length) { + value = typeof value == "number" || reIsUint.test(value) ? +value : -1; + length = length == null ? MAX_SAFE_INTEGER : length; + return value > -1 && value % 1 == 0 && value < length; + } + function isIterateeCall(value, index, object) { + if (!isObject(object)) { + return false; + } + var type = typeof index; + if (type == "number" ? isArrayLike(object) && isIndex(index, object.length) : type == "string" && index in object) { + var other = object[index]; + return value === value ? value === other : other !== other; + } + return false; + } + function isKey(value, object) { + var type = typeof value; + if (type == "string" && reIsPlainProp.test(value) || type == "number") { + return true; + } + if (isArray(value)) { + return false; + } + var result = !reIsDeepProp.test(value); + return result || object != null && value in toObject(object); + } + function isLaziable(func) { + var funcName = getFuncName(func), other = lodash[funcName]; + if (typeof other != "function" || !(funcName in LazyWrapper.prototype)) { + return false; + } + if (func === other) { + return true; + } + var data = getData(other); + return !!data && func === data[0]; + } + function isLength(value) { + return typeof value == "number" && value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER; + } + function isStrictComparable(value) { + return value === value && !isObject(value); + } + function mergeData(data, source) { + var bitmask = data[1], srcBitmask = source[1], newBitmask = bitmask | srcBitmask, isCommon = newBitmask < ARY_FLAG; + var isCombo = srcBitmask == ARY_FLAG && bitmask == CURRY_FLAG || srcBitmask == ARY_FLAG && bitmask == REARG_FLAG && data[7].length <= source[8] || srcBitmask == (ARY_FLAG | REARG_FLAG) && bitmask == CURRY_FLAG; + if (!(isCommon || isCombo)) { + return data; + } + if (srcBitmask & BIND_FLAG) { + data[2] = source[2]; + newBitmask |= bitmask & BIND_FLAG ? 0 : CURRY_BOUND_FLAG; + } + var value = source[3]; + if (value) { + var partials = data[3]; + data[3] = partials ? composeArgs(partials, value, source[4]) : arrayCopy(value); + data[4] = partials ? replaceHolders(data[3], PLACEHOLDER) : arrayCopy(source[4]); + } + value = source[5]; + if (value) { + partials = data[5]; + data[5] = partials ? composeArgsRight(partials, value, source[6]) : arrayCopy(value); + data[6] = partials ? replaceHolders(data[5], PLACEHOLDER) : arrayCopy(source[6]); + } + value = source[7]; + if (value) { + data[7] = arrayCopy(value); + } + if (srcBitmask & ARY_FLAG) { + data[8] = data[8] == null ? source[8] : nativeMin(data[8], source[8]); + } + if (data[9] == null) { + data[9] = source[9]; + } + data[0] = source[0]; + data[1] = newBitmask; + return data; + } + function mergeDefaults(objectValue, sourceValue) { + return objectValue === undefined ? sourceValue : merge(objectValue, sourceValue, mergeDefaults); + } + function pickByArray(object, props) { + object = toObject(object); + var index = -1, length = props.length, result = {}; + while (++index < length) { + var key = props[index]; + if (key in object) { + result[key] = object[key]; + } + } + return result; + } + function pickByCallback(object, predicate) { + var result = {}; + baseForIn(object, function(value, key, object) { + if (predicate(value, key, object)) { + result[key] = value; + } + }); + return result; + } + function reorder(array, indexes) { + var arrLength = array.length, length = nativeMin(indexes.length, arrLength), oldArray = arrayCopy(array); + while (length--) { + var index = indexes[length]; + array[length] = isIndex(index, arrLength) ? oldArray[index] : undefined; + } + return array; + } + var setData = function() { + var count = 0, lastCalled = 0; + return function(key, value) { + var stamp = now(), remaining = HOT_SPAN - (stamp - lastCalled); + lastCalled = stamp; + if (remaining > 0) { + if (++count >= HOT_COUNT) { + return key; + } + } else { + count = 0; + } + return baseSetData(key, value); + }; + }(); + function shimKeys(object) { + var props = keysIn(object), propsLength = props.length, length = propsLength && object.length; + var allowIndexes = !!length && isLength(length) && (isArray(object) || isArguments(object)); + var index = -1, result = []; + while (++index < propsLength) { + var key = props[index]; + if (allowIndexes && isIndex(key, length) || hasOwnProperty.call(object, key)) { + result.push(key); + } + } + return result; + } + function toIterable(value) { + if (value == null) { + return []; + } + if (!isArrayLike(value)) { + return values(value); + } + return isObject(value) ? value : Object(value); + } + function toObject(value) { + return isObject(value) ? value : Object(value); + } + function toPath(value) { + if (isArray(value)) { + return value; + } + var result = []; + baseToString(value).replace(rePropName, function(match, number, quote, string) { + result.push(quote ? string.replace(reEscapeChar, "$1") : number || match); + }); + return result; + } + function wrapperClone(wrapper) { + return wrapper instanceof LazyWrapper ? wrapper.clone() : new LodashWrapper(wrapper.__wrapped__, wrapper.__chain__, arrayCopy(wrapper.__actions__)); + } + function chunk(array, size, guard) { + if (guard ? isIterateeCall(array, size, guard) : size == null) { + size = 1; + } else { + size = nativeMax(nativeFloor(size) || 1, 1); + } + var index = 0, length = array ? array.length : 0, resIndex = -1, result = Array(nativeCeil(length / size)); + while (index < length) { + result[++resIndex] = baseSlice(array, index, index += size); + } + return result; + } + function compact(array) { + var index = -1, length = array ? array.length : 0, resIndex = -1, result = []; + while (++index < length) { + var value = array[index]; + if (value) { + result[++resIndex] = value; + } + } + return result; + } + var difference = restParam(function(array, values) { + return isObjectLike(array) && isArrayLike(array) ? baseDifference(array, baseFlatten(values, false, true)) : []; + }); + function drop(array, n, guard) { + var length = array ? array.length : 0; + if (!length) { + return []; + } + if (guard ? isIterateeCall(array, n, guard) : n == null) { + n = 1; + } + return baseSlice(array, n < 0 ? 0 : n); + } + function dropRight(array, n, guard) { + var length = array ? array.length : 0; + if (!length) { + return []; + } + if (guard ? isIterateeCall(array, n, guard) : n == null) { + n = 1; + } + n = length - (+n || 0); + return baseSlice(array, 0, n < 0 ? 0 : n); + } + function dropRightWhile(array, predicate, thisArg) { + return array && array.length ? baseWhile(array, getCallback(predicate, thisArg, 3), true, true) : []; + } + function dropWhile(array, predicate, thisArg) { + return array && array.length ? baseWhile(array, getCallback(predicate, thisArg, 3), true) : []; + } + function fill(array, value, start, end) { + var length = array ? array.length : 0; + if (!length) { + return []; + } + if (start && typeof start != "number" && isIterateeCall(array, value, start)) { + start = 0; + end = length; + } + return baseFill(array, value, start, end); + } + var findIndex = createFindIndex(); + var findLastIndex = createFindIndex(true); + function first(array) { + return array ? array[0] : undefined; + } + function flatten(array, isDeep, guard) { + var length = array ? array.length : 0; + if (guard && isIterateeCall(array, isDeep, guard)) { + isDeep = false; + } + return length ? baseFlatten(array, isDeep) : []; + } + function flattenDeep(array) { + var length = array ? array.length : 0; + return length ? baseFlatten(array, true) : []; + } + function indexOf(array, value, fromIndex) { + var length = array ? array.length : 0; + if (!length) { + return -1; + } + if (typeof fromIndex == "number") { + fromIndex = fromIndex < 0 ? nativeMax(length + fromIndex, 0) : fromIndex; + } else if (fromIndex) { + var index = binaryIndex(array, value); + if (index < length && (value === value ? value === array[index] : array[index] !== array[index])) { + return index; + } + return -1; + } + return baseIndexOf(array, value, fromIndex || 0); + } + function initial(array) { + return dropRight(array, 1); + } + var intersection = restParam(function(arrays) { + var othLength = arrays.length, othIndex = othLength, caches = Array(length), indexOf = getIndexOf(), isCommon = indexOf === baseIndexOf, result = []; + while (othIndex--) { + var value = arrays[othIndex] = isArrayLike(value = arrays[othIndex]) ? value : []; + caches[othIndex] = isCommon && value.length >= 120 ? createCache(othIndex && value) : null; + } + var array = arrays[0], index = -1, length = array ? array.length : 0, seen = caches[0]; + outer: while (++index < length) { + value = array[index]; + if ((seen ? cacheIndexOf(seen, value) : indexOf(result, value, 0)) < 0) { + var othIndex = othLength; + while (--othIndex) { + var cache = caches[othIndex]; + if ((cache ? cacheIndexOf(cache, value) : indexOf(arrays[othIndex], value, 0)) < 0) { + continue outer; + } + } + if (seen) { + seen.push(value); + } + result.push(value); + } + } + return result; + }); + function last(array) { + var length = array ? array.length : 0; + return length ? array[length - 1] : undefined; + } + function lastIndexOf(array, value, fromIndex) { + var length = array ? array.length : 0; + if (!length) { + return -1; + } + var index = length; + if (typeof fromIndex == "number") { + index = (fromIndex < 0 ? nativeMax(length + fromIndex, 0) : nativeMin(fromIndex || 0, length - 1)) + 1; + } else if (fromIndex) { + index = binaryIndex(array, value, true) - 1; + var other = array[index]; + if (value === value ? value === other : other !== other) { + return index; + } + return -1; + } + if (value !== value) { + return indexOfNaN(array, index, true); + } + while (index--) { + if (array[index] === value) { + return index; + } + } + return -1; + } + function pull() { + var args = arguments, array = args[0]; + if (!(array && array.length)) { + return array; + } + var index = 0, indexOf = getIndexOf(), length = args.length; + while (++index < length) { + var fromIndex = 0, value = args[index]; + while ((fromIndex = indexOf(array, value, fromIndex)) > -1) { + splice.call(array, fromIndex, 1); + } + } + return array; + } + var pullAt = restParam(function(array, indexes) { + indexes = baseFlatten(indexes); + var result = baseAt(array, indexes); + basePullAt(array, indexes.sort(baseCompareAscending)); + return result; + }); + function remove(array, predicate, thisArg) { + var result = []; + if (!(array && array.length)) { + return result; + } + var index = -1, indexes = [], length = array.length; + predicate = getCallback(predicate, thisArg, 3); + while (++index < length) { + var value = array[index]; + if (predicate(value, index, array)) { + result.push(value); + indexes.push(index); + } + } + basePullAt(array, indexes); + return result; + } + function rest(array) { + return drop(array, 1); + } + function slice(array, start, end) { + var length = array ? array.length : 0; + if (!length) { + return []; + } + if (end && typeof end != "number" && isIterateeCall(array, start, end)) { + start = 0; + end = length; + } + return baseSlice(array, start, end); + } + var sortedIndex = createSortedIndex(); + var sortedLastIndex = createSortedIndex(true); + function take(array, n, guard) { + var length = array ? array.length : 0; + if (!length) { + return []; + } + if (guard ? isIterateeCall(array, n, guard) : n == null) { + n = 1; + } + return baseSlice(array, 0, n < 0 ? 0 : n); + } + function takeRight(array, n, guard) { + var length = array ? array.length : 0; + if (!length) { + return []; + } + if (guard ? isIterateeCall(array, n, guard) : n == null) { + n = 1; + } + n = length - (+n || 0); + return baseSlice(array, n < 0 ? 0 : n); + } + function takeRightWhile(array, predicate, thisArg) { + return array && array.length ? baseWhile(array, getCallback(predicate, thisArg, 3), false, true) : []; + } + function takeWhile(array, predicate, thisArg) { + return array && array.length ? baseWhile(array, getCallback(predicate, thisArg, 3)) : []; + } + var union = restParam(function(arrays) { + return baseUniq(baseFlatten(arrays, false, true)); + }); + function uniq(array, isSorted, iteratee, thisArg) { + var length = array ? array.length : 0; + if (!length) { + return []; + } + if (isSorted != null && typeof isSorted != "boolean") { + thisArg = iteratee; + iteratee = isIterateeCall(array, isSorted, thisArg) ? undefined : isSorted; + isSorted = false; + } + var callback = getCallback(); + if (!(iteratee == null && callback === baseCallback)) { + iteratee = callback(iteratee, thisArg, 3); + } + return isSorted && getIndexOf() === baseIndexOf ? sortedUniq(array, iteratee) : baseUniq(array, iteratee); + } + function unzip(array) { + if (!(array && array.length)) { + return []; + } + var index = -1, length = 0; + array = arrayFilter(array, function(group) { + if (isArrayLike(group)) { + length = nativeMax(group.length, length); + return true; + } + }); + var result = Array(length); + while (++index < length) { + result[index] = arrayMap(array, baseProperty(index)); + } + return result; + } + function unzipWith(array, iteratee, thisArg) { + var length = array ? array.length : 0; + if (!length) { + return []; + } + var result = unzip(array); + if (iteratee == null) { + return result; + } + iteratee = bindCallback(iteratee, thisArg, 4); + return arrayMap(result, function(group) { + return arrayReduce(group, iteratee, undefined, true); + }); + } + var without = restParam(function(array, values) { + return isArrayLike(array) ? baseDifference(array, values) : []; + }); + function xor() { + var index = -1, length = arguments.length; + while (++index < length) { + var array = arguments[index]; + if (isArrayLike(array)) { + var result = result ? arrayPush(baseDifference(result, array), baseDifference(array, result)) : array; + } + } + return result ? baseUniq(result) : []; + } + var zip = restParam(unzip); + function zipObject(props, values) { + var index = -1, length = props ? props.length : 0, result = {}; + if (length && !values && !isArray(props[0])) { + values = []; + } + while (++index < length) { + var key = props[index]; + if (values) { + result[key] = values[index]; + } else if (key) { + result[key[0]] = key[1]; + } + } + return result; + } + var zipWith = restParam(function(arrays) { + var length = arrays.length, iteratee = length > 2 ? arrays[length - 2] : undefined, thisArg = length > 1 ? arrays[length - 1] : undefined; + if (length > 2 && typeof iteratee == "function") { + length -= 2; + } else { + iteratee = length > 1 && typeof thisArg == "function" ? (--length, thisArg) : undefined; + thisArg = undefined; + } + arrays.length = length; + return unzipWith(arrays, iteratee, thisArg); + }); + function chain(value) { + var result = lodash(value); + result.__chain__ = true; + return result; + } + function tap(value, interceptor, thisArg) { + interceptor.call(thisArg, value); + return value; + } + function thru(value, interceptor, thisArg) { + return interceptor.call(thisArg, value); + } + function wrapperChain() { + return chain(this); + } + function wrapperCommit() { + return new LodashWrapper(this.value(), this.__chain__); + } + var wrapperConcat = restParam(function(values) { + values = baseFlatten(values); + return this.thru(function(array) { + return arrayConcat(isArray(array) ? array : [ toObject(array) ], values); + }); + }); + function wrapperPlant(value) { + var result, parent = this; + while (parent instanceof baseLodash) { + var clone = wrapperClone(parent); + if (result) { + previous.__wrapped__ = clone; + } else { + result = clone; + } + var previous = clone; + parent = parent.__wrapped__; + } + previous.__wrapped__ = value; + return result; + } + function wrapperReverse() { + var value = this.__wrapped__; + var interceptor = function(value) { + return value.reverse(); + }; + if (value instanceof LazyWrapper) { + var wrapped = value; + if (this.__actions__.length) { + wrapped = new LazyWrapper(this); + } + wrapped = wrapped.reverse(); + wrapped.__actions__.push({ + func: thru, + args: [ interceptor ], + thisArg: undefined + }); + return new LodashWrapper(wrapped, this.__chain__); + } + return this.thru(interceptor); + } + function wrapperToString() { + return this.value() + ""; + } + function wrapperValue() { + return baseWrapperValue(this.__wrapped__, this.__actions__); + } + var at = restParam(function(collection, props) { + return baseAt(collection, baseFlatten(props)); + }); + var countBy = createAggregator(function(result, value, key) { + hasOwnProperty.call(result, key) ? ++result[key] : result[key] = 1; + }); + function every(collection, predicate, thisArg) { + var func = isArray(collection) ? arrayEvery : baseEvery; + if (thisArg && isIterateeCall(collection, predicate, thisArg)) { + predicate = undefined; + } + if (typeof predicate != "function" || thisArg !== undefined) { + predicate = getCallback(predicate, thisArg, 3); + } + return func(collection, predicate); + } + function filter(collection, predicate, thisArg) { + var func = isArray(collection) ? arrayFilter : baseFilter; + predicate = getCallback(predicate, thisArg, 3); + return func(collection, predicate); + } + var find = createFind(baseEach); + var findLast = createFind(baseEachRight, true); + function findWhere(collection, source) { + return find(collection, baseMatches(source)); + } + var forEach = createForEach(arrayEach, baseEach); + var forEachRight = createForEach(arrayEachRight, baseEachRight); + var groupBy = createAggregator(function(result, value, key) { + if (hasOwnProperty.call(result, key)) { + result[key].push(value); + } else { + result[key] = [ value ]; + } + }); + function includes(collection, target, fromIndex, guard) { + var length = collection ? getLength(collection) : 0; + if (!isLength(length)) { + collection = values(collection); + length = collection.length; + } + if (typeof fromIndex != "number" || guard && isIterateeCall(target, fromIndex, guard)) { + fromIndex = 0; + } else { + fromIndex = fromIndex < 0 ? nativeMax(length + fromIndex, 0) : fromIndex || 0; + } + return typeof collection == "string" || !isArray(collection) && isString(collection) ? fromIndex <= length && collection.indexOf(target, fromIndex) > -1 : !!length && getIndexOf(collection, target, fromIndex) > -1; + } + var indexBy = createAggregator(function(result, value, key) { + result[key] = value; + }); + var invoke = restParam(function(collection, path, args) { + var index = -1, isFunc = typeof path == "function", isProp = isKey(path), result = isArrayLike(collection) ? Array(collection.length) : []; + baseEach(collection, function(value) { + var func = isFunc ? path : isProp && value != null ? value[path] : undefined; + result[++index] = func ? func.apply(value, args) : invokePath(value, path, args); + }); + return result; + }); + function map(collection, iteratee, thisArg) { + var func = isArray(collection) ? arrayMap : baseMap; + iteratee = getCallback(iteratee, thisArg, 3); + return func(collection, iteratee); + } + var partition = createAggregator(function(result, value, key) { + result[key ? 0 : 1].push(value); + }, function() { + return [ [], [] ]; + }); + function pluck(collection, path) { + return map(collection, property(path)); + } + var reduce = createReduce(arrayReduce, baseEach); + var reduceRight = createReduce(arrayReduceRight, baseEachRight); + function reject(collection, predicate, thisArg) { + var func = isArray(collection) ? arrayFilter : baseFilter; + predicate = getCallback(predicate, thisArg, 3); + return func(collection, function(value, index, collection) { + return !predicate(value, index, collection); + }); + } + function sample(collection, n, guard) { + if (guard ? isIterateeCall(collection, n, guard) : n == null) { + collection = toIterable(collection); + var length = collection.length; + return length > 0 ? collection[baseRandom(0, length - 1)] : undefined; + } + var index = -1, result = toArray(collection), length = result.length, lastIndex = length - 1; + n = nativeMin(n < 0 ? 0 : +n || 0, length); + while (++index < n) { + var rand = baseRandom(index, lastIndex), value = result[rand]; + result[rand] = result[index]; + result[index] = value; + } + result.length = n; + return result; + } + function shuffle(collection) { + return sample(collection, POSITIVE_INFINITY); + } + function size(collection) { + var length = collection ? getLength(collection) : 0; + return isLength(length) ? length : keys(collection).length; + } + function some(collection, predicate, thisArg) { + var func = isArray(collection) ? arraySome : baseSome; + if (thisArg && isIterateeCall(collection, predicate, thisArg)) { + predicate = undefined; + } + if (typeof predicate != "function" || thisArg !== undefined) { + predicate = getCallback(predicate, thisArg, 3); + } + return func(collection, predicate); + } + function sortBy(collection, iteratee, thisArg) { + if (collection == null) { + return []; + } + if (thisArg && isIterateeCall(collection, iteratee, thisArg)) { + iteratee = undefined; + } + var index = -1; + iteratee = getCallback(iteratee, thisArg, 3); + var result = baseMap(collection, function(value, key, collection) { + return { + criteria: iteratee(value, key, collection), + index: ++index, + value: value + }; + }); + return baseSortBy(result, compareAscending); + } + var sortByAll = restParam(function(collection, iteratees) { + if (collection == null) { + return []; + } + var guard = iteratees[2]; + if (guard && isIterateeCall(iteratees[0], iteratees[1], guard)) { + iteratees.length = 1; + } + return baseSortByOrder(collection, baseFlatten(iteratees), []); + }); + function sortByOrder(collection, iteratees, orders, guard) { + if (collection == null) { + return []; + } + if (guard && isIterateeCall(iteratees, orders, guard)) { + orders = undefined; + } + if (!isArray(iteratees)) { + iteratees = iteratees == null ? [] : [ iteratees ]; + } + if (!isArray(orders)) { + orders = orders == null ? [] : [ orders ]; + } + return baseSortByOrder(collection, iteratees, orders); + } + function where(collection, source) { + return filter(collection, baseMatches(source)); + } + var now = nativeNow || function() { + return new Date().getTime(); + }; + function after(n, func) { + if (typeof func != "function") { + if (typeof n == "function") { + var temp = n; + n = func; + func = temp; + } else { + throw new TypeError(FUNC_ERROR_TEXT); + } + } + n = nativeIsFinite(n = +n) ? n : 0; + return function() { + if (--n < 1) { + return func.apply(this, arguments); + } + }; + } + function ary(func, n, guard) { + if (guard && isIterateeCall(func, n, guard)) { + n = undefined; + } + n = func && n == null ? func.length : nativeMax(+n || 0, 0); + return createWrapper(func, ARY_FLAG, undefined, undefined, undefined, undefined, n); + } + function before(n, func) { + var result; + if (typeof func != "function") { + if (typeof n == "function") { + var temp = n; + n = func; + func = temp; + } else { + throw new TypeError(FUNC_ERROR_TEXT); + } + } + return function() { + if (--n > 0) { + result = func.apply(this, arguments); + } + if (n <= 1) { + func = undefined; + } + return result; + }; + } + var bind = restParam(function(func, thisArg, partials) { + var bitmask = BIND_FLAG; + if (partials.length) { + var holders = replaceHolders(partials, bind.placeholder); + bitmask |= PARTIAL_FLAG; + } + return createWrapper(func, bitmask, thisArg, partials, holders); + }); + var bindAll = restParam(function(object, methodNames) { + methodNames = methodNames.length ? baseFlatten(methodNames) : functions(object); + var index = -1, length = methodNames.length; + while (++index < length) { + var key = methodNames[index]; + object[key] = createWrapper(object[key], BIND_FLAG, object); + } + return object; + }); + var bindKey = restParam(function(object, key, partials) { + var bitmask = BIND_FLAG | BIND_KEY_FLAG; + if (partials.length) { + var holders = replaceHolders(partials, bindKey.placeholder); + bitmask |= PARTIAL_FLAG; + } + return createWrapper(key, bitmask, object, partials, holders); + }); + var curry = createCurry(CURRY_FLAG); + var curryRight = createCurry(CURRY_RIGHT_FLAG); + function debounce(func, wait, options) { + var args, maxTimeoutId, result, stamp, thisArg, timeoutId, trailingCall, lastCalled = 0, maxWait = false, trailing = true; + if (typeof func != "function") { + throw new TypeError(FUNC_ERROR_TEXT); + } + wait = wait < 0 ? 0 : +wait || 0; + if (options === true) { + var leading = true; + trailing = false; + } else if (isObject(options)) { + leading = !!options.leading; + maxWait = "maxWait" in options && nativeMax(+options.maxWait || 0, wait); + trailing = "trailing" in options ? !!options.trailing : trailing; + } + function cancel() { + if (timeoutId) { + clearTimeout(timeoutId); + } + if (maxTimeoutId) { + clearTimeout(maxTimeoutId); + } + lastCalled = 0; + maxTimeoutId = timeoutId = trailingCall = undefined; + } + function complete(isCalled, id) { + if (id) { + clearTimeout(id); + } + maxTimeoutId = timeoutId = trailingCall = undefined; + if (isCalled) { + lastCalled = now(); + result = func.apply(thisArg, args); + if (!timeoutId && !maxTimeoutId) { + args = thisArg = undefined; + } + } + } + function delayed() { + var remaining = wait - (now() - stamp); + if (remaining <= 0 || remaining > wait) { + complete(trailingCall, maxTimeoutId); + } else { + timeoutId = setTimeout(delayed, remaining); + } + } + function maxDelayed() { + complete(trailing, timeoutId); + } + function debounced() { + args = arguments; + stamp = now(); + thisArg = this; + trailingCall = trailing && (timeoutId || !leading); + if (maxWait === false) { + var leadingCall = leading && !timeoutId; + } else { + if (!maxTimeoutId && !leading) { + lastCalled = stamp; + } + var remaining = maxWait - (stamp - lastCalled), isCalled = remaining <= 0 || remaining > maxWait; + if (isCalled) { + if (maxTimeoutId) { + maxTimeoutId = clearTimeout(maxTimeoutId); + } + lastCalled = stamp; + result = func.apply(thisArg, args); + } else if (!maxTimeoutId) { + maxTimeoutId = setTimeout(maxDelayed, remaining); + } + } + if (isCalled && timeoutId) { + timeoutId = clearTimeout(timeoutId); + } else if (!timeoutId && wait !== maxWait) { + timeoutId = setTimeout(delayed, wait); + } + if (leadingCall) { + isCalled = true; + result = func.apply(thisArg, args); + } + if (isCalled && !timeoutId && !maxTimeoutId) { + args = thisArg = undefined; + } + return result; + } + debounced.cancel = cancel; + return debounced; + } + var defer = restParam(function(func, args) { + return baseDelay(func, 1, args); + }); + var delay = restParam(function(func, wait, args) { + return baseDelay(func, wait, args); + }); + var flow = createFlow(); + var flowRight = createFlow(true); + function memoize(func, resolver) { + if (typeof func != "function" || resolver && typeof resolver != "function") { + throw new TypeError(FUNC_ERROR_TEXT); + } + var memoized = function() { + var args = arguments, key = resolver ? resolver.apply(this, args) : args[0], cache = memoized.cache; + if (cache.has(key)) { + return cache.get(key); + } + var result = func.apply(this, args); + memoized.cache = cache.set(key, result); + return result; + }; + memoized.cache = new memoize.Cache(); + return memoized; + } + var modArgs = restParam(function(func, transforms) { + transforms = baseFlatten(transforms); + if (typeof func != "function" || !arrayEvery(transforms, baseIsFunction)) { + throw new TypeError(FUNC_ERROR_TEXT); + } + var length = transforms.length; + return restParam(function(args) { + var index = nativeMin(args.length, length); + while (index--) { + args[index] = transforms[index](args[index]); + } + return func.apply(this, args); + }); + }); + function negate(predicate) { + if (typeof predicate != "function") { + throw new TypeError(FUNC_ERROR_TEXT); + } + return function() { + return !predicate.apply(this, arguments); + }; + } + function once(func) { + return before(2, func); + } + var partial = createPartial(PARTIAL_FLAG); + var partialRight = createPartial(PARTIAL_RIGHT_FLAG); + var rearg = restParam(function(func, indexes) { + return createWrapper(func, REARG_FLAG, undefined, undefined, undefined, baseFlatten(indexes)); + }); + function restParam(func, start) { + if (typeof func != "function") { + throw new TypeError(FUNC_ERROR_TEXT); + } + start = nativeMax(start === undefined ? func.length - 1 : +start || 0, 0); + return function() { + var args = arguments, index = -1, length = nativeMax(args.length - start, 0), rest = Array(length); + while (++index < length) { + rest[index] = args[start + index]; + } + switch (start) { + case 0: + return func.call(this, rest); + + case 1: + return func.call(this, args[0], rest); + + case 2: + return func.call(this, args[0], args[1], rest); + } + var otherArgs = Array(start + 1); + index = -1; + while (++index < start) { + otherArgs[index] = args[index]; + } + otherArgs[start] = rest; + return func.apply(this, otherArgs); + }; + } + function spread(func) { + if (typeof func != "function") { + throw new TypeError(FUNC_ERROR_TEXT); + } + return function(array) { + return func.apply(this, array); + }; + } + function throttle(func, wait, options) { + var leading = true, trailing = true; + if (typeof func != "function") { + throw new TypeError(FUNC_ERROR_TEXT); + } + if (options === false) { + leading = false; + } else if (isObject(options)) { + leading = "leading" in options ? !!options.leading : leading; + trailing = "trailing" in options ? !!options.trailing : trailing; + } + return debounce(func, wait, { + leading: leading, + maxWait: +wait, + trailing: trailing + }); + } + function wrap(value, wrapper) { + wrapper = wrapper == null ? identity : wrapper; + return createWrapper(wrapper, PARTIAL_FLAG, undefined, [ value ], []); + } + function clone(value, isDeep, customizer, thisArg) { + if (isDeep && typeof isDeep != "boolean" && isIterateeCall(value, isDeep, customizer)) { + isDeep = false; + } else if (typeof isDeep == "function") { + thisArg = customizer; + customizer = isDeep; + isDeep = false; + } + return typeof customizer == "function" ? baseClone(value, isDeep, bindCallback(customizer, thisArg, 3)) : baseClone(value, isDeep); + } + function cloneDeep(value, customizer, thisArg) { + return typeof customizer == "function" ? baseClone(value, true, bindCallback(customizer, thisArg, 3)) : baseClone(value, true); + } + function gt(value, other) { + return value > other; + } + function gte(value, other) { + return value >= other; + } + function isArguments(value) { + return isObjectLike(value) && isArrayLike(value) && hasOwnProperty.call(value, "callee") && !propertyIsEnumerable.call(value, "callee"); + } + var isArray = nativeIsArray || function(value) { + return isObjectLike(value) && isLength(value.length) && objToString.call(value) == arrayTag; + }; + function isBoolean(value) { + return value === true || value === false || isObjectLike(value) && objToString.call(value) == boolTag; + } + function isDate(value) { + return isObjectLike(value) && objToString.call(value) == dateTag; + } + function isElement(value) { + return !!value && value.nodeType === 1 && isObjectLike(value) && !isPlainObject(value); + } + function isEmpty(value) { + if (value == null) { + return true; + } + if (isArrayLike(value) && (isArray(value) || isString(value) || isArguments(value) || isObjectLike(value) && isFunction(value.splice))) { + return !value.length; + } + return !keys(value).length; + } + function isEqual(value, other, customizer, thisArg) { + customizer = typeof customizer == "function" ? bindCallback(customizer, thisArg, 3) : undefined; + var result = customizer ? customizer(value, other) : undefined; + return result === undefined ? baseIsEqual(value, other, customizer) : !!result; + } + function isError(value) { + return isObjectLike(value) && typeof value.message == "string" && objToString.call(value) == errorTag; + } + function isFinite(value) { + return typeof value == "number" && nativeIsFinite(value); + } + function isFunction(value) { + return isObject(value) && objToString.call(value) == funcTag; + } + function isObject(value) { + var type = typeof value; + return !!value && (type == "object" || type == "function"); + } + function isMatch(object, source, customizer, thisArg) { + customizer = typeof customizer == "function" ? bindCallback(customizer, thisArg, 3) : undefined; + return baseIsMatch(object, getMatchData(source), customizer); + } + function isNaN(value) { + return isNumber(value) && value != +value; + } + function isNative(value) { + if (value == null) { + return false; + } + if (isFunction(value)) { + return reIsNative.test(fnToString.call(value)); + } + return isObjectLike(value) && reIsHostCtor.test(value); + } + function isNull(value) { + return value === null; + } + function isNumber(value) { + return typeof value == "number" || isObjectLike(value) && objToString.call(value) == numberTag; + } + function isPlainObject(value) { + var Ctor; + if (!(isObjectLike(value) && objToString.call(value) == objectTag && !isArguments(value)) || !hasOwnProperty.call(value, "constructor") && (Ctor = value.constructor, + typeof Ctor == "function" && !(Ctor instanceof Ctor))) { + return false; + } + var result; + baseForIn(value, function(subValue, key) { + result = key; + }); + return result === undefined || hasOwnProperty.call(value, result); + } + function isRegExp(value) { + return isObject(value) && objToString.call(value) == regexpTag; + } + function isString(value) { + return typeof value == "string" || isObjectLike(value) && objToString.call(value) == stringTag; + } + function isTypedArray(value) { + return isObjectLike(value) && isLength(value.length) && !!typedArrayTags[objToString.call(value)]; + } + function isUndefined(value) { + return value === undefined; + } + function lt(value, other) { + return value < other; + } + function lte(value, other) { + return value <= other; + } + function toArray(value) { + var length = value ? getLength(value) : 0; + if (!isLength(length)) { + return values(value); + } + if (!length) { + return []; + } + return arrayCopy(value); + } + function toPlainObject(value) { + return baseCopy(value, keysIn(value)); + } + var merge = createAssigner(baseMerge); + var assign = createAssigner(function(object, source, customizer) { + return customizer ? assignWith(object, source, customizer) : baseAssign(object, source); + }); + function create(prototype, properties, guard) { + var result = baseCreate(prototype); + if (guard && isIterateeCall(prototype, properties, guard)) { + properties = undefined; + } + return properties ? baseAssign(result, properties) : result; + } + var defaults = createDefaults(assign, assignDefaults); + var defaultsDeep = createDefaults(merge, mergeDefaults); + var findKey = createFindKey(baseForOwn); + var findLastKey = createFindKey(baseForOwnRight); + var forIn = createForIn(baseFor); + var forInRight = createForIn(baseForRight); + var forOwn = createForOwn(baseForOwn); + var forOwnRight = createForOwn(baseForOwnRight); + function functions(object) { + return baseFunctions(object, keysIn(object)); + } + function get(object, path, defaultValue) { + var result = object == null ? undefined : baseGet(object, toPath(path), path + ""); + return result === undefined ? defaultValue : result; + } + function has(object, path) { + if (object == null) { + return false; + } + var result = hasOwnProperty.call(object, path); + if (!result && !isKey(path)) { + path = toPath(path); + object = path.length == 1 ? object : baseGet(object, baseSlice(path, 0, -1)); + if (object == null) { + return false; + } + path = last(path); + result = hasOwnProperty.call(object, path); + } + return result || isLength(object.length) && isIndex(path, object.length) && (isArray(object) || isArguments(object)); + } + function invert(object, multiValue, guard) { + if (guard && isIterateeCall(object, multiValue, guard)) { + multiValue = undefined; + } + var index = -1, props = keys(object), length = props.length, result = {}; + while (++index < length) { + var key = props[index], value = object[key]; + if (multiValue) { + if (hasOwnProperty.call(result, value)) { + result[value].push(key); + } else { + result[value] = [ key ]; + } + } else { + result[value] = key; + } + } + return result; + } + var keys = !nativeKeys ? shimKeys : function(object) { + var Ctor = object == null ? undefined : object.constructor; + if (typeof Ctor == "function" && Ctor.prototype === object || typeof object != "function" && isArrayLike(object)) { + return shimKeys(object); + } + return isObject(object) ? nativeKeys(object) : []; + }; + function keysIn(object) { + if (object == null) { + return []; + } + if (!isObject(object)) { + object = Object(object); + } + var length = object.length; + length = length && isLength(length) && (isArray(object) || isArguments(object)) && length || 0; + var Ctor = object.constructor, index = -1, isProto = typeof Ctor == "function" && Ctor.prototype === object, result = Array(length), skipIndexes = length > 0; + while (++index < length) { + result[index] = index + ""; + } + for (var key in object) { + if (!(skipIndexes && isIndex(key, length)) && !(key == "constructor" && (isProto || !hasOwnProperty.call(object, key)))) { + result.push(key); + } + } + return result; + } + var mapKeys = createObjectMapper(true); + var mapValues = createObjectMapper(); + var omit = restParam(function(object, props) { + if (object == null) { + return {}; + } + if (typeof props[0] != "function") { + var props = arrayMap(baseFlatten(props), String); + return pickByArray(object, baseDifference(keysIn(object), props)); + } + var predicate = bindCallback(props[0], props[1], 3); + return pickByCallback(object, function(value, key, object) { + return !predicate(value, key, object); + }); + }); + function pairs(object) { + object = toObject(object); + var index = -1, props = keys(object), length = props.length, result = Array(length); + while (++index < length) { + var key = props[index]; + result[index] = [ key, object[key] ]; + } + return result; + } + var pick = restParam(function(object, props) { + if (object == null) { + return {}; + } + return typeof props[0] == "function" ? pickByCallback(object, bindCallback(props[0], props[1], 3)) : pickByArray(object, baseFlatten(props)); + }); + function result(object, path, defaultValue) { + var result = object == null ? undefined : object[path]; + if (result === undefined) { + if (object != null && !isKey(path, object)) { + path = toPath(path); + object = path.length == 1 ? object : baseGet(object, baseSlice(path, 0, -1)); + result = object == null ? undefined : object[last(path)]; + } + result = result === undefined ? defaultValue : result; + } + return isFunction(result) ? result.call(object) : result; + } + function set(object, path, value) { + if (object == null) { + return object; + } + var pathKey = path + ""; + path = object[pathKey] != null || isKey(path, object) ? [ pathKey ] : toPath(path); + var index = -1, length = path.length, lastIndex = length - 1, nested = object; + while (nested != null && ++index < length) { + var key = path[index]; + if (isObject(nested)) { + if (index == lastIndex) { + nested[key] = value; + } else if (nested[key] == null) { + nested[key] = isIndex(path[index + 1]) ? [] : {}; + } + } + nested = nested[key]; + } + return object; + } + function transform(object, iteratee, accumulator, thisArg) { + var isArr = isArray(object) || isTypedArray(object); + iteratee = getCallback(iteratee, thisArg, 4); + if (accumulator == null) { + if (isArr || isObject(object)) { + var Ctor = object.constructor; + if (isArr) { + accumulator = isArray(object) ? new Ctor() : []; + } else { + accumulator = baseCreate(isFunction(Ctor) ? Ctor.prototype : undefined); + } + } else { + accumulator = {}; + } + } + (isArr ? arrayEach : baseForOwn)(object, function(value, index, object) { + return iteratee(accumulator, value, index, object); + }); + return accumulator; + } + function values(object) { + return baseValues(object, keys(object)); + } + function valuesIn(object) { + return baseValues(object, keysIn(object)); + } + function inRange(value, start, end) { + start = +start || 0; + if (end === undefined) { + end = start; + start = 0; + } else { + end = +end || 0; + } + return value >= nativeMin(start, end) && value < nativeMax(start, end); + } + function random(min, max, floating) { + if (floating && isIterateeCall(min, max, floating)) { + max = floating = undefined; + } + var noMin = min == null, noMax = max == null; + if (floating == null) { + if (noMax && typeof min == "boolean") { + floating = min; + min = 1; + } else if (typeof max == "boolean") { + floating = max; + noMax = true; + } + } + if (noMin && noMax) { + max = 1; + noMax = false; + } + min = +min || 0; + if (noMax) { + max = min; + min = 0; + } else { + max = +max || 0; + } + if (floating || min % 1 || max % 1) { + var rand = nativeRandom(); + return nativeMin(min + rand * (max - min + parseFloat("1e-" + ((rand + "").length - 1))), max); + } + return baseRandom(min, max); + } + var camelCase = createCompounder(function(result, word, index) { + word = word.toLowerCase(); + return result + (index ? word.charAt(0).toUpperCase() + word.slice(1) : word); + }); + function capitalize(string) { + string = baseToString(string); + return string && string.charAt(0).toUpperCase() + string.slice(1); + } + function deburr(string) { + string = baseToString(string); + return string && string.replace(reLatin1, deburrLetter).replace(reComboMark, ""); + } + function endsWith(string, target, position) { + string = baseToString(string); + target = target + ""; + var length = string.length; + position = position === undefined ? length : nativeMin(position < 0 ? 0 : +position || 0, length); + position -= target.length; + return position >= 0 && string.indexOf(target, position) == position; + } + function escape(string) { + string = baseToString(string); + return string && reHasUnescapedHtml.test(string) ? string.replace(reUnescapedHtml, escapeHtmlChar) : string; + } + function escapeRegExp(string) { + string = baseToString(string); + return string && reHasRegExpChars.test(string) ? string.replace(reRegExpChars, escapeRegExpChar) : string || "(?:)"; + } + var kebabCase = createCompounder(function(result, word, index) { + return result + (index ? "-" : "") + word.toLowerCase(); + }); + function pad(string, length, chars) { + string = baseToString(string); + length = +length; + var strLength = string.length; + if (strLength >= length || !nativeIsFinite(length)) { + return string; + } + var mid = (length - strLength) / 2, leftLength = nativeFloor(mid), rightLength = nativeCeil(mid); + chars = createPadding("", rightLength, chars); + return chars.slice(0, leftLength) + string + chars; + } + var padLeft = createPadDir(); + var padRight = createPadDir(true); + function parseInt(string, radix, guard) { + if (guard ? isIterateeCall(string, radix, guard) : radix == null) { + radix = 0; + } else if (radix) { + radix = +radix; + } + string = trim(string); + return nativeParseInt(string, radix || (reHasHexPrefix.test(string) ? 16 : 10)); + } + function repeat(string, n) { + var result = ""; + string = baseToString(string); + n = +n; + if (n < 1 || !string || !nativeIsFinite(n)) { + return result; + } + do { + if (n % 2) { + result += string; + } + n = nativeFloor(n / 2); + string += string; + } while (n); + return result; + } + var snakeCase = createCompounder(function(result, word, index) { + return result + (index ? "_" : "") + word.toLowerCase(); + }); + var startCase = createCompounder(function(result, word, index) { + return result + (index ? " " : "") + (word.charAt(0).toUpperCase() + word.slice(1)); + }); + function startsWith(string, target, position) { + string = baseToString(string); + position = position == null ? 0 : nativeMin(position < 0 ? 0 : +position || 0, string.length); + return string.lastIndexOf(target, position) == position; + } + function template(string, options, otherOptions) { + var settings = lodash.templateSettings; + if (otherOptions && isIterateeCall(string, options, otherOptions)) { + options = otherOptions = undefined; + } + string = baseToString(string); + options = assignWith(baseAssign({}, otherOptions || options), settings, assignOwnDefaults); + var imports = assignWith(baseAssign({}, options.imports), settings.imports, assignOwnDefaults), importsKeys = keys(imports), importsValues = baseValues(imports, importsKeys); + var isEscaping, isEvaluating, index = 0, interpolate = options.interpolate || reNoMatch, source = "__p += '"; + var reDelimiters = RegExp((options.escape || reNoMatch).source + "|" + interpolate.source + "|" + (interpolate === reInterpolate ? reEsTemplate : reNoMatch).source + "|" + (options.evaluate || reNoMatch).source + "|$", "g"); + var sourceURL = "//# sourceURL=" + ("sourceURL" in options ? options.sourceURL : "lodash.templateSources[" + ++templateCounter + "]") + "\n"; + string.replace(reDelimiters, function(match, escapeValue, interpolateValue, esTemplateValue, evaluateValue, offset) { + interpolateValue || (interpolateValue = esTemplateValue); + source += string.slice(index, offset).replace(reUnescapedString, escapeStringChar); + if (escapeValue) { + isEscaping = true; + source += "' +\n__e(" + escapeValue + ") +\n'"; + } + if (evaluateValue) { + isEvaluating = true; + source += "';\n" + evaluateValue + ";\n__p += '"; + } + if (interpolateValue) { + source += "' +\n((__t = (" + interpolateValue + ")) == null ? '' : __t) +\n'"; + } + index = offset + match.length; + return match; + }); + source += "';\n"; + var variable = options.variable; + if (!variable) { + source = "with (obj) {\n" + source + "\n}\n"; + } + source = (isEvaluating ? source.replace(reEmptyStringLeading, "") : source).replace(reEmptyStringMiddle, "$1").replace(reEmptyStringTrailing, "$1;"); + source = "function(" + (variable || "obj") + ") {\n" + (variable ? "" : "obj || (obj = {});\n") + "var __t, __p = ''" + (isEscaping ? ", __e = _.escape" : "") + (isEvaluating ? ", __j = Array.prototype.join;\n" + "function print() { __p += __j.call(arguments, '') }\n" : ";\n") + source + "return __p\n}"; + var result = attempt(function() { + return Function(importsKeys, sourceURL + "return " + source).apply(undefined, importsValues); + }); + result.source = source; + if (isError(result)) { + throw result; + } + return result; + } + function trim(string, chars, guard) { + var value = string; + string = baseToString(string); + if (!string) { + return string; + } + if (guard ? isIterateeCall(value, chars, guard) : chars == null) { + return string.slice(trimmedLeftIndex(string), trimmedRightIndex(string) + 1); + } + chars = chars + ""; + return string.slice(charsLeftIndex(string, chars), charsRightIndex(string, chars) + 1); + } + function trimLeft(string, chars, guard) { + var value = string; + string = baseToString(string); + if (!string) { + return string; + } + if (guard ? isIterateeCall(value, chars, guard) : chars == null) { + return string.slice(trimmedLeftIndex(string)); + } + return string.slice(charsLeftIndex(string, chars + "")); + } + function trimRight(string, chars, guard) { + var value = string; + string = baseToString(string); + if (!string) { + return string; + } + if (guard ? isIterateeCall(value, chars, guard) : chars == null) { + return string.slice(0, trimmedRightIndex(string) + 1); + } + return string.slice(0, charsRightIndex(string, chars + "") + 1); + } + function trunc(string, options, guard) { + if (guard && isIterateeCall(string, options, guard)) { + options = undefined; + } + var length = DEFAULT_TRUNC_LENGTH, omission = DEFAULT_TRUNC_OMISSION; + if (options != null) { + if (isObject(options)) { + var separator = "separator" in options ? options.separator : separator; + length = "length" in options ? +options.length || 0 : length; + omission = "omission" in options ? baseToString(options.omission) : omission; + } else { + length = +options || 0; + } + } + string = baseToString(string); + if (length >= string.length) { + return string; + } + var end = length - omission.length; + if (end < 1) { + return omission; + } + var result = string.slice(0, end); + if (separator == null) { + return result + omission; + } + if (isRegExp(separator)) { + if (string.slice(end).search(separator)) { + var match, newEnd, substring = string.slice(0, end); + if (!separator.global) { + separator = RegExp(separator.source, (reFlags.exec(separator) || "") + "g"); + } + separator.lastIndex = 0; + while (match = separator.exec(substring)) { + newEnd = match.index; + } + result = result.slice(0, newEnd == null ? end : newEnd); + } + } else if (string.indexOf(separator, end) != end) { + var index = result.lastIndexOf(separator); + if (index > -1) { + result = result.slice(0, index); + } + } + return result + omission; + } + function unescape(string) { + string = baseToString(string); + return string && reHasEscapedHtml.test(string) ? string.replace(reEscapedHtml, unescapeHtmlChar) : string; + } + function words(string, pattern, guard) { + if (guard && isIterateeCall(string, pattern, guard)) { + pattern = undefined; + } + string = baseToString(string); + return string.match(pattern || reWords) || []; + } + var attempt = restParam(function(func, args) { + try { + return func.apply(undefined, args); + } catch (e) { + return isError(e) ? e : new Error(e); + } + }); + function callback(func, thisArg, guard) { + if (guard && isIterateeCall(func, thisArg, guard)) { + thisArg = undefined; + } + return isObjectLike(func) ? matches(func) : baseCallback(func, thisArg); + } + function constant(value) { + return function() { + return value; + }; + } + function identity(value) { + return value; + } + function matches(source) { + return baseMatches(baseClone(source, true)); + } + function matchesProperty(path, srcValue) { + return baseMatchesProperty(path, baseClone(srcValue, true)); + } + var method = restParam(function(path, args) { + return function(object) { + return invokePath(object, path, args); + }; + }); + var methodOf = restParam(function(object, args) { + return function(path) { + return invokePath(object, path, args); + }; + }); + function mixin(object, source, options) { + if (options == null) { + var isObj = isObject(source), props = isObj ? keys(source) : undefined, methodNames = props && props.length ? baseFunctions(source, props) : undefined; + if (!(methodNames ? methodNames.length : isObj)) { + methodNames = false; + options = source; + source = object; + object = this; + } + } + if (!methodNames) { + methodNames = baseFunctions(source, keys(source)); + } + var chain = true, index = -1, isFunc = isFunction(object), length = methodNames.length; + if (options === false) { + chain = false; + } else if (isObject(options) && "chain" in options) { + chain = options.chain; + } + while (++index < length) { + var methodName = methodNames[index], func = source[methodName]; + object[methodName] = func; + if (isFunc) { + object.prototype[methodName] = function(func) { + return function() { + var chainAll = this.__chain__; + if (chain || chainAll) { + var result = object(this.__wrapped__), actions = result.__actions__ = arrayCopy(this.__actions__); + actions.push({ + func: func, + args: arguments, + thisArg: object + }); + result.__chain__ = chainAll; + return result; + } + return func.apply(object, arrayPush([ this.value() ], arguments)); + }; + }(func); + } + } + return object; + } + function noConflict() { + root._ = oldDash; + return this; + } + function noop() {} + function property(path) { + return isKey(path) ? baseProperty(path) : basePropertyDeep(path); + } + function propertyOf(object) { + return function(path) { + return baseGet(object, toPath(path), path + ""); + }; + } + function range(start, end, step) { + if (step && isIterateeCall(start, end, step)) { + end = step = undefined; + } + start = +start || 0; + step = step == null ? 1 : +step || 0; + if (end == null) { + end = start; + start = 0; + } else { + end = +end || 0; + } + var index = -1, length = nativeMax(nativeCeil((end - start) / (step || 1)), 0), result = Array(length); + while (++index < length) { + result[index] = start; + start += step; + } + return result; + } + function times(n, iteratee, thisArg) { + n = nativeFloor(n); + if (n < 1 || !nativeIsFinite(n)) { + return []; + } + var index = -1, result = Array(nativeMin(n, MAX_ARRAY_LENGTH)); + iteratee = bindCallback(iteratee, thisArg, 1); + while (++index < n) { + if (index < MAX_ARRAY_LENGTH) { + result[index] = iteratee(index); + } else { + iteratee(index); + } + } + return result; + } + function uniqueId(prefix) { + var id = ++idCounter; + return baseToString(prefix) + id; + } + function add(augend, addend) { + return (+augend || 0) + (+addend || 0); + } + var ceil = createRound("ceil"); + var floor = createRound("floor"); + var max = createExtremum(gt, NEGATIVE_INFINITY); + var min = createExtremum(lt, POSITIVE_INFINITY); + var round = createRound("round"); + function sum(collection, iteratee, thisArg) { + if (thisArg && isIterateeCall(collection, iteratee, thisArg)) { + iteratee = undefined; + } + iteratee = getCallback(iteratee, thisArg, 3); + return iteratee.length == 1 ? arraySum(isArray(collection) ? collection : toIterable(collection), iteratee) : baseSum(collection, iteratee); + } + lodash.prototype = baseLodash.prototype; + LodashWrapper.prototype = baseCreate(baseLodash.prototype); + LodashWrapper.prototype.constructor = LodashWrapper; + LazyWrapper.prototype = baseCreate(baseLodash.prototype); + LazyWrapper.prototype.constructor = LazyWrapper; + MapCache.prototype["delete"] = mapDelete; + MapCache.prototype.get = mapGet; + MapCache.prototype.has = mapHas; + MapCache.prototype.set = mapSet; + SetCache.prototype.push = cachePush; + memoize.Cache = MapCache; + lodash.after = after; + lodash.ary = ary; + lodash.assign = assign; + lodash.at = at; + lodash.before = before; + lodash.bind = bind; + lodash.bindAll = bindAll; + lodash.bindKey = bindKey; + lodash.callback = callback; + lodash.chain = chain; + lodash.chunk = chunk; + lodash.compact = compact; + lodash.constant = constant; + lodash.countBy = countBy; + lodash.create = create; + lodash.curry = curry; + lodash.curryRight = curryRight; + lodash.debounce = debounce; + lodash.defaults = defaults; + lodash.defaultsDeep = defaultsDeep; + lodash.defer = defer; + lodash.delay = delay; + lodash.difference = difference; + lodash.drop = drop; + lodash.dropRight = dropRight; + lodash.dropRightWhile = dropRightWhile; + lodash.dropWhile = dropWhile; + lodash.fill = fill; + lodash.filter = filter; + lodash.flatten = flatten; + lodash.flattenDeep = flattenDeep; + lodash.flow = flow; + lodash.flowRight = flowRight; + lodash.forEach = forEach; + lodash.forEachRight = forEachRight; + lodash.forIn = forIn; + lodash.forInRight = forInRight; + lodash.forOwn = forOwn; + lodash.forOwnRight = forOwnRight; + lodash.functions = functions; + lodash.groupBy = groupBy; + lodash.indexBy = indexBy; + lodash.initial = initial; + lodash.intersection = intersection; + lodash.invert = invert; + lodash.invoke = invoke; + lodash.keys = keys; + lodash.keysIn = keysIn; + lodash.map = map; + lodash.mapKeys = mapKeys; + lodash.mapValues = mapValues; + lodash.matches = matches; + lodash.matchesProperty = matchesProperty; + lodash.memoize = memoize; + lodash.merge = merge; + lodash.method = method; + lodash.methodOf = methodOf; + lodash.mixin = mixin; + lodash.modArgs = modArgs; + lodash.negate = negate; + lodash.omit = omit; + lodash.once = once; + lodash.pairs = pairs; + lodash.partial = partial; + lodash.partialRight = partialRight; + lodash.partition = partition; + lodash.pick = pick; + lodash.pluck = pluck; + lodash.property = property; + lodash.propertyOf = propertyOf; + lodash.pull = pull; + lodash.pullAt = pullAt; + lodash.range = range; + lodash.rearg = rearg; + lodash.reject = reject; + lodash.remove = remove; + lodash.rest = rest; + lodash.restParam = restParam; + lodash.set = set; + lodash.shuffle = shuffle; + lodash.slice = slice; + lodash.sortBy = sortBy; + lodash.sortByAll = sortByAll; + lodash.sortByOrder = sortByOrder; + lodash.spread = spread; + lodash.take = take; + lodash.takeRight = takeRight; + lodash.takeRightWhile = takeRightWhile; + lodash.takeWhile = takeWhile; + lodash.tap = tap; + lodash.throttle = throttle; + lodash.thru = thru; + lodash.times = times; + lodash.toArray = toArray; + lodash.toPlainObject = toPlainObject; + lodash.transform = transform; + lodash.union = union; + lodash.uniq = uniq; + lodash.unzip = unzip; + lodash.unzipWith = unzipWith; + lodash.values = values; + lodash.valuesIn = valuesIn; + lodash.where = where; + lodash.without = without; + lodash.wrap = wrap; + lodash.xor = xor; + lodash.zip = zip; + lodash.zipObject = zipObject; + lodash.zipWith = zipWith; + lodash.backflow = flowRight; + lodash.collect = map; + lodash.compose = flowRight; + lodash.each = forEach; + lodash.eachRight = forEachRight; + lodash.extend = assign; + lodash.iteratee = callback; + lodash.methods = functions; + lodash.object = zipObject; + lodash.select = filter; + lodash.tail = rest; + lodash.unique = uniq; + mixin(lodash, lodash); + lodash.add = add; + lodash.attempt = attempt; + lodash.camelCase = camelCase; + lodash.capitalize = capitalize; + lodash.ceil = ceil; + lodash.clone = clone; + lodash.cloneDeep = cloneDeep; + lodash.deburr = deburr; + lodash.endsWith = endsWith; + lodash.escape = escape; + lodash.escapeRegExp = escapeRegExp; + lodash.every = every; + lodash.find = find; + lodash.findIndex = findIndex; + lodash.findKey = findKey; + lodash.findLast = findLast; + lodash.findLastIndex = findLastIndex; + lodash.findLastKey = findLastKey; + lodash.findWhere = findWhere; + lodash.first = first; + lodash.floor = floor; + lodash.get = get; + lodash.gt = gt; + lodash.gte = gte; + lodash.has = has; + lodash.identity = identity; + lodash.includes = includes; + lodash.indexOf = indexOf; + lodash.inRange = inRange; + lodash.isArguments = isArguments; + lodash.isArray = isArray; + lodash.isBoolean = isBoolean; + lodash.isDate = isDate; + lodash.isElement = isElement; + lodash.isEmpty = isEmpty; + lodash.isEqual = isEqual; + lodash.isError = isError; + lodash.isFinite = isFinite; + lodash.isFunction = isFunction; + lodash.isMatch = isMatch; + lodash.isNaN = isNaN; + lodash.isNative = isNative; + lodash.isNull = isNull; + lodash.isNumber = isNumber; + lodash.isObject = isObject; + lodash.isPlainObject = isPlainObject; + lodash.isRegExp = isRegExp; + lodash.isString = isString; + lodash.isTypedArray = isTypedArray; + lodash.isUndefined = isUndefined; + lodash.kebabCase = kebabCase; + lodash.last = last; + lodash.lastIndexOf = lastIndexOf; + lodash.lt = lt; + lodash.lte = lte; + lodash.max = max; + lodash.min = min; + lodash.noConflict = noConflict; + lodash.noop = noop; + lodash.now = now; + lodash.pad = pad; + lodash.padLeft = padLeft; + lodash.padRight = padRight; + lodash.parseInt = parseInt; + lodash.random = random; + lodash.reduce = reduce; + lodash.reduceRight = reduceRight; + lodash.repeat = repeat; + lodash.result = result; + lodash.round = round; + lodash.runInContext = runInContext; + lodash.size = size; + lodash.snakeCase = snakeCase; + lodash.some = some; + lodash.sortedIndex = sortedIndex; + lodash.sortedLastIndex = sortedLastIndex; + lodash.startCase = startCase; + lodash.startsWith = startsWith; + lodash.sum = sum; + lodash.template = template; + lodash.trim = trim; + lodash.trimLeft = trimLeft; + lodash.trimRight = trimRight; + lodash.trunc = trunc; + lodash.unescape = unescape; + lodash.uniqueId = uniqueId; + lodash.words = words; + lodash.all = every; + lodash.any = some; + lodash.contains = includes; + lodash.eq = isEqual; + lodash.detect = find; + lodash.foldl = reduce; + lodash.foldr = reduceRight; + lodash.head = first; + lodash.include = includes; + lodash.inject = reduce; + mixin(lodash, function() { + var source = {}; + baseForOwn(lodash, function(func, methodName) { + if (!lodash.prototype[methodName]) { + source[methodName] = func; + } + }); + return source; + }(), false); + lodash.sample = sample; + lodash.prototype.sample = function(n) { + if (!this.__chain__ && n == null) { + return sample(this.value()); + } + return this.thru(function(value) { + return sample(value, n); + }); + }; + lodash.VERSION = VERSION; + arrayEach([ "bind", "bindKey", "curry", "curryRight", "partial", "partialRight" ], function(methodName) { + lodash[methodName].placeholder = lodash; + }); + arrayEach([ "drop", "take" ], function(methodName, index) { + LazyWrapper.prototype[methodName] = function(n) { + var filtered = this.__filtered__; + if (filtered && !index) { + return new LazyWrapper(this); + } + n = n == null ? 1 : nativeMax(nativeFloor(n) || 0, 0); + var result = this.clone(); + if (filtered) { + result.__takeCount__ = nativeMin(result.__takeCount__, n); + } else { + result.__views__.push({ + size: n, + type: methodName + (result.__dir__ < 0 ? "Right" : "") + }); + } + return result; + }; + LazyWrapper.prototype[methodName + "Right"] = function(n) { + return this.reverse()[methodName](n).reverse(); + }; + }); + arrayEach([ "filter", "map", "takeWhile" ], function(methodName, index) { + var type = index + 1, isFilter = type != LAZY_MAP_FLAG; + LazyWrapper.prototype[methodName] = function(iteratee, thisArg) { + var result = this.clone(); + result.__iteratees__.push({ + iteratee: getCallback(iteratee, thisArg, 1), + type: type + }); + result.__filtered__ = result.__filtered__ || isFilter; + return result; + }; + }); + arrayEach([ "first", "last" ], function(methodName, index) { + var takeName = "take" + (index ? "Right" : ""); + LazyWrapper.prototype[methodName] = function() { + return this[takeName](1).value()[0]; + }; + }); + arrayEach([ "initial", "rest" ], function(methodName, index) { + var dropName = "drop" + (index ? "" : "Right"); + LazyWrapper.prototype[methodName] = function() { + return this.__filtered__ ? new LazyWrapper(this) : this[dropName](1); + }; + }); + arrayEach([ "pluck", "where" ], function(methodName, index) { + var operationName = index ? "filter" : "map", createCallback = index ? baseMatches : property; + LazyWrapper.prototype[methodName] = function(value) { + return this[operationName](createCallback(value)); + }; + }); + LazyWrapper.prototype.compact = function() { + return this.filter(identity); + }; + LazyWrapper.prototype.reject = function(predicate, thisArg) { + predicate = getCallback(predicate, thisArg, 1); + return this.filter(function(value) { + return !predicate(value); + }); + }; + LazyWrapper.prototype.slice = function(start, end) { + start = start == null ? 0 : +start || 0; + var result = this; + if (result.__filtered__ && (start > 0 || end < 0)) { + return new LazyWrapper(result); + } + if (start < 0) { + result = result.takeRight(-start); + } else if (start) { + result = result.drop(start); + } + if (end !== undefined) { + end = +end || 0; + result = end < 0 ? result.dropRight(-end) : result.take(end - start); + } + return result; + }; + LazyWrapper.prototype.takeRightWhile = function(predicate, thisArg) { + return this.reverse().takeWhile(predicate, thisArg).reverse(); + }; + LazyWrapper.prototype.toArray = function() { + return this.take(POSITIVE_INFINITY); + }; + baseForOwn(LazyWrapper.prototype, function(func, methodName) { + var checkIteratee = /^(?:filter|map|reject)|While$/.test(methodName), retUnwrapped = /^(?:first|last)$/.test(methodName), lodashFunc = lodash[retUnwrapped ? "take" + (methodName == "last" ? "Right" : "") : methodName]; + if (!lodashFunc) { + return; + } + lodash.prototype[methodName] = function() { + var args = retUnwrapped ? [ 1 ] : arguments, chainAll = this.__chain__, value = this.__wrapped__, isHybrid = !!this.__actions__.length, isLazy = value instanceof LazyWrapper, iteratee = args[0], useLazy = isLazy || isArray(value); + if (useLazy && checkIteratee && typeof iteratee == "function" && iteratee.length != 1) { + isLazy = useLazy = false; + } + var interceptor = function(value) { + return retUnwrapped && chainAll ? lodashFunc(value, 1)[0] : lodashFunc.apply(undefined, arrayPush([ value ], args)); + }; + var action = { + func: thru, + args: [ interceptor ], + thisArg: undefined + }, onlyLazy = isLazy && !isHybrid; + if (retUnwrapped && !chainAll) { + if (onlyLazy) { + value = value.clone(); + value.__actions__.push(action); + return func.call(value); + } + return lodashFunc.call(undefined, this.value())[0]; + } + if (!retUnwrapped && useLazy) { + value = onlyLazy ? value : new LazyWrapper(this); + var result = func.apply(value, args); + result.__actions__.push(action); + return new LodashWrapper(result, chainAll); + } + return this.thru(interceptor); + }; + }); + arrayEach([ "join", "pop", "push", "replace", "shift", "sort", "splice", "split", "unshift" ], function(methodName) { + var func = (/^(?:replace|split)$/.test(methodName) ? stringProto : arrayProto)[methodName], chainName = /^(?:push|sort|unshift)$/.test(methodName) ? "tap" : "thru", retUnwrapped = /^(?:join|pop|replace|shift)$/.test(methodName); + lodash.prototype[methodName] = function() { + var args = arguments; + if (retUnwrapped && !this.__chain__) { + return func.apply(this.value(), args); + } + return this[chainName](function(value) { + return func.apply(value, args); + }); + }; + }); + baseForOwn(LazyWrapper.prototype, function(func, methodName) { + var lodashFunc = lodash[methodName]; + if (lodashFunc) { + var key = lodashFunc.name + "", names = realNames[key] || (realNames[key] = []); + names.push({ + name: methodName, + func: lodashFunc + }); + } + }); + realNames[createHybridWrapper(undefined, BIND_KEY_FLAG).name] = [ { + name: "wrapper", + func: undefined + } ]; + LazyWrapper.prototype.clone = lazyClone; + LazyWrapper.prototype.reverse = lazyReverse; + LazyWrapper.prototype.value = lazyValue; + lodash.prototype.chain = wrapperChain; + lodash.prototype.commit = wrapperCommit; + lodash.prototype.concat = wrapperConcat; + lodash.prototype.plant = wrapperPlant; + lodash.prototype.reverse = wrapperReverse; + lodash.prototype.toString = wrapperToString; + lodash.prototype.run = lodash.prototype.toJSON = lodash.prototype.valueOf = lodash.prototype.value = wrapperValue; + lodash.prototype.collect = lodash.prototype.map; + lodash.prototype.head = lodash.prototype.first; + lodash.prototype.select = lodash.prototype.filter; + lodash.prototype.tail = lodash.prototype.rest; + return lodash; + } + var _ = runInContext(); + if (typeof define == "function" && typeof define.amd == "object" && define.amd) { + root._ = _; + define(function() { + return _; + }); + } else if (freeExports && freeModule) { + if (moduleExports) { + (freeModule.exports = _)._ = _; + } else { + freeExports._ = _; + } + } else { + root._ = _; + } +}).call(this); + (function(window, document, undefined) { "use strict"; function minErr(module, ErrorConstructor) { @@ -5391,7 +9332,7 @@ } return match; }); - message += "\nhttp://errors.angularjs.org/1.4.6/" + (module ? module + "/" : "") + code; + message += "\nhttp://errors.angularjs.org/1.4.7/" + (module ? module + "/" : "") + code; for (i = SKIP_INDEXES, paramPrefix = "?"; i < templateArgs.length; i++, paramPrefix = "&") { message += paramPrefix + "p" + (i - SKIP_INDEXES) + "=" + encodeURIComponent(toDebugString(templateArgs[i])); } @@ -6210,11 +10151,11 @@ return obj; } var version = { - full: "1.4.6", + full: "1.4.7", major: 1, minor: 4, - dot: 6, - codeName: "multiplicative-elevation" + dot: 7, + codeName: "dark-luminescence" }; function publishExternalAPI(angular) { extend(angular, { @@ -6323,6 +10264,7 @@ $httpParamSerializer: $HttpParamSerializerProvider, $httpParamSerializerJQLike: $HttpParamSerializerJQLikeProvider, $httpBackend: $HttpBackendProvider, + $xhrFactory: $xhrFactoryProvider, $location: $LocationProvider, $log: $LogProvider, $parse: $ParseProvider, @@ -6368,10 +10310,10 @@ return offset ? letter.toUpperCase() : letter; }).replace(MOZ_HACK_REGEXP, "Moz$1"); } - var SINGLE_TAG_REGEXP = /^<(\w+)\s*\/?>(?:<\/\1>|)$/; + var SINGLE_TAG_REGEXP = /^<([\w-]+)\s*\/?>(?:<\/\1>|)$/; var HTML_REGEXP = /<|&#?\w+;/; - var TAG_NAME_REGEXP = /<([\w:]+)/; - var XHTML_TAG_REGEXP = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi; + var TAG_NAME_REGEXP = /<([\w:-]+)/; + var XHTML_TAG_REGEXP = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:-]+)[^>]*)\/>/gi; var wrapMap = { option: [ 1, '" ], thead: [ 1, "", "
        " ], @@ -7614,6 +11556,9 @@ } }; return function(element, options) { + if (options.cleanupStyles) { + options.from = options.to = null; + } if (options.from) { element.css(options.from); options.from = null; @@ -8879,7 +12824,7 @@ compile: function() { return { pre: function attrInterpolatePreLinkFn(scope, element, attr) { - var $$observers = attr.$$observers || (attr.$$observers = {}); + var $$observers = attr.$$observers || (attr.$$observers = createMap()); if (EVENT_HANDLER_ATTR_REGEXP.test(name)) { throw $compileMinErr("nodomevents", "Interpolations for HTML DOM event attributes are disallowed. Please use the " + "ng- versions (such as ng-click instead of onclick) instead."); } @@ -9542,12 +13487,16 @@ } } ]; } - function createXhr() { - return new window.XMLHttpRequest(); + function $xhrFactoryProvider() { + this.$get = function() { + return function createXhr() { + return new window.XMLHttpRequest(); + }; + }; } function $HttpBackendProvider() { - this.$get = [ "$browser", "$window", "$document", function($browser, $window, $document) { - return createHttpBackend($browser, createXhr, $browser.defer, $window.angular.callbacks, $document[0]); + this.$get = [ "$browser", "$window", "$document", "$xhrFactory", function($browser, $window, $document, $xhrFactory) { + return createHttpBackend($browser, $xhrFactory, $browser.defer, $window.angular.callbacks, $document[0]); } ]; } function createHttpBackend($browser, createXhr, $browserDefer, callbacks, rawDocument) { @@ -9565,7 +13514,7 @@ callbacks[callbackId] = noop; }); } else { - var xhr = createXhr(); + var xhr = createXhr(method, url); xhr.open(method, url, true); forEach(headers, function(value, key) { if (isDefined(value)) { @@ -10273,12 +14222,18 @@ } var $parseMinErr = minErr("$parse"); function ensureSafeMemberName(name, fullExpression) { - name = isObject(name) && name.toString ? name.toString() : name; if (name === "__defineGetter__" || name === "__defineSetter__" || name === "__lookupGetter__" || name === "__lookupSetter__" || name === "__proto__") { throw $parseMinErr("isecfld", "Attempting to access a disallowed field in Angular expressions! " + "Expression: {0}", fullExpression); } return name; } + function getStringValue(name, fullExpression) { + name = name + ""; + if (!isString(name)) { + throw $parseMinErr("iseccst", "Cannot convert object to primitive value! " + "Expression: {0}", fullExpression); + } + return name; + } function ensureSafeObject(obj, fullExpression) { if (obj) { if (obj.constructor === obj) { @@ -10305,6 +14260,13 @@ } } } + function ensureSafeAssignContext(obj, fullExpression) { + if (obj) { + if (obj === 0..constructor || obj === false.constructor || obj === "".constructor || obj === {}.constructor || obj === [].constructor || obj === Function.constructor) { + throw $parseMinErr("isecaf", "Assigning to a constructor is disallowed! Expression: {0}", fullExpression); + } + } + } var OPERATORS = createMap(); forEach("+ - * / % === !== == != < > <= >= && || ! = |".split(" "), function(operator) { OPERATORS[operator] = true; @@ -11053,7 +15015,7 @@ this.stage = "main"; this.recurse(ast); var fnString = '"' + this.USE + " " + this.STRICT + '";\n' + this.filterPrefix() + "var fn=" + this.generateFunction("fn", "s,l,a,i") + extra + this.watchFns() + "return fn;"; - var fn = new Function("$filter", "ensureSafeMemberName", "ensureSafeObject", "ensureSafeFunction", "ifDefined", "plus", "text", fnString)(this.$filter, ensureSafeMemberName, ensureSafeObject, ensureSafeFunction, ifDefined, plusFn, expression); + var fn = new Function("$filter", "ensureSafeMemberName", "ensureSafeObject", "ensureSafeFunction", "getStringValue", "ensureSafeAssignContext", "ifDefined", "plus", "text", fnString)(this.$filter, ensureSafeMemberName, ensureSafeObject, ensureSafeFunction, getStringValue, ensureSafeAssignContext, ifDefined, plusFn, expression); this.state = this.stage = undefined; fn.literal = isLiteral(ast); fn.constant = isConstant(ast); @@ -11190,6 +15152,7 @@ if (ast.computed) { right = self.nextId(); self.recurse(ast.property, right); + self.getStringValue(right); self.addEnsureSafeMemberName(right); if (create && create !== 1) { self.if_(self.not(self.computedMember(left, right)), self.lazyAssign(self.computedMember(left, right), "{}")); @@ -11275,6 +15238,7 @@ self.if_(self.notNull(left.context), function() { self.recurse(ast.right, right); self.addEnsureSafeObject(self.member(left.context, left.name, left.computed)); + self.addEnsureSafeAssignContext(left.context); expression = self.member(left.context, left.name, left.computed) + ast.operator + right; self.assign(intoId, expression); recursionFn(intoId || expression); @@ -11385,6 +15349,9 @@ addEnsureSafeFunction: function(item) { this.current().body.push(this.ensureSafeFunction(item), ";"); }, + addEnsureSafeAssignContext: function(item) { + this.current().body.push(this.ensureSafeAssignContext(item), ";"); + }, ensureSafeObject: function(item) { return "ensureSafeObject(" + item + ",text)"; }, @@ -11394,6 +15361,12 @@ ensureSafeFunction: function(item) { return "ensureSafeFunction(" + item + ",text)"; }, + getStringValue: function(item) { + this.assign(item, "getStringValue(" + item + ",text)"); + }, + ensureSafeAssignContext: function(item) { + return "ensureSafeAssignContext(" + item + ",text)"; + }, lazyRecurse: function(ast, intoId, nameId, recursionFn, create, skipWatchIdCheck) { var self = this; return function() { @@ -11561,6 +15534,7 @@ var lhs = left(scope, locals, assign, inputs); var rhs = right(scope, locals, assign, inputs); ensureSafeObject(lhs.value, self.expression); + ensureSafeAssignContext(lhs.context); lhs.context[lhs.name] = rhs; return context ? { value: rhs @@ -11818,6 +15792,7 @@ var value; if (lhs != null) { rhs = right(scope, locals, assign, inputs); + rhs = getStringValue(rhs); ensureSafeMemberName(rhs, expression); if (create && create !== 1 && lhs && !lhs[rhs]) { lhs[rhs] = {}; @@ -13500,6 +17475,7 @@ if (fractionSize > 0 && number < 1) { formatedText = number.toFixed(fractionSize); number = parseFloat(formatedText); + formatedText = formatedText.replace(DECIMAL_SEP, decimalSep); } } if (number === 0) { @@ -15517,11 +19493,11 @@ function updateOptionElement(option, element) { option.element = element; element.disabled = option.disabled; - if (option.value !== element.value) element.value = option.selectValue; if (option.label !== element.label) { element.label = option.label; element.textContent = option.label; } + if (option.value !== element.value) element.value = option.selectValue; } function addOrReuseElement(parent, current, type, templateElement) { var element; @@ -15549,7 +19525,7 @@ var emptyOption_ = emptyOption && emptyOption[0]; var unknownOption_ = unknownOption && unknownOption[0]; if (emptyOption_ || unknownOption_) { - while (current && (current === emptyOption_ || current === unknownOption_)) { + while (current && (current === emptyOption_ || current === unknownOption_ || emptyOption_ && emptyOption_.nodeType === NODE_TYPE_COMMENT)) { current = current.nextSibling; } } @@ -26461,8 +30437,33 @@ function responseHandler($timeout, $modal) { function error(message) { show("error", message, 5e3); } + function yesno(status, message, callback) { + var controller = function($scope, $modalInstance) { + $scope.status = status; + $scope.message = message; + $scope.yes = function() { + $modalInstance.close(true); + }; + $scope.no = function() { + $modalInstance.close(false); + }; + }; + $modal.open({ + animation: true, + templateUrl: "responseHandlerYesNoModal.html", + controller: controller, + size: "lg", + backdrop: "static", + keyboard: false + }).result.then(function(result) { + callback(result); + }, function() { + callback(false); + }); + } return { success: success, - error: error + error: error, + yesno: yesno }; } \ No newline at end of file diff --git a/lingvodoc/static/js/lingvodoc.js b/lingvodoc/static/js/maps.js similarity index 81% rename from lingvodoc/static/js/lingvodoc.js rename to lingvodoc/static/js/maps.js index a711dc566..d683fd6d3 100644 --- a/lingvodoc/static/js/lingvodoc.js +++ b/lingvodoc/static/js/maps.js @@ -5377,23901 +5377,24829 @@ return jQuery; }); -(function(window, document, undefined) { - "use strict"; - function minErr(module, ErrorConstructor) { - ErrorConstructor = ErrorConstructor || Error; - return function() { - var SKIP_INDEXES = 2; - var templateArgs = arguments, code = templateArgs[0], message = "[" + (module ? module + ":" : "") + code + "] ", template = templateArgs[1], paramPrefix, i; - message += template.replace(/\{\d+\}/g, function(match) { - var index = +match.slice(1, -1), shiftedIndex = index + SKIP_INDEXES; - if (shiftedIndex < templateArgs.length) { - return toDebugString(templateArgs[shiftedIndex]); - } - return match; - }); - message += "\nhttp://errors.angularjs.org/1.4.6/" + (module ? module + "/" : "") + code; - for (i = SKIP_INDEXES, paramPrefix = "?"; i < templateArgs.length; i++, paramPrefix = "&") { - message += paramPrefix + "p" + (i - SKIP_INDEXES) + "=" + encodeURIComponent(toDebugString(templateArgs[i])); +(function() { + var undefined; + var VERSION = "3.10.1"; + var BIND_FLAG = 1, BIND_KEY_FLAG = 2, CURRY_BOUND_FLAG = 4, CURRY_FLAG = 8, CURRY_RIGHT_FLAG = 16, PARTIAL_FLAG = 32, PARTIAL_RIGHT_FLAG = 64, ARY_FLAG = 128, REARG_FLAG = 256; + var DEFAULT_TRUNC_LENGTH = 30, DEFAULT_TRUNC_OMISSION = "..."; + var HOT_COUNT = 150, HOT_SPAN = 16; + var LARGE_ARRAY_SIZE = 200; + var LAZY_FILTER_FLAG = 1, LAZY_MAP_FLAG = 2; + var FUNC_ERROR_TEXT = "Expected a function"; + var PLACEHOLDER = "__lodash_placeholder__"; + var argsTag = "[object Arguments]", arrayTag = "[object Array]", boolTag = "[object Boolean]", dateTag = "[object Date]", errorTag = "[object Error]", funcTag = "[object Function]", mapTag = "[object Map]", numberTag = "[object Number]", objectTag = "[object Object]", regexpTag = "[object RegExp]", setTag = "[object Set]", stringTag = "[object String]", weakMapTag = "[object WeakMap]"; + var arrayBufferTag = "[object ArrayBuffer]", float32Tag = "[object Float32Array]", float64Tag = "[object Float64Array]", int8Tag = "[object Int8Array]", int16Tag = "[object Int16Array]", int32Tag = "[object Int32Array]", uint8Tag = "[object Uint8Array]", uint8ClampedTag = "[object Uint8ClampedArray]", uint16Tag = "[object Uint16Array]", uint32Tag = "[object Uint32Array]"; + var reEmptyStringLeading = /\b__p \+= '';/g, reEmptyStringMiddle = /\b(__p \+=) '' \+/g, reEmptyStringTrailing = /(__e\(.*?\)|\b__t\)) \+\n'';/g; + var reEscapedHtml = /&(?:amp|lt|gt|quot|#39|#96);/g, reUnescapedHtml = /[&<>"'`]/g, reHasEscapedHtml = RegExp(reEscapedHtml.source), reHasUnescapedHtml = RegExp(reUnescapedHtml.source); + var reEscape = /<%-([\s\S]+?)%>/g, reEvaluate = /<%([\s\S]+?)%>/g, reInterpolate = /<%=([\s\S]+?)%>/g; + var reIsDeepProp = /\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\n\\]|\\.)*?\1)\]/, reIsPlainProp = /^\w*$/, rePropName = /[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\n\\]|\\.)*?)\2)\]/g; + var reRegExpChars = /^[:!,]|[\\^$.*+?()[\]{}|\/]|(^[0-9a-fA-Fnrtuvx])|([\n\r\u2028\u2029])/g, reHasRegExpChars = RegExp(reRegExpChars.source); + var reComboMark = /[\u0300-\u036f\ufe20-\ufe23]/g; + var reEscapeChar = /\\(\\)?/g; + var reEsTemplate = /\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g; + var reFlags = /\w*$/; + var reHasHexPrefix = /^0[xX]/; + var reIsHostCtor = /^\[object .+?Constructor\]$/; + var reIsUint = /^\d+$/; + var reLatin1 = /[\xc0-\xd6\xd8-\xde\xdf-\xf6\xf8-\xff]/g; + var reNoMatch = /($^)/; + var reUnescapedString = /['\n\r\u2028\u2029\\]/g; + var reWords = function() { + var upper = "[A-Z\\xc0-\\xd6\\xd8-\\xde]", lower = "[a-z\\xdf-\\xf6\\xf8-\\xff]+"; + return RegExp(upper + "+(?=" + upper + lower + ")|" + upper + "?" + lower + "|" + upper + "+|[0-9]+", "g"); + }(); + var contextProps = [ "Array", "ArrayBuffer", "Date", "Error", "Float32Array", "Float64Array", "Function", "Int8Array", "Int16Array", "Int32Array", "Math", "Number", "Object", "RegExp", "Set", "String", "_", "clearTimeout", "isFinite", "parseFloat", "parseInt", "setTimeout", "TypeError", "Uint8Array", "Uint8ClampedArray", "Uint16Array", "Uint32Array", "WeakMap" ]; + var templateCounter = -1; + var typedArrayTags = {}; + typedArrayTags[float32Tag] = typedArrayTags[float64Tag] = typedArrayTags[int8Tag] = typedArrayTags[int16Tag] = typedArrayTags[int32Tag] = typedArrayTags[uint8Tag] = typedArrayTags[uint8ClampedTag] = typedArrayTags[uint16Tag] = typedArrayTags[uint32Tag] = true; + typedArrayTags[argsTag] = typedArrayTags[arrayTag] = typedArrayTags[arrayBufferTag] = typedArrayTags[boolTag] = typedArrayTags[dateTag] = typedArrayTags[errorTag] = typedArrayTags[funcTag] = typedArrayTags[mapTag] = typedArrayTags[numberTag] = typedArrayTags[objectTag] = typedArrayTags[regexpTag] = typedArrayTags[setTag] = typedArrayTags[stringTag] = typedArrayTags[weakMapTag] = false; + var cloneableTags = {}; + cloneableTags[argsTag] = cloneableTags[arrayTag] = cloneableTags[arrayBufferTag] = cloneableTags[boolTag] = cloneableTags[dateTag] = cloneableTags[float32Tag] = cloneableTags[float64Tag] = cloneableTags[int8Tag] = cloneableTags[int16Tag] = cloneableTags[int32Tag] = cloneableTags[numberTag] = cloneableTags[objectTag] = cloneableTags[regexpTag] = cloneableTags[stringTag] = cloneableTags[uint8Tag] = cloneableTags[uint8ClampedTag] = cloneableTags[uint16Tag] = cloneableTags[uint32Tag] = true; + cloneableTags[errorTag] = cloneableTags[funcTag] = cloneableTags[mapTag] = cloneableTags[setTag] = cloneableTags[weakMapTag] = false; + var deburredLetters = { + "À": "A", + "Á": "A", + "Â": "A", + "Ã": "A", + "Ä": "A", + "Å": "A", + "à": "a", + "á": "a", + "â": "a", + "ã": "a", + "ä": "a", + "å": "a", + "Ç": "C", + "ç": "c", + "Ð": "D", + "ð": "d", + "È": "E", + "É": "E", + "Ê": "E", + "Ë": "E", + "è": "e", + "é": "e", + "ê": "e", + "ë": "e", + "Ì": "I", + "Í": "I", + "Î": "I", + "Ï": "I", + "ì": "i", + "í": "i", + "î": "i", + "ï": "i", + "Ñ": "N", + "ñ": "n", + "Ò": "O", + "Ó": "O", + "Ô": "O", + "Õ": "O", + "Ö": "O", + "Ø": "O", + "ò": "o", + "ó": "o", + "ô": "o", + "õ": "o", + "ö": "o", + "ø": "o", + "Ù": "U", + "Ú": "U", + "Û": "U", + "Ü": "U", + "ù": "u", + "ú": "u", + "û": "u", + "ü": "u", + "Ý": "Y", + "ý": "y", + "ÿ": "y", + "Æ": "Ae", + "æ": "ae", + "Þ": "Th", + "þ": "th", + "ß": "ss" + }; + var htmlEscapes = { + "&": "&", + "<": "<", + ">": ">", + '"': """, + "'": "'", + "`": "`" + }; + var htmlUnescapes = { + "&": "&", + "<": "<", + ">": ">", + """: '"', + "'": "'", + "`": "`" + }; + var objectTypes = { + "function": true, + object: true + }; + var regexpEscapes = { + "0": "x30", + "1": "x31", + "2": "x32", + "3": "x33", + "4": "x34", + "5": "x35", + "6": "x36", + "7": "x37", + "8": "x38", + "9": "x39", + A: "x41", + B: "x42", + C: "x43", + D: "x44", + E: "x45", + F: "x46", + a: "x61", + b: "x62", + c: "x63", + d: "x64", + e: "x65", + f: "x66", + n: "x6e", + r: "x72", + t: "x74", + u: "x75", + v: "x76", + x: "x78" + }; + var stringEscapes = { + "\\": "\\", + "'": "'", + "\n": "n", + "\r": "r", + "\u2028": "u2028", + "\u2029": "u2029" + }; + var freeExports = objectTypes[typeof exports] && exports && !exports.nodeType && exports; + var freeModule = objectTypes[typeof module] && module && !module.nodeType && module; + var freeGlobal = freeExports && freeModule && typeof global == "object" && global && global.Object && global; + var freeSelf = objectTypes[typeof self] && self && self.Object && self; + var freeWindow = objectTypes[typeof window] && window && window.Object && window; + var moduleExports = freeModule && freeModule.exports === freeExports && freeExports; + var root = freeGlobal || freeWindow !== (this && this.window) && freeWindow || freeSelf || this; + function baseCompareAscending(value, other) { + if (value !== other) { + var valIsNull = value === null, valIsUndef = value === undefined, valIsReflexive = value === value; + var othIsNull = other === null, othIsUndef = other === undefined, othIsReflexive = other === other; + if (value > other && !othIsNull || !valIsReflexive || valIsNull && !othIsUndef && othIsReflexive || valIsUndef && othIsReflexive) { + return 1; + } + if (value < other && !valIsNull || !othIsReflexive || othIsNull && !valIsUndef && valIsReflexive || othIsUndef && valIsReflexive) { + return -1; + } + } + return 0; + } + function baseFindIndex(array, predicate, fromRight) { + var length = array.length, index = fromRight ? length : -1; + while (fromRight ? index-- : ++index < length) { + if (predicate(array[index], index, array)) { + return index; } - return new ErrorConstructor(message); - }; - } - var REGEX_STRING_REGEXP = /^\/(.+)\/([a-z]*)$/; - var VALIDITY_STATE_PROPERTY = "validity"; - var lowercase = function(string) { - return isString(string) ? string.toLowerCase() : string; - }; - var hasOwnProperty = Object.prototype.hasOwnProperty; - var uppercase = function(string) { - return isString(string) ? string.toUpperCase() : string; - }; - var manualLowercase = function(s) { - return isString(s) ? s.replace(/[A-Z]/g, function(ch) { - return String.fromCharCode(ch.charCodeAt(0) | 32); - }) : s; - }; - var manualUppercase = function(s) { - return isString(s) ? s.replace(/[a-z]/g, function(ch) { - return String.fromCharCode(ch.charCodeAt(0) & ~32); - }) : s; - }; - if ("i" !== "I".toLowerCase()) { - lowercase = manualLowercase; - uppercase = manualUppercase; - } - var msie, jqLite, jQuery, slice = [].slice, splice = [].splice, push = [].push, toString = Object.prototype.toString, getPrototypeOf = Object.getPrototypeOf, ngMinErr = minErr("ng"), angular = window.angular || (window.angular = {}), angularModule, uid = 0; - msie = document.documentMode; - function isArrayLike(obj) { - if (obj == null || isWindow(obj)) { - return false; } - var length = "length" in Object(obj) && obj.length; - if (obj.nodeType === NODE_TYPE_ELEMENT && length) { - return true; - } - return isString(obj) || isArray(obj) || length === 0 || typeof length === "number" && length > 0 && length - 1 in obj; + return -1; } - function forEach(obj, iterator, context) { - var key, length; - if (obj) { - if (isFunction(obj)) { - for (key in obj) { - if (key != "prototype" && key != "length" && key != "name" && (!obj.hasOwnProperty || obj.hasOwnProperty(key))) { - iterator.call(context, obj[key], key, obj); - } - } - } else if (isArray(obj) || isArrayLike(obj)) { - var isPrimitive = typeof obj !== "object"; - for (key = 0, length = obj.length; key < length; key++) { - if (isPrimitive || key in obj) { - iterator.call(context, obj[key], key, obj); - } - } - } else if (obj.forEach && obj.forEach !== forEach) { - obj.forEach(iterator, context, obj); - } else if (isBlankObject(obj)) { - for (key in obj) { - iterator.call(context, obj[key], key, obj); - } - } else if (typeof obj.hasOwnProperty === "function") { - for (key in obj) { - if (obj.hasOwnProperty(key)) { - iterator.call(context, obj[key], key, obj); - } - } - } else { - for (key in obj) { - if (hasOwnProperty.call(obj, key)) { - iterator.call(context, obj[key], key, obj); - } - } + function baseIndexOf(array, value, fromIndex) { + if (value !== value) { + return indexOfNaN(array, fromIndex); + } + var index = fromIndex - 1, length = array.length; + while (++index < length) { + if (array[index] === value) { + return index; } } - return obj; + return -1; } - function forEachSorted(obj, iterator, context) { - var keys = Object.keys(obj).sort(); - for (var i = 0; i < keys.length; i++) { - iterator.call(context, obj[keys[i]], keys[i]); - } - return keys; + function baseIsFunction(value) { + return typeof value == "function" || false; } - function reverseParams(iteratorFn) { - return function(value, key) { - iteratorFn(key, value); - }; + function baseToString(value) { + return value == null ? "" : value + ""; } - function nextUid() { - return ++uid; + function charsLeftIndex(string, chars) { + var index = -1, length = string.length; + while (++index < length && chars.indexOf(string.charAt(index)) > -1) {} + return index; } - function setHashKey(obj, h) { - if (h) { - obj.$$hashKey = h; - } else { - delete obj.$$hashKey; - } + function charsRightIndex(string, chars) { + var index = string.length; + while (index-- && chars.indexOf(string.charAt(index)) > -1) {} + return index; } - function baseExtend(dst, objs, deep) { - var h = dst.$$hashKey; - for (var i = 0, ii = objs.length; i < ii; ++i) { - var obj = objs[i]; - if (!isObject(obj) && !isFunction(obj)) continue; - var keys = Object.keys(obj); - for (var j = 0, jj = keys.length; j < jj; j++) { - var key = keys[j]; - var src = obj[key]; - if (deep && isObject(src)) { - if (isDate(src)) { - dst[key] = new Date(src.valueOf()); - } else if (isRegExp(src)) { - dst[key] = new RegExp(src); - } else { - if (!isObject(dst[key])) dst[key] = isArray(src) ? [] : {}; - baseExtend(dst[key], [ src ], true); - } - } else { - dst[key] = src; + function compareAscending(object, other) { + return baseCompareAscending(object.criteria, other.criteria) || object.index - other.index; + } + function compareMultiple(object, other, orders) { + var index = -1, objCriteria = object.criteria, othCriteria = other.criteria, length = objCriteria.length, ordersLength = orders.length; + while (++index < length) { + var result = baseCompareAscending(objCriteria[index], othCriteria[index]); + if (result) { + if (index >= ordersLength) { + return result; } + var order = orders[index]; + return result * (order === "asc" || order === true ? 1 : -1); } } - setHashKey(dst, h); - return dst; - } - function extend(dst) { - return baseExtend(dst, slice.call(arguments, 1), false); - } - function merge(dst) { - return baseExtend(dst, slice.call(arguments, 1), true); - } - function toInt(str) { - return parseInt(str, 10); - } - function inherit(parent, extra) { - return extend(Object.create(parent), extra); - } - function noop() {} - noop.$inject = []; - function identity($) { - return $; - } - identity.$inject = []; - function valueFn(value) { - return function() { - return value; - }; - } - function hasCustomToString(obj) { - return isFunction(obj.toString) && obj.toString !== Object.prototype.toString; - } - function isUndefined(value) { - return typeof value === "undefined"; - } - function isDefined(value) { - return typeof value !== "undefined"; - } - function isObject(value) { - return value !== null && typeof value === "object"; - } - function isBlankObject(value) { - return value !== null && typeof value === "object" && !getPrototypeOf(value); - } - function isString(value) { - return typeof value === "string"; - } - function isNumber(value) { - return typeof value === "number"; - } - function isDate(value) { - return toString.call(value) === "[object Date]"; - } - var isArray = Array.isArray; - function isFunction(value) { - return typeof value === "function"; - } - function isRegExp(value) { - return toString.call(value) === "[object RegExp]"; - } - function isWindow(obj) { - return obj && obj.window === obj; - } - function isScope(obj) { - return obj && obj.$evalAsync && obj.$watch; + return object.index - other.index; } - function isFile(obj) { - return toString.call(obj) === "[object File]"; + function deburrLetter(letter) { + return deburredLetters[letter]; } - function isFormData(obj) { - return toString.call(obj) === "[object FormData]"; + function escapeHtmlChar(chr) { + return htmlEscapes[chr]; } - function isBlob(obj) { - return toString.call(obj) === "[object Blob]"; + function escapeRegExpChar(chr, leadingChar, whitespaceChar) { + if (leadingChar) { + chr = regexpEscapes[chr]; + } else if (whitespaceChar) { + chr = stringEscapes[chr]; + } + return "\\" + chr; } - function isBoolean(value) { - return typeof value === "boolean"; + function escapeStringChar(chr) { + return "\\" + stringEscapes[chr]; } - function isPromiseLike(obj) { - return obj && isFunction(obj.then); + function indexOfNaN(array, fromIndex, fromRight) { + var length = array.length, index = fromIndex + (fromRight ? 0 : -1); + while (fromRight ? index-- : ++index < length) { + var other = array[index]; + if (other !== other) { + return index; + } + } + return -1; } - var TYPED_ARRAY_REGEXP = /^\[object (Uint8(Clamped)?)|(Uint16)|(Uint32)|(Int8)|(Int16)|(Int32)|(Float(32)|(64))Array\]$/; - function isTypedArray(value) { - return TYPED_ARRAY_REGEXP.test(toString.call(value)); + function isObjectLike(value) { + return !!value && typeof value == "object"; } - var trim = function(value) { - return isString(value) ? value.trim() : value; - }; - var escapeForRegexp = function(s) { - return s.replace(/([-()\[\]{}+?*.$\^|,:#= 9 && charCode <= 13) || charCode == 32 || charCode == 160 || charCode == 5760 || charCode == 6158 || charCode >= 8192 && (charCode <= 8202 || charCode == 8232 || charCode == 8233 || charCode == 8239 || charCode == 8287 || charCode == 12288 || charCode == 65279); } - function makeMap(str) { - var obj = {}, items = str.split(","), i; - for (i = 0; i < items.length; i++) { - obj[items[i]] = true; + function replaceHolders(array, placeholder) { + var index = -1, length = array.length, resIndex = -1, result = []; + while (++index < length) { + if (array[index] === placeholder) { + array[index] = PLACEHOLDER; + result[++resIndex] = index; + } } - return obj; + return result; } - function nodeName_(element) { - return lowercase(element.nodeName || element[0] && element[0].nodeName); + function sortedUniq(array, iteratee) { + var seen, index = -1, length = array.length, resIndex = -1, result = []; + while (++index < length) { + var value = array[index], computed = iteratee ? iteratee(value, index, array) : value; + if (!index || seen !== computed) { + seen = computed; + result[++resIndex] = value; + } + } + return result; } - function includes(array, obj) { - return Array.prototype.indexOf.call(array, obj) != -1; + function trimmedLeftIndex(string) { + var index = -1, length = string.length; + while (++index < length && isSpace(string.charCodeAt(index))) {} + return index; } - function arrayRemove(array, value) { - var index = array.indexOf(value); - if (index >= 0) { - array.splice(index, 1); - } + function trimmedRightIndex(string) { + var index = string.length; + while (index-- && isSpace(string.charCodeAt(index))) {} return index; } - function copy(source, destination, stackSource, stackDest) { - if (isWindow(source) || isScope(source)) { - throw ngMinErr("cpws", "Can't copy! Making copies of Window or Scope instances is not supported."); + function unescapeHtmlChar(chr) { + return htmlUnescapes[chr]; + } + function runInContext(context) { + context = context ? _.defaults(root.Object(), context, _.pick(root, contextProps)) : root; + var Array = context.Array, Date = context.Date, Error = context.Error, Function = context.Function, Math = context.Math, Number = context.Number, Object = context.Object, RegExp = context.RegExp, String = context.String, TypeError = context.TypeError; + var arrayProto = Array.prototype, objectProto = Object.prototype, stringProto = String.prototype; + var fnToString = Function.prototype.toString; + var hasOwnProperty = objectProto.hasOwnProperty; + var idCounter = 0; + var objToString = objectProto.toString; + var oldDash = root._; + var reIsNative = RegExp("^" + fnToString.call(hasOwnProperty).replace(/[\\^$.*+?()[\]{}|]/g, "\\$&").replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g, "$1.*?") + "$"); + var ArrayBuffer = context.ArrayBuffer, clearTimeout = context.clearTimeout, parseFloat = context.parseFloat, pow = Math.pow, propertyIsEnumerable = objectProto.propertyIsEnumerable, Set = getNative(context, "Set"), setTimeout = context.setTimeout, splice = arrayProto.splice, Uint8Array = context.Uint8Array, WeakMap = getNative(context, "WeakMap"); + var nativeCeil = Math.ceil, nativeCreate = getNative(Object, "create"), nativeFloor = Math.floor, nativeIsArray = getNative(Array, "isArray"), nativeIsFinite = context.isFinite, nativeKeys = getNative(Object, "keys"), nativeMax = Math.max, nativeMin = Math.min, nativeNow = getNative(Date, "now"), nativeParseInt = context.parseInt, nativeRandom = Math.random; + var NEGATIVE_INFINITY = Number.NEGATIVE_INFINITY, POSITIVE_INFINITY = Number.POSITIVE_INFINITY; + var MAX_ARRAY_LENGTH = 4294967295, MAX_ARRAY_INDEX = MAX_ARRAY_LENGTH - 1, HALF_MAX_ARRAY_LENGTH = MAX_ARRAY_LENGTH >>> 1; + var MAX_SAFE_INTEGER = 9007199254740991; + var metaMap = WeakMap && new WeakMap(); + var realNames = {}; + function lodash(value) { + if (isObjectLike(value) && !isArray(value) && !(value instanceof LazyWrapper)) { + if (value instanceof LodashWrapper) { + return value; + } + if (hasOwnProperty.call(value, "__chain__") && hasOwnProperty.call(value, "__wrapped__")) { + return wrapperClone(value); + } + } + return new LodashWrapper(value); + } + function baseLodash() {} + function LodashWrapper(value, chainAll, actions) { + this.__wrapped__ = value; + this.__actions__ = actions || []; + this.__chain__ = !!chainAll; + } + var support = lodash.support = {}; + lodash.templateSettings = { + escape: reEscape, + evaluate: reEvaluate, + interpolate: reInterpolate, + variable: "", + imports: { + _: lodash + } + }; + function LazyWrapper(value) { + this.__wrapped__ = value; + this.__actions__ = []; + this.__dir__ = 1; + this.__filtered__ = false; + this.__iteratees__ = []; + this.__takeCount__ = POSITIVE_INFINITY; + this.__views__ = []; + } + function lazyClone() { + var result = new LazyWrapper(this.__wrapped__); + result.__actions__ = arrayCopy(this.__actions__); + result.__dir__ = this.__dir__; + result.__filtered__ = this.__filtered__; + result.__iteratees__ = arrayCopy(this.__iteratees__); + result.__takeCount__ = this.__takeCount__; + result.__views__ = arrayCopy(this.__views__); + return result; } - if (isTypedArray(destination)) { - throw ngMinErr("cpta", "Can't copy! TypedArray destination cannot be mutated."); + function lazyReverse() { + if (this.__filtered__) { + var result = new LazyWrapper(this); + result.__dir__ = -1; + result.__filtered__ = true; + } else { + result = this.clone(); + result.__dir__ *= -1; + } + return result; } - if (!destination) { - destination = source; - if (isObject(source)) { - var index; - if (stackSource && (index = stackSource.indexOf(source)) !== -1) { - return stackDest[index]; + function lazyValue() { + var array = this.__wrapped__.value(), dir = this.__dir__, isArr = isArray(array), isRight = dir < 0, arrLength = isArr ? array.length : 0, view = getView(0, arrLength, this.__views__), start = view.start, end = view.end, length = end - start, index = isRight ? end : start - 1, iteratees = this.__iteratees__, iterLength = iteratees.length, resIndex = 0, takeCount = nativeMin(length, this.__takeCount__); + if (!isArr || arrLength < LARGE_ARRAY_SIZE || arrLength == length && takeCount == length) { + return baseWrapperValue(array, this.__actions__); + } + var result = []; + outer: while (length-- && resIndex < takeCount) { + index += dir; + var iterIndex = -1, value = array[index]; + while (++iterIndex < iterLength) { + var data = iteratees[iterIndex], iteratee = data.iteratee, type = data.type, computed = iteratee(value); + if (type == LAZY_MAP_FLAG) { + value = computed; + } else if (!computed) { + if (type == LAZY_FILTER_FLAG) { + continue outer; + } else { + break outer; + } + } } - if (isArray(source)) { - return copy(source, [], stackSource, stackDest); - } else if (isTypedArray(source)) { - destination = new source.constructor(source); - } else if (isDate(source)) { - destination = new Date(source.getTime()); - } else if (isRegExp(source)) { - destination = new RegExp(source.source, source.toString().match(/[^\/]*$/)[0]); - destination.lastIndex = source.lastIndex; - } else if (isFunction(source.cloneNode)) { - destination = source.cloneNode(true); - } else { - var emptyObject = Object.create(getPrototypeOf(source)); - return copy(source, emptyObject, stackSource, stackDest); + result[resIndex++] = value; + } + return result; + } + function MapCache() { + this.__data__ = {}; + } + function mapDelete(key) { + return this.has(key) && delete this.__data__[key]; + } + function mapGet(key) { + return key == "__proto__" ? undefined : this.__data__[key]; + } + function mapHas(key) { + return key != "__proto__" && hasOwnProperty.call(this.__data__, key); + } + function mapSet(key, value) { + if (key != "__proto__") { + this.__data__[key] = value; + } + return this; + } + function SetCache(values) { + var length = values ? values.length : 0; + this.data = { + hash: nativeCreate(null), + set: new Set() + }; + while (length--) { + this.push(values[length]); + } + } + function cacheIndexOf(cache, value) { + var data = cache.data, result = typeof value == "string" || isObject(value) ? data.set.has(value) : data.hash[value]; + return result ? 0 : -1; + } + function cachePush(value) { + var data = this.data; + if (typeof value == "string" || isObject(value)) { + data.set.add(value); + } else { + data.hash[value] = true; + } + } + function arrayConcat(array, other) { + var index = -1, length = array.length, othIndex = -1, othLength = other.length, result = Array(length + othLength); + while (++index < length) { + result[index] = array[index]; + } + while (++othIndex < othLength) { + result[index++] = other[othIndex]; + } + return result; + } + function arrayCopy(source, array) { + var index = -1, length = source.length; + array || (array = Array(length)); + while (++index < length) { + array[index] = source[index]; + } + return array; + } + function arrayEach(array, iteratee) { + var index = -1, length = array.length; + while (++index < length) { + if (iteratee(array[index], index, array) === false) { + break; } - if (stackDest) { - stackSource.push(source); - stackDest.push(destination); + } + return array; + } + function arrayEachRight(array, iteratee) { + var length = array.length; + while (length--) { + if (iteratee(array[length], length, array) === false) { + break; } } - } else { - if (source === destination) throw ngMinErr("cpi", "Can't copy! Source and destination are identical."); - stackSource = stackSource || []; - stackDest = stackDest || []; - if (isObject(source)) { - stackSource.push(source); - stackDest.push(destination); + return array; + } + function arrayEvery(array, predicate) { + var index = -1, length = array.length; + while (++index < length) { + if (!predicate(array[index], index, array)) { + return false; + } } - var result, key; - if (isArray(source)) { - destination.length = 0; - for (var i = 0; i < source.length; i++) { - destination.push(copy(source[i], null, stackSource, stackDest)); + return true; + } + function arrayExtremum(array, iteratee, comparator, exValue) { + var index = -1, length = array.length, computed = exValue, result = computed; + while (++index < length) { + var value = array[index], current = +iteratee(value); + if (comparator(current, computed)) { + computed = current; + result = value; } - } else { - var h = destination.$$hashKey; - if (isArray(destination)) { - destination.length = 0; - } else { - forEach(destination, function(value, key) { - delete destination[key]; - }); + } + return result; + } + function arrayFilter(array, predicate) { + var index = -1, length = array.length, resIndex = -1, result = []; + while (++index < length) { + var value = array[index]; + if (predicate(value, index, array)) { + result[++resIndex] = value; } - if (isBlankObject(source)) { - for (key in source) { - destination[key] = copy(source[key], null, stackSource, stackDest); - } - } else if (source && typeof source.hasOwnProperty === "function") { - for (key in source) { - if (source.hasOwnProperty(key)) { - destination[key] = copy(source[key], null, stackSource, stackDest); - } - } - } else { - for (key in source) { - if (hasOwnProperty.call(source, key)) { - destination[key] = copy(source[key], null, stackSource, stackDest); - } - } + } + return result; + } + function arrayMap(array, iteratee) { + var index = -1, length = array.length, result = Array(length); + while (++index < length) { + result[index] = iteratee(array[index], index, array); + } + return result; + } + function arrayPush(array, values) { + var index = -1, length = values.length, offset = array.length; + while (++index < length) { + array[offset + index] = values[index]; + } + return array; + } + function arrayReduce(array, iteratee, accumulator, initFromArray) { + var index = -1, length = array.length; + if (initFromArray && length) { + accumulator = array[++index]; + } + while (++index < length) { + accumulator = iteratee(accumulator, array[index], index, array); + } + return accumulator; + } + function arrayReduceRight(array, iteratee, accumulator, initFromArray) { + var length = array.length; + if (initFromArray && length) { + accumulator = array[--length]; + } + while (length--) { + accumulator = iteratee(accumulator, array[length], length, array); + } + return accumulator; + } + function arraySome(array, predicate) { + var index = -1, length = array.length; + while (++index < length) { + if (predicate(array[index], index, array)) { + return true; } - setHashKey(destination, h); } + return false; } - return destination; - } - function shallowCopy(src, dst) { - if (isArray(src)) { - dst = dst || []; - for (var i = 0, ii = src.length; i < ii; i++) { - dst[i] = src[i]; + function arraySum(array, iteratee) { + var length = array.length, result = 0; + while (length--) { + result += +iteratee(array[length]) || 0; } - } else if (isObject(src)) { - dst = dst || {}; - for (var key in src) { - if (!(key.charAt(0) === "$" && key.charAt(1) === "$")) { - dst[key] = src[key]; + return result; + } + function assignDefaults(objectValue, sourceValue) { + return objectValue === undefined ? sourceValue : objectValue; + } + function assignOwnDefaults(objectValue, sourceValue, key, object) { + return objectValue === undefined || !hasOwnProperty.call(object, key) ? sourceValue : objectValue; + } + function assignWith(object, source, customizer) { + var index = -1, props = keys(source), length = props.length; + while (++index < length) { + var key = props[index], value = object[key], result = customizer(value, source[key], key, object, source); + if ((result === result ? result !== value : value === value) || value === undefined && !(key in object)) { + object[key] = result; } } + return object; } - return dst || src; - } - function equals(o1, o2) { - if (o1 === o2) return true; - if (o1 === null || o2 === null) return false; - if (o1 !== o1 && o2 !== o2) return true; - var t1 = typeof o1, t2 = typeof o2, length, key, keySet; - if (t1 == t2) { - if (t1 == "object") { - if (isArray(o1)) { - if (!isArray(o2)) return false; - if ((length = o1.length) == o2.length) { - for (key = 0; key < length; key++) { - if (!equals(o1[key], o2[key])) return false; - } - return true; - } - } else if (isDate(o1)) { - if (!isDate(o2)) return false; - return equals(o1.getTime(), o2.getTime()); - } else if (isRegExp(o1)) { - return isRegExp(o2) ? o1.toString() == o2.toString() : false; + function baseAssign(object, source) { + return source == null ? object : baseCopy(source, keys(source), object); + } + function baseAt(collection, props) { + var index = -1, isNil = collection == null, isArr = !isNil && isArrayLike(collection), length = isArr ? collection.length : 0, propsLength = props.length, result = Array(propsLength); + while (++index < propsLength) { + var key = props[index]; + if (isArr) { + result[index] = isIndex(key, length) ? collection[key] : undefined; } else { - if (isScope(o1) || isScope(o2) || isWindow(o1) || isWindow(o2) || isArray(o2) || isDate(o2) || isRegExp(o2)) return false; - keySet = createMap(); - for (key in o1) { - if (key.charAt(0) === "$" || isFunction(o1[key])) continue; - if (!equals(o1[key], o2[key])) return false; - keySet[key] = true; - } - for (key in o2) { - if (!(key in keySet) && key.charAt(0) !== "$" && isDefined(o2[key]) && !isFunction(o2[key])) return false; - } - return true; + result[index] = isNil ? undefined : collection[key]; } } + return result; } - return false; - } - var csp = function() { - if (!isDefined(csp.rules)) { - var ngCspElement = document.querySelector("[ng-csp]") || document.querySelector("[data-ng-csp]"); - if (ngCspElement) { - var ngCspAttribute = ngCspElement.getAttribute("ng-csp") || ngCspElement.getAttribute("data-ng-csp"); - csp.rules = { - noUnsafeEval: !ngCspAttribute || ngCspAttribute.indexOf("no-unsafe-eval") !== -1, - noInlineStyle: !ngCspAttribute || ngCspAttribute.indexOf("no-inline-style") !== -1 - }; - } else { - csp.rules = { - noUnsafeEval: noUnsafeEval(), - noInlineStyle: false - }; + function baseCopy(source, props, object) { + object || (object = {}); + var index = -1, length = props.length; + while (++index < length) { + var key = props[index]; + object[key] = source[key]; } + return object; } - return csp.rules; - function noUnsafeEval() { - try { - new Function(""); - return false; - } catch (e) { - return true; + function baseCallback(func, thisArg, argCount) { + var type = typeof func; + if (type == "function") { + return thisArg === undefined ? func : bindCallback(func, thisArg, argCount); + } + if (func == null) { + return identity; + } + if (type == "object") { + return baseMatches(func); } + return thisArg === undefined ? property(func) : baseMatchesProperty(func, thisArg); } - }; - var jq = function() { - if (isDefined(jq.name_)) return jq.name_; - var el; - var i, ii = ngAttrPrefixes.length, prefix, name; - for (i = 0; i < ii; ++i) { - prefix = ngAttrPrefixes[i]; - if (el = document.querySelector("[" + prefix.replace(":", "\\:") + "jq]")) { - name = el.getAttribute(prefix + "jq"); - break; + function baseClone(value, isDeep, customizer, key, object, stackA, stackB) { + var result; + if (customizer) { + result = object ? customizer(value, key, object) : customizer(value); + } + if (result !== undefined) { + return result; + } + if (!isObject(value)) { + return value; + } + var isArr = isArray(value); + if (isArr) { + result = initCloneArray(value); + if (!isDeep) { + return arrayCopy(value, result); + } + } else { + var tag = objToString.call(value), isFunc = tag == funcTag; + if (tag == objectTag || tag == argsTag || isFunc && !object) { + result = initCloneObject(isFunc ? {} : value); + if (!isDeep) { + return baseAssign(result, value); + } + } else { + return cloneableTags[tag] ? initCloneByTag(value, tag, isDeep) : object ? value : {}; + } } + stackA || (stackA = []); + stackB || (stackB = []); + var length = stackA.length; + while (length--) { + if (stackA[length] == value) { + return stackB[length]; + } + } + stackA.push(value); + stackB.push(result); + (isArr ? arrayEach : baseForOwn)(value, function(subValue, key) { + result[key] = baseClone(subValue, isDeep, customizer, key, value, stackA, stackB); + }); + return result; } - return jq.name_ = name; - }; - function concat(array1, array2, index) { - return array1.concat(slice.call(array2, index)); - } - function sliceArgs(args, startIndex) { - return slice.call(args, startIndex || 0); - } - function bind(self, fn) { - var curryArgs = arguments.length > 2 ? sliceArgs(arguments, 2) : []; - if (isFunction(fn) && !(fn instanceof RegExp)) { - return curryArgs.length ? function() { - return arguments.length ? fn.apply(self, concat(curryArgs, arguments, 0)) : fn.apply(self, curryArgs); - } : function() { - return arguments.length ? fn.apply(self, arguments) : fn.call(self); + var baseCreate = function() { + function object() {} + return function(prototype) { + if (isObject(prototype)) { + object.prototype = prototype; + var result = new object(); + object.prototype = undefined; + } + return result || {}; }; - } else { - return fn; + }(); + function baseDelay(func, wait, args) { + if (typeof func != "function") { + throw new TypeError(FUNC_ERROR_TEXT); + } + return setTimeout(function() { + func.apply(undefined, args); + }, wait); } - } - function toJsonReplacer(key, value) { - var val = value; - if (typeof key === "string" && key.charAt(0) === "$" && key.charAt(1) === "$") { - val = undefined; - } else if (isWindow(value)) { - val = "$WINDOW"; - } else if (value && document === value) { - val = "$DOCUMENT"; - } else if (isScope(value)) { - val = "$SCOPE"; + function baseDifference(array, values) { + var length = array ? array.length : 0, result = []; + if (!length) { + return result; + } + var index = -1, indexOf = getIndexOf(), isCommon = indexOf === baseIndexOf, cache = isCommon && values.length >= LARGE_ARRAY_SIZE ? createCache(values) : null, valuesLength = values.length; + if (cache) { + indexOf = cacheIndexOf; + isCommon = false; + values = cache; + } + outer: while (++index < length) { + var value = array[index]; + if (isCommon && value === value) { + var valuesIndex = valuesLength; + while (valuesIndex--) { + if (values[valuesIndex] === value) { + continue outer; + } + } + result.push(value); + } else if (indexOf(values, value, 0) < 0) { + result.push(value); + } + } + return result; } - return val; - } - function toJson(obj, pretty) { - if (typeof obj === "undefined") return undefined; - if (!isNumber(pretty)) { - pretty = pretty ? 2 : null; + var baseEach = createBaseEach(baseForOwn); + var baseEachRight = createBaseEach(baseForOwnRight, true); + function baseEvery(collection, predicate) { + var result = true; + baseEach(collection, function(value, index, collection) { + result = !!predicate(value, index, collection); + return result; + }); + return result; } - return JSON.stringify(obj, toJsonReplacer, pretty); - } - function fromJson(json) { - return isString(json) ? JSON.parse(json) : json; - } - function timezoneToOffset(timezone, fallback) { - var requestedTimezoneOffset = Date.parse("Jan 01, 1970 00:00:00 " + timezone) / 6e4; - return isNaN(requestedTimezoneOffset) ? fallback : requestedTimezoneOffset; - } - function addDateMinutes(date, minutes) { - date = new Date(date.getTime()); - date.setMinutes(date.getMinutes() + minutes); - return date; - } - function convertTimezoneToLocal(date, timezone, reverse) { - reverse = reverse ? -1 : 1; - var timezoneOffset = timezoneToOffset(timezone, date.getTimezoneOffset()); - return addDateMinutes(date, reverse * (timezoneOffset - date.getTimezoneOffset())); - } - function startingTag(element) { - element = jqLite(element).clone(); - try { - element.empty(); - } catch (e) {} - var elemHtml = jqLite("
        ").append(element).html(); - try { - return element[0].nodeType === NODE_TYPE_TEXT ? lowercase(elemHtml) : elemHtml.match(/^(<[^>]+>)/)[1].replace(/^<([\w\-]+)/, function(match, nodeName) { - return "<" + lowercase(nodeName); + function baseExtremum(collection, iteratee, comparator, exValue) { + var computed = exValue, result = computed; + baseEach(collection, function(value, index, collection) { + var current = +iteratee(value, index, collection); + if (comparator(current, computed) || current === exValue && current === result) { + computed = current; + result = value; + } }); - } catch (e) { - return lowercase(elemHtml); + return result; } - } - function tryDecodeURIComponent(value) { - try { - return decodeURIComponent(value); - } catch (e) {} - } - function parseKeyValue(keyValue) { - var obj = {}; - forEach((keyValue || "").split("&"), function(keyValue) { - var splitPoint, key, val; - if (keyValue) { - key = keyValue = keyValue.replace(/\+/g, "%20"); - splitPoint = keyValue.indexOf("="); - if (splitPoint !== -1) { - key = keyValue.substring(0, splitPoint); - val = keyValue.substring(splitPoint + 1); + function baseFill(array, value, start, end) { + var length = array.length; + start = start == null ? 0 : +start || 0; + if (start < 0) { + start = -start > length ? 0 : length + start; + } + end = end === undefined || end > length ? length : +end || 0; + if (end < 0) { + end += length; + } + length = start > end ? 0 : end >>> 0; + start >>>= 0; + while (start < length) { + array[start++] = value; + } + return array; + } + function baseFilter(collection, predicate) { + var result = []; + baseEach(collection, function(value, index, collection) { + if (predicate(value, index, collection)) { + result.push(value); } - key = tryDecodeURIComponent(key); - if (isDefined(key)) { - val = isDefined(val) ? tryDecodeURIComponent(val) : true; - if (!hasOwnProperty.call(obj, key)) { - obj[key] = val; - } else if (isArray(obj[key])) { - obj[key].push(val); + }); + return result; + } + function baseFind(collection, predicate, eachFunc, retKey) { + var result; + eachFunc(collection, function(value, key, collection) { + if (predicate(value, key, collection)) { + result = retKey ? key : value; + return false; + } + }); + return result; + } + function baseFlatten(array, isDeep, isStrict, result) { + result || (result = []); + var index = -1, length = array.length; + while (++index < length) { + var value = array[index]; + if (isObjectLike(value) && isArrayLike(value) && (isStrict || isArray(value) || isArguments(value))) { + if (isDeep) { + baseFlatten(value, isDeep, isStrict, result); } else { - obj[key] = [ obj[key], val ]; + arrayPush(result, value); } + } else if (!isStrict) { + result[result.length] = value; } } - }); - return obj; - } - function toKeyValue(obj) { - var parts = []; - forEach(obj, function(value, key) { - if (isArray(value)) { - forEach(value, function(arrayValue) { - parts.push(encodeUriQuery(key, true) + (arrayValue === true ? "" : "=" + encodeUriQuery(arrayValue, true))); - }); - } else { - parts.push(encodeUriQuery(key, true) + (value === true ? "" : "=" + encodeUriQuery(value, true))); + return result; + } + var baseFor = createBaseFor(); + var baseForRight = createBaseFor(true); + function baseForIn(object, iteratee) { + return baseFor(object, iteratee, keysIn); + } + function baseForOwn(object, iteratee) { + return baseFor(object, iteratee, keys); + } + function baseForOwnRight(object, iteratee) { + return baseForRight(object, iteratee, keys); + } + function baseFunctions(object, props) { + var index = -1, length = props.length, resIndex = -1, result = []; + while (++index < length) { + var key = props[index]; + if (isFunction(object[key])) { + result[++resIndex] = key; + } } - }); - return parts.length ? parts.join("&") : ""; - } - function encodeUriSegment(val) { - return encodeUriQuery(val, true).replace(/%26/gi, "&").replace(/%3D/gi, "=").replace(/%2B/gi, "+"); - } - function encodeUriQuery(val, pctEncodeSpaces) { - return encodeURIComponent(val).replace(/%40/gi, "@").replace(/%3A/gi, ":").replace(/%24/g, "$").replace(/%2C/gi, ",").replace(/%3B/gi, ";").replace(/%20/g, pctEncodeSpaces ? "%20" : "+"); - } - var ngAttrPrefixes = [ "ng-", "data-ng-", "ng:", "x-ng-" ]; - function getNgAttribute(element, ngAttr) { - var attr, i, ii = ngAttrPrefixes.length; - for (i = 0; i < ii; ++i) { - attr = ngAttrPrefixes[i] + ngAttr; - if (isString(attr = element.getAttribute(attr))) { - return attr; + return result; + } + function baseGet(object, path, pathKey) { + if (object == null) { + return; + } + if (pathKey !== undefined && pathKey in toObject(object)) { + path = [ pathKey ]; } + var index = 0, length = path.length; + while (object != null && index < length) { + object = object[path[index++]]; + } + return index && index == length ? object : undefined; } - return null; - } - function angularInit(element, bootstrap) { - var appElement, module, config = {}; - forEach(ngAttrPrefixes, function(prefix) { - var name = prefix + "app"; - if (!appElement && element.hasAttribute && element.hasAttribute(name)) { - appElement = element; - module = element.getAttribute(name); + function baseIsEqual(value, other, customizer, isLoose, stackA, stackB) { + if (value === other) { + return true; } - }); - forEach(ngAttrPrefixes, function(prefix) { - var name = prefix + "app"; - var candidate; - if (!appElement && (candidate = element.querySelector("[" + name.replace(":", "\\:") + "]"))) { - appElement = candidate; - module = candidate.getAttribute(name); + if (value == null || other == null || !isObject(value) && !isObjectLike(other)) { + return value !== value && other !== other; } - }); - if (appElement) { - config.strictDi = getNgAttribute(appElement, "strict-di") !== null; - bootstrap(appElement, module ? [ module ] : [], config); + return baseIsEqualDeep(value, other, baseIsEqual, customizer, isLoose, stackA, stackB); } - } - function bootstrap(element, modules, config) { - if (!isObject(config)) config = {}; - var defaultConfig = { - strictDi: false - }; - config = extend(defaultConfig, config); - var doBootstrap = function() { - element = jqLite(element); - if (element.injector()) { - var tag = element[0] === document ? "document" : startingTag(element); - throw ngMinErr("btstrpd", "App Already Bootstrapped with this Element '{0}'", tag.replace(//, ">")); + function baseIsEqualDeep(object, other, equalFunc, customizer, isLoose, stackA, stackB) { + var objIsArr = isArray(object), othIsArr = isArray(other), objTag = arrayTag, othTag = arrayTag; + if (!objIsArr) { + objTag = objToString.call(object); + if (objTag == argsTag) { + objTag = objectTag; + } else if (objTag != objectTag) { + objIsArr = isTypedArray(object); + } } - modules = modules || []; - modules.unshift([ "$provide", function($provide) { - $provide.value("$rootElement", element); - } ]); - if (config.debugInfoEnabled) { - modules.push([ "$compileProvider", function($compileProvider) { - $compileProvider.debugInfoEnabled(true); - } ]); + if (!othIsArr) { + othTag = objToString.call(other); + if (othTag == argsTag) { + othTag = objectTag; + } else if (othTag != objectTag) { + othIsArr = isTypedArray(other); + } } - modules.unshift("ng"); - var injector = createInjector(modules, config.strictDi); - injector.invoke([ "$rootScope", "$rootElement", "$compile", "$injector", function bootstrapApply(scope, element, compile, injector) { - scope.$apply(function() { - element.data("$injector", injector); - compile(element)(scope); - }); - } ]); - return injector; - }; - var NG_ENABLE_DEBUG_INFO = /^NG_ENABLE_DEBUG_INFO!/; - var NG_DEFER_BOOTSTRAP = /^NG_DEFER_BOOTSTRAP!/; - if (window && NG_ENABLE_DEBUG_INFO.test(window.name)) { - config.debugInfoEnabled = true; - window.name = window.name.replace(NG_ENABLE_DEBUG_INFO, ""); + var objIsObj = objTag == objectTag, othIsObj = othTag == objectTag, isSameTag = objTag == othTag; + if (isSameTag && !(objIsArr || objIsObj)) { + return equalByTag(object, other, objTag); + } + if (!isLoose) { + var objIsWrapped = objIsObj && hasOwnProperty.call(object, "__wrapped__"), othIsWrapped = othIsObj && hasOwnProperty.call(other, "__wrapped__"); + if (objIsWrapped || othIsWrapped) { + return equalFunc(objIsWrapped ? object.value() : object, othIsWrapped ? other.value() : other, customizer, isLoose, stackA, stackB); + } + } + if (!isSameTag) { + return false; + } + stackA || (stackA = []); + stackB || (stackB = []); + var length = stackA.length; + while (length--) { + if (stackA[length] == object) { + return stackB[length] == other; + } + } + stackA.push(object); + stackB.push(other); + var result = (objIsArr ? equalArrays : equalObjects)(object, other, equalFunc, customizer, isLoose, stackA, stackB); + stackA.pop(); + stackB.pop(); + return result; } - if (window && !NG_DEFER_BOOTSTRAP.test(window.name)) { - return doBootstrap(); + function baseIsMatch(object, matchData, customizer) { + var index = matchData.length, length = index, noCustomizer = !customizer; + if (object == null) { + return !length; + } + object = toObject(object); + while (index--) { + var data = matchData[index]; + if (noCustomizer && data[2] ? data[1] !== object[data[0]] : !(data[0] in object)) { + return false; + } + } + while (++index < length) { + data = matchData[index]; + var key = data[0], objValue = object[key], srcValue = data[1]; + if (noCustomizer && data[2]) { + if (objValue === undefined && !(key in object)) { + return false; + } + } else { + var result = customizer ? customizer(objValue, srcValue, key) : undefined; + if (!(result === undefined ? baseIsEqual(srcValue, objValue, customizer, true) : result)) { + return false; + } + } + } + return true; } - window.name = window.name.replace(NG_DEFER_BOOTSTRAP, ""); - angular.resumeBootstrap = function(extraModules) { - forEach(extraModules, function(module) { - modules.push(module); + function baseMap(collection, iteratee) { + var index = -1, result = isArrayLike(collection) ? Array(collection.length) : []; + baseEach(collection, function(value, key, collection) { + result[++index] = iteratee(value, key, collection); }); - return doBootstrap(); - }; - if (isFunction(angular.resumeDeferredBootstrap)) { - angular.resumeDeferredBootstrap(); + return result; } - } - function reloadWithDebugInfo() { - window.name = "NG_ENABLE_DEBUG_INFO!" + window.name; - window.location.reload(); - } - function getTestability(rootElement) { - var injector = angular.element(rootElement).injector(); - if (!injector) { - throw ngMinErr("test", "no injector found for element argument to getTestability"); + function baseMatches(source) { + var matchData = getMatchData(source); + if (matchData.length == 1 && matchData[0][2]) { + var key = matchData[0][0], value = matchData[0][1]; + return function(object) { + if (object == null) { + return false; + } + return object[key] === value && (value !== undefined || key in toObject(object)); + }; + } + return function(object) { + return baseIsMatch(object, matchData); + }; } - return injector.get("$$testability"); - } - var SNAKE_CASE_REGEXP = /[A-Z]/g; - function snake_case(name, separator) { - separator = separator || "_"; - return name.replace(SNAKE_CASE_REGEXP, function(letter, pos) { - return (pos ? separator : "") + letter.toLowerCase(); - }); - } - var bindJQueryFired = false; - var skipDestroyOnNextJQueryCleanData; - function bindJQuery() { - var originalCleanData; - if (bindJQueryFired) { - return; + function baseMatchesProperty(path, srcValue) { + var isArr = isArray(path), isCommon = isKey(path) && isStrictComparable(srcValue), pathKey = path + ""; + path = toPath(path); + return function(object) { + if (object == null) { + return false; + } + var key = pathKey; + object = toObject(object); + if ((isArr || !isCommon) && !(key in object)) { + object = path.length == 1 ? object : baseGet(object, baseSlice(path, 0, -1)); + if (object == null) { + return false; + } + key = last(path); + object = toObject(object); + } + return object[key] === srcValue ? srcValue !== undefined || key in object : baseIsEqual(srcValue, object[key], undefined, true); + }; } - var jqName = jq(); - jQuery = isUndefined(jqName) ? window.jQuery : !jqName ? undefined : window[jqName]; - if (jQuery && jQuery.fn.on) { - jqLite = jQuery; - extend(jQuery.fn, { - scope: JQLitePrototype.scope, - isolateScope: JQLitePrototype.isolateScope, - controller: JQLitePrototype.controller, - injector: JQLitePrototype.injector, - inheritedData: JQLitePrototype.inheritedData - }); - originalCleanData = jQuery.cleanData; - jQuery.cleanData = function(elems) { - var events; - if (!skipDestroyOnNextJQueryCleanData) { - for (var i = 0, elem; (elem = elems[i]) != null; i++) { - events = jQuery._data(elem, "events"); - if (events && events.$destroy) { - jQuery(elem).triggerHandler("$destroy"); - } + function baseMerge(object, source, customizer, stackA, stackB) { + if (!isObject(object)) { + return object; + } + var isSrcArr = isArrayLike(source) && (isArray(source) || isTypedArray(source)), props = isSrcArr ? undefined : keys(source); + arrayEach(props || source, function(srcValue, key) { + if (props) { + key = srcValue; + srcValue = source[key]; + } + if (isObjectLike(srcValue)) { + stackA || (stackA = []); + stackB || (stackB = []); + baseMergeDeep(object, source, key, baseMerge, customizer, stackA, stackB); + } else { + var value = object[key], result = customizer ? customizer(value, srcValue, key, object, source) : undefined, isCommon = result === undefined; + if (isCommon) { + result = srcValue; } + if ((result !== undefined || isSrcArr && !(key in object)) && (isCommon || (result === result ? result !== value : value === value))) { + object[key] = result; + } + } + }); + return object; + } + function baseMergeDeep(object, source, key, mergeFunc, customizer, stackA, stackB) { + var length = stackA.length, srcValue = source[key]; + while (length--) { + if (stackA[length] == srcValue) { + object[key] = stackB[length]; + return; + } + } + var value = object[key], result = customizer ? customizer(value, srcValue, key, object, source) : undefined, isCommon = result === undefined; + if (isCommon) { + result = srcValue; + if (isArrayLike(srcValue) && (isArray(srcValue) || isTypedArray(srcValue))) { + result = isArray(value) ? value : isArrayLike(value) ? arrayCopy(value) : []; + } else if (isPlainObject(srcValue) || isArguments(srcValue)) { + result = isArguments(value) ? toPlainObject(value) : isPlainObject(value) ? value : {}; } else { - skipDestroyOnNextJQueryCleanData = false; + isCommon = false; } - originalCleanData(elems); + } + stackA.push(srcValue); + stackB.push(result); + if (isCommon) { + object[key] = mergeFunc(result, srcValue, customizer, stackA, stackB); + } else if (result === result ? result !== value : value === value) { + object[key] = result; + } + } + function baseProperty(key) { + return function(object) { + return object == null ? undefined : object[key]; }; - } else { - jqLite = JQLite; } - angular.element = jqLite; - bindJQueryFired = true; - } - function assertArg(arg, name, reason) { - if (!arg) { - throw ngMinErr("areq", "Argument '{0}' is {1}", name || "?", reason || "required"); + function basePropertyDeep(path) { + var pathKey = path + ""; + path = toPath(path); + return function(object) { + return baseGet(object, path, pathKey); + }; } - return arg; - } - function assertArgFn(arg, name, acceptArrayAnnotation) { - if (acceptArrayAnnotation && isArray(arg)) { - arg = arg[arg.length - 1]; + function basePullAt(array, indexes) { + var length = array ? indexes.length : 0; + while (length--) { + var index = indexes[length]; + if (index != previous && isIndex(index)) { + var previous = index; + splice.call(array, index, 1); + } + } + return array; } - assertArg(isFunction(arg), name, "not a function, got " + (arg && typeof arg === "object" ? arg.constructor.name || "Object" : typeof arg)); - return arg; - } - function assertNotHasOwnProperty(name, context) { - if (name === "hasOwnProperty") { - throw ngMinErr("badname", "hasOwnProperty is not a valid {0} name", context); + function baseRandom(min, max) { + return min + nativeFloor(nativeRandom() * (max - min + 1)); } - } - function getter(obj, path, bindFnToScope) { - if (!path) return obj; - var keys = path.split("."); - var key; - var lastInstance = obj; - var len = keys.length; - for (var i = 0; i < len; i++) { - key = keys[i]; - if (obj) { - obj = (lastInstance = obj)[key]; + function baseReduce(collection, iteratee, accumulator, initFromCollection, eachFunc) { + eachFunc(collection, function(value, index, collection) { + accumulator = initFromCollection ? (initFromCollection = false, value) : iteratee(accumulator, value, index, collection); + }); + return accumulator; + } + var baseSetData = !metaMap ? identity : function(func, data) { + metaMap.set(func, data); + return func; + }; + function baseSlice(array, start, end) { + var index = -1, length = array.length; + start = start == null ? 0 : +start || 0; + if (start < 0) { + start = -start > length ? 0 : length + start; + } + end = end === undefined || end > length ? length : +end || 0; + if (end < 0) { + end += length; } + length = start > end ? 0 : end - start >>> 0; + start >>>= 0; + var result = Array(length); + while (++index < length) { + result[index] = array[index + start]; + } + return result; } - if (!bindFnToScope && isFunction(obj)) { - return bind(lastInstance, obj); + function baseSome(collection, predicate) { + var result; + baseEach(collection, function(value, index, collection) { + result = predicate(value, index, collection); + return !result; + }); + return !!result; } - return obj; - } - function getBlockNodes(nodes) { - var node = nodes[0]; - var endNode = nodes[nodes.length - 1]; - var blockNodes; - for (var i = 1; node !== endNode && (node = node.nextSibling); i++) { - if (blockNodes || nodes[i] !== node) { - if (!blockNodes) { - blockNodes = jqLite(slice.call(nodes, 0, i)); - } - blockNodes.push(node); + function baseSortBy(array, comparer) { + var length = array.length; + array.sort(comparer); + while (length--) { + array[length] = array[length].value; } + return array; } - return blockNodes || nodes; - } - function createMap() { - return Object.create(null); - } - var NODE_TYPE_ELEMENT = 1; - var NODE_TYPE_ATTRIBUTE = 2; - var NODE_TYPE_TEXT = 3; - var NODE_TYPE_COMMENT = 8; - var NODE_TYPE_DOCUMENT = 9; - var NODE_TYPE_DOCUMENT_FRAGMENT = 11; - function setupModuleLoader(window) { - var $injectorMinErr = minErr("$injector"); - var ngMinErr = minErr("ng"); - function ensure(obj, name, factory) { - return obj[name] || (obj[name] = factory()); + function baseSortByOrder(collection, iteratees, orders) { + var callback = getCallback(), index = -1; + iteratees = arrayMap(iteratees, function(iteratee) { + return callback(iteratee); + }); + var result = baseMap(collection, function(value) { + var criteria = arrayMap(iteratees, function(iteratee) { + return iteratee(value); + }); + return { + criteria: criteria, + index: ++index, + value: value + }; + }); + return baseSortBy(result, function(object, other) { + return compareMultiple(object, other, orders); + }); } - var angular = ensure(window, "angular", Object); - angular.$$minErr = angular.$$minErr || minErr; - return ensure(angular, "module", function() { - var modules = {}; - return function module(name, requires, configFn) { - var assertNotHasOwnProperty = function(name, context) { - if (name === "hasOwnProperty") { - throw ngMinErr("badname", "hasOwnProperty is not a valid {0} name", context); + function baseSum(collection, iteratee) { + var result = 0; + baseEach(collection, function(value, index, collection) { + result += +iteratee(value, index, collection) || 0; + }); + return result; + } + function baseUniq(array, iteratee) { + var index = -1, indexOf = getIndexOf(), length = array.length, isCommon = indexOf === baseIndexOf, isLarge = isCommon && length >= LARGE_ARRAY_SIZE, seen = isLarge ? createCache() : null, result = []; + if (seen) { + indexOf = cacheIndexOf; + isCommon = false; + } else { + isLarge = false; + seen = iteratee ? [] : result; + } + outer: while (++index < length) { + var value = array[index], computed = iteratee ? iteratee(value, index, array) : value; + if (isCommon && value === value) { + var seenIndex = seen.length; + while (seenIndex--) { + if (seen[seenIndex] === computed) { + continue outer; + } } - }; - assertNotHasOwnProperty(name, "module"); - if (requires && modules.hasOwnProperty(name)) { - modules[name] = null; + if (iteratee) { + seen.push(computed); + } + result.push(value); + } else if (indexOf(seen, computed, 0) < 0) { + if (iteratee || isLarge) { + seen.push(computed); + } + result.push(value); } - return ensure(modules, name, function() { - if (!requires) { - throw $injectorMinErr("nomod", "Module '{0}' is not available! You either misspelled " + "the module name or forgot to load it. If registering a module ensure that you " + "specify the dependencies as the second argument.", name); + } + return result; + } + function baseValues(object, props) { + var index = -1, length = props.length, result = Array(length); + while (++index < length) { + result[index] = object[props[index]]; + } + return result; + } + function baseWhile(array, predicate, isDrop, fromRight) { + var length = array.length, index = fromRight ? length : -1; + while ((fromRight ? index-- : ++index < length) && predicate(array[index], index, array)) {} + return isDrop ? baseSlice(array, fromRight ? 0 : index, fromRight ? index + 1 : length) : baseSlice(array, fromRight ? index + 1 : 0, fromRight ? length : index); + } + function baseWrapperValue(value, actions) { + var result = value; + if (result instanceof LazyWrapper) { + result = result.value(); + } + var index = -1, length = actions.length; + while (++index < length) { + var action = actions[index]; + result = action.func.apply(action.thisArg, arrayPush([ result ], action.args)); + } + return result; + } + function binaryIndex(array, value, retHighest) { + var low = 0, high = array ? array.length : low; + if (typeof value == "number" && value === value && high <= HALF_MAX_ARRAY_LENGTH) { + while (low < high) { + var mid = low + high >>> 1, computed = array[mid]; + if ((retHighest ? computed <= value : computed < value) && computed !== null) { + low = mid + 1; + } else { + high = mid; + } + } + return high; + } + return binaryIndexBy(array, value, identity, retHighest); + } + function binaryIndexBy(array, value, iteratee, retHighest) { + value = iteratee(value); + var low = 0, high = array ? array.length : 0, valIsNaN = value !== value, valIsNull = value === null, valIsUndef = value === undefined; + while (low < high) { + var mid = nativeFloor((low + high) / 2), computed = iteratee(array[mid]), isDef = computed !== undefined, isReflexive = computed === computed; + if (valIsNaN) { + var setLow = isReflexive || retHighest; + } else if (valIsNull) { + setLow = isReflexive && isDef && (retHighest || computed != null); + } else if (valIsUndef) { + setLow = isReflexive && (retHighest || isDef); + } else if (computed == null) { + setLow = false; + } else { + setLow = retHighest ? computed <= value : computed < value; + } + if (setLow) { + low = mid + 1; + } else { + high = mid; + } + } + return nativeMin(high, MAX_ARRAY_INDEX); + } + function bindCallback(func, thisArg, argCount) { + if (typeof func != "function") { + return identity; + } + if (thisArg === undefined) { + return func; + } + switch (argCount) { + case 1: + return function(value) { + return func.call(thisArg, value); + }; + + case 3: + return function(value, index, collection) { + return func.call(thisArg, value, index, collection); + }; + + case 4: + return function(accumulator, value, index, collection) { + return func.call(thisArg, accumulator, value, index, collection); + }; + + case 5: + return function(value, other, key, object, source) { + return func.call(thisArg, value, other, key, object, source); + }; + } + return function() { + return func.apply(thisArg, arguments); + }; + } + function bufferClone(buffer) { + var result = new ArrayBuffer(buffer.byteLength), view = new Uint8Array(result); + view.set(new Uint8Array(buffer)); + return result; + } + function composeArgs(args, partials, holders) { + var holdersLength = holders.length, argsIndex = -1, argsLength = nativeMax(args.length - holdersLength, 0), leftIndex = -1, leftLength = partials.length, result = Array(leftLength + argsLength); + while (++leftIndex < leftLength) { + result[leftIndex] = partials[leftIndex]; + } + while (++argsIndex < holdersLength) { + result[holders[argsIndex]] = args[argsIndex]; + } + while (argsLength--) { + result[leftIndex++] = args[argsIndex++]; + } + return result; + } + function composeArgsRight(args, partials, holders) { + var holdersIndex = -1, holdersLength = holders.length, argsIndex = -1, argsLength = nativeMax(args.length - holdersLength, 0), rightIndex = -1, rightLength = partials.length, result = Array(argsLength + rightLength); + while (++argsIndex < argsLength) { + result[argsIndex] = args[argsIndex]; + } + var offset = argsIndex; + while (++rightIndex < rightLength) { + result[offset + rightIndex] = partials[rightIndex]; + } + while (++holdersIndex < holdersLength) { + result[offset + holders[holdersIndex]] = args[argsIndex++]; + } + return result; + } + function createAggregator(setter, initializer) { + return function(collection, iteratee, thisArg) { + var result = initializer ? initializer() : {}; + iteratee = getCallback(iteratee, thisArg, 3); + if (isArray(collection)) { + var index = -1, length = collection.length; + while (++index < length) { + var value = collection[index]; + setter(result, value, iteratee(value, index, collection), collection); } - var invokeQueue = []; - var configBlocks = []; - var runBlocks = []; - var config = invokeLater("$injector", "invoke", "push", configBlocks); - var moduleInstance = { - _invokeQueue: invokeQueue, - _configBlocks: configBlocks, - _runBlocks: runBlocks, - requires: requires, - name: name, - provider: invokeLaterAndSetModuleName("$provide", "provider"), - factory: invokeLaterAndSetModuleName("$provide", "factory"), - service: invokeLaterAndSetModuleName("$provide", "service"), - value: invokeLater("$provide", "value"), - constant: invokeLater("$provide", "constant", "unshift"), - decorator: invokeLaterAndSetModuleName("$provide", "decorator"), - animation: invokeLaterAndSetModuleName("$animateProvider", "register"), - filter: invokeLaterAndSetModuleName("$filterProvider", "register"), - controller: invokeLaterAndSetModuleName("$controllerProvider", "register"), - directive: invokeLaterAndSetModuleName("$compileProvider", "directive"), - config: config, - run: function(block) { - runBlocks.push(block); - return this; - } - }; - if (configFn) { - config(configFn); + } else { + baseEach(collection, function(value, key, collection) { + setter(result, value, iteratee(value, key, collection), collection); + }); + } + return result; + }; + } + function createAssigner(assigner) { + return restParam(function(object, sources) { + var index = -1, length = object == null ? 0 : sources.length, customizer = length > 2 ? sources[length - 2] : undefined, guard = length > 2 ? sources[2] : undefined, thisArg = length > 1 ? sources[length - 1] : undefined; + if (typeof customizer == "function") { + customizer = bindCallback(customizer, thisArg, 5); + length -= 2; + } else { + customizer = typeof thisArg == "function" ? thisArg : undefined; + length -= customizer ? 1 : 0; + } + if (guard && isIterateeCall(sources[0], sources[1], guard)) { + customizer = length < 3 ? undefined : customizer; + length = 1; + } + while (++index < length) { + var source = sources[index]; + if (source) { + assigner(object, source, customizer); } - return moduleInstance; - function invokeLater(provider, method, insertMethod, queue) { - if (!queue) queue = invokeQueue; - return function() { - queue[insertMethod || "push"]([ provider, method, arguments ]); - return moduleInstance; - }; + } + return object; + }); + } + function createBaseEach(eachFunc, fromRight) { + return function(collection, iteratee) { + var length = collection ? getLength(collection) : 0; + if (!isLength(length)) { + return eachFunc(collection, iteratee); + } + var index = fromRight ? length : -1, iterable = toObject(collection); + while (fromRight ? index-- : ++index < length) { + if (iteratee(iterable[index], index, iterable) === false) { + break; } - function invokeLaterAndSetModuleName(provider, method) { - return function(recipeName, factoryFunction) { - if (factoryFunction && isFunction(factoryFunction)) factoryFunction.$$moduleName = name; - invokeQueue.push([ provider, method, arguments ]); - return moduleInstance; - }; + } + return collection; + }; + } + function createBaseFor(fromRight) { + return function(object, iteratee, keysFunc) { + var iterable = toObject(object), props = keysFunc(object), length = props.length, index = fromRight ? length : -1; + while (fromRight ? index-- : ++index < length) { + var key = props[index]; + if (iteratee(iterable[key], key, iterable) === false) { + break; } - }); + } + return object; }; - }); - } - function serializeObject(obj) { - var seen = []; - return JSON.stringify(obj, function(key, val) { - val = toJsonReplacer(key, val); - if (isObject(val)) { - if (seen.indexOf(val) >= 0) return "..."; - seen.push(val); + } + function createBindWrapper(func, thisArg) { + var Ctor = createCtorWrapper(func); + function wrapper() { + var fn = this && this !== root && this instanceof wrapper ? Ctor : func; + return fn.apply(thisArg, arguments); } - return val; - }); - } - function toDebugString(obj) { - if (typeof obj === "function") { - return obj.toString().replace(/ \{[\s\S]*$/, ""); - } else if (isUndefined(obj)) { - return "undefined"; - } else if (typeof obj !== "string") { - return serializeObject(obj); + return wrapper; } - return obj; - } - var version = { - full: "1.4.6", - major: 1, - minor: 4, - dot: 6, - codeName: "multiplicative-elevation" - }; - function publishExternalAPI(angular) { - extend(angular, { - bootstrap: bootstrap, - copy: copy, - extend: extend, - merge: merge, - equals: equals, - element: jqLite, - forEach: forEach, - injector: createInjector, - noop: noop, - bind: bind, - toJson: toJson, - fromJson: fromJson, - identity: identity, - isUndefined: isUndefined, - isDefined: isDefined, - isString: isString, - isFunction: isFunction, - isObject: isObject, - isNumber: isNumber, - isElement: isElement, - isArray: isArray, - version: version, - isDate: isDate, - lowercase: lowercase, - uppercase: uppercase, - callbacks: { - counter: 0 - }, - getTestability: getTestability, - $$minErr: minErr, - $$csp: csp, - reloadWithDebugInfo: reloadWithDebugInfo - }); - angularModule = setupModuleLoader(window); - angularModule("ng", [ "ngLocale" ], [ "$provide", function ngModule($provide) { - $provide.provider({ - $$sanitizeUri: $$SanitizeUriProvider - }); - $provide.provider("$compile", $CompileProvider).directive({ - a: htmlAnchorDirective, - input: inputDirective, - textarea: inputDirective, - form: formDirective, - script: scriptDirective, - select: selectDirective, - style: styleDirective, - option: optionDirective, - ngBind: ngBindDirective, - ngBindHtml: ngBindHtmlDirective, - ngBindTemplate: ngBindTemplateDirective, - ngClass: ngClassDirective, - ngClassEven: ngClassEvenDirective, - ngClassOdd: ngClassOddDirective, - ngCloak: ngCloakDirective, - ngController: ngControllerDirective, - ngForm: ngFormDirective, - ngHide: ngHideDirective, - ngIf: ngIfDirective, - ngInclude: ngIncludeDirective, - ngInit: ngInitDirective, - ngNonBindable: ngNonBindableDirective, - ngPluralize: ngPluralizeDirective, - ngRepeat: ngRepeatDirective, - ngShow: ngShowDirective, - ngStyle: ngStyleDirective, - ngSwitch: ngSwitchDirective, - ngSwitchWhen: ngSwitchWhenDirective, - ngSwitchDefault: ngSwitchDefaultDirective, - ngOptions: ngOptionsDirective, - ngTransclude: ngTranscludeDirective, - ngModel: ngModelDirective, - ngList: ngListDirective, - ngChange: ngChangeDirective, - pattern: patternDirective, - ngPattern: patternDirective, - required: requiredDirective, - ngRequired: requiredDirective, - minlength: minlengthDirective, - ngMinlength: minlengthDirective, - maxlength: maxlengthDirective, - ngMaxlength: maxlengthDirective, - ngValue: ngValueDirective, - ngModelOptions: ngModelOptionsDirective - }).directive({ - ngInclude: ngIncludeFillContentDirective - }).directive(ngAttributeAliasDirectives).directive(ngEventDirectives); - $provide.provider({ - $anchorScroll: $AnchorScrollProvider, - $animate: $AnimateProvider, - $animateCss: $CoreAnimateCssProvider, - $$animateQueue: $$CoreAnimateQueueProvider, - $$AnimateRunner: $$CoreAnimateRunnerProvider, - $browser: $BrowserProvider, - $cacheFactory: $CacheFactoryProvider, - $controller: $ControllerProvider, - $document: $DocumentProvider, - $exceptionHandler: $ExceptionHandlerProvider, - $filter: $FilterProvider, - $$forceReflow: $$ForceReflowProvider, - $interpolate: $InterpolateProvider, - $interval: $IntervalProvider, - $http: $HttpProvider, - $httpParamSerializer: $HttpParamSerializerProvider, - $httpParamSerializerJQLike: $HttpParamSerializerJQLikeProvider, - $httpBackend: $HttpBackendProvider, - $location: $LocationProvider, - $log: $LogProvider, - $parse: $ParseProvider, - $rootScope: $RootScopeProvider, - $q: $QProvider, - $$q: $$QProvider, - $sce: $SceProvider, - $sceDelegate: $SceDelegateProvider, - $sniffer: $SnifferProvider, - $templateCache: $TemplateCacheProvider, - $templateRequest: $TemplateRequestProvider, - $$testability: $$TestabilityProvider, - $timeout: $TimeoutProvider, - $window: $WindowProvider, - $$rAF: $$RAFProvider, - $$jqLite: $$jqLiteProvider, - $$HashMap: $$HashMapProvider, - $$cookieReader: $$CookieReaderProvider - }); - } ]); - } - JQLite.expando = "ng339"; - var jqCache = JQLite.cache = {}, jqId = 1, addEventListenerFn = function(element, type, fn) { - element.addEventListener(type, fn, false); - }, removeEventListenerFn = function(element, type, fn) { - element.removeEventListener(type, fn, false); - }; - JQLite._data = function(node) { - return this.cache[node[this.expando]] || {}; - }; - function jqNextId() { - return ++jqId; - } - var SPECIAL_CHARS_REGEXP = /([\:\-\_]+(.))/g; - var MOZ_HACK_REGEXP = /^moz([A-Z])/; - var MOUSE_EVENT_MAP = { - mouseleave: "mouseout", - mouseenter: "mouseover" - }; - var jqLiteMinErr = minErr("jqLite"); - function camelCase(name) { - return name.replace(SPECIAL_CHARS_REGEXP, function(_, separator, letter, offset) { - return offset ? letter.toUpperCase() : letter; - }).replace(MOZ_HACK_REGEXP, "Moz$1"); - } - var SINGLE_TAG_REGEXP = /^<(\w+)\s*\/?>(?:<\/\1>|)$/; - var HTML_REGEXP = /<|&#?\w+;/; - var TAG_NAME_REGEXP = /<([\w:]+)/; - var XHTML_TAG_REGEXP = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi; - var wrapMap = { - option: [ 1, '" ], - thead: [ 1, "", "
        " ], - col: [ 2, "", "
        " ], - tr: [ 2, "", "
        " ], - td: [ 3, "", "
        " ], - _default: [ 0, "", "" ] - }; - wrapMap.optgroup = wrapMap.option; - wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead; - wrapMap.th = wrapMap.td; - function jqLiteIsTextNode(html) { - return !HTML_REGEXP.test(html); - } - function jqLiteAcceptsData(node) { - var nodeType = node.nodeType; - return nodeType === NODE_TYPE_ELEMENT || !nodeType || nodeType === NODE_TYPE_DOCUMENT; - } - function jqLiteHasData(node) { - for (var key in jqCache[node.ng339]) { - return true; + function createCache(values) { + return nativeCreate && Set ? new SetCache(values) : null; } - return false; - } - function jqLiteBuildFragment(html, context) { - var tmp, tag, wrap, fragment = context.createDocumentFragment(), nodes = [], i; - if (jqLiteIsTextNode(html)) { - nodes.push(context.createTextNode(html)); - } else { - tmp = tmp || fragment.appendChild(context.createElement("div")); - tag = (TAG_NAME_REGEXP.exec(html) || [ "", "" ])[1].toLowerCase(); - wrap = wrapMap[tag] || wrapMap._default; - tmp.innerHTML = wrap[1] + html.replace(XHTML_TAG_REGEXP, "<$1>") + wrap[2]; - i = wrap[0]; - while (i--) { - tmp = tmp.lastChild; - } - nodes = concat(nodes, tmp.childNodes); - tmp = fragment.firstChild; - tmp.textContent = ""; + function createCompounder(callback) { + return function(string) { + var index = -1, array = words(deburr(string)), length = array.length, result = ""; + while (++index < length) { + result = callback(result, array[index], index); + } + return result; + }; } - fragment.textContent = ""; - fragment.innerHTML = ""; - forEach(nodes, function(node) { - fragment.appendChild(node); - }); - return fragment; - } - function jqLiteParseHTML(html, context) { - context = context || document; - var parsed; - if (parsed = SINGLE_TAG_REGEXP.exec(html)) { - return [ context.createElement(parsed[1]) ]; + function createCtorWrapper(Ctor) { + return function() { + var args = arguments; + switch (args.length) { + case 0: + return new Ctor(); + + case 1: + return new Ctor(args[0]); + + case 2: + return new Ctor(args[0], args[1]); + + case 3: + return new Ctor(args[0], args[1], args[2]); + + case 4: + return new Ctor(args[0], args[1], args[2], args[3]); + + case 5: + return new Ctor(args[0], args[1], args[2], args[3], args[4]); + + case 6: + return new Ctor(args[0], args[1], args[2], args[3], args[4], args[5]); + + case 7: + return new Ctor(args[0], args[1], args[2], args[3], args[4], args[5], args[6]); + } + var thisBinding = baseCreate(Ctor.prototype), result = Ctor.apply(thisBinding, args); + return isObject(result) ? result : thisBinding; + }; } - if (parsed = jqLiteBuildFragment(html, context)) { - return parsed.childNodes; + function createCurry(flag) { + function curryFunc(func, arity, guard) { + if (guard && isIterateeCall(func, arity, guard)) { + arity = undefined; + } + var result = createWrapper(func, flag, undefined, undefined, undefined, undefined, undefined, arity); + result.placeholder = curryFunc.placeholder; + return result; + } + return curryFunc; } - return []; - } - function JQLite(element) { - if (element instanceof JQLite) { - return element; + function createDefaults(assigner, customizer) { + return restParam(function(args) { + var object = args[0]; + if (object == null) { + return object; + } + args.push(customizer); + return assigner.apply(undefined, args); + }); } - var argIsString; - if (isString(element)) { - element = trim(element); - argIsString = true; + function createExtremum(comparator, exValue) { + return function(collection, iteratee, thisArg) { + if (thisArg && isIterateeCall(collection, iteratee, thisArg)) { + iteratee = undefined; + } + iteratee = getCallback(iteratee, thisArg, 3); + if (iteratee.length == 1) { + collection = isArray(collection) ? collection : toIterable(collection); + var result = arrayExtremum(collection, iteratee, comparator, exValue); + if (!(collection.length && result === exValue)) { + return result; + } + } + return baseExtremum(collection, iteratee, comparator, exValue); + }; } - if (!(this instanceof JQLite)) { - if (argIsString && element.charAt(0) != "<") { - throw jqLiteMinErr("nosel", "Looking up elements via selectors is not supported by jqLite! See: http://docs.angularjs.org/api/angular.element"); - } - return new JQLite(element); + function createFind(eachFunc, fromRight) { + return function(collection, predicate, thisArg) { + predicate = getCallback(predicate, thisArg, 3); + if (isArray(collection)) { + var index = baseFindIndex(collection, predicate, fromRight); + return index > -1 ? collection[index] : undefined; + } + return baseFind(collection, predicate, eachFunc); + }; } - if (argIsString) { - jqLiteAddNodes(this, jqLiteParseHTML(element)); - } else { - jqLiteAddNodes(this, element); + function createFindIndex(fromRight) { + return function(array, predicate, thisArg) { + if (!(array && array.length)) { + return -1; + } + predicate = getCallback(predicate, thisArg, 3); + return baseFindIndex(array, predicate, fromRight); + }; } - } - function jqLiteClone(element) { - return element.cloneNode(true); - } - function jqLiteDealoc(element, onlyDescendants) { - if (!onlyDescendants) jqLiteRemoveData(element); - if (element.querySelectorAll) { - var descendants = element.querySelectorAll("*"); - for (var i = 0, l = descendants.length; i < l; i++) { - jqLiteRemoveData(descendants[i]); - } + function createFindKey(objectFunc) { + return function(object, predicate, thisArg) { + predicate = getCallback(predicate, thisArg, 3); + return baseFind(object, predicate, objectFunc, true); + }; } - } - function jqLiteOff(element, type, fn, unsupported) { - if (isDefined(unsupported)) throw jqLiteMinErr("offargs", "jqLite#off() does not support the `selector` argument"); - var expandoStore = jqLiteExpandoStore(element); - var events = expandoStore && expandoStore.events; - var handle = expandoStore && expandoStore.handle; - if (!handle) return; - if (!type) { - for (type in events) { - if (type !== "$destroy") { - removeEventListenerFn(element, type, handle); + function createFlow(fromRight) { + return function() { + var wrapper, length = arguments.length, index = fromRight ? length : -1, leftIndex = 0, funcs = Array(length); + while (fromRight ? index-- : ++index < length) { + var func = funcs[leftIndex++] = arguments[index]; + if (typeof func != "function") { + throw new TypeError(FUNC_ERROR_TEXT); + } + if (!wrapper && LodashWrapper.prototype.thru && getFuncName(func) == "wrapper") { + wrapper = new LodashWrapper([], true); + } + } + index = wrapper ? -1 : length; + while (++index < length) { + func = funcs[index]; + var funcName = getFuncName(func), data = funcName == "wrapper" ? getData(func) : undefined; + if (data && isLaziable(data[0]) && data[1] == (ARY_FLAG | CURRY_FLAG | PARTIAL_FLAG | REARG_FLAG) && !data[4].length && data[9] == 1) { + wrapper = wrapper[getFuncName(data[0])].apply(wrapper, data[3]); + } else { + wrapper = func.length == 1 && isLaziable(func) ? wrapper[funcName]() : wrapper.thru(func); + } } - delete events[type]; - } - } else { - forEach(type.split(" "), function(type) { - if (isDefined(fn)) { - var listenerFns = events[type]; - arrayRemove(listenerFns || [], fn); - if (listenerFns && listenerFns.length > 0) { - return; + return function() { + var args = arguments, value = args[0]; + if (wrapper && args.length == 1 && isArray(value) && value.length >= LARGE_ARRAY_SIZE) { + return wrapper.plant(value).value(); + } + var index = 0, result = length ? funcs[index].apply(this, args) : value; + while (++index < length) { + result = funcs[index].call(this, result); } + return result; + }; + }; + } + function createForEach(arrayFunc, eachFunc) { + return function(collection, iteratee, thisArg) { + return typeof iteratee == "function" && thisArg === undefined && isArray(collection) ? arrayFunc(collection, iteratee) : eachFunc(collection, bindCallback(iteratee, thisArg, 3)); + }; + } + function createForIn(objectFunc) { + return function(object, iteratee, thisArg) { + if (typeof iteratee != "function" || thisArg !== undefined) { + iteratee = bindCallback(iteratee, thisArg, 3); } - removeEventListenerFn(element, type, handle); - delete events[type]; + return objectFunc(object, iteratee, keysIn); + }; + } + function createForOwn(objectFunc) { + return function(object, iteratee, thisArg) { + if (typeof iteratee != "function" || thisArg !== undefined) { + iteratee = bindCallback(iteratee, thisArg, 3); + } + return objectFunc(object, iteratee); + }; + } + function createObjectMapper(isMapKeys) { + return function(object, iteratee, thisArg) { + var result = {}; + iteratee = getCallback(iteratee, thisArg, 3); + baseForOwn(object, function(value, key, object) { + var mapped = iteratee(value, key, object); + key = isMapKeys ? mapped : key; + value = isMapKeys ? value : mapped; + result[key] = value; + }); + return result; + }; + } + function createPadDir(fromRight) { + return function(string, length, chars) { + string = baseToString(string); + return (fromRight ? string : "") + createPadding(string, length, chars) + (fromRight ? "" : string); + }; + } + function createPartial(flag) { + var partialFunc = restParam(function(func, partials) { + var holders = replaceHolders(partials, partialFunc.placeholder); + return createWrapper(func, flag, undefined, partials, holders); }); + return partialFunc; } - } - function jqLiteRemoveData(element, name) { - var expandoId = element.ng339; - var expandoStore = expandoId && jqCache[expandoId]; - if (expandoStore) { - if (name) { - delete expandoStore.data[name]; - return; + function createReduce(arrayFunc, eachFunc) { + return function(collection, iteratee, accumulator, thisArg) { + var initFromArray = arguments.length < 3; + return typeof iteratee == "function" && thisArg === undefined && isArray(collection) ? arrayFunc(collection, iteratee, accumulator, initFromArray) : baseReduce(collection, getCallback(iteratee, thisArg, 4), accumulator, initFromArray, eachFunc); + }; + } + function createHybridWrapper(func, bitmask, thisArg, partials, holders, partialsRight, holdersRight, argPos, ary, arity) { + var isAry = bitmask & ARY_FLAG, isBind = bitmask & BIND_FLAG, isBindKey = bitmask & BIND_KEY_FLAG, isCurry = bitmask & CURRY_FLAG, isCurryBound = bitmask & CURRY_BOUND_FLAG, isCurryRight = bitmask & CURRY_RIGHT_FLAG, Ctor = isBindKey ? undefined : createCtorWrapper(func); + function wrapper() { + var length = arguments.length, index = length, args = Array(length); + while (index--) { + args[index] = arguments[index]; + } + if (partials) { + args = composeArgs(args, partials, holders); + } + if (partialsRight) { + args = composeArgsRight(args, partialsRight, holdersRight); + } + if (isCurry || isCurryRight) { + var placeholder = wrapper.placeholder, argsHolders = replaceHolders(args, placeholder); + length -= argsHolders.length; + if (length < arity) { + var newArgPos = argPos ? arrayCopy(argPos) : undefined, newArity = nativeMax(arity - length, 0), newsHolders = isCurry ? argsHolders : undefined, newHoldersRight = isCurry ? undefined : argsHolders, newPartials = isCurry ? args : undefined, newPartialsRight = isCurry ? undefined : args; + bitmask |= isCurry ? PARTIAL_FLAG : PARTIAL_RIGHT_FLAG; + bitmask &= ~(isCurry ? PARTIAL_RIGHT_FLAG : PARTIAL_FLAG); + if (!isCurryBound) { + bitmask &= ~(BIND_FLAG | BIND_KEY_FLAG); + } + var newData = [ func, bitmask, thisArg, newPartials, newsHolders, newPartialsRight, newHoldersRight, newArgPos, ary, newArity ], result = createHybridWrapper.apply(undefined, newData); + if (isLaziable(func)) { + setData(result, newData); + } + result.placeholder = placeholder; + return result; + } + } + var thisBinding = isBind ? thisArg : this, fn = isBindKey ? thisBinding[func] : func; + if (argPos) { + args = reorder(args, argPos); + } + if (isAry && ary < args.length) { + args.length = ary; + } + if (this && this !== root && this instanceof wrapper) { + fn = Ctor || createCtorWrapper(func); + } + return fn.apply(thisBinding, args); } - if (expandoStore.handle) { - if (expandoStore.events.$destroy) { - expandoStore.handle({}, "$destroy"); + return wrapper; + } + function createPadding(string, length, chars) { + var strLength = string.length; + length = +length; + if (strLength >= length || !nativeIsFinite(length)) { + return ""; + } + var padLength = length - strLength; + chars = chars == null ? " " : chars + ""; + return repeat(chars, nativeCeil(padLength / chars.length)).slice(0, padLength); + } + function createPartialWrapper(func, bitmask, thisArg, partials) { + var isBind = bitmask & BIND_FLAG, Ctor = createCtorWrapper(func); + function wrapper() { + var argsIndex = -1, argsLength = arguments.length, leftIndex = -1, leftLength = partials.length, args = Array(leftLength + argsLength); + while (++leftIndex < leftLength) { + args[leftIndex] = partials[leftIndex]; } - jqLiteOff(element); + while (argsLength--) { + args[leftIndex++] = arguments[++argsIndex]; + } + var fn = this && this !== root && this instanceof wrapper ? Ctor : func; + return fn.apply(isBind ? thisArg : this, args); } - delete jqCache[expandoId]; - element.ng339 = undefined; + return wrapper; } - } - function jqLiteExpandoStore(element, createIfNecessary) { - var expandoId = element.ng339, expandoStore = expandoId && jqCache[expandoId]; - if (createIfNecessary && !expandoStore) { - element.ng339 = expandoId = jqNextId(); - expandoStore = jqCache[expandoId] = { - events: {}, - data: {}, - handle: undefined + function createRound(methodName) { + var func = Math[methodName]; + return function(number, precision) { + precision = precision === undefined ? 0 : +precision || 0; + if (precision) { + precision = pow(10, precision); + return func(number * precision) / precision; + } + return func(number); }; } - return expandoStore; - } - function jqLiteData(element, key, value) { - if (jqLiteAcceptsData(element)) { - var isSimpleSetter = isDefined(value); - var isSimpleGetter = !isSimpleSetter && key && !isObject(key); - var massGetter = !key; - var expandoStore = jqLiteExpandoStore(element, !isSimpleGetter); - var data = expandoStore && expandoStore.data; - if (isSimpleSetter) { - data[key] = value; + function createSortedIndex(retHighest) { + return function(array, value, iteratee, thisArg) { + var callback = getCallback(iteratee); + return iteratee == null && callback === baseCallback ? binaryIndex(array, value, retHighest) : binaryIndexBy(array, value, callback(iteratee, thisArg, 1), retHighest); + }; + } + function createWrapper(func, bitmask, thisArg, partials, holders, argPos, ary, arity) { + var isBindKey = bitmask & BIND_KEY_FLAG; + if (!isBindKey && typeof func != "function") { + throw new TypeError(FUNC_ERROR_TEXT); + } + var length = partials ? partials.length : 0; + if (!length) { + bitmask &= ~(PARTIAL_FLAG | PARTIAL_RIGHT_FLAG); + partials = holders = undefined; + } + length -= holders ? holders.length : 0; + if (bitmask & PARTIAL_RIGHT_FLAG) { + var partialsRight = partials, holdersRight = holders; + partials = holders = undefined; + } + var data = isBindKey ? undefined : getData(func), newData = [ func, bitmask, thisArg, partials, holders, partialsRight, holdersRight, argPos, ary, arity ]; + if (data) { + mergeData(newData, data); + bitmask = newData[1]; + arity = newData[9]; + } + newData[9] = arity == null ? isBindKey ? 0 : func.length : nativeMax(arity - length, 0) || 0; + if (bitmask == BIND_FLAG) { + var result = createBindWrapper(newData[0], newData[2]); + } else if ((bitmask == PARTIAL_FLAG || bitmask == (BIND_FLAG | PARTIAL_FLAG)) && !newData[4].length) { + result = createPartialWrapper.apply(undefined, newData); } else { - if (massGetter) { - return data; - } else { - if (isSimpleGetter) { - return data && data[key]; - } else { - extend(data, key); + result = createHybridWrapper.apply(undefined, newData); + } + var setter = data ? baseSetData : setData; + return setter(result, newData); + } + function equalArrays(array, other, equalFunc, customizer, isLoose, stackA, stackB) { + var index = -1, arrLength = array.length, othLength = other.length; + if (arrLength != othLength && !(isLoose && othLength > arrLength)) { + return false; + } + while (++index < arrLength) { + var arrValue = array[index], othValue = other[index], result = customizer ? customizer(isLoose ? othValue : arrValue, isLoose ? arrValue : othValue, index) : undefined; + if (result !== undefined) { + if (result) { + continue; + } + return false; + } + if (isLoose) { + if (!arraySome(other, function(othValue) { + return arrValue === othValue || equalFunc(arrValue, othValue, customizer, isLoose, stackA, stackB); + })) { + return false; } + } else if (!(arrValue === othValue || equalFunc(arrValue, othValue, customizer, isLoose, stackA, stackB))) { + return false; } } + return true; } - } - function jqLiteHasClass(element, selector) { - if (!element.getAttribute) return false; - return (" " + (element.getAttribute("class") || "") + " ").replace(/[\n\t]/g, " ").indexOf(" " + selector + " ") > -1; - } - function jqLiteRemoveClass(element, cssClasses) { - if (cssClasses && element.setAttribute) { - forEach(cssClasses.split(" "), function(cssClass) { - element.setAttribute("class", trim((" " + (element.getAttribute("class") || "") + " ").replace(/[\n\t]/g, " ").replace(" " + trim(cssClass) + " ", " "))); - }); + function equalByTag(object, other, tag) { + switch (tag) { + case boolTag: + case dateTag: + return +object == +other; + + case errorTag: + return object.name == other.name && object.message == other.message; + + case numberTag: + return object != +object ? other != +other : object == +other; + + case regexpTag: + case stringTag: + return object == other + ""; + } + return false; } - } - function jqLiteAddClass(element, cssClasses) { - if (cssClasses && element.setAttribute) { - var existingClasses = (" " + (element.getAttribute("class") || "") + " ").replace(/[\n\t]/g, " "); - forEach(cssClasses.split(" "), function(cssClass) { - cssClass = trim(cssClass); - if (existingClasses.indexOf(" " + cssClass + " ") === -1) { - existingClasses += cssClass + " "; + function equalObjects(object, other, equalFunc, customizer, isLoose, stackA, stackB) { + var objProps = keys(object), objLength = objProps.length, othProps = keys(other), othLength = othProps.length; + if (objLength != othLength && !isLoose) { + return false; + } + var index = objLength; + while (index--) { + var key = objProps[index]; + if (!(isLoose ? key in other : hasOwnProperty.call(other, key))) { + return false; } - }); - element.setAttribute("class", trim(existingClasses)); + } + var skipCtor = isLoose; + while (++index < objLength) { + key = objProps[index]; + var objValue = object[key], othValue = other[key], result = customizer ? customizer(isLoose ? othValue : objValue, isLoose ? objValue : othValue, key) : undefined; + if (!(result === undefined ? equalFunc(objValue, othValue, customizer, isLoose, stackA, stackB) : result)) { + return false; + } + skipCtor || (skipCtor = key == "constructor"); + } + if (!skipCtor) { + var objCtor = object.constructor, othCtor = other.constructor; + if (objCtor != othCtor && ("constructor" in object && "constructor" in other) && !(typeof objCtor == "function" && objCtor instanceof objCtor && typeof othCtor == "function" && othCtor instanceof othCtor)) { + return false; + } + } + return true; } - } - function jqLiteAddNodes(root, elements) { - if (elements) { - if (elements.nodeType) { - root[root.length++] = elements; - } else { - var length = elements.length; - if (typeof length === "number" && elements.window !== elements) { - if (length) { - for (var i = 0; i < length; i++) { - root[root.length++] = elements[i]; - } - } - } else { - root[root.length++] = elements; + function getCallback(func, thisArg, argCount) { + var result = lodash.callback || callback; + result = result === callback ? baseCallback : result; + return argCount ? result(func, thisArg, argCount) : result; + } + var getData = !metaMap ? noop : function(func) { + return metaMap.get(func); + }; + function getFuncName(func) { + var result = func.name + "", array = realNames[result], length = array ? array.length : 0; + while (length--) { + var data = array[length], otherFunc = data.func; + if (otherFunc == null || otherFunc == func) { + return data.name; } } + return result; } - } - function jqLiteController(element, name) { - return jqLiteInheritedData(element, "$" + (name || "ngController") + "Controller"); - } - function jqLiteInheritedData(element, name, value) { - if (element.nodeType == NODE_TYPE_DOCUMENT) { - element = element.documentElement; + function getIndexOf(collection, target, fromIndex) { + var result = lodash.indexOf || indexOf; + result = result === indexOf ? baseIndexOf : result; + return collection ? result(collection, target, fromIndex) : result; } - var names = isArray(name) ? name : [ name ]; - while (element) { - for (var i = 0, ii = names.length; i < ii; i++) { - if (isDefined(value = jqLite.data(element, names[i]))) return value; + var getLength = baseProperty("length"); + function getMatchData(object) { + var result = pairs(object), length = result.length; + while (length--) { + result[length][2] = isStrictComparable(result[length][1]); } - element = element.parentNode || element.nodeType === NODE_TYPE_DOCUMENT_FRAGMENT && element.host; + return result; } - } - function jqLiteEmpty(element) { - jqLiteDealoc(element, true); - while (element.firstChild) { - element.removeChild(element.firstChild); + function getNative(object, key) { + var value = object == null ? undefined : object[key]; + return isNative(value) ? value : undefined; + } + function getView(start, end, transforms) { + var index = -1, length = transforms.length; + while (++index < length) { + var data = transforms[index], size = data.size; + switch (data.type) { + case "drop": + start += size; + break; + + case "dropRight": + end -= size; + break; + + case "take": + end = nativeMin(end, start + size); + break; + + case "takeRight": + start = nativeMax(start, end - size); + break; + } + } + return { + start: start, + end: end + }; } - } - function jqLiteRemove(element, keepData) { - if (!keepData) jqLiteDealoc(element); - var parent = element.parentNode; - if (parent) parent.removeChild(element); - } - function jqLiteDocumentLoaded(action, win) { - win = win || window; - if (win.document.readyState === "complete") { - win.setTimeout(action); - } else { - jqLite(win).on("load", action); + function initCloneArray(array) { + var length = array.length, result = new array.constructor(length); + if (length && typeof array[0] == "string" && hasOwnProperty.call(array, "index")) { + result.index = array.index; + result.input = array.input; + } + return result; } - } - var JQLitePrototype = JQLite.prototype = { - ready: function(fn) { - var fired = false; - function trigger() { - if (fired) return; - fired = true; - fn(); + function initCloneObject(object) { + var Ctor = object.constructor; + if (!(typeof Ctor == "function" && Ctor instanceof Ctor)) { + Ctor = Object; } - if (document.readyState === "complete") { - setTimeout(trigger); - } else { - this.on("DOMContentLoaded", trigger); - JQLite(window).on("load", trigger); + return new Ctor(); + } + function initCloneByTag(object, tag, isDeep) { + var Ctor = object.constructor; + switch (tag) { + case arrayBufferTag: + return bufferClone(object); + + case boolTag: + case dateTag: + return new Ctor(+object); + + case float32Tag: + case float64Tag: + case int8Tag: + case int16Tag: + case int32Tag: + case uint8Tag: + case uint8ClampedTag: + case uint16Tag: + case uint32Tag: + var buffer = object.buffer; + return new Ctor(isDeep ? bufferClone(buffer) : buffer, object.byteOffset, object.length); + + case numberTag: + case stringTag: + return new Ctor(object); + + case regexpTag: + var result = new Ctor(object.source, reFlags.exec(object)); + result.lastIndex = object.lastIndex; } - }, - toString: function() { - var value = []; - forEach(this, function(e) { - value.push("" + e); - }); - return "[" + value.join(", ") + "]"; - }, - eq: function(index) { - return index >= 0 ? jqLite(this[index]) : jqLite(this[this.length + index]); - }, - length: 0, - push: push, - sort: [].sort, - splice: [].splice - }; - var BOOLEAN_ATTR = {}; - forEach("multiple,selected,checked,disabled,readOnly,required,open".split(","), function(value) { - BOOLEAN_ATTR[lowercase(value)] = value; - }); - var BOOLEAN_ELEMENTS = {}; - forEach("input,select,option,textarea,button,form,details".split(","), function(value) { - BOOLEAN_ELEMENTS[value] = true; - }); - var ALIASED_ATTR = { - ngMinlength: "minlength", - ngMaxlength: "maxlength", - ngMin: "min", - ngMax: "max", - ngPattern: "pattern" - }; - function getBooleanAttrName(element, name) { - var booleanAttr = BOOLEAN_ATTR[name.toLowerCase()]; - return booleanAttr && BOOLEAN_ELEMENTS[nodeName_(element)] && booleanAttr; - } - function getAliasedAttrName(name) { - return ALIASED_ATTR[name]; - } - forEach({ - data: jqLiteData, - removeData: jqLiteRemoveData, - hasData: jqLiteHasData - }, function(fn, name) { - JQLite[name] = fn; - }); - forEach({ - data: jqLiteData, - inheritedData: jqLiteInheritedData, - scope: function(element) { - return jqLite.data(element, "$scope") || jqLiteInheritedData(element.parentNode || element, [ "$isolateScope", "$scope" ]); - }, - isolateScope: function(element) { - return jqLite.data(element, "$isolateScope") || jqLite.data(element, "$isolateScopeNoTemplate"); - }, - controller: jqLiteController, - injector: function(element) { - return jqLiteInheritedData(element, "$injector"); - }, - removeAttr: function(element, name) { - element.removeAttribute(name); - }, - hasClass: jqLiteHasClass, - css: function(element, name, value) { - name = camelCase(name); - if (isDefined(value)) { - element.style[name] = value; - } else { - return element.style[name]; + return result; + } + function invokePath(object, path, args) { + if (object != null && !isKey(path, object)) { + path = toPath(path); + object = path.length == 1 ? object : baseGet(object, baseSlice(path, 0, -1)); + path = last(path); } - }, - attr: function(element, name, value) { - var nodeType = element.nodeType; - if (nodeType === NODE_TYPE_TEXT || nodeType === NODE_TYPE_ATTRIBUTE || nodeType === NODE_TYPE_COMMENT) { - return; + var func = object == null ? object : object[path]; + return func == null ? undefined : func.apply(object, args); + } + function isArrayLike(value) { + return value != null && isLength(getLength(value)); + } + function isIndex(value, length) { + value = typeof value == "number" || reIsUint.test(value) ? +value : -1; + length = length == null ? MAX_SAFE_INTEGER : length; + return value > -1 && value % 1 == 0 && value < length; + } + function isIterateeCall(value, index, object) { + if (!isObject(object)) { + return false; } - var lowercasedName = lowercase(name); - if (BOOLEAN_ATTR[lowercasedName]) { - if (isDefined(value)) { - if (!!value) { - element[name] = true; - element.setAttribute(name, lowercasedName); - } else { - element[name] = false; - element.removeAttribute(lowercasedName); + var type = typeof index; + if (type == "number" ? isArrayLike(object) && isIndex(index, object.length) : type == "string" && index in object) { + var other = object[index]; + return value === value ? value === other : other !== other; + } + return false; + } + function isKey(value, object) { + var type = typeof value; + if (type == "string" && reIsPlainProp.test(value) || type == "number") { + return true; + } + if (isArray(value)) { + return false; + } + var result = !reIsDeepProp.test(value); + return result || object != null && value in toObject(object); + } + function isLaziable(func) { + var funcName = getFuncName(func), other = lodash[funcName]; + if (typeof other != "function" || !(funcName in LazyWrapper.prototype)) { + return false; + } + if (func === other) { + return true; + } + var data = getData(other); + return !!data && func === data[0]; + } + function isLength(value) { + return typeof value == "number" && value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER; + } + function isStrictComparable(value) { + return value === value && !isObject(value); + } + function mergeData(data, source) { + var bitmask = data[1], srcBitmask = source[1], newBitmask = bitmask | srcBitmask, isCommon = newBitmask < ARY_FLAG; + var isCombo = srcBitmask == ARY_FLAG && bitmask == CURRY_FLAG || srcBitmask == ARY_FLAG && bitmask == REARG_FLAG && data[7].length <= source[8] || srcBitmask == (ARY_FLAG | REARG_FLAG) && bitmask == CURRY_FLAG; + if (!(isCommon || isCombo)) { + return data; + } + if (srcBitmask & BIND_FLAG) { + data[2] = source[2]; + newBitmask |= bitmask & BIND_FLAG ? 0 : CURRY_BOUND_FLAG; + } + var value = source[3]; + if (value) { + var partials = data[3]; + data[3] = partials ? composeArgs(partials, value, source[4]) : arrayCopy(value); + data[4] = partials ? replaceHolders(data[3], PLACEHOLDER) : arrayCopy(source[4]); + } + value = source[5]; + if (value) { + partials = data[5]; + data[5] = partials ? composeArgsRight(partials, value, source[6]) : arrayCopy(value); + data[6] = partials ? replaceHolders(data[5], PLACEHOLDER) : arrayCopy(source[6]); + } + value = source[7]; + if (value) { + data[7] = arrayCopy(value); + } + if (srcBitmask & ARY_FLAG) { + data[8] = data[8] == null ? source[8] : nativeMin(data[8], source[8]); + } + if (data[9] == null) { + data[9] = source[9]; + } + data[0] = source[0]; + data[1] = newBitmask; + return data; + } + function mergeDefaults(objectValue, sourceValue) { + return objectValue === undefined ? sourceValue : merge(objectValue, sourceValue, mergeDefaults); + } + function pickByArray(object, props) { + object = toObject(object); + var index = -1, length = props.length, result = {}; + while (++index < length) { + var key = props[index]; + if (key in object) { + result[key] = object[key]; + } + } + return result; + } + function pickByCallback(object, predicate) { + var result = {}; + baseForIn(object, function(value, key, object) { + if (predicate(value, key, object)) { + result[key] = value; + } + }); + return result; + } + function reorder(array, indexes) { + var arrLength = array.length, length = nativeMin(indexes.length, arrLength), oldArray = arrayCopy(array); + while (length--) { + var index = indexes[length]; + array[length] = isIndex(index, arrLength) ? oldArray[index] : undefined; + } + return array; + } + var setData = function() { + var count = 0, lastCalled = 0; + return function(key, value) { + var stamp = now(), remaining = HOT_SPAN - (stamp - lastCalled); + lastCalled = stamp; + if (remaining > 0) { + if (++count >= HOT_COUNT) { + return key; } } else { - return element[name] || (element.attributes.getNamedItem(name) || noop).specified ? lowercasedName : undefined; + count = 0; + } + return baseSetData(key, value); + }; + }(); + function shimKeys(object) { + var props = keysIn(object), propsLength = props.length, length = propsLength && object.length; + var allowIndexes = !!length && isLength(length) && (isArray(object) || isArguments(object)); + var index = -1, result = []; + while (++index < propsLength) { + var key = props[index]; + if (allowIndexes && isIndex(key, length) || hasOwnProperty.call(object, key)) { + result.push(key); } - } else if (isDefined(value)) { - element.setAttribute(name, value); - } else if (element.getAttribute) { - var ret = element.getAttribute(name, 2); - return ret === null ? undefined : ret; } - }, - prop: function(element, name, value) { - if (isDefined(value)) { - element[name] = value; + return result; + } + function toIterable(value) { + if (value == null) { + return []; + } + if (!isArrayLike(value)) { + return values(value); + } + return isObject(value) ? value : Object(value); + } + function toObject(value) { + return isObject(value) ? value : Object(value); + } + function toPath(value) { + if (isArray(value)) { + return value; + } + var result = []; + baseToString(value).replace(rePropName, function(match, number, quote, string) { + result.push(quote ? string.replace(reEscapeChar, "$1") : number || match); + }); + return result; + } + function wrapperClone(wrapper) { + return wrapper instanceof LazyWrapper ? wrapper.clone() : new LodashWrapper(wrapper.__wrapped__, wrapper.__chain__, arrayCopy(wrapper.__actions__)); + } + function chunk(array, size, guard) { + if (guard ? isIterateeCall(array, size, guard) : size == null) { + size = 1; } else { - return element[name]; + size = nativeMax(nativeFloor(size) || 1, 1); } - }, - text: function() { - getText.$dv = ""; - return getText; - function getText(element, value) { - if (isUndefined(value)) { - var nodeType = element.nodeType; - return nodeType === NODE_TYPE_ELEMENT || nodeType === NODE_TYPE_TEXT ? element.textContent : ""; + var index = 0, length = array ? array.length : 0, resIndex = -1, result = Array(nativeCeil(length / size)); + while (index < length) { + result[++resIndex] = baseSlice(array, index, index += size); + } + return result; + } + function compact(array) { + var index = -1, length = array ? array.length : 0, resIndex = -1, result = []; + while (++index < length) { + var value = array[index]; + if (value) { + result[++resIndex] = value; } - element.textContent = value; } - }(), - val: function(element, value) { - if (isUndefined(value)) { - if (element.multiple && nodeName_(element) === "select") { - var result = []; - forEach(element.options, function(option) { - if (option.selected) { - result.push(option.value || option.text); - } - }); - return result.length === 0 ? null : result; + return result; + } + var difference = restParam(function(array, values) { + return isObjectLike(array) && isArrayLike(array) ? baseDifference(array, baseFlatten(values, false, true)) : []; + }); + function drop(array, n, guard) { + var length = array ? array.length : 0; + if (!length) { + return []; + } + if (guard ? isIterateeCall(array, n, guard) : n == null) { + n = 1; + } + return baseSlice(array, n < 0 ? 0 : n); + } + function dropRight(array, n, guard) { + var length = array ? array.length : 0; + if (!length) { + return []; + } + if (guard ? isIterateeCall(array, n, guard) : n == null) { + n = 1; + } + n = length - (+n || 0); + return baseSlice(array, 0, n < 0 ? 0 : n); + } + function dropRightWhile(array, predicate, thisArg) { + return array && array.length ? baseWhile(array, getCallback(predicate, thisArg, 3), true, true) : []; + } + function dropWhile(array, predicate, thisArg) { + return array && array.length ? baseWhile(array, getCallback(predicate, thisArg, 3), true) : []; + } + function fill(array, value, start, end) { + var length = array ? array.length : 0; + if (!length) { + return []; + } + if (start && typeof start != "number" && isIterateeCall(array, value, start)) { + start = 0; + end = length; + } + return baseFill(array, value, start, end); + } + var findIndex = createFindIndex(); + var findLastIndex = createFindIndex(true); + function first(array) { + return array ? array[0] : undefined; + } + function flatten(array, isDeep, guard) { + var length = array ? array.length : 0; + if (guard && isIterateeCall(array, isDeep, guard)) { + isDeep = false; + } + return length ? baseFlatten(array, isDeep) : []; + } + function flattenDeep(array) { + var length = array ? array.length : 0; + return length ? baseFlatten(array, true) : []; + } + function indexOf(array, value, fromIndex) { + var length = array ? array.length : 0; + if (!length) { + return -1; + } + if (typeof fromIndex == "number") { + fromIndex = fromIndex < 0 ? nativeMax(length + fromIndex, 0) : fromIndex; + } else if (fromIndex) { + var index = binaryIndex(array, value); + if (index < length && (value === value ? value === array[index] : array[index] !== array[index])) { + return index; } - return element.value; + return -1; } - element.value = value; - }, - html: function(element, value) { - if (isUndefined(value)) { - return element.innerHTML; + return baseIndexOf(array, value, fromIndex || 0); + } + function initial(array) { + return dropRight(array, 1); + } + var intersection = restParam(function(arrays) { + var othLength = arrays.length, othIndex = othLength, caches = Array(length), indexOf = getIndexOf(), isCommon = indexOf === baseIndexOf, result = []; + while (othIndex--) { + var value = arrays[othIndex] = isArrayLike(value = arrays[othIndex]) ? value : []; + caches[othIndex] = isCommon && value.length >= 120 ? createCache(othIndex && value) : null; } - jqLiteDealoc(element, true); - element.innerHTML = value; - }, - empty: jqLiteEmpty - }, function(fn, name) { - JQLite.prototype[name] = function(arg1, arg2) { - var i, key; - var nodeCount = this.length; - if (fn !== jqLiteEmpty && isUndefined(fn.length == 2 && (fn !== jqLiteHasClass && fn !== jqLiteController) ? arg1 : arg2)) { - if (isObject(arg1)) { - for (i = 0; i < nodeCount; i++) { - if (fn === jqLiteData) { - fn(this[i], arg1); - } else { - for (key in arg1) { - fn(this[i], key, arg1[key]); - } + var array = arrays[0], index = -1, length = array ? array.length : 0, seen = caches[0]; + outer: while (++index < length) { + value = array[index]; + if ((seen ? cacheIndexOf(seen, value) : indexOf(result, value, 0)) < 0) { + var othIndex = othLength; + while (--othIndex) { + var cache = caches[othIndex]; + if ((cache ? cacheIndexOf(cache, value) : indexOf(arrays[othIndex], value, 0)) < 0) { + continue outer; } } - return this; - } else { - var value = fn.$dv; - var jj = isUndefined(value) ? Math.min(nodeCount, 1) : nodeCount; - for (var j = 0; j < jj; j++) { - var nodeValue = fn(this[j], arg1, arg2); - value = value ? value + nodeValue : nodeValue; + if (seen) { + seen.push(value); } - return value; + result.push(value); } - } else { - for (i = 0; i < nodeCount; i++) { - fn(this[i], arg1, arg2); + } + return result; + }); + function last(array) { + var length = array ? array.length : 0; + return length ? array[length - 1] : undefined; + } + function lastIndexOf(array, value, fromIndex) { + var length = array ? array.length : 0; + if (!length) { + return -1; + } + var index = length; + if (typeof fromIndex == "number") { + index = (fromIndex < 0 ? nativeMax(length + fromIndex, 0) : nativeMin(fromIndex || 0, length - 1)) + 1; + } else if (fromIndex) { + index = binaryIndex(array, value, true) - 1; + var other = array[index]; + if (value === value ? value === other : other !== other) { + return index; } - return this; + return -1; } - }; - }); - function createEventHandler(element, events) { - var eventHandler = function(event, type) { - event.isDefaultPrevented = function() { - return event.defaultPrevented; - }; - var eventFns = events[type || event.type]; - var eventFnsLength = eventFns ? eventFns.length : 0; - if (!eventFnsLength) return; - if (isUndefined(event.immediatePropagationStopped)) { - var originalStopImmediatePropagation = event.stopImmediatePropagation; - event.stopImmediatePropagation = function() { - event.immediatePropagationStopped = true; - if (event.stopPropagation) { - event.stopPropagation(); - } - if (originalStopImmediatePropagation) { - originalStopImmediatePropagation.call(event); - } - }; + if (value !== value) { + return indexOfNaN(array, index, true); } - event.isImmediatePropagationStopped = function() { - return event.immediatePropagationStopped === true; - }; - if (eventFnsLength > 1) { - eventFns = shallowCopy(eventFns); - } - for (var i = 0; i < eventFnsLength; i++) { - if (!event.isImmediatePropagationStopped()) { - eventFns[i].call(element, event); + while (index--) { + if (array[index] === value) { + return index; } } - }; - eventHandler.elem = element; - return eventHandler; - } - forEach({ - removeData: jqLiteRemoveData, - on: function jqLiteOn(element, type, fn, unsupported) { - if (isDefined(unsupported)) throw jqLiteMinErr("onargs", "jqLite#on() does not support the `selector` or `eventData` parameters"); - if (!jqLiteAcceptsData(element)) { - return; - } - var expandoStore = jqLiteExpandoStore(element, true); - var events = expandoStore.events; - var handle = expandoStore.handle; - if (!handle) { - handle = expandoStore.handle = createEventHandler(element, events); + return -1; + } + function pull() { + var args = arguments, array = args[0]; + if (!(array && array.length)) { + return array; } - var types = type.indexOf(" ") >= 0 ? type.split(" ") : [ type ]; - var i = types.length; - while (i--) { - type = types[i]; - var eventFns = events[type]; - if (!eventFns) { - events[type] = []; - if (type === "mouseenter" || type === "mouseleave") { - jqLiteOn(element, MOUSE_EVENT_MAP[type], function(event) { - var target = this, related = event.relatedTarget; - if (!related || related !== target && !target.contains(related)) { - handle(event, type); - } - }); - } else { - if (type !== "$destroy") { - addEventListenerFn(element, type, handle); - } - } - eventFns = events[type]; + var index = 0, indexOf = getIndexOf(), length = args.length; + while (++index < length) { + var fromIndex = 0, value = args[index]; + while ((fromIndex = indexOf(array, value, fromIndex)) > -1) { + splice.call(array, fromIndex, 1); } - eventFns.push(fn); } - }, - off: jqLiteOff, - one: function(element, type, fn) { - element = jqLite(element); - element.on(type, function onFn() { - element.off(type, fn); - element.off(type, onFn); - }); - element.on(type, fn); - }, - replaceWith: function(element, replaceNode) { - var index, parent = element.parentNode; - jqLiteDealoc(element); - forEach(new JQLite(replaceNode), function(node) { - if (index) { - parent.insertBefore(node, index.nextSibling); - } else { - parent.replaceChild(node, element); - } - index = node; - }); - }, - children: function(element) { - var children = []; - forEach(element.childNodes, function(element) { - if (element.nodeType === NODE_TYPE_ELEMENT) { - children.push(element); + return array; + } + var pullAt = restParam(function(array, indexes) { + indexes = baseFlatten(indexes); + var result = baseAt(array, indexes); + basePullAt(array, indexes.sort(baseCompareAscending)); + return result; + }); + function remove(array, predicate, thisArg) { + var result = []; + if (!(array && array.length)) { + return result; + } + var index = -1, indexes = [], length = array.length; + predicate = getCallback(predicate, thisArg, 3); + while (++index < length) { + var value = array[index]; + if (predicate(value, index, array)) { + result.push(value); + indexes.push(index); } - }); - return children; - }, - contents: function(element) { - return element.contentDocument || element.childNodes || []; - }, - append: function(element, node) { - var nodeType = element.nodeType; - if (nodeType !== NODE_TYPE_ELEMENT && nodeType !== NODE_TYPE_DOCUMENT_FRAGMENT) return; - node = new JQLite(node); - for (var i = 0, ii = node.length; i < ii; i++) { - var child = node[i]; - element.appendChild(child); } - }, - prepend: function(element, node) { - if (element.nodeType === NODE_TYPE_ELEMENT) { - var index = element.firstChild; - forEach(new JQLite(node), function(child) { - element.insertBefore(child, index); - }); + basePullAt(array, indexes); + return result; + } + function rest(array) { + return drop(array, 1); + } + function slice(array, start, end) { + var length = array ? array.length : 0; + if (!length) { + return []; } - }, - wrap: function(element, wrapNode) { - wrapNode = jqLite(wrapNode).eq(0).clone()[0]; - var parent = element.parentNode; - if (parent) { - parent.replaceChild(wrapNode, element); + if (end && typeof end != "number" && isIterateeCall(array, start, end)) { + start = 0; + end = length; } - wrapNode.appendChild(element); - }, - remove: jqLiteRemove, - detach: function(element) { - jqLiteRemove(element, true); - }, - after: function(element, newElement) { - var index = element, parent = element.parentNode; - newElement = new JQLite(newElement); - for (var i = 0, ii = newElement.length; i < ii; i++) { - var node = newElement[i]; - parent.insertBefore(node, index.nextSibling); - index = node; + return baseSlice(array, start, end); + } + var sortedIndex = createSortedIndex(); + var sortedLastIndex = createSortedIndex(true); + function take(array, n, guard) { + var length = array ? array.length : 0; + if (!length) { + return []; } - }, - addClass: jqLiteAddClass, - removeClass: jqLiteRemoveClass, - toggleClass: function(element, selector, condition) { - if (selector) { - forEach(selector.split(" "), function(className) { - var classCondition = condition; - if (isUndefined(classCondition)) { - classCondition = !jqLiteHasClass(element, className); - } - (classCondition ? jqLiteAddClass : jqLiteRemoveClass)(element, className); - }); + if (guard ? isIterateeCall(array, n, guard) : n == null) { + n = 1; } - }, - parent: function(element) { - var parent = element.parentNode; - return parent && parent.nodeType !== NODE_TYPE_DOCUMENT_FRAGMENT ? parent : null; - }, - next: function(element) { - return element.nextElementSibling; - }, - find: function(element, selector) { - if (element.getElementsByTagName) { - return element.getElementsByTagName(selector); - } else { + return baseSlice(array, 0, n < 0 ? 0 : n); + } + function takeRight(array, n, guard) { + var length = array ? array.length : 0; + if (!length) { return []; } - }, - clone: jqLiteClone, - triggerHandler: function(element, event, extraParameters) { - var dummyEvent, eventFnsCopy, handlerArgs; - var eventName = event.type || event; - var expandoStore = jqLiteExpandoStore(element); - var events = expandoStore && expandoStore.events; - var eventFns = events && events[eventName]; - if (eventFns) { - dummyEvent = { - preventDefault: function() { - this.defaultPrevented = true; - }, - isDefaultPrevented: function() { - return this.defaultPrevented === true; - }, - stopImmediatePropagation: function() { - this.immediatePropagationStopped = true; - }, - isImmediatePropagationStopped: function() { - return this.immediatePropagationStopped === true; - }, - stopPropagation: noop, - type: eventName, - target: element - }; - if (event.type) { - dummyEvent = extend(dummyEvent, event); - } - eventFnsCopy = shallowCopy(eventFns); - handlerArgs = extraParameters ? [ dummyEvent ].concat(extraParameters) : [ dummyEvent ]; - forEach(eventFnsCopy, function(fn) { - if (!dummyEvent.isImmediatePropagationStopped()) { - fn.apply(element, handlerArgs); - } - }); + if (guard ? isIterateeCall(array, n, guard) : n == null) { + n = 1; } + n = length - (+n || 0); + return baseSlice(array, n < 0 ? 0 : n); } - }, function(fn, name) { - JQLite.prototype[name] = function(arg1, arg2, arg3) { - var value; - for (var i = 0, ii = this.length; i < ii; i++) { - if (isUndefined(value)) { - value = fn(this[i], arg1, arg2, arg3); - if (isDefined(value)) { - value = jqLite(value); - } - } else { - jqLiteAddNodes(value, fn(this[i], arg1, arg2, arg3)); - } + function takeRightWhile(array, predicate, thisArg) { + return array && array.length ? baseWhile(array, getCallback(predicate, thisArg, 3), false, true) : []; + } + function takeWhile(array, predicate, thisArg) { + return array && array.length ? baseWhile(array, getCallback(predicate, thisArg, 3)) : []; + } + var union = restParam(function(arrays) { + return baseUniq(baseFlatten(arrays, false, true)); + }); + function uniq(array, isSorted, iteratee, thisArg) { + var length = array ? array.length : 0; + if (!length) { + return []; } - return isDefined(value) ? value : this; - }; - JQLite.prototype.bind = JQLite.prototype.on; - JQLite.prototype.unbind = JQLite.prototype.off; - }); - function $$jqLiteProvider() { - this.$get = function $$jqLite() { - return extend(JQLite, { - hasClass: function(node, classes) { - if (node.attr) node = node[0]; - return jqLiteHasClass(node, classes); - }, - addClass: function(node, classes) { - if (node.attr) node = node[0]; - return jqLiteAddClass(node, classes); - }, - removeClass: function(node, classes) { - if (node.attr) node = node[0]; - return jqLiteRemoveClass(node, classes); + if (isSorted != null && typeof isSorted != "boolean") { + thisArg = iteratee; + iteratee = isIterateeCall(array, isSorted, thisArg) ? undefined : isSorted; + isSorted = false; + } + var callback = getCallback(); + if (!(iteratee == null && callback === baseCallback)) { + iteratee = callback(iteratee, thisArg, 3); + } + return isSorted && getIndexOf() === baseIndexOf ? sortedUniq(array, iteratee) : baseUniq(array, iteratee); + } + function unzip(array) { + if (!(array && array.length)) { + return []; + } + var index = -1, length = 0; + array = arrayFilter(array, function(group) { + if (isArrayLike(group)) { + length = nativeMax(group.length, length); + return true; } }); - }; - } - function hashKey(obj, nextUidFn) { - var key = obj && obj.$$hashKey; - if (key) { - if (typeof key === "function") { - key = obj.$$hashKey(); + var result = Array(length); + while (++index < length) { + result[index] = arrayMap(array, baseProperty(index)); } - return key; + return result; } - var objType = typeof obj; - if (objType == "function" || objType == "object" && obj !== null) { - key = obj.$$hashKey = objType + ":" + (nextUidFn || nextUid)(); - } else { - key = objType + ":" + obj; + function unzipWith(array, iteratee, thisArg) { + var length = array ? array.length : 0; + if (!length) { + return []; + } + var result = unzip(array); + if (iteratee == null) { + return result; + } + iteratee = bindCallback(iteratee, thisArg, 4); + return arrayMap(result, function(group) { + return arrayReduce(group, iteratee, undefined, true); + }); } - return key; - } - function HashMap(array, isolatedUid) { - if (isolatedUid) { - var uid = 0; - this.nextUid = function() { - return ++uid; - }; + var without = restParam(function(array, values) { + return isArrayLike(array) ? baseDifference(array, values) : []; + }); + function xor() { + var index = -1, length = arguments.length; + while (++index < length) { + var array = arguments[index]; + if (isArrayLike(array)) { + var result = result ? arrayPush(baseDifference(result, array), baseDifference(array, result)) : array; + } + } + return result ? baseUniq(result) : []; } - forEach(array, this.put, this); - } - HashMap.prototype = { - put: function(key, value) { - this[hashKey(key, this.nextUid)] = value; - }, - get: function(key) { - return this[hashKey(key, this.nextUid)]; - }, - remove: function(key) { - var value = this[key = hashKey(key, this.nextUid)]; - delete this[key]; + var zip = restParam(unzip); + function zipObject(props, values) { + var index = -1, length = props ? props.length : 0, result = {}; + if (length && !values && !isArray(props[0])) { + values = []; + } + while (++index < length) { + var key = props[index]; + if (values) { + result[key] = values[index]; + } else if (key) { + result[key[0]] = key[1]; + } + } + return result; + } + var zipWith = restParam(function(arrays) { + var length = arrays.length, iteratee = length > 2 ? arrays[length - 2] : undefined, thisArg = length > 1 ? arrays[length - 1] : undefined; + if (length > 2 && typeof iteratee == "function") { + length -= 2; + } else { + iteratee = length > 1 && typeof thisArg == "function" ? (--length, thisArg) : undefined; + thisArg = undefined; + } + arrays.length = length; + return unzipWith(arrays, iteratee, thisArg); + }); + function chain(value) { + var result = lodash(value); + result.__chain__ = true; + return result; + } + function tap(value, interceptor, thisArg) { + interceptor.call(thisArg, value); return value; } - }; - var $$HashMapProvider = [ function() { - this.$get = [ function() { - return HashMap; - } ]; - } ]; - var FN_ARGS = /^[^\(]*\(\s*([^\)]*)\)/m; - var FN_ARG_SPLIT = /,/; - var FN_ARG = /^\s*(_?)(\S+?)\1\s*$/; - var STRIP_COMMENTS = /((\/\/.*$)|(\/\*[\s\S]*?\*\/))/gm; - var $injectorMinErr = minErr("$injector"); - function anonFn(fn) { - var fnText = fn.toString().replace(STRIP_COMMENTS, ""), args = fnText.match(FN_ARGS); - if (args) { - return "function(" + (args[1] || "").replace(/[\s\r\n]+/, " ") + ")"; + function thru(value, interceptor, thisArg) { + return interceptor.call(thisArg, value); } - return "fn"; - } - function annotate(fn, strictDi, name) { - var $inject, fnText, argDecl, last; - if (typeof fn === "function") { - if (!($inject = fn.$inject)) { - $inject = []; - if (fn.length) { - if (strictDi) { - if (!isString(name) || !name) { - name = fn.name || anonFn(fn); - } - throw $injectorMinErr("strictdi", "{0} is not using explicit annotation and cannot be invoked in strict mode", name); - } - fnText = fn.toString().replace(STRIP_COMMENTS, ""); - argDecl = fnText.match(FN_ARGS); - forEach(argDecl[1].split(FN_ARG_SPLIT), function(arg) { - arg.replace(FN_ARG, function(all, underscore, name) { - $inject.push(name); - }); - }); + function wrapperChain() { + return chain(this); + } + function wrapperCommit() { + return new LodashWrapper(this.value(), this.__chain__); + } + var wrapperConcat = restParam(function(values) { + values = baseFlatten(values); + return this.thru(function(array) { + return arrayConcat(isArray(array) ? array : [ toObject(array) ], values); + }); + }); + function wrapperPlant(value) { + var result, parent = this; + while (parent instanceof baseLodash) { + var clone = wrapperClone(parent); + if (result) { + previous.__wrapped__ = clone; + } else { + result = clone; } - fn.$inject = $inject; + var previous = clone; + parent = parent.__wrapped__; } - } else if (isArray(fn)) { - last = fn.length - 1; - assertArgFn(fn[last], "fn"); - $inject = fn.slice(0, last); - } else { - assertArgFn(fn, "fn", true); + previous.__wrapped__ = value; + return result; } - return $inject; - } - function createInjector(modulesToLoad, strictDi) { - strictDi = strictDi === true; - var INSTANTIATING = {}, providerSuffix = "Provider", path = [], loadedModules = new HashMap([], true), providerCache = { - $provide: { - provider: supportObject(provider), - factory: supportObject(factory), - service: supportObject(service), - value: supportObject(value), - constant: supportObject(constant), - decorator: decorator + function wrapperReverse() { + var value = this.__wrapped__; + var interceptor = function(value) { + return value.reverse(); + }; + if (value instanceof LazyWrapper) { + var wrapped = value; + if (this.__actions__.length) { + wrapped = new LazyWrapper(this); + } + wrapped = wrapped.reverse(); + wrapped.__actions__.push({ + func: thru, + args: [ interceptor ], + thisArg: undefined + }); + return new LodashWrapper(wrapped, this.__chain__); } - }, providerInjector = providerCache.$injector = createInternalInjector(providerCache, function(serviceName, caller) { - if (angular.isString(caller)) { - path.push(caller); + return this.thru(interceptor); + } + function wrapperToString() { + return this.value() + ""; + } + function wrapperValue() { + return baseWrapperValue(this.__wrapped__, this.__actions__); + } + var at = restParam(function(collection, props) { + return baseAt(collection, baseFlatten(props)); + }); + var countBy = createAggregator(function(result, value, key) { + hasOwnProperty.call(result, key) ? ++result[key] : result[key] = 1; + }); + function every(collection, predicate, thisArg) { + var func = isArray(collection) ? arrayEvery : baseEvery; + if (thisArg && isIterateeCall(collection, predicate, thisArg)) { + predicate = undefined; + } + if (typeof predicate != "function" || thisArg !== undefined) { + predicate = getCallback(predicate, thisArg, 3); + } + return func(collection, predicate); + } + function filter(collection, predicate, thisArg) { + var func = isArray(collection) ? arrayFilter : baseFilter; + predicate = getCallback(predicate, thisArg, 3); + return func(collection, predicate); + } + var find = createFind(baseEach); + var findLast = createFind(baseEachRight, true); + function findWhere(collection, source) { + return find(collection, baseMatches(source)); + } + var forEach = createForEach(arrayEach, baseEach); + var forEachRight = createForEach(arrayEachRight, baseEachRight); + var groupBy = createAggregator(function(result, value, key) { + if (hasOwnProperty.call(result, key)) { + result[key].push(value); + } else { + result[key] = [ value ]; } - throw $injectorMinErr("unpr", "Unknown provider: {0}", path.join(" <- ")); - }), instanceCache = {}, instanceInjector = instanceCache.$injector = createInternalInjector(instanceCache, function(serviceName, caller) { - var provider = providerInjector.get(serviceName + providerSuffix, caller); - return instanceInjector.invoke(provider.$get, provider, undefined, serviceName); }); - forEach(loadModules(modulesToLoad), function(fn) { - if (fn) instanceInjector.invoke(fn); + function includes(collection, target, fromIndex, guard) { + var length = collection ? getLength(collection) : 0; + if (!isLength(length)) { + collection = values(collection); + length = collection.length; + } + if (typeof fromIndex != "number" || guard && isIterateeCall(target, fromIndex, guard)) { + fromIndex = 0; + } else { + fromIndex = fromIndex < 0 ? nativeMax(length + fromIndex, 0) : fromIndex || 0; + } + return typeof collection == "string" || !isArray(collection) && isString(collection) ? fromIndex <= length && collection.indexOf(target, fromIndex) > -1 : !!length && getIndexOf(collection, target, fromIndex) > -1; + } + var indexBy = createAggregator(function(result, value, key) { + result[key] = value; }); - return instanceInjector; - function supportObject(delegate) { - return function(key, value) { - if (isObject(key)) { - forEach(key, reverseParams(delegate)); - } else { - return delegate(key, value); - } - }; + var invoke = restParam(function(collection, path, args) { + var index = -1, isFunc = typeof path == "function", isProp = isKey(path), result = isArrayLike(collection) ? Array(collection.length) : []; + baseEach(collection, function(value) { + var func = isFunc ? path : isProp && value != null ? value[path] : undefined; + result[++index] = func ? func.apply(value, args) : invokePath(value, path, args); + }); + return result; + }); + function map(collection, iteratee, thisArg) { + var func = isArray(collection) ? arrayMap : baseMap; + iteratee = getCallback(iteratee, thisArg, 3); + return func(collection, iteratee); } - function provider(name, provider_) { - assertNotHasOwnProperty(name, "service"); - if (isFunction(provider_) || isArray(provider_)) { - provider_ = providerInjector.instantiate(provider_); + var partition = createAggregator(function(result, value, key) { + result[key ? 0 : 1].push(value); + }, function() { + return [ [], [] ]; + }); + function pluck(collection, path) { + return map(collection, property(path)); + } + var reduce = createReduce(arrayReduce, baseEach); + var reduceRight = createReduce(arrayReduceRight, baseEachRight); + function reject(collection, predicate, thisArg) { + var func = isArray(collection) ? arrayFilter : baseFilter; + predicate = getCallback(predicate, thisArg, 3); + return func(collection, function(value, index, collection) { + return !predicate(value, index, collection); + }); + } + function sample(collection, n, guard) { + if (guard ? isIterateeCall(collection, n, guard) : n == null) { + collection = toIterable(collection); + var length = collection.length; + return length > 0 ? collection[baseRandom(0, length - 1)] : undefined; + } + var index = -1, result = toArray(collection), length = result.length, lastIndex = length - 1; + n = nativeMin(n < 0 ? 0 : +n || 0, length); + while (++index < n) { + var rand = baseRandom(index, lastIndex), value = result[rand]; + result[rand] = result[index]; + result[index] = value; + } + result.length = n; + return result; + } + function shuffle(collection) { + return sample(collection, POSITIVE_INFINITY); + } + function size(collection) { + var length = collection ? getLength(collection) : 0; + return isLength(length) ? length : keys(collection).length; + } + function some(collection, predicate, thisArg) { + var func = isArray(collection) ? arraySome : baseSome; + if (thisArg && isIterateeCall(collection, predicate, thisArg)) { + predicate = undefined; } - if (!provider_.$get) { - throw $injectorMinErr("pget", "Provider '{0}' must define $get factory method.", name); + if (typeof predicate != "function" || thisArg !== undefined) { + predicate = getCallback(predicate, thisArg, 3); } - return providerCache[name + providerSuffix] = provider_; - } - function enforceReturnValue(name, factory) { - return function enforcedReturnValue() { - var result = instanceInjector.invoke(factory, this); - if (isUndefined(result)) { - throw $injectorMinErr("undef", "Provider '{0}' must return a value from $get factory method.", name); - } - return result; - }; + return func(collection, predicate); } - function factory(name, factoryFn, enforce) { - return provider(name, { - $get: enforce !== false ? enforceReturnValue(name, factoryFn) : factoryFn + function sortBy(collection, iteratee, thisArg) { + if (collection == null) { + return []; + } + if (thisArg && isIterateeCall(collection, iteratee, thisArg)) { + iteratee = undefined; + } + var index = -1; + iteratee = getCallback(iteratee, thisArg, 3); + var result = baseMap(collection, function(value, key, collection) { + return { + criteria: iteratee(value, key, collection), + index: ++index, + value: value + }; }); + return baseSortBy(result, compareAscending); } - function service(name, constructor) { - return factory(name, [ "$injector", function($injector) { - return $injector.instantiate(constructor); - } ]); - } - function value(name, val) { - return factory(name, valueFn(val), false); + var sortByAll = restParam(function(collection, iteratees) { + if (collection == null) { + return []; + } + var guard = iteratees[2]; + if (guard && isIterateeCall(iteratees[0], iteratees[1], guard)) { + iteratees.length = 1; + } + return baseSortByOrder(collection, baseFlatten(iteratees), []); + }); + function sortByOrder(collection, iteratees, orders, guard) { + if (collection == null) { + return []; + } + if (guard && isIterateeCall(iteratees, orders, guard)) { + orders = undefined; + } + if (!isArray(iteratees)) { + iteratees = iteratees == null ? [] : [ iteratees ]; + } + if (!isArray(orders)) { + orders = orders == null ? [] : [ orders ]; + } + return baseSortByOrder(collection, iteratees, orders); } - function constant(name, value) { - assertNotHasOwnProperty(name, "constant"); - providerCache[name] = value; - instanceCache[name] = value; + function where(collection, source) { + return filter(collection, baseMatches(source)); } - function decorator(serviceName, decorFn) { - var origProvider = providerInjector.get(serviceName + providerSuffix), orig$get = origProvider.$get; - origProvider.$get = function() { - var origInstance = instanceInjector.invoke(orig$get, origProvider); - return instanceInjector.invoke(decorFn, null, { - $delegate: origInstance - }); + var now = nativeNow || function() { + return new Date().getTime(); + }; + function after(n, func) { + if (typeof func != "function") { + if (typeof n == "function") { + var temp = n; + n = func; + func = temp; + } else { + throw new TypeError(FUNC_ERROR_TEXT); + } + } + n = nativeIsFinite(n = +n) ? n : 0; + return function() { + if (--n < 1) { + return func.apply(this, arguments); + } }; } - function loadModules(modulesToLoad) { - assertArg(isUndefined(modulesToLoad) || isArray(modulesToLoad), "modulesToLoad", "not an array"); - var runBlocks = [], moduleFn; - forEach(modulesToLoad, function(module) { - if (loadedModules.get(module)) return; - loadedModules.put(module, true); - function runInvokeQueue(queue) { - var i, ii; - for (i = 0, ii = queue.length; i < ii; i++) { - var invokeArgs = queue[i], provider = providerInjector.get(invokeArgs[0]); - provider[invokeArgs[1]].apply(provider, invokeArgs[2]); - } + function ary(func, n, guard) { + if (guard && isIterateeCall(func, n, guard)) { + n = undefined; + } + n = func && n == null ? func.length : nativeMax(+n || 0, 0); + return createWrapper(func, ARY_FLAG, undefined, undefined, undefined, undefined, n); + } + function before(n, func) { + var result; + if (typeof func != "function") { + if (typeof n == "function") { + var temp = n; + n = func; + func = temp; + } else { + throw new TypeError(FUNC_ERROR_TEXT); } - try { - if (isString(module)) { - moduleFn = angularModule(module); - runBlocks = runBlocks.concat(loadModules(moduleFn.requires)).concat(moduleFn._runBlocks); - runInvokeQueue(moduleFn._invokeQueue); - runInvokeQueue(moduleFn._configBlocks); - } else if (isFunction(module)) { - runBlocks.push(providerInjector.invoke(module)); - } else if (isArray(module)) { - runBlocks.push(providerInjector.invoke(module)); - } else { - assertArgFn(module, "module"); - } - } catch (e) { - if (isArray(module)) { - module = module[module.length - 1]; - } - if (e.message && e.stack && e.stack.indexOf(e.message) == -1) { - e = e.message + "\n" + e.stack; - } - throw $injectorMinErr("modulerr", "Failed to instantiate module {0} due to:\n{1}", module, e.stack || e.message || e); + } + return function() { + if (--n > 0) { + result = func.apply(this, arguments); } - }); - return runBlocks; + if (n <= 1) { + func = undefined; + } + return result; + }; } - function createInternalInjector(cache, factory) { - function getService(serviceName, caller) { - if (cache.hasOwnProperty(serviceName)) { - if (cache[serviceName] === INSTANTIATING) { - throw $injectorMinErr("cdep", "Circular dependency found: {0}", serviceName + " <- " + path.join(" <- ")); - } - return cache[serviceName]; + var bind = restParam(function(func, thisArg, partials) { + var bitmask = BIND_FLAG; + if (partials.length) { + var holders = replaceHolders(partials, bind.placeholder); + bitmask |= PARTIAL_FLAG; + } + return createWrapper(func, bitmask, thisArg, partials, holders); + }); + var bindAll = restParam(function(object, methodNames) { + methodNames = methodNames.length ? baseFlatten(methodNames) : functions(object); + var index = -1, length = methodNames.length; + while (++index < length) { + var key = methodNames[index]; + object[key] = createWrapper(object[key], BIND_FLAG, object); + } + return object; + }); + var bindKey = restParam(function(object, key, partials) { + var bitmask = BIND_FLAG | BIND_KEY_FLAG; + if (partials.length) { + var holders = replaceHolders(partials, bindKey.placeholder); + bitmask |= PARTIAL_FLAG; + } + return createWrapper(key, bitmask, object, partials, holders); + }); + var curry = createCurry(CURRY_FLAG); + var curryRight = createCurry(CURRY_RIGHT_FLAG); + function debounce(func, wait, options) { + var args, maxTimeoutId, result, stamp, thisArg, timeoutId, trailingCall, lastCalled = 0, maxWait = false, trailing = true; + if (typeof func != "function") { + throw new TypeError(FUNC_ERROR_TEXT); + } + wait = wait < 0 ? 0 : +wait || 0; + if (options === true) { + var leading = true; + trailing = false; + } else if (isObject(options)) { + leading = !!options.leading; + maxWait = "maxWait" in options && nativeMax(+options.maxWait || 0, wait); + trailing = "trailing" in options ? !!options.trailing : trailing; + } + function cancel() { + if (timeoutId) { + clearTimeout(timeoutId); + } + if (maxTimeoutId) { + clearTimeout(maxTimeoutId); + } + lastCalled = 0; + maxTimeoutId = timeoutId = trailingCall = undefined; + } + function complete(isCalled, id) { + if (id) { + clearTimeout(id); + } + maxTimeoutId = timeoutId = trailingCall = undefined; + if (isCalled) { + lastCalled = now(); + result = func.apply(thisArg, args); + if (!timeoutId && !maxTimeoutId) { + args = thisArg = undefined; + } + } + } + function delayed() { + var remaining = wait - (now() - stamp); + if (remaining <= 0 || remaining > wait) { + complete(trailingCall, maxTimeoutId); } else { - try { - path.unshift(serviceName); - cache[serviceName] = INSTANTIATING; - return cache[serviceName] = factory(serviceName, caller); - } catch (err) { - if (cache[serviceName] === INSTANTIATING) { - delete cache[serviceName]; + timeoutId = setTimeout(delayed, remaining); + } + } + function maxDelayed() { + complete(trailing, timeoutId); + } + function debounced() { + args = arguments; + stamp = now(); + thisArg = this; + trailingCall = trailing && (timeoutId || !leading); + if (maxWait === false) { + var leadingCall = leading && !timeoutId; + } else { + if (!maxTimeoutId && !leading) { + lastCalled = stamp; + } + var remaining = maxWait - (stamp - lastCalled), isCalled = remaining <= 0 || remaining > maxWait; + if (isCalled) { + if (maxTimeoutId) { + maxTimeoutId = clearTimeout(maxTimeoutId); } - throw err; - } finally { - path.shift(); + lastCalled = stamp; + result = func.apply(thisArg, args); + } else if (!maxTimeoutId) { + maxTimeoutId = setTimeout(maxDelayed, remaining); } } - } - function invoke(fn, self, locals, serviceName) { - if (typeof locals === "string") { - serviceName = locals; - locals = null; + if (isCalled && timeoutId) { + timeoutId = clearTimeout(timeoutId); + } else if (!timeoutId && wait !== maxWait) { + timeoutId = setTimeout(delayed, wait); } - var args = [], $inject = createInjector.$$annotate(fn, strictDi, serviceName), length, i, key; - for (i = 0, length = $inject.length; i < length; i++) { - key = $inject[i]; - if (typeof key !== "string") { - throw $injectorMinErr("itkn", "Incorrect injection token! Expected service name as string, got {0}", key); - } - args.push(locals && locals.hasOwnProperty(key) ? locals[key] : getService(key, serviceName)); + if (leadingCall) { + isCalled = true; + result = func.apply(thisArg, args); } - if (isArray(fn)) { - fn = fn[length]; + if (isCalled && !timeoutId && !maxTimeoutId) { + args = thisArg = undefined; } - return fn.apply(self, args); + return result; } - function instantiate(Type, locals, serviceName) { - var instance = Object.create((isArray(Type) ? Type[Type.length - 1] : Type).prototype || null); - var returnedValue = invoke(Type, instance, locals, serviceName); - return isObject(returnedValue) || isFunction(returnedValue) ? returnedValue : instance; + debounced.cancel = cancel; + return debounced; + } + var defer = restParam(function(func, args) { + return baseDelay(func, 1, args); + }); + var delay = restParam(function(func, wait, args) { + return baseDelay(func, wait, args); + }); + var flow = createFlow(); + var flowRight = createFlow(true); + function memoize(func, resolver) { + if (typeof func != "function" || resolver && typeof resolver != "function") { + throw new TypeError(FUNC_ERROR_TEXT); + } + var memoized = function() { + var args = arguments, key = resolver ? resolver.apply(this, args) : args[0], cache = memoized.cache; + if (cache.has(key)) { + return cache.get(key); + } + var result = func.apply(this, args); + memoized.cache = cache.set(key, result); + return result; + }; + memoized.cache = new memoize.Cache(); + return memoized; + } + var modArgs = restParam(function(func, transforms) { + transforms = baseFlatten(transforms); + if (typeof func != "function" || !arrayEvery(transforms, baseIsFunction)) { + throw new TypeError(FUNC_ERROR_TEXT); } - return { - invoke: invoke, - instantiate: instantiate, - get: getService, - annotate: createInjector.$$annotate, - has: function(name) { - return providerCache.hasOwnProperty(name + providerSuffix) || cache.hasOwnProperty(name); + var length = transforms.length; + return restParam(function(args) { + var index = nativeMin(args.length, length); + while (index--) { + args[index] = transforms[index](args[index]); } + return func.apply(this, args); + }); + }); + function negate(predicate) { + if (typeof predicate != "function") { + throw new TypeError(FUNC_ERROR_TEXT); + } + return function() { + return !predicate.apply(this, arguments); }; } - } - createInjector.$$annotate = annotate; - function $AnchorScrollProvider() { - var autoScrollingEnabled = true; - this.disableAutoScrolling = function() { - autoScrollingEnabled = false; + function once(func) { + return before(2, func); + } + var partial = createPartial(PARTIAL_FLAG); + var partialRight = createPartial(PARTIAL_RIGHT_FLAG); + var rearg = restParam(function(func, indexes) { + return createWrapper(func, REARG_FLAG, undefined, undefined, undefined, baseFlatten(indexes)); + }); + function restParam(func, start) { + if (typeof func != "function") { + throw new TypeError(FUNC_ERROR_TEXT); + } + start = nativeMax(start === undefined ? func.length - 1 : +start || 0, 0); + return function() { + var args = arguments, index = -1, length = nativeMax(args.length - start, 0), rest = Array(length); + while (++index < length) { + rest[index] = args[start + index]; + } + switch (start) { + case 0: + return func.call(this, rest); + + case 1: + return func.call(this, args[0], rest); + + case 2: + return func.call(this, args[0], args[1], rest); + } + var otherArgs = Array(start + 1); + index = -1; + while (++index < start) { + otherArgs[index] = args[index]; + } + otherArgs[start] = rest; + return func.apply(this, otherArgs); + }; + } + function spread(func) { + if (typeof func != "function") { + throw new TypeError(FUNC_ERROR_TEXT); + } + return function(array) { + return func.apply(this, array); + }; + } + function throttle(func, wait, options) { + var leading = true, trailing = true; + if (typeof func != "function") { + throw new TypeError(FUNC_ERROR_TEXT); + } + if (options === false) { + leading = false; + } else if (isObject(options)) { + leading = "leading" in options ? !!options.leading : leading; + trailing = "trailing" in options ? !!options.trailing : trailing; + } + return debounce(func, wait, { + leading: leading, + maxWait: +wait, + trailing: trailing + }); + } + function wrap(value, wrapper) { + wrapper = wrapper == null ? identity : wrapper; + return createWrapper(wrapper, PARTIAL_FLAG, undefined, [ value ], []); + } + function clone(value, isDeep, customizer, thisArg) { + if (isDeep && typeof isDeep != "boolean" && isIterateeCall(value, isDeep, customizer)) { + isDeep = false; + } else if (typeof isDeep == "function") { + thisArg = customizer; + customizer = isDeep; + isDeep = false; + } + return typeof customizer == "function" ? baseClone(value, isDeep, bindCallback(customizer, thisArg, 3)) : baseClone(value, isDeep); + } + function cloneDeep(value, customizer, thisArg) { + return typeof customizer == "function" ? baseClone(value, true, bindCallback(customizer, thisArg, 3)) : baseClone(value, true); + } + function gt(value, other) { + return value > other; + } + function gte(value, other) { + return value >= other; + } + function isArguments(value) { + return isObjectLike(value) && isArrayLike(value) && hasOwnProperty.call(value, "callee") && !propertyIsEnumerable.call(value, "callee"); + } + var isArray = nativeIsArray || function(value) { + return isObjectLike(value) && isLength(value.length) && objToString.call(value) == arrayTag; }; - this.$get = [ "$window", "$location", "$rootScope", function($window, $location, $rootScope) { - var document = $window.document; - function getFirstAnchor(list) { - var result = null; - Array.prototype.some.call(list, function(element) { - if (nodeName_(element) === "a") { - result = element; - return true; - } - }); - return result; + function isBoolean(value) { + return value === true || value === false || isObjectLike(value) && objToString.call(value) == boolTag; + } + function isDate(value) { + return isObjectLike(value) && objToString.call(value) == dateTag; + } + function isElement(value) { + return !!value && value.nodeType === 1 && isObjectLike(value) && !isPlainObject(value); + } + function isEmpty(value) { + if (value == null) { + return true; } - function getYOffset() { - var offset = scroll.yOffset; - if (isFunction(offset)) { - offset = offset(); - } else if (isElement(offset)) { - var elem = offset[0]; - var style = $window.getComputedStyle(elem); - if (style.position !== "fixed") { - offset = 0; - } else { - offset = elem.getBoundingClientRect().bottom; - } - } else if (!isNumber(offset)) { - offset = 0; + if (isArrayLike(value) && (isArray(value) || isString(value) || isArguments(value) || isObjectLike(value) && isFunction(value.splice))) { + return !value.length; + } + return !keys(value).length; + } + function isEqual(value, other, customizer, thisArg) { + customizer = typeof customizer == "function" ? bindCallback(customizer, thisArg, 3) : undefined; + var result = customizer ? customizer(value, other) : undefined; + return result === undefined ? baseIsEqual(value, other, customizer) : !!result; + } + function isError(value) { + return isObjectLike(value) && typeof value.message == "string" && objToString.call(value) == errorTag; + } + function isFinite(value) { + return typeof value == "number" && nativeIsFinite(value); + } + function isFunction(value) { + return isObject(value) && objToString.call(value) == funcTag; + } + function isObject(value) { + var type = typeof value; + return !!value && (type == "object" || type == "function"); + } + function isMatch(object, source, customizer, thisArg) { + customizer = typeof customizer == "function" ? bindCallback(customizer, thisArg, 3) : undefined; + return baseIsMatch(object, getMatchData(source), customizer); + } + function isNaN(value) { + return isNumber(value) && value != +value; + } + function isNative(value) { + if (value == null) { + return false; + } + if (isFunction(value)) { + return reIsNative.test(fnToString.call(value)); + } + return isObjectLike(value) && reIsHostCtor.test(value); + } + function isNull(value) { + return value === null; + } + function isNumber(value) { + return typeof value == "number" || isObjectLike(value) && objToString.call(value) == numberTag; + } + function isPlainObject(value) { + var Ctor; + if (!(isObjectLike(value) && objToString.call(value) == objectTag && !isArguments(value)) || !hasOwnProperty.call(value, "constructor") && (Ctor = value.constructor, + typeof Ctor == "function" && !(Ctor instanceof Ctor))) { + return false; + } + var result; + baseForIn(value, function(subValue, key) { + result = key; + }); + return result === undefined || hasOwnProperty.call(value, result); + } + function isRegExp(value) { + return isObject(value) && objToString.call(value) == regexpTag; + } + function isString(value) { + return typeof value == "string" || isObjectLike(value) && objToString.call(value) == stringTag; + } + function isTypedArray(value) { + return isObjectLike(value) && isLength(value.length) && !!typedArrayTags[objToString.call(value)]; + } + function isUndefined(value) { + return value === undefined; + } + function lt(value, other) { + return value < other; + } + function lte(value, other) { + return value <= other; + } + function toArray(value) { + var length = value ? getLength(value) : 0; + if (!isLength(length)) { + return values(value); + } + if (!length) { + return []; + } + return arrayCopy(value); + } + function toPlainObject(value) { + return baseCopy(value, keysIn(value)); + } + var merge = createAssigner(baseMerge); + var assign = createAssigner(function(object, source, customizer) { + return customizer ? assignWith(object, source, customizer) : baseAssign(object, source); + }); + function create(prototype, properties, guard) { + var result = baseCreate(prototype); + if (guard && isIterateeCall(prototype, properties, guard)) { + properties = undefined; + } + return properties ? baseAssign(result, properties) : result; + } + var defaults = createDefaults(assign, assignDefaults); + var defaultsDeep = createDefaults(merge, mergeDefaults); + var findKey = createFindKey(baseForOwn); + var findLastKey = createFindKey(baseForOwnRight); + var forIn = createForIn(baseFor); + var forInRight = createForIn(baseForRight); + var forOwn = createForOwn(baseForOwn); + var forOwnRight = createForOwn(baseForOwnRight); + function functions(object) { + return baseFunctions(object, keysIn(object)); + } + function get(object, path, defaultValue) { + var result = object == null ? undefined : baseGet(object, toPath(path), path + ""); + return result === undefined ? defaultValue : result; + } + function has(object, path) { + if (object == null) { + return false; + } + var result = hasOwnProperty.call(object, path); + if (!result && !isKey(path)) { + path = toPath(path); + object = path.length == 1 ? object : baseGet(object, baseSlice(path, 0, -1)); + if (object == null) { + return false; } - return offset; + path = last(path); + result = hasOwnProperty.call(object, path); } - function scrollTo(elem) { - if (elem) { - elem.scrollIntoView(); - var offset = getYOffset(); - if (offset) { - var elemTop = elem.getBoundingClientRect().top; - $window.scrollBy(0, elemTop - offset); + return result || isLength(object.length) && isIndex(path, object.length) && (isArray(object) || isArguments(object)); + } + function invert(object, multiValue, guard) { + if (guard && isIterateeCall(object, multiValue, guard)) { + multiValue = undefined; + } + var index = -1, props = keys(object), length = props.length, result = {}; + while (++index < length) { + var key = props[index], value = object[key]; + if (multiValue) { + if (hasOwnProperty.call(result, value)) { + result[value].push(key); + } else { + result[value] = [ key ]; } } else { - $window.scrollTo(0, 0); + result[value] = key; } } - function scroll(hash) { - hash = isString(hash) ? hash : $location.hash(); - var elm; - if (!hash) scrollTo(null); else if (elm = document.getElementById(hash)) scrollTo(elm); else if (elm = getFirstAnchor(document.getElementsByName(hash))) scrollTo(elm); else if (hash === "top") scrollTo(null); + return result; + } + var keys = !nativeKeys ? shimKeys : function(object) { + var Ctor = object == null ? undefined : object.constructor; + if (typeof Ctor == "function" && Ctor.prototype === object || typeof object != "function" && isArrayLike(object)) { + return shimKeys(object); } - if (autoScrollingEnabled) { - $rootScope.$watch(function autoScrollWatch() { - return $location.hash(); - }, function autoScrollWatchAction(newVal, oldVal) { - if (newVal === oldVal && newVal === "") return; - jqLiteDocumentLoaded(function() { - $rootScope.$evalAsync(scroll); - }); - }); + return isObject(object) ? nativeKeys(object) : []; + }; + function keysIn(object) { + if (object == null) { + return []; } - return scroll; - } ]; - } - var $animateMinErr = minErr("$animate"); - var ELEMENT_NODE = 1; - var NG_ANIMATE_CLASSNAME = "ng-animate"; - function mergeClasses(a, b) { - if (!a && !b) return ""; - if (!a) return b; - if (!b) return a; - if (isArray(a)) a = a.join(" "); - if (isArray(b)) b = b.join(" "); - return a + " " + b; - } - function extractElementNode(element) { - for (var i = 0; i < element.length; i++) { - var elm = element[i]; - if (elm.nodeType === ELEMENT_NODE) { - return elm; + if (!isObject(object)) { + object = Object(object); + } + var length = object.length; + length = length && isLength(length) && (isArray(object) || isArguments(object)) && length || 0; + var Ctor = object.constructor, index = -1, isProto = typeof Ctor == "function" && Ctor.prototype === object, result = Array(length), skipIndexes = length > 0; + while (++index < length) { + result[index] = index + ""; + } + for (var key in object) { + if (!(skipIndexes && isIndex(key, length)) && !(key == "constructor" && (isProto || !hasOwnProperty.call(object, key)))) { + result.push(key); + } } + return result; } - } - function splitClasses(classes) { - if (isString(classes)) { - classes = classes.split(" "); + var mapKeys = createObjectMapper(true); + var mapValues = createObjectMapper(); + var omit = restParam(function(object, props) { + if (object == null) { + return {}; + } + if (typeof props[0] != "function") { + var props = arrayMap(baseFlatten(props), String); + return pickByArray(object, baseDifference(keysIn(object), props)); + } + var predicate = bindCallback(props[0], props[1], 3); + return pickByCallback(object, function(value, key, object) { + return !predicate(value, key, object); + }); + }); + function pairs(object) { + object = toObject(object); + var index = -1, props = keys(object), length = props.length, result = Array(length); + while (++index < length) { + var key = props[index]; + result[index] = [ key, object[key] ]; + } + return result; } - var obj = createMap(); - forEach(classes, function(klass) { - if (klass.length) { - obj[klass] = true; + var pick = restParam(function(object, props) { + if (object == null) { + return {}; } + return typeof props[0] == "function" ? pickByCallback(object, bindCallback(props[0], props[1], 3)) : pickByArray(object, baseFlatten(props)); }); - return obj; - } - function prepareAnimateOptions(options) { - return isObject(options) ? options : {}; - } - var $$CoreAnimateRunnerProvider = function() { - this.$get = [ "$q", "$$rAF", function($q, $$rAF) { - function AnimateRunner() {} - AnimateRunner.all = noop; - AnimateRunner.chain = noop; - AnimateRunner.prototype = { - end: noop, - cancel: noop, - resume: noop, - pause: noop, - complete: noop, - then: function(pass, fail) { - return $q(function(resolve) { - $$rAF(function() { - resolve(); - }); - }).then(pass, fail); - } - }; - return AnimateRunner; - } ]; - }; - var $$CoreAnimateQueueProvider = function() { - var postDigestQueue = new HashMap(); - var postDigestElements = []; - this.$get = [ "$$AnimateRunner", "$rootScope", function($$AnimateRunner, $rootScope) { - return { - enabled: noop, - on: noop, - off: noop, - pin: noop, - push: function(element, event, options, domOperation) { - domOperation && domOperation(); - options = options || {}; - options.from && element.css(options.from); - options.to && element.css(options.to); - if (options.addClass || options.removeClass) { - addRemoveClassesPostDigest(element, options.addClass, options.removeClass); + function result(object, path, defaultValue) { + var result = object == null ? undefined : object[path]; + if (result === undefined) { + if (object != null && !isKey(path, object)) { + path = toPath(path); + object = path.length == 1 ? object : baseGet(object, baseSlice(path, 0, -1)); + result = object == null ? undefined : object[last(path)]; + } + result = result === undefined ? defaultValue : result; + } + return isFunction(result) ? result.call(object) : result; + } + function set(object, path, value) { + if (object == null) { + return object; + } + var pathKey = path + ""; + path = object[pathKey] != null || isKey(path, object) ? [ pathKey ] : toPath(path); + var index = -1, length = path.length, lastIndex = length - 1, nested = object; + while (nested != null && ++index < length) { + var key = path[index]; + if (isObject(nested)) { + if (index == lastIndex) { + nested[key] = value; + } else if (nested[key] == null) { + nested[key] = isIndex(path[index + 1]) ? [] : {}; + } + } + nested = nested[key]; + } + return object; + } + function transform(object, iteratee, accumulator, thisArg) { + var isArr = isArray(object) || isTypedArray(object); + iteratee = getCallback(iteratee, thisArg, 4); + if (accumulator == null) { + if (isArr || isObject(object)) { + var Ctor = object.constructor; + if (isArr) { + accumulator = isArray(object) ? new Ctor() : []; + } else { + accumulator = baseCreate(isFunction(Ctor) ? Ctor.prototype : undefined); } - return new $$AnimateRunner(); - } - }; - function updateData(data, classes, value) { - var changed = false; - if (classes) { - classes = isString(classes) ? classes.split(" ") : isArray(classes) ? classes : []; - forEach(classes, function(className) { - if (className) { - changed = true; - data[className] = value; - } - }); + } else { + accumulator = {}; } - return changed; } - function handleCSSClassChanges() { - forEach(postDigestElements, function(element) { - var data = postDigestQueue.get(element); - if (data) { - var existing = splitClasses(element.attr("class")); - var toAdd = ""; - var toRemove = ""; - forEach(data, function(status, className) { - var hasClass = !!existing[className]; - if (status !== hasClass) { - if (status) { - toAdd += (toAdd.length ? " " : "") + className; - } else { - toRemove += (toRemove.length ? " " : "") + className; - } - } - }); - forEach(element, function(elm) { - toAdd && jqLiteAddClass(elm, toAdd); - toRemove && jqLiteRemoveClass(elm, toRemove); - }); - postDigestQueue.remove(element); - } - }); - postDigestElements.length = 0; + (isArr ? arrayEach : baseForOwn)(object, function(value, index, object) { + return iteratee(accumulator, value, index, object); + }); + return accumulator; + } + function values(object) { + return baseValues(object, keys(object)); + } + function valuesIn(object) { + return baseValues(object, keysIn(object)); + } + function inRange(value, start, end) { + start = +start || 0; + if (end === undefined) { + end = start; + start = 0; + } else { + end = +end || 0; } - function addRemoveClassesPostDigest(element, add, remove) { - var data = postDigestQueue.get(element) || {}; - var classesAdded = updateData(data, add, true); - var classesRemoved = updateData(data, remove, false); - if (classesAdded || classesRemoved) { - postDigestQueue.put(element, data); - postDigestElements.push(element); - if (postDigestElements.length === 1) { - $rootScope.$$postDigest(handleCSSClassChanges); - } + return value >= nativeMin(start, end) && value < nativeMax(start, end); + } + function random(min, max, floating) { + if (floating && isIterateeCall(min, max, floating)) { + max = floating = undefined; + } + var noMin = min == null, noMax = max == null; + if (floating == null) { + if (noMax && typeof min == "boolean") { + floating = min; + min = 1; + } else if (typeof max == "boolean") { + floating = max; + noMax = true; } } - } ]; - }; - var $AnimateProvider = [ "$provide", function($provide) { - var provider = this; - this.$$registeredAnimations = Object.create(null); - this.register = function(name, factory) { - if (name && name.charAt(0) !== ".") { - throw $animateMinErr("notcsel", "Expecting class selector starting with '.' got '{0}'.", name); + if (noMin && noMax) { + max = 1; + noMax = false; } - var key = name + "-animation"; - provider.$$registeredAnimations[name.substr(1)] = key; - $provide.factory(key, factory); - }; - this.classNameFilter = function(expression) { - if (arguments.length === 1) { - this.$$classNameFilter = expression instanceof RegExp ? expression : null; - if (this.$$classNameFilter) { - var reservedRegex = new RegExp("(\\s+|\\/)" + NG_ANIMATE_CLASSNAME + "(\\s+|\\/)"); - if (reservedRegex.test(this.$$classNameFilter.toString())) { - throw $animateMinErr("nongcls", '$animateProvider.classNameFilter(regex) prohibits accepting a regex value which matches/contains the "{0}" CSS class.', NG_ANIMATE_CLASSNAME); - } - } + min = +min || 0; + if (noMax) { + max = min; + min = 0; + } else { + max = +max || 0; } - return this.$$classNameFilter; - }; - this.$get = [ "$$animateQueue", function($$animateQueue) { - function domInsert(element, parentElement, afterElement) { - if (afterElement) { - var afterNode = extractElementNode(afterElement); - if (afterNode && !afterNode.parentNode && !afterNode.previousElementSibling) { - afterElement = null; - } - } - afterElement ? afterElement.after(element) : parentElement.prepend(element); + if (floating || min % 1 || max % 1) { + var rand = nativeRandom(); + return nativeMin(min + rand * (max - min + parseFloat("1e-" + ((rand + "").length - 1))), max); } - return { - on: $$animateQueue.on, - off: $$animateQueue.off, - pin: $$animateQueue.pin, - enabled: $$animateQueue.enabled, - cancel: function(runner) { - runner.end && runner.end(); - }, - enter: function(element, parent, after, options) { - parent = parent && jqLite(parent); - after = after && jqLite(after); - parent = parent || after.parent(); - domInsert(element, parent, after); - return $$animateQueue.push(element, "enter", prepareAnimateOptions(options)); - }, - move: function(element, parent, after, options) { - parent = parent && jqLite(parent); - after = after && jqLite(after); - parent = parent || after.parent(); - domInsert(element, parent, after); - return $$animateQueue.push(element, "move", prepareAnimateOptions(options)); - }, - leave: function(element, options) { - return $$animateQueue.push(element, "leave", prepareAnimateOptions(options), function() { - element.remove(); - }); - }, - addClass: function(element, className, options) { - options = prepareAnimateOptions(options); - options.addClass = mergeClasses(options.addclass, className); - return $$animateQueue.push(element, "addClass", options); - }, - removeClass: function(element, className, options) { - options = prepareAnimateOptions(options); - options.removeClass = mergeClasses(options.removeClass, className); - return $$animateQueue.push(element, "removeClass", options); - }, - setClass: function(element, add, remove, options) { - options = prepareAnimateOptions(options); - options.addClass = mergeClasses(options.addClass, add); - options.removeClass = mergeClasses(options.removeClass, remove); - return $$animateQueue.push(element, "setClass", options); - }, - animate: function(element, from, to, className, options) { - options = prepareAnimateOptions(options); - options.from = options.from ? extend(options.from, from) : from; - options.to = options.to ? extend(options.to, to) : to; - className = className || "ng-inline-animate"; - options.tempClasses = mergeClasses(options.tempClasses, className); - return $$animateQueue.push(element, "animate", options); - } - }; - } ]; - } ]; - var $CoreAnimateCssProvider = function() { - this.$get = [ "$$rAF", "$q", function($$rAF, $q) { - var RAFPromise = function() {}; - RAFPromise.prototype = { - done: function(cancel) { - this.defer && this.defer[cancel === true ? "reject" : "resolve"](); - }, - end: function() { - this.done(); - }, - cancel: function() { - this.done(true); - }, - getPromise: function() { - if (!this.defer) { - this.defer = $q.defer(); - } - return this.defer.promise; - }, - then: function(f1, f2) { - return this.getPromise().then(f1, f2); - }, - "catch": function(f1) { - return this.getPromise()["catch"](f1); - }, - "finally": function(f1) { - return this.getPromise()["finally"](f1); - } - }; - return function(element, options) { - if (options.from) { - element.css(options.from); - options.from = null; + return baseRandom(min, max); + } + var camelCase = createCompounder(function(result, word, index) { + word = word.toLowerCase(); + return result + (index ? word.charAt(0).toUpperCase() + word.slice(1) : word); + }); + function capitalize(string) { + string = baseToString(string); + return string && string.charAt(0).toUpperCase() + string.slice(1); + } + function deburr(string) { + string = baseToString(string); + return string && string.replace(reLatin1, deburrLetter).replace(reComboMark, ""); + } + function endsWith(string, target, position) { + string = baseToString(string); + target = target + ""; + var length = string.length; + position = position === undefined ? length : nativeMin(position < 0 ? 0 : +position || 0, length); + position -= target.length; + return position >= 0 && string.indexOf(target, position) == position; + } + function escape(string) { + string = baseToString(string); + return string && reHasUnescapedHtml.test(string) ? string.replace(reUnescapedHtml, escapeHtmlChar) : string; + } + function escapeRegExp(string) { + string = baseToString(string); + return string && reHasRegExpChars.test(string) ? string.replace(reRegExpChars, escapeRegExpChar) : string || "(?:)"; + } + var kebabCase = createCompounder(function(result, word, index) { + return result + (index ? "-" : "") + word.toLowerCase(); + }); + function pad(string, length, chars) { + string = baseToString(string); + length = +length; + var strLength = string.length; + if (strLength >= length || !nativeIsFinite(length)) { + return string; + } + var mid = (length - strLength) / 2, leftLength = nativeFloor(mid), rightLength = nativeCeil(mid); + chars = createPadding("", rightLength, chars); + return chars.slice(0, leftLength) + string + chars; + } + var padLeft = createPadDir(); + var padRight = createPadDir(true); + function parseInt(string, radix, guard) { + if (guard ? isIterateeCall(string, radix, guard) : radix == null) { + radix = 0; + } else if (radix) { + radix = +radix; + } + string = trim(string); + return nativeParseInt(string, radix || (reHasHexPrefix.test(string) ? 16 : 10)); + } + function repeat(string, n) { + var result = ""; + string = baseToString(string); + n = +n; + if (n < 1 || !string || !nativeIsFinite(n)) { + return result; + } + do { + if (n % 2) { + result += string; } - var closed, runner = new RAFPromise(); - return { - start: run, - end: run - }; - function run() { - $$rAF(function() { - close(); - if (!closed) { - runner.done(); - } - closed = true; - }); - return runner; + n = nativeFloor(n / 2); + string += string; + } while (n); + return result; + } + var snakeCase = createCompounder(function(result, word, index) { + return result + (index ? "_" : "") + word.toLowerCase(); + }); + var startCase = createCompounder(function(result, word, index) { + return result + (index ? " " : "") + (word.charAt(0).toUpperCase() + word.slice(1)); + }); + function startsWith(string, target, position) { + string = baseToString(string); + position = position == null ? 0 : nativeMin(position < 0 ? 0 : +position || 0, string.length); + return string.lastIndexOf(target, position) == position; + } + function template(string, options, otherOptions) { + var settings = lodash.templateSettings; + if (otherOptions && isIterateeCall(string, options, otherOptions)) { + options = otherOptions = undefined; + } + string = baseToString(string); + options = assignWith(baseAssign({}, otherOptions || options), settings, assignOwnDefaults); + var imports = assignWith(baseAssign({}, options.imports), settings.imports, assignOwnDefaults), importsKeys = keys(imports), importsValues = baseValues(imports, importsKeys); + var isEscaping, isEvaluating, index = 0, interpolate = options.interpolate || reNoMatch, source = "__p += '"; + var reDelimiters = RegExp((options.escape || reNoMatch).source + "|" + interpolate.source + "|" + (interpolate === reInterpolate ? reEsTemplate : reNoMatch).source + "|" + (options.evaluate || reNoMatch).source + "|$", "g"); + var sourceURL = "//# sourceURL=" + ("sourceURL" in options ? options.sourceURL : "lodash.templateSources[" + ++templateCounter + "]") + "\n"; + string.replace(reDelimiters, function(match, escapeValue, interpolateValue, esTemplateValue, evaluateValue, offset) { + interpolateValue || (interpolateValue = esTemplateValue); + source += string.slice(index, offset).replace(reUnescapedString, escapeStringChar); + if (escapeValue) { + isEscaping = true; + source += "' +\n__e(" + escapeValue + ") +\n'"; + } + if (evaluateValue) { + isEvaluating = true; + source += "';\n" + evaluateValue + ";\n__p += '"; + } + if (interpolateValue) { + source += "' +\n((__t = (" + interpolateValue + ")) == null ? '' : __t) +\n'"; + } + index = offset + match.length; + return match; + }); + source += "';\n"; + var variable = options.variable; + if (!variable) { + source = "with (obj) {\n" + source + "\n}\n"; + } + source = (isEvaluating ? source.replace(reEmptyStringLeading, "") : source).replace(reEmptyStringMiddle, "$1").replace(reEmptyStringTrailing, "$1;"); + source = "function(" + (variable || "obj") + ") {\n" + (variable ? "" : "obj || (obj = {});\n") + "var __t, __p = ''" + (isEscaping ? ", __e = _.escape" : "") + (isEvaluating ? ", __j = Array.prototype.join;\n" + "function print() { __p += __j.call(arguments, '') }\n" : ";\n") + source + "return __p\n}"; + var result = attempt(function() { + return Function(importsKeys, sourceURL + "return " + source).apply(undefined, importsValues); + }); + result.source = source; + if (isError(result)) { + throw result; + } + return result; + } + function trim(string, chars, guard) { + var value = string; + string = baseToString(string); + if (!string) { + return string; + } + if (guard ? isIterateeCall(value, chars, guard) : chars == null) { + return string.slice(trimmedLeftIndex(string), trimmedRightIndex(string) + 1); + } + chars = chars + ""; + return string.slice(charsLeftIndex(string, chars), charsRightIndex(string, chars) + 1); + } + function trimLeft(string, chars, guard) { + var value = string; + string = baseToString(string); + if (!string) { + return string; + } + if (guard ? isIterateeCall(value, chars, guard) : chars == null) { + return string.slice(trimmedLeftIndex(string)); + } + return string.slice(charsLeftIndex(string, chars + "")); + } + function trimRight(string, chars, guard) { + var value = string; + string = baseToString(string); + if (!string) { + return string; + } + if (guard ? isIterateeCall(value, chars, guard) : chars == null) { + return string.slice(0, trimmedRightIndex(string) + 1); + } + return string.slice(0, charsRightIndex(string, chars + "") + 1); + } + function trunc(string, options, guard) { + if (guard && isIterateeCall(string, options, guard)) { + options = undefined; + } + var length = DEFAULT_TRUNC_LENGTH, omission = DEFAULT_TRUNC_OMISSION; + if (options != null) { + if (isObject(options)) { + var separator = "separator" in options ? options.separator : separator; + length = "length" in options ? +options.length || 0 : length; + omission = "omission" in options ? baseToString(options.omission) : omission; + } else { + length = +options || 0; } - function close() { - if (options.addClass) { - element.addClass(options.addClass); - options.addClass = null; - } - if (options.removeClass) { - element.removeClass(options.removeClass); - options.removeClass = null; + } + string = baseToString(string); + if (length >= string.length) { + return string; + } + var end = length - omission.length; + if (end < 1) { + return omission; + } + var result = string.slice(0, end); + if (separator == null) { + return result + omission; + } + if (isRegExp(separator)) { + if (string.slice(end).search(separator)) { + var match, newEnd, substring = string.slice(0, end); + if (!separator.global) { + separator = RegExp(separator.source, (reFlags.exec(separator) || "") + "g"); } - if (options.to) { - element.css(options.to); - options.to = null; + separator.lastIndex = 0; + while (match = separator.exec(substring)) { + newEnd = match.index; } + result = result.slice(0, newEnd == null ? end : newEnd); } - }; - } ]; - }; - function Browser(window, document, $log, $sniffer) { - var self = this, rawDocument = document[0], location = window.location, history = window.history, setTimeout = window.setTimeout, clearTimeout = window.clearTimeout, pendingDeferIds = {}; - self.isMock = false; - var outstandingRequestCount = 0; - var outstandingRequestCallbacks = []; - self.$$completeOutstandingRequest = completeOutstandingRequest; - self.$$incOutstandingRequestCount = function() { - outstandingRequestCount++; - }; - function completeOutstandingRequest(fn) { - try { - fn.apply(null, sliceArgs(arguments, 1)); - } finally { - outstandingRequestCount--; - if (outstandingRequestCount === 0) { - while (outstandingRequestCallbacks.length) { - try { - outstandingRequestCallbacks.pop()(); - } catch (e) { - $log.error(e); - } - } + } else if (string.indexOf(separator, end) != end) { + var index = result.lastIndexOf(separator); + if (index > -1) { + result = result.slice(0, index); } } + return result + omission; } - function getHash(url) { - var index = url.indexOf("#"); - return index === -1 ? "" : url.substr(index); + function unescape(string) { + string = baseToString(string); + return string && reHasEscapedHtml.test(string) ? string.replace(reEscapedHtml, unescapeHtmlChar) : string; } - self.notifyWhenNoOutstandingRequests = function(callback) { - if (outstandingRequestCount === 0) { - callback(); - } else { - outstandingRequestCallbacks.push(callback); - } - }; - var cachedState, lastHistoryState, lastBrowserUrl = location.href, baseElement = document.find("base"), pendingLocation = null; - cacheState(); - lastHistoryState = cachedState; - self.url = function(url, replace, state) { - if (isUndefined(state)) { - state = null; + function words(string, pattern, guard) { + if (guard && isIterateeCall(string, pattern, guard)) { + pattern = undefined; } - if (location !== window.location) location = window.location; - if (history !== window.history) history = window.history; - if (url) { - var sameState = lastHistoryState === state; - if (lastBrowserUrl === url && (!$sniffer.history || sameState)) { - return self; - } - var sameBase = lastBrowserUrl && stripHash(lastBrowserUrl) === stripHash(url); - lastBrowserUrl = url; - lastHistoryState = state; - if ($sniffer.history && (!sameBase || !sameState)) { - history[replace ? "replaceState" : "pushState"](state, "", url); - cacheState(); - lastHistoryState = cachedState; - } else { - if (!sameBase || pendingLocation) { - pendingLocation = url; - } - if (replace) { - location.replace(url); - } else if (!sameBase) { - location.href = url; - } else { - location.hash = getHash(url); - } - if (location.href !== url) { - pendingLocation = url; - } - } - return self; - } else { - return pendingLocation || location.href.replace(/%27/g, "'"); - } - }; - self.state = function() { - return cachedState; - }; - var urlChangeListeners = [], urlChangeInit = false; - function cacheStateAndFireUrlChange() { - pendingLocation = null; - cacheState(); - fireUrlChange(); + string = baseToString(string); + return string.match(pattern || reWords) || []; } - function getCurrentState() { + var attempt = restParam(function(func, args) { try { - return history.state; - } catch (e) {} + return func.apply(undefined, args); + } catch (e) { + return isError(e) ? e : new Error(e); + } + }); + function callback(func, thisArg, guard) { + if (guard && isIterateeCall(func, thisArg, guard)) { + thisArg = undefined; + } + return isObjectLike(func) ? matches(func) : baseCallback(func, thisArg); } - var lastCachedState = null; - function cacheState() { - cachedState = getCurrentState(); - cachedState = isUndefined(cachedState) ? null : cachedState; - if (equals(cachedState, lastCachedState)) { - cachedState = lastCachedState; + function constant(value) { + return function() { + return value; + }; + } + function identity(value) { + return value; + } + function matches(source) { + return baseMatches(baseClone(source, true)); + } + function matchesProperty(path, srcValue) { + return baseMatchesProperty(path, baseClone(srcValue, true)); + } + var method = restParam(function(path, args) { + return function(object) { + return invokePath(object, path, args); + }; + }); + var methodOf = restParam(function(object, args) { + return function(path) { + return invokePath(object, path, args); + }; + }); + function mixin(object, source, options) { + if (options == null) { + var isObj = isObject(source), props = isObj ? keys(source) : undefined, methodNames = props && props.length ? baseFunctions(source, props) : undefined; + if (!(methodNames ? methodNames.length : isObj)) { + methodNames = false; + options = source; + source = object; + object = this; + } + } + if (!methodNames) { + methodNames = baseFunctions(source, keys(source)); + } + var chain = true, index = -1, isFunc = isFunction(object), length = methodNames.length; + if (options === false) { + chain = false; + } else if (isObject(options) && "chain" in options) { + chain = options.chain; + } + while (++index < length) { + var methodName = methodNames[index], func = source[methodName]; + object[methodName] = func; + if (isFunc) { + object.prototype[methodName] = function(func) { + return function() { + var chainAll = this.__chain__; + if (chain || chainAll) { + var result = object(this.__wrapped__), actions = result.__actions__ = arrayCopy(this.__actions__); + actions.push({ + func: func, + args: arguments, + thisArg: object + }); + result.__chain__ = chainAll; + return result; + } + return func.apply(object, arrayPush([ this.value() ], arguments)); + }; + }(func); + } } - lastCachedState = cachedState; + return object; } - function fireUrlChange() { - if (lastBrowserUrl === self.url() && lastHistoryState === cachedState) { - return; + function noConflict() { + root._ = oldDash; + return this; + } + function noop() {} + function property(path) { + return isKey(path) ? baseProperty(path) : basePropertyDeep(path); + } + function propertyOf(object) { + return function(path) { + return baseGet(object, toPath(path), path + ""); + }; + } + function range(start, end, step) { + if (step && isIterateeCall(start, end, step)) { + end = step = undefined; } - lastBrowserUrl = self.url(); - lastHistoryState = cachedState; - forEach(urlChangeListeners, function(listener) { - listener(self.url(), cachedState); - }); + start = +start || 0; + step = step == null ? 1 : +step || 0; + if (end == null) { + end = start; + start = 0; + } else { + end = +end || 0; + } + var index = -1, length = nativeMax(nativeCeil((end - start) / (step || 1)), 0), result = Array(length); + while (++index < length) { + result[index] = start; + start += step; + } + return result; } - self.onUrlChange = function(callback) { - if (!urlChangeInit) { - if ($sniffer.history) jqLite(window).on("popstate", cacheStateAndFireUrlChange); - jqLite(window).on("hashchange", cacheStateAndFireUrlChange); - urlChangeInit = true; + function times(n, iteratee, thisArg) { + n = nativeFloor(n); + if (n < 1 || !nativeIsFinite(n)) { + return []; } - urlChangeListeners.push(callback); - return callback; + var index = -1, result = Array(nativeMin(n, MAX_ARRAY_LENGTH)); + iteratee = bindCallback(iteratee, thisArg, 1); + while (++index < n) { + if (index < MAX_ARRAY_LENGTH) { + result[index] = iteratee(index); + } else { + iteratee(index); + } + } + return result; + } + function uniqueId(prefix) { + var id = ++idCounter; + return baseToString(prefix) + id; + } + function add(augend, addend) { + return (+augend || 0) + (+addend || 0); + } + var ceil = createRound("ceil"); + var floor = createRound("floor"); + var max = createExtremum(gt, NEGATIVE_INFINITY); + var min = createExtremum(lt, POSITIVE_INFINITY); + var round = createRound("round"); + function sum(collection, iteratee, thisArg) { + if (thisArg && isIterateeCall(collection, iteratee, thisArg)) { + iteratee = undefined; + } + iteratee = getCallback(iteratee, thisArg, 3); + return iteratee.length == 1 ? arraySum(isArray(collection) ? collection : toIterable(collection), iteratee) : baseSum(collection, iteratee); + } + lodash.prototype = baseLodash.prototype; + LodashWrapper.prototype = baseCreate(baseLodash.prototype); + LodashWrapper.prototype.constructor = LodashWrapper; + LazyWrapper.prototype = baseCreate(baseLodash.prototype); + LazyWrapper.prototype.constructor = LazyWrapper; + MapCache.prototype["delete"] = mapDelete; + MapCache.prototype.get = mapGet; + MapCache.prototype.has = mapHas; + MapCache.prototype.set = mapSet; + SetCache.prototype.push = cachePush; + memoize.Cache = MapCache; + lodash.after = after; + lodash.ary = ary; + lodash.assign = assign; + lodash.at = at; + lodash.before = before; + lodash.bind = bind; + lodash.bindAll = bindAll; + lodash.bindKey = bindKey; + lodash.callback = callback; + lodash.chain = chain; + lodash.chunk = chunk; + lodash.compact = compact; + lodash.constant = constant; + lodash.countBy = countBy; + lodash.create = create; + lodash.curry = curry; + lodash.curryRight = curryRight; + lodash.debounce = debounce; + lodash.defaults = defaults; + lodash.defaultsDeep = defaultsDeep; + lodash.defer = defer; + lodash.delay = delay; + lodash.difference = difference; + lodash.drop = drop; + lodash.dropRight = dropRight; + lodash.dropRightWhile = dropRightWhile; + lodash.dropWhile = dropWhile; + lodash.fill = fill; + lodash.filter = filter; + lodash.flatten = flatten; + lodash.flattenDeep = flattenDeep; + lodash.flow = flow; + lodash.flowRight = flowRight; + lodash.forEach = forEach; + lodash.forEachRight = forEachRight; + lodash.forIn = forIn; + lodash.forInRight = forInRight; + lodash.forOwn = forOwn; + lodash.forOwnRight = forOwnRight; + lodash.functions = functions; + lodash.groupBy = groupBy; + lodash.indexBy = indexBy; + lodash.initial = initial; + lodash.intersection = intersection; + lodash.invert = invert; + lodash.invoke = invoke; + lodash.keys = keys; + lodash.keysIn = keysIn; + lodash.map = map; + lodash.mapKeys = mapKeys; + lodash.mapValues = mapValues; + lodash.matches = matches; + lodash.matchesProperty = matchesProperty; + lodash.memoize = memoize; + lodash.merge = merge; + lodash.method = method; + lodash.methodOf = methodOf; + lodash.mixin = mixin; + lodash.modArgs = modArgs; + lodash.negate = negate; + lodash.omit = omit; + lodash.once = once; + lodash.pairs = pairs; + lodash.partial = partial; + lodash.partialRight = partialRight; + lodash.partition = partition; + lodash.pick = pick; + lodash.pluck = pluck; + lodash.property = property; + lodash.propertyOf = propertyOf; + lodash.pull = pull; + lodash.pullAt = pullAt; + lodash.range = range; + lodash.rearg = rearg; + lodash.reject = reject; + lodash.remove = remove; + lodash.rest = rest; + lodash.restParam = restParam; + lodash.set = set; + lodash.shuffle = shuffle; + lodash.slice = slice; + lodash.sortBy = sortBy; + lodash.sortByAll = sortByAll; + lodash.sortByOrder = sortByOrder; + lodash.spread = spread; + lodash.take = take; + lodash.takeRight = takeRight; + lodash.takeRightWhile = takeRightWhile; + lodash.takeWhile = takeWhile; + lodash.tap = tap; + lodash.throttle = throttle; + lodash.thru = thru; + lodash.times = times; + lodash.toArray = toArray; + lodash.toPlainObject = toPlainObject; + lodash.transform = transform; + lodash.union = union; + lodash.uniq = uniq; + lodash.unzip = unzip; + lodash.unzipWith = unzipWith; + lodash.values = values; + lodash.valuesIn = valuesIn; + lodash.where = where; + lodash.without = without; + lodash.wrap = wrap; + lodash.xor = xor; + lodash.zip = zip; + lodash.zipObject = zipObject; + lodash.zipWith = zipWith; + lodash.backflow = flowRight; + lodash.collect = map; + lodash.compose = flowRight; + lodash.each = forEach; + lodash.eachRight = forEachRight; + lodash.extend = assign; + lodash.iteratee = callback; + lodash.methods = functions; + lodash.object = zipObject; + lodash.select = filter; + lodash.tail = rest; + lodash.unique = uniq; + mixin(lodash, lodash); + lodash.add = add; + lodash.attempt = attempt; + lodash.camelCase = camelCase; + lodash.capitalize = capitalize; + lodash.ceil = ceil; + lodash.clone = clone; + lodash.cloneDeep = cloneDeep; + lodash.deburr = deburr; + lodash.endsWith = endsWith; + lodash.escape = escape; + lodash.escapeRegExp = escapeRegExp; + lodash.every = every; + lodash.find = find; + lodash.findIndex = findIndex; + lodash.findKey = findKey; + lodash.findLast = findLast; + lodash.findLastIndex = findLastIndex; + lodash.findLastKey = findLastKey; + lodash.findWhere = findWhere; + lodash.first = first; + lodash.floor = floor; + lodash.get = get; + lodash.gt = gt; + lodash.gte = gte; + lodash.has = has; + lodash.identity = identity; + lodash.includes = includes; + lodash.indexOf = indexOf; + lodash.inRange = inRange; + lodash.isArguments = isArguments; + lodash.isArray = isArray; + lodash.isBoolean = isBoolean; + lodash.isDate = isDate; + lodash.isElement = isElement; + lodash.isEmpty = isEmpty; + lodash.isEqual = isEqual; + lodash.isError = isError; + lodash.isFinite = isFinite; + lodash.isFunction = isFunction; + lodash.isMatch = isMatch; + lodash.isNaN = isNaN; + lodash.isNative = isNative; + lodash.isNull = isNull; + lodash.isNumber = isNumber; + lodash.isObject = isObject; + lodash.isPlainObject = isPlainObject; + lodash.isRegExp = isRegExp; + lodash.isString = isString; + lodash.isTypedArray = isTypedArray; + lodash.isUndefined = isUndefined; + lodash.kebabCase = kebabCase; + lodash.last = last; + lodash.lastIndexOf = lastIndexOf; + lodash.lt = lt; + lodash.lte = lte; + lodash.max = max; + lodash.min = min; + lodash.noConflict = noConflict; + lodash.noop = noop; + lodash.now = now; + lodash.pad = pad; + lodash.padLeft = padLeft; + lodash.padRight = padRight; + lodash.parseInt = parseInt; + lodash.random = random; + lodash.reduce = reduce; + lodash.reduceRight = reduceRight; + lodash.repeat = repeat; + lodash.result = result; + lodash.round = round; + lodash.runInContext = runInContext; + lodash.size = size; + lodash.snakeCase = snakeCase; + lodash.some = some; + lodash.sortedIndex = sortedIndex; + lodash.sortedLastIndex = sortedLastIndex; + lodash.startCase = startCase; + lodash.startsWith = startsWith; + lodash.sum = sum; + lodash.template = template; + lodash.trim = trim; + lodash.trimLeft = trimLeft; + lodash.trimRight = trimRight; + lodash.trunc = trunc; + lodash.unescape = unescape; + lodash.uniqueId = uniqueId; + lodash.words = words; + lodash.all = every; + lodash.any = some; + lodash.contains = includes; + lodash.eq = isEqual; + lodash.detect = find; + lodash.foldl = reduce; + lodash.foldr = reduceRight; + lodash.head = first; + lodash.include = includes; + lodash.inject = reduce; + mixin(lodash, function() { + var source = {}; + baseForOwn(lodash, function(func, methodName) { + if (!lodash.prototype[methodName]) { + source[methodName] = func; + } + }); + return source; + }(), false); + lodash.sample = sample; + lodash.prototype.sample = function(n) { + if (!this.__chain__ && n == null) { + return sample(this.value()); + } + return this.thru(function(value) { + return sample(value, n); + }); + }; + lodash.VERSION = VERSION; + arrayEach([ "bind", "bindKey", "curry", "curryRight", "partial", "partialRight" ], function(methodName) { + lodash[methodName].placeholder = lodash; + }); + arrayEach([ "drop", "take" ], function(methodName, index) { + LazyWrapper.prototype[methodName] = function(n) { + var filtered = this.__filtered__; + if (filtered && !index) { + return new LazyWrapper(this); + } + n = n == null ? 1 : nativeMax(nativeFloor(n) || 0, 0); + var result = this.clone(); + if (filtered) { + result.__takeCount__ = nativeMin(result.__takeCount__, n); + } else { + result.__views__.push({ + size: n, + type: methodName + (result.__dir__ < 0 ? "Right" : "") + }); + } + return result; + }; + LazyWrapper.prototype[methodName + "Right"] = function(n) { + return this.reverse()[methodName](n).reverse(); + }; + }); + arrayEach([ "filter", "map", "takeWhile" ], function(methodName, index) { + var type = index + 1, isFilter = type != LAZY_MAP_FLAG; + LazyWrapper.prototype[methodName] = function(iteratee, thisArg) { + var result = this.clone(); + result.__iteratees__.push({ + iteratee: getCallback(iteratee, thisArg, 1), + type: type + }); + result.__filtered__ = result.__filtered__ || isFilter; + return result; + }; + }); + arrayEach([ "first", "last" ], function(methodName, index) { + var takeName = "take" + (index ? "Right" : ""); + LazyWrapper.prototype[methodName] = function() { + return this[takeName](1).value()[0]; + }; + }); + arrayEach([ "initial", "rest" ], function(methodName, index) { + var dropName = "drop" + (index ? "" : "Right"); + LazyWrapper.prototype[methodName] = function() { + return this.__filtered__ ? new LazyWrapper(this) : this[dropName](1); + }; + }); + arrayEach([ "pluck", "where" ], function(methodName, index) { + var operationName = index ? "filter" : "map", createCallback = index ? baseMatches : property; + LazyWrapper.prototype[methodName] = function(value) { + return this[operationName](createCallback(value)); + }; + }); + LazyWrapper.prototype.compact = function() { + return this.filter(identity); }; - self.$$applicationDestroyed = function() { - jqLite(window).off("hashchange popstate", cacheStateAndFireUrlChange); + LazyWrapper.prototype.reject = function(predicate, thisArg) { + predicate = getCallback(predicate, thisArg, 1); + return this.filter(function(value) { + return !predicate(value); + }); }; - self.$$checkUrlChange = fireUrlChange; - self.baseHref = function() { - var href = baseElement.attr("href"); - return href ? href.replace(/^(https?\:)?\/\/[^\/]*/, "") : ""; + LazyWrapper.prototype.slice = function(start, end) { + start = start == null ? 0 : +start || 0; + var result = this; + if (result.__filtered__ && (start > 0 || end < 0)) { + return new LazyWrapper(result); + } + if (start < 0) { + result = result.takeRight(-start); + } else if (start) { + result = result.drop(start); + } + if (end !== undefined) { + end = +end || 0; + result = end < 0 ? result.dropRight(-end) : result.take(end - start); + } + return result; }; - self.defer = function(fn, delay) { - var timeoutId; - outstandingRequestCount++; - timeoutId = setTimeout(function() { - delete pendingDeferIds[timeoutId]; - completeOutstandingRequest(fn); - }, delay || 0); - pendingDeferIds[timeoutId] = true; - return timeoutId; + LazyWrapper.prototype.takeRightWhile = function(predicate, thisArg) { + return this.reverse().takeWhile(predicate, thisArg).reverse(); }; - self.defer.cancel = function(deferId) { - if (pendingDeferIds[deferId]) { - delete pendingDeferIds[deferId]; - clearTimeout(deferId); - completeOutstandingRequest(noop); - return true; - } - return false; + LazyWrapper.prototype.toArray = function() { + return this.take(POSITIVE_INFINITY); }; - } - function $BrowserProvider() { - this.$get = [ "$window", "$log", "$sniffer", "$document", function($window, $log, $sniffer, $document) { - return new Browser($window, $document, $log, $sniffer); - } ]; - } - function $CacheFactoryProvider() { - this.$get = function() { - var caches = {}; - function cacheFactory(cacheId, options) { - if (cacheId in caches) { - throw minErr("$cacheFactory")("iid", "CacheId '{0}' is already taken!", cacheId); + baseForOwn(LazyWrapper.prototype, function(func, methodName) { + var checkIteratee = /^(?:filter|map|reject)|While$/.test(methodName), retUnwrapped = /^(?:first|last)$/.test(methodName), lodashFunc = lodash[retUnwrapped ? "take" + (methodName == "last" ? "Right" : "") : methodName]; + if (!lodashFunc) { + return; + } + lodash.prototype[methodName] = function() { + var args = retUnwrapped ? [ 1 ] : arguments, chainAll = this.__chain__, value = this.__wrapped__, isHybrid = !!this.__actions__.length, isLazy = value instanceof LazyWrapper, iteratee = args[0], useLazy = isLazy || isArray(value); + if (useLazy && checkIteratee && typeof iteratee == "function" && iteratee.length != 1) { + isLazy = useLazy = false; } - var size = 0, stats = extend({}, options, { - id: cacheId - }), data = {}, capacity = options && options.capacity || Number.MAX_VALUE, lruHash = {}, freshEnd = null, staleEnd = null; - return caches[cacheId] = { - put: function(key, value) { - if (isUndefined(value)) return; - if (capacity < Number.MAX_VALUE) { - var lruEntry = lruHash[key] || (lruHash[key] = { - key: key - }); - refresh(lruEntry); - } - if (!(key in data)) size++; - data[key] = value; - if (size > capacity) { - this.remove(staleEnd.key); - } - return value; - }, - get: function(key) { - if (capacity < Number.MAX_VALUE) { - var lruEntry = lruHash[key]; - if (!lruEntry) return; - refresh(lruEntry); - } - return data[key]; - }, - remove: function(key) { - if (capacity < Number.MAX_VALUE) { - var lruEntry = lruHash[key]; - if (!lruEntry) return; - if (lruEntry == freshEnd) freshEnd = lruEntry.p; - if (lruEntry == staleEnd) staleEnd = lruEntry.n; - link(lruEntry.n, lruEntry.p); - delete lruHash[key]; - } - delete data[key]; - size--; - }, - removeAll: function() { - data = {}; - size = 0; - lruHash = {}; - freshEnd = staleEnd = null; - }, - destroy: function() { - data = null; - stats = null; - lruHash = null; - delete caches[cacheId]; - }, - info: function() { - return extend({}, stats, { - size: size - }); - } + var interceptor = function(value) { + return retUnwrapped && chainAll ? lodashFunc(value, 1)[0] : lodashFunc.apply(undefined, arrayPush([ value ], args)); }; - function refresh(entry) { - if (entry != freshEnd) { - if (!staleEnd) { - staleEnd = entry; - } else if (staleEnd == entry) { - staleEnd = entry.n; - } - link(entry.n, entry.p); - link(entry, freshEnd); - freshEnd = entry; - freshEnd.n = null; - } - } - function link(nextEntry, prevEntry) { - if (nextEntry != prevEntry) { - if (nextEntry) nextEntry.p = prevEntry; - if (prevEntry) prevEntry.n = nextEntry; - } - } - } - cacheFactory.info = function() { - var info = {}; - forEach(caches, function(cache, cacheId) { - info[cacheId] = cache.info(); - }); - return info; + var action = { + func: thru, + args: [ interceptor ], + thisArg: undefined + }, onlyLazy = isLazy && !isHybrid; + if (retUnwrapped && !chainAll) { + if (onlyLazy) { + value = value.clone(); + value.__actions__.push(action); + return func.call(value); + } + return lodashFunc.call(undefined, this.value())[0]; + } + if (!retUnwrapped && useLazy) { + value = onlyLazy ? value : new LazyWrapper(this); + var result = func.apply(value, args); + result.__actions__.push(action); + return new LodashWrapper(result, chainAll); + } + return this.thru(interceptor); }; - cacheFactory.get = function(cacheId) { - return caches[cacheId]; + }); + arrayEach([ "join", "pop", "push", "replace", "shift", "sort", "splice", "split", "unshift" ], function(methodName) { + var func = (/^(?:replace|split)$/.test(methodName) ? stringProto : arrayProto)[methodName], chainName = /^(?:push|sort|unshift)$/.test(methodName) ? "tap" : "thru", retUnwrapped = /^(?:join|pop|replace|shift)$/.test(methodName); + lodash.prototype[methodName] = function() { + var args = arguments; + if (retUnwrapped && !this.__chain__) { + return func.apply(this.value(), args); + } + return this[chainName](function(value) { + return func.apply(value, args); + }); }; - return cacheFactory; - }; - } - function $TemplateCacheProvider() { - this.$get = [ "$cacheFactory", function($cacheFactory) { - return $cacheFactory("templates"); - } ]; + }); + baseForOwn(LazyWrapper.prototype, function(func, methodName) { + var lodashFunc = lodash[methodName]; + if (lodashFunc) { + var key = lodashFunc.name + "", names = realNames[key] || (realNames[key] = []); + names.push({ + name: methodName, + func: lodashFunc + }); + } + }); + realNames[createHybridWrapper(undefined, BIND_KEY_FLAG).name] = [ { + name: "wrapper", + func: undefined + } ]; + LazyWrapper.prototype.clone = lazyClone; + LazyWrapper.prototype.reverse = lazyReverse; + LazyWrapper.prototype.value = lazyValue; + lodash.prototype.chain = wrapperChain; + lodash.prototype.commit = wrapperCommit; + lodash.prototype.concat = wrapperConcat; + lodash.prototype.plant = wrapperPlant; + lodash.prototype.reverse = wrapperReverse; + lodash.prototype.toString = wrapperToString; + lodash.prototype.run = lodash.prototype.toJSON = lodash.prototype.valueOf = lodash.prototype.value = wrapperValue; + lodash.prototype.collect = lodash.prototype.map; + lodash.prototype.head = lodash.prototype.first; + lodash.prototype.select = lodash.prototype.filter; + lodash.prototype.tail = lodash.prototype.rest; + return lodash; + } + var _ = runInContext(); + if (typeof define == "function" && typeof define.amd == "object" && define.amd) { + root._ = _; + define(function() { + return _; + }); + } else if (freeExports && freeModule) { + if (moduleExports) { + (freeModule.exports = _)._ = _; + } else { + freeExports._ = _; + } + } else { + root._ = _; } - var $compileMinErr = minErr("$compile"); - $CompileProvider.$inject = [ "$provide", "$$sanitizeUriProvider" ]; - function $CompileProvider($provide, $$sanitizeUriProvider) { - var hasDirectives = {}, Suffix = "Directive", COMMENT_DIRECTIVE_REGEXP = /^\s*directive\:\s*([\w\-]+)\s+(.*)$/, CLASS_DIRECTIVE_REGEXP = /(([\w\-]+)(?:\:([^;]+))?;?)/, ALL_OR_NOTHING_ATTRS = makeMap("ngSrc,ngSrcset,src,srcset"), REQUIRE_PREFIX_REGEXP = /^(?:(\^\^?)?(\?)?(\^\^?)?)?/; - var EVENT_HANDLER_ATTR_REGEXP = /^(on[a-z]+|formaction)$/; - function parseIsolateBindings(scope, directiveName, isController) { - var LOCAL_REGEXP = /^\s*([@&]|=(\*?))(\??)\s*(\w*)\s*$/; - var bindings = {}; - forEach(scope, function(definition, scopeName) { - var match = definition.match(LOCAL_REGEXP); - if (!match) { - throw $compileMinErr("iscp", "Invalid {3} for directive '{0}'." + " Definition: {... {1}: '{2}' ...}", directiveName, scopeName, definition, isController ? "controller bindings definition" : "isolate scope definition"); +}).call(this); + +(function(window, document, undefined) { + "use strict"; + function minErr(module, ErrorConstructor) { + ErrorConstructor = ErrorConstructor || Error; + return function() { + var SKIP_INDEXES = 2; + var templateArgs = arguments, code = templateArgs[0], message = "[" + (module ? module + ":" : "") + code + "] ", template = templateArgs[1], paramPrefix, i; + message += template.replace(/\{\d+\}/g, function(match) { + var index = +match.slice(1, -1), shiftedIndex = index + SKIP_INDEXES; + if (shiftedIndex < templateArgs.length) { + return toDebugString(templateArgs[shiftedIndex]); } - bindings[scopeName] = { - mode: match[1][0], - collection: match[2] === "*", - optional: match[3] === "?", - attrName: match[4] || scopeName - }; + return match; }); - return bindings; + message += "\nhttp://errors.angularjs.org/1.4.7/" + (module ? module + "/" : "") + code; + for (i = SKIP_INDEXES, paramPrefix = "?"; i < templateArgs.length; i++, paramPrefix = "&") { + message += paramPrefix + "p" + (i - SKIP_INDEXES) + "=" + encodeURIComponent(toDebugString(templateArgs[i])); + } + return new ErrorConstructor(message); + }; + } + var REGEX_STRING_REGEXP = /^\/(.+)\/([a-z]*)$/; + var VALIDITY_STATE_PROPERTY = "validity"; + var lowercase = function(string) { + return isString(string) ? string.toLowerCase() : string; + }; + var hasOwnProperty = Object.prototype.hasOwnProperty; + var uppercase = function(string) { + return isString(string) ? string.toUpperCase() : string; + }; + var manualLowercase = function(s) { + return isString(s) ? s.replace(/[A-Z]/g, function(ch) { + return String.fromCharCode(ch.charCodeAt(0) | 32); + }) : s; + }; + var manualUppercase = function(s) { + return isString(s) ? s.replace(/[a-z]/g, function(ch) { + return String.fromCharCode(ch.charCodeAt(0) & ~32); + }) : s; + }; + if ("i" !== "I".toLowerCase()) { + lowercase = manualLowercase; + uppercase = manualUppercase; + } + var msie, jqLite, jQuery, slice = [].slice, splice = [].splice, push = [].push, toString = Object.prototype.toString, getPrototypeOf = Object.getPrototypeOf, ngMinErr = minErr("ng"), angular = window.angular || (window.angular = {}), angularModule, uid = 0; + msie = document.documentMode; + function isArrayLike(obj) { + if (obj == null || isWindow(obj)) { + return false; } - function parseDirectiveBindings(directive, directiveName) { - var bindings = { - isolateScope: null, - bindToController: null - }; - if (isObject(directive.scope)) { - if (directive.bindToController === true) { - bindings.bindToController = parseIsolateBindings(directive.scope, directiveName, true); - bindings.isolateScope = {}; - } else { - bindings.isolateScope = parseIsolateBindings(directive.scope, directiveName, false); + var length = "length" in Object(obj) && obj.length; + if (obj.nodeType === NODE_TYPE_ELEMENT && length) { + return true; + } + return isString(obj) || isArray(obj) || length === 0 || typeof length === "number" && length > 0 && length - 1 in obj; + } + function forEach(obj, iterator, context) { + var key, length; + if (obj) { + if (isFunction(obj)) { + for (key in obj) { + if (key != "prototype" && key != "length" && key != "name" && (!obj.hasOwnProperty || obj.hasOwnProperty(key))) { + iterator.call(context, obj[key], key, obj); + } } - } - if (isObject(directive.bindToController)) { - bindings.bindToController = parseIsolateBindings(directive.bindToController, directiveName, true); - } - if (isObject(bindings.bindToController)) { - var controller = directive.controller; - var controllerAs = directive.controllerAs; - if (!controller) { - throw $compileMinErr("noctrl", "Cannot bind to controller without directive '{0}'s controller.", directiveName); - } else if (!identifierForController(controller, controllerAs)) { - throw $compileMinErr("noident", "Cannot bind to controller without identifier for directive '{0}'.", directiveName); + } else if (isArray(obj) || isArrayLike(obj)) { + var isPrimitive = typeof obj !== "object"; + for (key = 0, length = obj.length; key < length; key++) { + if (isPrimitive || key in obj) { + iterator.call(context, obj[key], key, obj); + } + } + } else if (obj.forEach && obj.forEach !== forEach) { + obj.forEach(iterator, context, obj); + } else if (isBlankObject(obj)) { + for (key in obj) { + iterator.call(context, obj[key], key, obj); + } + } else if (typeof obj.hasOwnProperty === "function") { + for (key in obj) { + if (obj.hasOwnProperty(key)) { + iterator.call(context, obj[key], key, obj); + } + } + } else { + for (key in obj) { + if (hasOwnProperty.call(obj, key)) { + iterator.call(context, obj[key], key, obj); + } } } - return bindings; } - function assertValidDirectiveName(name) { - var letter = name.charAt(0); - if (!letter || letter !== lowercase(letter)) { - throw $compileMinErr("baddir", "Directive name '{0}' is invalid. The first character must be a lowercase letter", name); - } - if (name !== name.trim()) { - throw $compileMinErr("baddir", "Directive name '{0}' is invalid. The name should not contain leading or trailing whitespaces", name); - } + return obj; + } + function forEachSorted(obj, iterator, context) { + var keys = Object.keys(obj).sort(); + for (var i = 0; i < keys.length; i++) { + iterator.call(context, obj[keys[i]], keys[i]); } - this.directive = function registerDirective(name, directiveFactory) { - assertNotHasOwnProperty(name, "directive"); - if (isString(name)) { - assertValidDirectiveName(name); - assertArg(directiveFactory, "directiveFactory"); - if (!hasDirectives.hasOwnProperty(name)) { - hasDirectives[name] = []; - $provide.factory(name + Suffix, [ "$injector", "$exceptionHandler", function($injector, $exceptionHandler) { - var directives = []; - forEach(hasDirectives[name], function(directiveFactory, index) { - try { - var directive = $injector.invoke(directiveFactory); - if (isFunction(directive)) { - directive = { - compile: valueFn(directive) - }; - } else if (!directive.compile && directive.link) { - directive.compile = valueFn(directive.link); - } - directive.priority = directive.priority || 0; - directive.index = index; - directive.name = directive.name || name; - directive.require = directive.require || directive.controller && directive.name; - directive.restrict = directive.restrict || "EA"; - var bindings = directive.$$bindings = parseDirectiveBindings(directive, directive.name); - if (isObject(bindings.isolateScope)) { - directive.$$isolateBindings = bindings.isolateScope; - } - directive.$$moduleName = directiveFactory.$$moduleName; - directives.push(directive); - } catch (e) { - $exceptionHandler(e); - } - }); - return directives; - } ]); + return keys; + } + function reverseParams(iteratorFn) { + return function(value, key) { + iteratorFn(key, value); + }; + } + function nextUid() { + return ++uid; + } + function setHashKey(obj, h) { + if (h) { + obj.$$hashKey = h; + } else { + delete obj.$$hashKey; + } + } + function baseExtend(dst, objs, deep) { + var h = dst.$$hashKey; + for (var i = 0, ii = objs.length; i < ii; ++i) { + var obj = objs[i]; + if (!isObject(obj) && !isFunction(obj)) continue; + var keys = Object.keys(obj); + for (var j = 0, jj = keys.length; j < jj; j++) { + var key = keys[j]; + var src = obj[key]; + if (deep && isObject(src)) { + if (isDate(src)) { + dst[key] = new Date(src.valueOf()); + } else if (isRegExp(src)) { + dst[key] = new RegExp(src); + } else { + if (!isObject(dst[key])) dst[key] = isArray(src) ? [] : {}; + baseExtend(dst[key], [ src ], true); + } + } else { + dst[key] = src; } - hasDirectives[name].push(directiveFactory); - } else { - forEach(name, reverseParams(registerDirective)); } - return this; + } + setHashKey(dst, h); + return dst; + } + function extend(dst) { + return baseExtend(dst, slice.call(arguments, 1), false); + } + function merge(dst) { + return baseExtend(dst, slice.call(arguments, 1), true); + } + function toInt(str) { + return parseInt(str, 10); + } + function inherit(parent, extra) { + return extend(Object.create(parent), extra); + } + function noop() {} + noop.$inject = []; + function identity($) { + return $; + } + identity.$inject = []; + function valueFn(value) { + return function() { + return value; }; - this.aHrefSanitizationWhitelist = function(regexp) { - if (isDefined(regexp)) { - $$sanitizeUriProvider.aHrefSanitizationWhitelist(regexp); - return this; - } else { - return $$sanitizeUriProvider.aHrefSanitizationWhitelist(); - } - }; - this.imgSrcSanitizationWhitelist = function(regexp) { - if (isDefined(regexp)) { - $$sanitizeUriProvider.imgSrcSanitizationWhitelist(regexp); - return this; - } else { - return $$sanitizeUriProvider.imgSrcSanitizationWhitelist(); + } + function hasCustomToString(obj) { + return isFunction(obj.toString) && obj.toString !== Object.prototype.toString; + } + function isUndefined(value) { + return typeof value === "undefined"; + } + function isDefined(value) { + return typeof value !== "undefined"; + } + function isObject(value) { + return value !== null && typeof value === "object"; + } + function isBlankObject(value) { + return value !== null && typeof value === "object" && !getPrototypeOf(value); + } + function isString(value) { + return typeof value === "string"; + } + function isNumber(value) { + return typeof value === "number"; + } + function isDate(value) { + return toString.call(value) === "[object Date]"; + } + var isArray = Array.isArray; + function isFunction(value) { + return typeof value === "function"; + } + function isRegExp(value) { + return toString.call(value) === "[object RegExp]"; + } + function isWindow(obj) { + return obj && obj.window === obj; + } + function isScope(obj) { + return obj && obj.$evalAsync && obj.$watch; + } + function isFile(obj) { + return toString.call(obj) === "[object File]"; + } + function isFormData(obj) { + return toString.call(obj) === "[object FormData]"; + } + function isBlob(obj) { + return toString.call(obj) === "[object Blob]"; + } + function isBoolean(value) { + return typeof value === "boolean"; + } + function isPromiseLike(obj) { + return obj && isFunction(obj.then); + } + var TYPED_ARRAY_REGEXP = /^\[object (Uint8(Clamped)?)|(Uint16)|(Uint32)|(Int8)|(Int16)|(Int32)|(Float(32)|(64))Array\]$/; + function isTypedArray(value) { + return TYPED_ARRAY_REGEXP.test(toString.call(value)); + } + var trim = function(value) { + return isString(value) ? value.trim() : value; + }; + var escapeForRegexp = function(s) { + return s.replace(/([-()\[\]{}+?*.$\^|,:#= 0) { + array.splice(index, 1); + } + return index; + } + function copy(source, destination, stackSource, stackDest) { + if (isWindow(source) || isScope(source)) { + throw ngMinErr("cpws", "Can't copy! Making copies of Window or Scope instances is not supported."); + } + if (isTypedArray(destination)) { + throw ngMinErr("cpta", "Can't copy! TypedArray destination cannot be mutated."); + } + if (!destination) { + destination = source; + if (isObject(source)) { + var index; + if (stackSource && (index = stackSource.indexOf(source)) !== -1) { + return stackDest[index]; + } + if (isArray(source)) { + return copy(source, [], stackSource, stackDest); + } else if (isTypedArray(source)) { + destination = new source.constructor(source); + } else if (isDate(source)) { + destination = new Date(source.getTime()); + } else if (isRegExp(source)) { + destination = new RegExp(source.source, source.toString().match(/[^\/]*$/)[0]); + destination.lastIndex = source.lastIndex; + } else if (isFunction(source.cloneNode)) { + destination = source.cloneNode(true); + } else { + var emptyObject = Object.create(getPrototypeOf(source)); + return copy(source, emptyObject, stackSource, stackDest); + } + if (stackDest) { + stackSource.push(source); + stackDest.push(destination); + } } - }; - var debugInfoEnabled = true; - this.debugInfoEnabled = function(enabled) { - if (isDefined(enabled)) { - debugInfoEnabled = enabled; - return this; + } else { + if (source === destination) throw ngMinErr("cpi", "Can't copy! Source and destination are identical."); + stackSource = stackSource || []; + stackDest = stackDest || []; + if (isObject(source)) { + stackSource.push(source); + stackDest.push(destination); } - return debugInfoEnabled; - }; - this.$get = [ "$injector", "$interpolate", "$exceptionHandler", "$templateRequest", "$parse", "$controller", "$rootScope", "$document", "$sce", "$animate", "$$sanitizeUri", function($injector, $interpolate, $exceptionHandler, $templateRequest, $parse, $controller, $rootScope, $document, $sce, $animate, $$sanitizeUri) { - var Attributes = function(element, attributesToCopy) { - if (attributesToCopy) { - var keys = Object.keys(attributesToCopy); - var i, l, key; - for (i = 0, l = keys.length; i < l; i++) { - key = keys[i]; - this[key] = attributesToCopy[key]; - } + var result, key; + if (isArray(source)) { + destination.length = 0; + for (var i = 0; i < source.length; i++) { + destination.push(copy(source[i], null, stackSource, stackDest)); + } + } else { + var h = destination.$$hashKey; + if (isArray(destination)) { + destination.length = 0; } else { - this.$attr = {}; + forEach(destination, function(value, key) { + delete destination[key]; + }); } - this.$$element = element; - }; - Attributes.prototype = { - $normalize: directiveNormalize, - $addClass: function(classVal) { - if (classVal && classVal.length > 0) { - $animate.addClass(this.$$element, classVal); - } - }, - $removeClass: function(classVal) { - if (classVal && classVal.length > 0) { - $animate.removeClass(this.$$element, classVal); - } - }, - $updateClass: function(newClasses, oldClasses) { - var toAdd = tokenDifference(newClasses, oldClasses); - if (toAdd && toAdd.length) { - $animate.addClass(this.$$element, toAdd); - } - var toRemove = tokenDifference(oldClasses, newClasses); - if (toRemove && toRemove.length) { - $animate.removeClass(this.$$element, toRemove); - } - }, - $set: function(key, value, writeAttr, attrName) { - var node = this.$$element[0], booleanKey = getBooleanAttrName(node, key), aliasedKey = getAliasedAttrName(key), observer = key, nodeName; - if (booleanKey) { - this.$$element.prop(key, value); - attrName = booleanKey; - } else if (aliasedKey) { - this[aliasedKey] = value; - observer = aliasedKey; - } - this[key] = value; - if (attrName) { - this.$attr[key] = attrName; - } else { - attrName = this.$attr[key]; - if (!attrName) { - this.$attr[key] = attrName = snake_case(key, "-"); - } + if (isBlankObject(source)) { + for (key in source) { + destination[key] = copy(source[key], null, stackSource, stackDest); } - nodeName = nodeName_(this.$$element); - if (nodeName === "a" && key === "href" || nodeName === "img" && key === "src") { - this[key] = value = $$sanitizeUri(value, key === "src"); - } else if (nodeName === "img" && key === "srcset") { - var result = ""; - var trimmedSrcset = trim(value); - var srcPattern = /(\s+\d+x\s*,|\s+\d+w\s*,|\s+,|,\s+)/; - var pattern = /\s/.test(trimmedSrcset) ? srcPattern : /(,)/; - var rawUris = trimmedSrcset.split(pattern); - var nbrUrisWith2parts = Math.floor(rawUris.length / 2); - for (var i = 0; i < nbrUrisWith2parts; i++) { - var innerIdx = i * 2; - result += $$sanitizeUri(trim(rawUris[innerIdx]), true); - result += " " + trim(rawUris[innerIdx + 1]); - } - var lastTuple = trim(rawUris[i * 2]).split(/\s/); - result += $$sanitizeUri(trim(lastTuple[0]), true); - if (lastTuple.length === 2) { - result += " " + trim(lastTuple[1]); + } else if (source && typeof source.hasOwnProperty === "function") { + for (key in source) { + if (source.hasOwnProperty(key)) { + destination[key] = copy(source[key], null, stackSource, stackDest); } - this[key] = value = result; } - if (writeAttr !== false) { - if (value === null || isUndefined(value)) { - this.$$element.removeAttr(attrName); - } else { - this.$$element.attr(attrName, value); + } else { + for (key in source) { + if (hasOwnProperty.call(source, key)) { + destination[key] = copy(source[key], null, stackSource, stackDest); } } - var $$observers = this.$$observers; - $$observers && forEach($$observers[observer], function(fn) { - try { - fn(value); - } catch (e) { - $exceptionHandler(e); - } - }); - }, - $observe: function(key, fn) { - var attrs = this, $$observers = attrs.$$observers || (attrs.$$observers = createMap()), listeners = $$observers[key] || ($$observers[key] = []); - listeners.push(fn); - $rootScope.$evalAsync(function() { - if (!listeners.$$inter && attrs.hasOwnProperty(key) && !isUndefined(attrs[key])) { - fn(attrs[key]); - } - }); - return function() { - arrayRemove(listeners, fn); - }; } - }; - function safeAddClass($element, className) { - try { - $element.addClass(className); - } catch (e) {} + setHashKey(destination, h); } - var startSymbol = $interpolate.startSymbol(), endSymbol = $interpolate.endSymbol(), denormalizeTemplate = startSymbol == "{{" || endSymbol == "}}" ? identity : function denormalizeTemplate(template) { - return template.replace(/\{\{/g, startSymbol).replace(/}}/g, endSymbol); - }, NG_ATTR_BINDING = /^ngAttr[A-Z]/; - compile.$$addBindingInfo = debugInfoEnabled ? function $$addBindingInfo($element, binding) { - var bindings = $element.data("$binding") || []; - if (isArray(binding)) { - bindings = bindings.concat(binding); - } else { - bindings.push(binding); - } - $element.data("$binding", bindings); - } : noop; - compile.$$addBindingClass = debugInfoEnabled ? function $$addBindingClass($element) { - safeAddClass($element, "ng-binding"); - } : noop; - compile.$$addScopeInfo = debugInfoEnabled ? function $$addScopeInfo($element, scope, isolated, noTemplate) { - var dataName = isolated ? noTemplate ? "$isolateScopeNoTemplate" : "$isolateScope" : "$scope"; - $element.data(dataName, scope); - } : noop; - compile.$$addScopeClass = debugInfoEnabled ? function $$addScopeClass($element, isolated) { - safeAddClass($element, isolated ? "ng-isolate-scope" : "ng-scope"); - } : noop; - return compile; - function compile($compileNodes, transcludeFn, maxPriority, ignoreDirective, previousCompileContext) { - if (!($compileNodes instanceof jqLite)) { - $compileNodes = jqLite($compileNodes); - } - forEach($compileNodes, function(node, index) { - if (node.nodeType == NODE_TYPE_TEXT && node.nodeValue.match(/\S+/)) { - $compileNodes[index] = jqLite(node).wrap("").parent()[0]; - } - }); - var compositeLinkFn = compileNodes($compileNodes, transcludeFn, $compileNodes, maxPriority, ignoreDirective, previousCompileContext); - compile.$$addScopeClass($compileNodes); - var namespace = null; - return function publicLinkFn(scope, cloneConnectFn, options) { - assertArg(scope, "scope"); - options = options || {}; - var parentBoundTranscludeFn = options.parentBoundTranscludeFn, transcludeControllers = options.transcludeControllers, futureParentElement = options.futureParentElement; - if (parentBoundTranscludeFn && parentBoundTranscludeFn.$$boundTransclude) { - parentBoundTranscludeFn = parentBoundTranscludeFn.$$boundTransclude; - } - if (!namespace) { - namespace = detectNamespaceForChildElements(futureParentElement); - } - var $linkNode; - if (namespace !== "html") { - $linkNode = jqLite(wrapTemplate(namespace, jqLite("
        ").append($compileNodes).html())); - } else if (cloneConnectFn) { - $linkNode = JQLitePrototype.clone.call($compileNodes); - } else { - $linkNode = $compileNodes; - } - if (transcludeControllers) { - for (var controllerName in transcludeControllers) { - $linkNode.data("$" + controllerName + "Controller", transcludeControllers[controllerName].instance); - } - } - compile.$$addScopeInfo($linkNode, scope); - if (cloneConnectFn) cloneConnectFn($linkNode, scope); - if (compositeLinkFn) compositeLinkFn(scope, $linkNode, $linkNode, parentBoundTranscludeFn); - return $linkNode; - }; + } + return destination; + } + function shallowCopy(src, dst) { + if (isArray(src)) { + dst = dst || []; + for (var i = 0, ii = src.length; i < ii; i++) { + dst[i] = src[i]; } - function detectNamespaceForChildElements(parentElement) { - var node = parentElement && parentElement[0]; - if (!node) { - return "html"; - } else { - return nodeName_(node) !== "foreignobject" && node.toString().match(/SVG/) ? "svg" : "html"; + } else if (isObject(src)) { + dst = dst || {}; + for (var key in src) { + if (!(key.charAt(0) === "$" && key.charAt(1) === "$")) { + dst[key] = src[key]; } } - function compileNodes(nodeList, transcludeFn, $rootElement, maxPriority, ignoreDirective, previousCompileContext) { - var linkFns = [], attrs, directives, nodeLinkFn, childNodes, childLinkFn, linkFnFound, nodeLinkFnFound; - for (var i = 0; i < nodeList.length; i++) { - attrs = new Attributes(); - directives = collectDirectives(nodeList[i], [], attrs, i === 0 ? maxPriority : undefined, ignoreDirective); - nodeLinkFn = directives.length ? applyDirectivesToNode(directives, nodeList[i], attrs, transcludeFn, $rootElement, null, [], [], previousCompileContext) : null; - if (nodeLinkFn && nodeLinkFn.scope) { - compile.$$addScopeClass(attrs.$$element); - } - childLinkFn = nodeLinkFn && nodeLinkFn.terminal || !(childNodes = nodeList[i].childNodes) || !childNodes.length ? null : compileNodes(childNodes, nodeLinkFn ? (nodeLinkFn.transcludeOnThisElement || !nodeLinkFn.templateOnThisElement) && nodeLinkFn.transclude : transcludeFn); - if (nodeLinkFn || childLinkFn) { - linkFns.push(i, nodeLinkFn, childLinkFn); - linkFnFound = true; - nodeLinkFnFound = nodeLinkFnFound || nodeLinkFn; - } - previousCompileContext = null; - } - return linkFnFound ? compositeLinkFn : null; - function compositeLinkFn(scope, nodeList, $rootElement, parentBoundTranscludeFn) { - var nodeLinkFn, childLinkFn, node, childScope, i, ii, idx, childBoundTranscludeFn; - var stableNodeList; - if (nodeLinkFnFound) { - var nodeListLength = nodeList.length; - stableNodeList = new Array(nodeListLength); - for (i = 0; i < linkFns.length; i += 3) { - idx = linkFns[i]; - stableNodeList[idx] = nodeList[idx]; + } + return dst || src; + } + function equals(o1, o2) { + if (o1 === o2) return true; + if (o1 === null || o2 === null) return false; + if (o1 !== o1 && o2 !== o2) return true; + var t1 = typeof o1, t2 = typeof o2, length, key, keySet; + if (t1 == t2) { + if (t1 == "object") { + if (isArray(o1)) { + if (!isArray(o2)) return false; + if ((length = o1.length) == o2.length) { + for (key = 0; key < length; key++) { + if (!equals(o1[key], o2[key])) return false; } - } else { - stableNodeList = nodeList; + return true; } - for (i = 0, ii = linkFns.length; i < ii; ) { - node = stableNodeList[linkFns[i++]]; - nodeLinkFn = linkFns[i++]; - childLinkFn = linkFns[i++]; - if (nodeLinkFn) { - if (nodeLinkFn.scope) { - childScope = scope.$new(); - compile.$$addScopeInfo(jqLite(node), childScope); - var destroyBindings = nodeLinkFn.$$destroyBindings; - if (destroyBindings) { - nodeLinkFn.$$destroyBindings = null; - childScope.$on("$destroyed", destroyBindings); - } - } else { - childScope = scope; - } - if (nodeLinkFn.transcludeOnThisElement) { - childBoundTranscludeFn = createBoundTranscludeFn(scope, nodeLinkFn.transclude, parentBoundTranscludeFn); - } else if (!nodeLinkFn.templateOnThisElement && parentBoundTranscludeFn) { - childBoundTranscludeFn = parentBoundTranscludeFn; - } else if (!parentBoundTranscludeFn && transcludeFn) { - childBoundTranscludeFn = createBoundTranscludeFn(scope, transcludeFn); - } else { - childBoundTranscludeFn = null; - } - nodeLinkFn(childLinkFn, childScope, node, $rootElement, childBoundTranscludeFn, nodeLinkFn); - } else if (childLinkFn) { - childLinkFn(scope, node.childNodes, undefined, parentBoundTranscludeFn); - } + } else if (isDate(o1)) { + if (!isDate(o2)) return false; + return equals(o1.getTime(), o2.getTime()); + } else if (isRegExp(o1)) { + return isRegExp(o2) ? o1.toString() == o2.toString() : false; + } else { + if (isScope(o1) || isScope(o2) || isWindow(o1) || isWindow(o2) || isArray(o2) || isDate(o2) || isRegExp(o2)) return false; + keySet = createMap(); + for (key in o1) { + if (key.charAt(0) === "$" || isFunction(o1[key])) continue; + if (!equals(o1[key], o2[key])) return false; + keySet[key] = true; + } + for (key in o2) { + if (!(key in keySet) && key.charAt(0) !== "$" && isDefined(o2[key]) && !isFunction(o2[key])) return false; } + return true; } } - function createBoundTranscludeFn(scope, transcludeFn, previousBoundTranscludeFn) { - var boundTranscludeFn = function(transcludedScope, cloneFn, controllers, futureParentElement, containingScope) { - if (!transcludedScope) { - transcludedScope = scope.$new(false, containingScope); - transcludedScope.$$transcluded = true; - } - return transcludeFn(transcludedScope, cloneFn, { - parentBoundTranscludeFn: previousBoundTranscludeFn, - transcludeControllers: controllers, - futureParentElement: futureParentElement - }); + } + return false; + } + var csp = function() { + if (!isDefined(csp.rules)) { + var ngCspElement = document.querySelector("[ng-csp]") || document.querySelector("[data-ng-csp]"); + if (ngCspElement) { + var ngCspAttribute = ngCspElement.getAttribute("ng-csp") || ngCspElement.getAttribute("data-ng-csp"); + csp.rules = { + noUnsafeEval: !ngCspAttribute || ngCspAttribute.indexOf("no-unsafe-eval") !== -1, + noInlineStyle: !ngCspAttribute || ngCspAttribute.indexOf("no-inline-style") !== -1 + }; + } else { + csp.rules = { + noUnsafeEval: noUnsafeEval(), + noInlineStyle: false }; - return boundTranscludeFn; } - function collectDirectives(node, directives, attrs, maxPriority, ignoreDirective) { - var nodeType = node.nodeType, attrsMap = attrs.$attr, match, className; - switch (nodeType) { - case NODE_TYPE_ELEMENT: - addDirective(directives, directiveNormalize(nodeName_(node)), "E", maxPriority, ignoreDirective); - for (var attr, name, nName, ngAttrName, value, isNgAttr, nAttrs = node.attributes, j = 0, jj = nAttrs && nAttrs.length; j < jj; j++) { - var attrStartName = false; - var attrEndName = false; - attr = nAttrs[j]; - name = attr.name; - value = trim(attr.value); - ngAttrName = directiveNormalize(name); - if (isNgAttr = NG_ATTR_BINDING.test(ngAttrName)) { - name = name.replace(PREFIX_REGEXP, "").substr(8).replace(/_(.)/g, function(match, letter) { - return letter.toUpperCase(); - }); - } - var directiveNName = ngAttrName.replace(/(Start|End)$/, ""); - if (directiveIsMultiElement(directiveNName)) { - if (ngAttrName === directiveNName + "Start") { - attrStartName = name; - attrEndName = name.substr(0, name.length - 5) + "end"; - name = name.substr(0, name.length - 6); - } - } - nName = directiveNormalize(name.toLowerCase()); - attrsMap[nName] = name; - if (isNgAttr || !attrs.hasOwnProperty(nName)) { - attrs[nName] = value; - if (getBooleanAttrName(node, nName)) { - attrs[nName] = true; - } - } - addAttrInterpolateDirective(node, directives, value, nName, isNgAttr); - addDirective(directives, nName, "A", maxPriority, ignoreDirective, attrStartName, attrEndName); - } - className = node.className; - if (isObject(className)) { - className = className.animVal; - } - if (isString(className) && className !== "") { - while (match = CLASS_DIRECTIVE_REGEXP.exec(className)) { - nName = directiveNormalize(match[2]); - if (addDirective(directives, nName, "C", maxPriority, ignoreDirective)) { - attrs[nName] = trim(match[3]); - } - className = className.substr(match.index + match[0].length); - } - } - break; - - case NODE_TYPE_TEXT: - if (msie === 11) { - while (node.parentNode && node.nextSibling && node.nextSibling.nodeType === NODE_TYPE_TEXT) { - node.nodeValue = node.nodeValue + node.nextSibling.nodeValue; - node.parentNode.removeChild(node.nextSibling); - } + } + return csp.rules; + function noUnsafeEval() { + try { + new Function(""); + return false; + } catch (e) { + return true; + } + } + }; + var jq = function() { + if (isDefined(jq.name_)) return jq.name_; + var el; + var i, ii = ngAttrPrefixes.length, prefix, name; + for (i = 0; i < ii; ++i) { + prefix = ngAttrPrefixes[i]; + if (el = document.querySelector("[" + prefix.replace(":", "\\:") + "jq]")) { + name = el.getAttribute(prefix + "jq"); + break; + } + } + return jq.name_ = name; + }; + function concat(array1, array2, index) { + return array1.concat(slice.call(array2, index)); + } + function sliceArgs(args, startIndex) { + return slice.call(args, startIndex || 0); + } + function bind(self, fn) { + var curryArgs = arguments.length > 2 ? sliceArgs(arguments, 2) : []; + if (isFunction(fn) && !(fn instanceof RegExp)) { + return curryArgs.length ? function() { + return arguments.length ? fn.apply(self, concat(curryArgs, arguments, 0)) : fn.apply(self, curryArgs); + } : function() { + return arguments.length ? fn.apply(self, arguments) : fn.call(self); + }; + } else { + return fn; + } + } + function toJsonReplacer(key, value) { + var val = value; + if (typeof key === "string" && key.charAt(0) === "$" && key.charAt(1) === "$") { + val = undefined; + } else if (isWindow(value)) { + val = "$WINDOW"; + } else if (value && document === value) { + val = "$DOCUMENT"; + } else if (isScope(value)) { + val = "$SCOPE"; + } + return val; + } + function toJson(obj, pretty) { + if (typeof obj === "undefined") return undefined; + if (!isNumber(pretty)) { + pretty = pretty ? 2 : null; + } + return JSON.stringify(obj, toJsonReplacer, pretty); + } + function fromJson(json) { + return isString(json) ? JSON.parse(json) : json; + } + function timezoneToOffset(timezone, fallback) { + var requestedTimezoneOffset = Date.parse("Jan 01, 1970 00:00:00 " + timezone) / 6e4; + return isNaN(requestedTimezoneOffset) ? fallback : requestedTimezoneOffset; + } + function addDateMinutes(date, minutes) { + date = new Date(date.getTime()); + date.setMinutes(date.getMinutes() + minutes); + return date; + } + function convertTimezoneToLocal(date, timezone, reverse) { + reverse = reverse ? -1 : 1; + var timezoneOffset = timezoneToOffset(timezone, date.getTimezoneOffset()); + return addDateMinutes(date, reverse * (timezoneOffset - date.getTimezoneOffset())); + } + function startingTag(element) { + element = jqLite(element).clone(); + try { + element.empty(); + } catch (e) {} + var elemHtml = jqLite("
        ").append(element).html(); + try { + return element[0].nodeType === NODE_TYPE_TEXT ? lowercase(elemHtml) : elemHtml.match(/^(<[^>]+>)/)[1].replace(/^<([\w\-]+)/, function(match, nodeName) { + return "<" + lowercase(nodeName); + }); + } catch (e) { + return lowercase(elemHtml); + } + } + function tryDecodeURIComponent(value) { + try { + return decodeURIComponent(value); + } catch (e) {} + } + function parseKeyValue(keyValue) { + var obj = {}; + forEach((keyValue || "").split("&"), function(keyValue) { + var splitPoint, key, val; + if (keyValue) { + key = keyValue = keyValue.replace(/\+/g, "%20"); + splitPoint = keyValue.indexOf("="); + if (splitPoint !== -1) { + key = keyValue.substring(0, splitPoint); + val = keyValue.substring(splitPoint + 1); + } + key = tryDecodeURIComponent(key); + if (isDefined(key)) { + val = isDefined(val) ? tryDecodeURIComponent(val) : true; + if (!hasOwnProperty.call(obj, key)) { + obj[key] = val; + } else if (isArray(obj[key])) { + obj[key].push(val); + } else { + obj[key] = [ obj[key], val ]; } - addTextInterpolateDirective(directives, node.nodeValue); - break; - - case NODE_TYPE_COMMENT: - try { - match = COMMENT_DIRECTIVE_REGEXP.exec(node.nodeValue); - if (match) { - nName = directiveNormalize(match[1]); - if (addDirective(directives, nName, "M", maxPriority, ignoreDirective)) { - attrs[nName] = trim(match[2]); - } - } - } catch (e) {} - break; } - directives.sort(byPriority); - return directives; } - function groupScan(node, attrStart, attrEnd) { - var nodes = []; - var depth = 0; - if (attrStart && node.hasAttribute && node.hasAttribute(attrStart)) { - do { - if (!node) { - throw $compileMinErr("uterdir", "Unterminated attribute, found '{0}' but no matching '{1}' found.", attrStart, attrEnd); - } - if (node.nodeType == NODE_TYPE_ELEMENT) { - if (node.hasAttribute(attrStart)) depth++; - if (node.hasAttribute(attrEnd)) depth--; - } - nodes.push(node); - node = node.nextSibling; - } while (depth > 0); - } else { - nodes.push(node); - } - return jqLite(nodes); + }); + return obj; + } + function toKeyValue(obj) { + var parts = []; + forEach(obj, function(value, key) { + if (isArray(value)) { + forEach(value, function(arrayValue) { + parts.push(encodeUriQuery(key, true) + (arrayValue === true ? "" : "=" + encodeUriQuery(arrayValue, true))); + }); + } else { + parts.push(encodeUriQuery(key, true) + (value === true ? "" : "=" + encodeUriQuery(value, true))); } - function groupElementsLinkFnWrapper(linkFn, attrStart, attrEnd) { - return function(scope, element, attrs, controllers, transcludeFn) { - element = groupScan(element[0], attrStart, attrEnd); - return linkFn(scope, element, attrs, controllers, transcludeFn); - }; + }); + return parts.length ? parts.join("&") : ""; + } + function encodeUriSegment(val) { + return encodeUriQuery(val, true).replace(/%26/gi, "&").replace(/%3D/gi, "=").replace(/%2B/gi, "+"); + } + function encodeUriQuery(val, pctEncodeSpaces) { + return encodeURIComponent(val).replace(/%40/gi, "@").replace(/%3A/gi, ":").replace(/%24/g, "$").replace(/%2C/gi, ",").replace(/%3B/gi, ";").replace(/%20/g, pctEncodeSpaces ? "%20" : "+"); + } + var ngAttrPrefixes = [ "ng-", "data-ng-", "ng:", "x-ng-" ]; + function getNgAttribute(element, ngAttr) { + var attr, i, ii = ngAttrPrefixes.length; + for (i = 0; i < ii; ++i) { + attr = ngAttrPrefixes[i] + ngAttr; + if (isString(attr = element.getAttribute(attr))) { + return attr; } - function applyDirectivesToNode(directives, compileNode, templateAttrs, transcludeFn, jqCollection, originalReplaceDirective, preLinkFns, postLinkFns, previousCompileContext) { - previousCompileContext = previousCompileContext || {}; - var terminalPriority = -Number.MAX_VALUE, newScopeDirective = previousCompileContext.newScopeDirective, controllerDirectives = previousCompileContext.controllerDirectives, newIsolateScopeDirective = previousCompileContext.newIsolateScopeDirective, templateDirective = previousCompileContext.templateDirective, nonTlbTranscludeDirective = previousCompileContext.nonTlbTranscludeDirective, hasTranscludeDirective = false, hasTemplate = false, hasElementTranscludeDirective = previousCompileContext.hasElementTranscludeDirective, $compileNode = templateAttrs.$$element = jqLite(compileNode), directive, directiveName, $template, replaceDirective = originalReplaceDirective, childTranscludeFn = transcludeFn, linkFn, directiveValue; - for (var i = 0, ii = directives.length; i < ii; i++) { - directive = directives[i]; - var attrStart = directive.$$start; - var attrEnd = directive.$$end; - if (attrStart) { - $compileNode = groupScan(compileNode, attrStart, attrEnd); - } - $template = undefined; - if (terminalPriority > directive.priority) { - break; - } - if (directiveValue = directive.scope) { - if (!directive.templateUrl) { - if (isObject(directiveValue)) { - assertNoDuplicate("new/isolated scope", newIsolateScopeDirective || newScopeDirective, directive, $compileNode); - newIsolateScopeDirective = directive; - } else { - assertNoDuplicate("new/isolated scope", newIsolateScopeDirective, directive, $compileNode); - } - } - newScopeDirective = newScopeDirective || directive; - } - directiveName = directive.name; - if (!directive.templateUrl && directive.controller) { - directiveValue = directive.controller; - controllerDirectives = controllerDirectives || createMap(); - assertNoDuplicate("'" + directiveName + "' controller", controllerDirectives[directiveName], directive, $compileNode); - controllerDirectives[directiveName] = directive; - } - if (directiveValue = directive.transclude) { - hasTranscludeDirective = true; - if (!directive.$$tlb) { - assertNoDuplicate("transclusion", nonTlbTranscludeDirective, directive, $compileNode); - nonTlbTranscludeDirective = directive; - } - if (directiveValue == "element") { - hasElementTranscludeDirective = true; - terminalPriority = directive.priority; - $template = $compileNode; - $compileNode = templateAttrs.$$element = jqLite(document.createComment(" " + directiveName + ": " + templateAttrs[directiveName] + " ")); - compileNode = $compileNode[0]; - replaceWith(jqCollection, sliceArgs($template), compileNode); - childTranscludeFn = compile($template, transcludeFn, terminalPriority, replaceDirective && replaceDirective.name, { - nonTlbTranscludeDirective: nonTlbTranscludeDirective - }); - } else { - $template = jqLite(jqLiteClone(compileNode)).contents(); - $compileNode.empty(); - childTranscludeFn = compile($template, transcludeFn); - } - } - if (directive.template) { - hasTemplate = true; - assertNoDuplicate("template", templateDirective, directive, $compileNode); - templateDirective = directive; - directiveValue = isFunction(directive.template) ? directive.template($compileNode, templateAttrs) : directive.template; - directiveValue = denormalizeTemplate(directiveValue); - if (directive.replace) { - replaceDirective = directive; - if (jqLiteIsTextNode(directiveValue)) { - $template = []; - } else { - $template = removeComments(wrapTemplate(directive.templateNamespace, trim(directiveValue))); - } - compileNode = $template[0]; - if ($template.length != 1 || compileNode.nodeType !== NODE_TYPE_ELEMENT) { - throw $compileMinErr("tplrt", "Template for directive '{0}' must have exactly one root element. {1}", directiveName, ""); - } - replaceWith(jqCollection, $compileNode, compileNode); - var newTemplateAttrs = { - $attr: {} - }; - var templateDirectives = collectDirectives(compileNode, [], newTemplateAttrs); - var unprocessedDirectives = directives.splice(i + 1, directives.length - (i + 1)); - if (newIsolateScopeDirective) { - markDirectivesAsIsolate(templateDirectives); - } - directives = directives.concat(templateDirectives).concat(unprocessedDirectives); - mergeTemplateAttributes(templateAttrs, newTemplateAttrs); - ii = directives.length; - } else { - $compileNode.html(directiveValue); - } - } - if (directive.templateUrl) { - hasTemplate = true; - assertNoDuplicate("template", templateDirective, directive, $compileNode); - templateDirective = directive; - if (directive.replace) { - replaceDirective = directive; - } - nodeLinkFn = compileTemplateUrl(directives.splice(i, directives.length - i), $compileNode, templateAttrs, jqCollection, hasTranscludeDirective && childTranscludeFn, preLinkFns, postLinkFns, { - controllerDirectives: controllerDirectives, - newScopeDirective: newScopeDirective !== directive && newScopeDirective, - newIsolateScopeDirective: newIsolateScopeDirective, - templateDirective: templateDirective, - nonTlbTranscludeDirective: nonTlbTranscludeDirective - }); - ii = directives.length; - } else if (directive.compile) { - try { - linkFn = directive.compile($compileNode, templateAttrs, childTranscludeFn); - if (isFunction(linkFn)) { - addLinkFns(null, linkFn, attrStart, attrEnd); - } else if (linkFn) { - addLinkFns(linkFn.pre, linkFn.post, attrStart, attrEnd); - } - } catch (e) { - $exceptionHandler(e, startingTag($compileNode)); - } - } - if (directive.terminal) { - nodeLinkFn.terminal = true; - terminalPriority = Math.max(terminalPriority, directive.priority); - } - } - nodeLinkFn.scope = newScopeDirective && newScopeDirective.scope === true; - nodeLinkFn.transcludeOnThisElement = hasTranscludeDirective; - nodeLinkFn.templateOnThisElement = hasTemplate; - nodeLinkFn.transclude = childTranscludeFn; - previousCompileContext.hasElementTranscludeDirective = hasElementTranscludeDirective; - return nodeLinkFn; - function addLinkFns(pre, post, attrStart, attrEnd) { - if (pre) { - if (attrStart) pre = groupElementsLinkFnWrapper(pre, attrStart, attrEnd); - pre.require = directive.require; - pre.directiveName = directiveName; - if (newIsolateScopeDirective === directive || directive.$$isolateScope) { - pre = cloneAndAnnotateFn(pre, { - isolateScope: true - }); - } - preLinkFns.push(pre); - } - if (post) { - if (attrStart) post = groupElementsLinkFnWrapper(post, attrStart, attrEnd); - post.require = directive.require; - post.directiveName = directiveName; - if (newIsolateScopeDirective === directive || directive.$$isolateScope) { - post = cloneAndAnnotateFn(post, { - isolateScope: true - }); - } - postLinkFns.push(post); - } - } - function getControllers(directiveName, require, $element, elementControllers) { - var value; - if (isString(require)) { - var match = require.match(REQUIRE_PREFIX_REGEXP); - var name = require.substring(match[0].length); - var inheritType = match[1] || match[3]; - var optional = match[2] === "?"; - if (inheritType === "^^") { - $element = $element.parent(); - } else { - value = elementControllers && elementControllers[name]; - value = value && value.instance; - } - if (!value) { - var dataName = "$" + name + "Controller"; - value = inheritType ? $element.inheritedData(dataName) : $element.data(dataName); - } - if (!value && !optional) { - throw $compileMinErr("ctreq", "Controller '{0}', required by directive '{1}', can't be found!", name, directiveName); - } - } else if (isArray(require)) { - value = []; - for (var i = 0, ii = require.length; i < ii; i++) { - value[i] = getControllers(directiveName, require[i], $element, elementControllers); + } + return null; + } + function angularInit(element, bootstrap) { + var appElement, module, config = {}; + forEach(ngAttrPrefixes, function(prefix) { + var name = prefix + "app"; + if (!appElement && element.hasAttribute && element.hasAttribute(name)) { + appElement = element; + module = element.getAttribute(name); + } + }); + forEach(ngAttrPrefixes, function(prefix) { + var name = prefix + "app"; + var candidate; + if (!appElement && (candidate = element.querySelector("[" + name.replace(":", "\\:") + "]"))) { + appElement = candidate; + module = candidate.getAttribute(name); + } + }); + if (appElement) { + config.strictDi = getNgAttribute(appElement, "strict-di") !== null; + bootstrap(appElement, module ? [ module ] : [], config); + } + } + function bootstrap(element, modules, config) { + if (!isObject(config)) config = {}; + var defaultConfig = { + strictDi: false + }; + config = extend(defaultConfig, config); + var doBootstrap = function() { + element = jqLite(element); + if (element.injector()) { + var tag = element[0] === document ? "document" : startingTag(element); + throw ngMinErr("btstrpd", "App Already Bootstrapped with this Element '{0}'", tag.replace(//, ">")); + } + modules = modules || []; + modules.unshift([ "$provide", function($provide) { + $provide.value("$rootElement", element); + } ]); + if (config.debugInfoEnabled) { + modules.push([ "$compileProvider", function($compileProvider) { + $compileProvider.debugInfoEnabled(true); + } ]); + } + modules.unshift("ng"); + var injector = createInjector(modules, config.strictDi); + injector.invoke([ "$rootScope", "$rootElement", "$compile", "$injector", function bootstrapApply(scope, element, compile, injector) { + scope.$apply(function() { + element.data("$injector", injector); + compile(element)(scope); + }); + } ]); + return injector; + }; + var NG_ENABLE_DEBUG_INFO = /^NG_ENABLE_DEBUG_INFO!/; + var NG_DEFER_BOOTSTRAP = /^NG_DEFER_BOOTSTRAP!/; + if (window && NG_ENABLE_DEBUG_INFO.test(window.name)) { + config.debugInfoEnabled = true; + window.name = window.name.replace(NG_ENABLE_DEBUG_INFO, ""); + } + if (window && !NG_DEFER_BOOTSTRAP.test(window.name)) { + return doBootstrap(); + } + window.name = window.name.replace(NG_DEFER_BOOTSTRAP, ""); + angular.resumeBootstrap = function(extraModules) { + forEach(extraModules, function(module) { + modules.push(module); + }); + return doBootstrap(); + }; + if (isFunction(angular.resumeDeferredBootstrap)) { + angular.resumeDeferredBootstrap(); + } + } + function reloadWithDebugInfo() { + window.name = "NG_ENABLE_DEBUG_INFO!" + window.name; + window.location.reload(); + } + function getTestability(rootElement) { + var injector = angular.element(rootElement).injector(); + if (!injector) { + throw ngMinErr("test", "no injector found for element argument to getTestability"); + } + return injector.get("$$testability"); + } + var SNAKE_CASE_REGEXP = /[A-Z]/g; + function snake_case(name, separator) { + separator = separator || "_"; + return name.replace(SNAKE_CASE_REGEXP, function(letter, pos) { + return (pos ? separator : "") + letter.toLowerCase(); + }); + } + var bindJQueryFired = false; + var skipDestroyOnNextJQueryCleanData; + function bindJQuery() { + var originalCleanData; + if (bindJQueryFired) { + return; + } + var jqName = jq(); + jQuery = isUndefined(jqName) ? window.jQuery : !jqName ? undefined : window[jqName]; + if (jQuery && jQuery.fn.on) { + jqLite = jQuery; + extend(jQuery.fn, { + scope: JQLitePrototype.scope, + isolateScope: JQLitePrototype.isolateScope, + controller: JQLitePrototype.controller, + injector: JQLitePrototype.injector, + inheritedData: JQLitePrototype.inheritedData + }); + originalCleanData = jQuery.cleanData; + jQuery.cleanData = function(elems) { + var events; + if (!skipDestroyOnNextJQueryCleanData) { + for (var i = 0, elem; (elem = elems[i]) != null; i++) { + events = jQuery._data(elem, "events"); + if (events && events.$destroy) { + jQuery(elem).triggerHandler("$destroy"); } } - return value || null; - } - function setupControllers($element, attrs, transcludeFn, controllerDirectives, isolateScope, scope) { - var elementControllers = createMap(); - for (var controllerKey in controllerDirectives) { - var directive = controllerDirectives[controllerKey]; - var locals = { - $scope: directive === newIsolateScopeDirective || directive.$$isolateScope ? isolateScope : scope, - $element: $element, - $attrs: attrs, - $transclude: transcludeFn - }; - var controller = directive.controller; - if (controller == "@") { - controller = attrs[directive.name]; - } - var controllerInstance = $controller(controller, locals, true, directive.controllerAs); - elementControllers[directive.name] = controllerInstance; - if (!hasElementTranscludeDirective) { - $element.data("$" + directive.name + "Controller", controllerInstance.instance); - } - } - return elementControllers; - } - function nodeLinkFn(childLinkFn, scope, linkNode, $rootElement, boundTranscludeFn, thisLinkFn) { - var i, ii, linkFn, controller, isolateScope, elementControllers, transcludeFn, $element, attrs; - if (compileNode === linkNode) { - attrs = templateAttrs; - $element = templateAttrs.$$element; - } else { - $element = jqLite(linkNode); - attrs = new Attributes($element, templateAttrs); - } - if (newIsolateScopeDirective) { - isolateScope = scope.$new(true); - } - if (boundTranscludeFn) { - transcludeFn = controllersBoundTransclude; - transcludeFn.$$boundTransclude = boundTranscludeFn; - } - if (controllerDirectives) { - elementControllers = setupControllers($element, attrs, transcludeFn, controllerDirectives, isolateScope, scope); - } - if (newIsolateScopeDirective) { - compile.$$addScopeInfo($element, isolateScope, true, !(templateDirective && (templateDirective === newIsolateScopeDirective || templateDirective === newIsolateScopeDirective.$$originalDirective))); - compile.$$addScopeClass($element, true); - isolateScope.$$isolateBindings = newIsolateScopeDirective.$$isolateBindings; - initializeDirectiveBindings(scope, attrs, isolateScope, isolateScope.$$isolateBindings, newIsolateScopeDirective, isolateScope); - } - if (elementControllers) { - var scopeDirective = newIsolateScopeDirective || newScopeDirective; - var bindings; - var controllerForBindings; - if (scopeDirective && elementControllers[scopeDirective.name]) { - bindings = scopeDirective.$$bindings.bindToController; - controller = elementControllers[scopeDirective.name]; - if (controller && controller.identifier && bindings) { - controllerForBindings = controller; - thisLinkFn.$$destroyBindings = initializeDirectiveBindings(scope, attrs, controller.instance, bindings, scopeDirective); - } - } - for (i in elementControllers) { - controller = elementControllers[i]; - var controllerResult = controller(); - if (controllerResult !== controller.instance) { - controller.instance = controllerResult; - $element.data("$" + i + "Controller", controllerResult); - if (controller === controllerForBindings) { - thisLinkFn.$$destroyBindings(); - thisLinkFn.$$destroyBindings = initializeDirectiveBindings(scope, attrs, controllerResult, bindings, scopeDirective); - } - } - } - } - for (i = 0, ii = preLinkFns.length; i < ii; i++) { - linkFn = preLinkFns[i]; - invokeLinkFn(linkFn, linkFn.isolateScope ? isolateScope : scope, $element, attrs, linkFn.require && getControllers(linkFn.directiveName, linkFn.require, $element, elementControllers), transcludeFn); - } - var scopeToChild = scope; - if (newIsolateScopeDirective && (newIsolateScopeDirective.template || newIsolateScopeDirective.templateUrl === null)) { - scopeToChild = isolateScope; - } - childLinkFn && childLinkFn(scopeToChild, linkNode.childNodes, undefined, boundTranscludeFn); - for (i = postLinkFns.length - 1; i >= 0; i--) { - linkFn = postLinkFns[i]; - invokeLinkFn(linkFn, linkFn.isolateScope ? isolateScope : scope, $element, attrs, linkFn.require && getControllers(linkFn.directiveName, linkFn.require, $element, elementControllers), transcludeFn); - } - function controllersBoundTransclude(scope, cloneAttachFn, futureParentElement) { - var transcludeControllers; - if (!isScope(scope)) { - futureParentElement = cloneAttachFn; - cloneAttachFn = scope; - scope = undefined; - } - if (hasElementTranscludeDirective) { - transcludeControllers = elementControllers; - } - if (!futureParentElement) { - futureParentElement = hasElementTranscludeDirective ? $element.parent() : $element; - } - return boundTranscludeFn(scope, cloneAttachFn, transcludeControllers, futureParentElement, scopeToChild); - } + } else { + skipDestroyOnNextJQueryCleanData = false; } + originalCleanData(elems); + }; + } else { + jqLite = JQLite; + } + angular.element = jqLite; + bindJQueryFired = true; + } + function assertArg(arg, name, reason) { + if (!arg) { + throw ngMinErr("areq", "Argument '{0}' is {1}", name || "?", reason || "required"); + } + return arg; + } + function assertArgFn(arg, name, acceptArrayAnnotation) { + if (acceptArrayAnnotation && isArray(arg)) { + arg = arg[arg.length - 1]; + } + assertArg(isFunction(arg), name, "not a function, got " + (arg && typeof arg === "object" ? arg.constructor.name || "Object" : typeof arg)); + return arg; + } + function assertNotHasOwnProperty(name, context) { + if (name === "hasOwnProperty") { + throw ngMinErr("badname", "hasOwnProperty is not a valid {0} name", context); + } + } + function getter(obj, path, bindFnToScope) { + if (!path) return obj; + var keys = path.split("."); + var key; + var lastInstance = obj; + var len = keys.length; + for (var i = 0; i < len; i++) { + key = keys[i]; + if (obj) { + obj = (lastInstance = obj)[key]; } - function markDirectivesAsIsolate(directives) { - for (var j = 0, jj = directives.length; j < jj; j++) { - directives[j] = inherit(directives[j], { - $$isolateScope: true - }); + } + if (!bindFnToScope && isFunction(obj)) { + return bind(lastInstance, obj); + } + return obj; + } + function getBlockNodes(nodes) { + var node = nodes[0]; + var endNode = nodes[nodes.length - 1]; + var blockNodes; + for (var i = 1; node !== endNode && (node = node.nextSibling); i++) { + if (blockNodes || nodes[i] !== node) { + if (!blockNodes) { + blockNodes = jqLite(slice.call(nodes, 0, i)); } + blockNodes.push(node); } - function addDirective(tDirectives, name, location, maxPriority, ignoreDirective, startAttrName, endAttrName) { - if (name === ignoreDirective) return null; - var match = null; - if (hasDirectives.hasOwnProperty(name)) { - for (var directive, directives = $injector.get(name + Suffix), i = 0, ii = directives.length; i < ii; i++) { - try { - directive = directives[i]; - if ((isUndefined(maxPriority) || maxPriority > directive.priority) && directive.restrict.indexOf(location) != -1) { - if (startAttrName) { - directive = inherit(directive, { - $$start: startAttrName, - $$end: endAttrName - }); - } - tDirectives.push(directive); - match = directive; - } - } catch (e) { - $exceptionHandler(e); - } + } + return blockNodes || nodes; + } + function createMap() { + return Object.create(null); + } + var NODE_TYPE_ELEMENT = 1; + var NODE_TYPE_ATTRIBUTE = 2; + var NODE_TYPE_TEXT = 3; + var NODE_TYPE_COMMENT = 8; + var NODE_TYPE_DOCUMENT = 9; + var NODE_TYPE_DOCUMENT_FRAGMENT = 11; + function setupModuleLoader(window) { + var $injectorMinErr = minErr("$injector"); + var ngMinErr = minErr("ng"); + function ensure(obj, name, factory) { + return obj[name] || (obj[name] = factory()); + } + var angular = ensure(window, "angular", Object); + angular.$$minErr = angular.$$minErr || minErr; + return ensure(angular, "module", function() { + var modules = {}; + return function module(name, requires, configFn) { + var assertNotHasOwnProperty = function(name, context) { + if (name === "hasOwnProperty") { + throw ngMinErr("badname", "hasOwnProperty is not a valid {0} name", context); } + }; + assertNotHasOwnProperty(name, "module"); + if (requires && modules.hasOwnProperty(name)) { + modules[name] = null; } - return match; - } - function directiveIsMultiElement(name) { - if (hasDirectives.hasOwnProperty(name)) { - for (var directive, directives = $injector.get(name + Suffix), i = 0, ii = directives.length; i < ii; i++) { - directive = directives[i]; - if (directive.multiElement) { - return true; - } + return ensure(modules, name, function() { + if (!requires) { + throw $injectorMinErr("nomod", "Module '{0}' is not available! You either misspelled " + "the module name or forgot to load it. If registering a module ensure that you " + "specify the dependencies as the second argument.", name); } - } - return false; - } - function mergeTemplateAttributes(dst, src) { - var srcAttr = src.$attr, dstAttr = dst.$attr, $element = dst.$$element; - forEach(dst, function(value, key) { - if (key.charAt(0) != "$") { - if (src[key] && src[key] !== value) { - value += (key === "style" ? ";" : " ") + src[key]; + var invokeQueue = []; + var configBlocks = []; + var runBlocks = []; + var config = invokeLater("$injector", "invoke", "push", configBlocks); + var moduleInstance = { + _invokeQueue: invokeQueue, + _configBlocks: configBlocks, + _runBlocks: runBlocks, + requires: requires, + name: name, + provider: invokeLaterAndSetModuleName("$provide", "provider"), + factory: invokeLaterAndSetModuleName("$provide", "factory"), + service: invokeLaterAndSetModuleName("$provide", "service"), + value: invokeLater("$provide", "value"), + constant: invokeLater("$provide", "constant", "unshift"), + decorator: invokeLaterAndSetModuleName("$provide", "decorator"), + animation: invokeLaterAndSetModuleName("$animateProvider", "register"), + filter: invokeLaterAndSetModuleName("$filterProvider", "register"), + controller: invokeLaterAndSetModuleName("$controllerProvider", "register"), + directive: invokeLaterAndSetModuleName("$compileProvider", "directive"), + config: config, + run: function(block) { + runBlocks.push(block); + return this; } - dst.$set(key, value, true, srcAttr[key]); + }; + if (configFn) { + config(configFn); + } + return moduleInstance; + function invokeLater(provider, method, insertMethod, queue) { + if (!queue) queue = invokeQueue; + return function() { + queue[insertMethod || "push"]([ provider, method, arguments ]); + return moduleInstance; + }; + } + function invokeLaterAndSetModuleName(provider, method) { + return function(recipeName, factoryFunction) { + if (factoryFunction && isFunction(factoryFunction)) factoryFunction.$$moduleName = name; + invokeQueue.push([ provider, method, arguments ]); + return moduleInstance; + }; } }); - forEach(src, function(value, key) { - if (key == "class") { - safeAddClass($element, value); - dst["class"] = (dst["class"] ? dst["class"] + " " : "") + value; - } else if (key == "style") { - $element.attr("style", $element.attr("style") + ";" + value); - dst["style"] = (dst["style"] ? dst["style"] + ";" : "") + value; - } else if (key.charAt(0) != "$" && !dst.hasOwnProperty(key)) { - dst[key] = value; - dstAttr[key] = srcAttr[key]; - } - }); - } - function compileTemplateUrl(directives, $compileNode, tAttrs, $rootElement, childTranscludeFn, preLinkFns, postLinkFns, previousCompileContext) { - var linkQueue = [], afterTemplateNodeLinkFn, afterTemplateChildLinkFn, beforeTemplateCompileNode = $compileNode[0], origAsyncDirective = directives.shift(), derivedSyncDirective = inherit(origAsyncDirective, { - templateUrl: null, - transclude: null, - replace: null, - $$originalDirective: origAsyncDirective - }), templateUrl = isFunction(origAsyncDirective.templateUrl) ? origAsyncDirective.templateUrl($compileNode, tAttrs) : origAsyncDirective.templateUrl, templateNamespace = origAsyncDirective.templateNamespace; - $compileNode.empty(); - $templateRequest(templateUrl).then(function(content) { - var compileNode, tempTemplateAttrs, $template, childBoundTranscludeFn; - content = denormalizeTemplate(content); - if (origAsyncDirective.replace) { - if (jqLiteIsTextNode(content)) { - $template = []; - } else { - $template = removeComments(wrapTemplate(templateNamespace, trim(content))); - } - compileNode = $template[0]; - if ($template.length != 1 || compileNode.nodeType !== NODE_TYPE_ELEMENT) { - throw $compileMinErr("tplrt", "Template for directive '{0}' must have exactly one root element. {1}", origAsyncDirective.name, templateUrl); - } - tempTemplateAttrs = { - $attr: {} - }; - replaceWith($rootElement, $compileNode, compileNode); - var templateDirectives = collectDirectives(compileNode, [], tempTemplateAttrs); - if (isObject(origAsyncDirective.scope)) { - markDirectivesAsIsolate(templateDirectives); - } - directives = templateDirectives.concat(directives); - mergeTemplateAttributes(tAttrs, tempTemplateAttrs); - } else { - compileNode = beforeTemplateCompileNode; - $compileNode.html(content); - } - directives.unshift(derivedSyncDirective); - afterTemplateNodeLinkFn = applyDirectivesToNode(directives, compileNode, tAttrs, childTranscludeFn, $compileNode, origAsyncDirective, preLinkFns, postLinkFns, previousCompileContext); - forEach($rootElement, function(node, i) { - if (node == compileNode) { - $rootElement[i] = $compileNode[0]; - } - }); - afterTemplateChildLinkFn = compileNodes($compileNode[0].childNodes, childTranscludeFn); - while (linkQueue.length) { - var scope = linkQueue.shift(), beforeTemplateLinkNode = linkQueue.shift(), linkRootElement = linkQueue.shift(), boundTranscludeFn = linkQueue.shift(), linkNode = $compileNode[0]; - if (scope.$$destroyed) continue; - if (beforeTemplateLinkNode !== beforeTemplateCompileNode) { - var oldClasses = beforeTemplateLinkNode.className; - if (!(previousCompileContext.hasElementTranscludeDirective && origAsyncDirective.replace)) { - linkNode = jqLiteClone(compileNode); - } - replaceWith(linkRootElement, jqLite(beforeTemplateLinkNode), linkNode); - safeAddClass(jqLite(linkNode), oldClasses); - } - if (afterTemplateNodeLinkFn.transcludeOnThisElement) { - childBoundTranscludeFn = createBoundTranscludeFn(scope, afterTemplateNodeLinkFn.transclude, boundTranscludeFn); - } else { - childBoundTranscludeFn = boundTranscludeFn; - } - afterTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, linkNode, $rootElement, childBoundTranscludeFn, afterTemplateNodeLinkFn); - } - linkQueue = null; - }); - return function delayedNodeLinkFn(ignoreChildLinkFn, scope, node, rootElement, boundTranscludeFn) { - var childBoundTranscludeFn = boundTranscludeFn; - if (scope.$$destroyed) return; - if (linkQueue) { - linkQueue.push(scope, node, rootElement, childBoundTranscludeFn); - } else { - if (afterTemplateNodeLinkFn.transcludeOnThisElement) { - childBoundTranscludeFn = createBoundTranscludeFn(scope, afterTemplateNodeLinkFn.transclude, boundTranscludeFn); - } - afterTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, node, rootElement, childBoundTranscludeFn, afterTemplateNodeLinkFn); - } - }; - } - function byPriority(a, b) { - var diff = b.priority - a.priority; - if (diff !== 0) return diff; - if (a.name !== b.name) return a.name < b.name ? -1 : 1; - return a.index - b.index; - } - function assertNoDuplicate(what, previousDirective, directive, element) { - function wrapModuleNameIfDefined(moduleName) { - return moduleName ? " (module: " + moduleName + ")" : ""; - } - if (previousDirective) { - throw $compileMinErr("multidir", "Multiple directives [{0}{1}, {2}{3}] asking for {4} on: {5}", previousDirective.name, wrapModuleNameIfDefined(previousDirective.$$moduleName), directive.name, wrapModuleNameIfDefined(directive.$$moduleName), what, startingTag(element)); - } - } - function addTextInterpolateDirective(directives, text) { - var interpolateFn = $interpolate(text, true); - if (interpolateFn) { - directives.push({ - priority: 0, - compile: function textInterpolateCompileFn(templateNode) { - var templateNodeParent = templateNode.parent(), hasCompileParent = !!templateNodeParent.length; - if (hasCompileParent) compile.$$addBindingClass(templateNodeParent); - return function textInterpolateLinkFn(scope, node) { - var parent = node.parent(); - if (!hasCompileParent) compile.$$addBindingClass(parent); - compile.$$addBindingInfo(parent, interpolateFn.expressions); - scope.$watch(interpolateFn, function interpolateFnWatchAction(value) { - node[0].nodeValue = value; - }); - }; - } - }); - } - } - function wrapTemplate(type, template) { - type = lowercase(type || "html"); - switch (type) { - case "svg": - case "math": - var wrapper = document.createElement("div"); - wrapper.innerHTML = "<" + type + ">" + template + ""; - return wrapper.childNodes[0].childNodes; - - default: - return template; - } - } - function getTrustedContext(node, attrNormalizedName) { - if (attrNormalizedName == "srcdoc") { - return $sce.HTML; - } - var tag = nodeName_(node); - if (attrNormalizedName == "xlinkHref" || tag == "form" && attrNormalizedName == "action" || tag != "img" && (attrNormalizedName == "src" || attrNormalizedName == "ngSrc")) { - return $sce.RESOURCE_URL; - } - } - function addAttrInterpolateDirective(node, directives, value, name, allOrNothing) { - var trustedContext = getTrustedContext(node, name); - allOrNothing = ALL_OR_NOTHING_ATTRS[name] || allOrNothing; - var interpolateFn = $interpolate(value, true, trustedContext, allOrNothing); - if (!interpolateFn) return; - if (name === "multiple" && nodeName_(node) === "select") { - throw $compileMinErr("selmulti", "Binding to the 'multiple' attribute is not supported. Element: {0}", startingTag(node)); - } - directives.push({ - priority: 100, - compile: function() { - return { - pre: function attrInterpolatePreLinkFn(scope, element, attr) { - var $$observers = attr.$$observers || (attr.$$observers = {}); - if (EVENT_HANDLER_ATTR_REGEXP.test(name)) { - throw $compileMinErr("nodomevents", "Interpolations for HTML DOM event attributes are disallowed. Please use the " + "ng- versions (such as ng-click instead of onclick) instead."); - } - var newValue = attr[name]; - if (newValue !== value) { - interpolateFn = newValue && $interpolate(newValue, true, trustedContext, allOrNothing); - value = newValue; - } - if (!interpolateFn) return; - attr[name] = interpolateFn(scope); - ($$observers[name] || ($$observers[name] = [])).$$inter = true; - (attr.$$observers && attr.$$observers[name].$$scope || scope).$watch(interpolateFn, function interpolateFnWatchAction(newValue, oldValue) { - if (name === "class" && newValue != oldValue) { - attr.$updateClass(newValue, oldValue); - } else { - attr.$set(name, newValue); - } - }); - } - }; - } - }); - } - function replaceWith($rootElement, elementsToRemove, newNode) { - var firstElementToRemove = elementsToRemove[0], removeCount = elementsToRemove.length, parent = firstElementToRemove.parentNode, i, ii; - if ($rootElement) { - for (i = 0, ii = $rootElement.length; i < ii; i++) { - if ($rootElement[i] == firstElementToRemove) { - $rootElement[i++] = newNode; - for (var j = i, j2 = j + removeCount - 1, jj = $rootElement.length; j < jj; j++, - j2++) { - if (j2 < jj) { - $rootElement[j] = $rootElement[j2]; - } else { - delete $rootElement[j]; - } - } - $rootElement.length -= removeCount - 1; - if ($rootElement.context === firstElementToRemove) { - $rootElement.context = newNode; - } - break; - } - } - } - if (parent) { - parent.replaceChild(newNode, firstElementToRemove); - } - var fragment = document.createDocumentFragment(); - fragment.appendChild(firstElementToRemove); - if (jqLite.hasData(firstElementToRemove)) { - jqLite(newNode).data(jqLite(firstElementToRemove).data()); - if (!jQuery) { - delete jqLite.cache[firstElementToRemove[jqLite.expando]]; - } else { - skipDestroyOnNextJQueryCleanData = true; - jQuery.cleanData([ firstElementToRemove ]); - } - } - for (var k = 1, kk = elementsToRemove.length; k < kk; k++) { - var element = elementsToRemove[k]; - jqLite(element).remove(); - fragment.appendChild(element); - delete elementsToRemove[k]; - } - elementsToRemove[0] = newNode; - elementsToRemove.length = 1; - } - function cloneAndAnnotateFn(fn, annotation) { - return extend(function() { - return fn.apply(null, arguments); - }, fn, annotation); - } - function invokeLinkFn(linkFn, scope, $element, attrs, controllers, transcludeFn) { - try { - linkFn(scope, $element, attrs, controllers, transcludeFn); - } catch (e) { - $exceptionHandler(e, startingTag($element)); - } + }; + }); + } + function serializeObject(obj) { + var seen = []; + return JSON.stringify(obj, function(key, val) { + val = toJsonReplacer(key, val); + if (isObject(val)) { + if (seen.indexOf(val) >= 0) return "..."; + seen.push(val); } - function initializeDirectiveBindings(scope, attrs, destination, bindings, directive, newScope) { - var onNewScopeDestroyed; - forEach(bindings, function(definition, scopeName) { - var attrName = definition.attrName, optional = definition.optional, mode = definition.mode, lastValue, parentGet, parentSet, compare; - switch (mode) { - case "@": - if (!optional && !hasOwnProperty.call(attrs, attrName)) { - destination[scopeName] = attrs[attrName] = void 0; - } - attrs.$observe(attrName, function(value) { - if (isString(value)) { - destination[scopeName] = value; - } - }); - attrs.$$observers[attrName].$$scope = scope; - if (isString(attrs[attrName])) { - destination[scopeName] = $interpolate(attrs[attrName])(scope); - } - break; - - case "=": - if (!hasOwnProperty.call(attrs, attrName)) { - if (optional) break; - attrs[attrName] = void 0; - } - if (optional && !attrs[attrName]) break; - parentGet = $parse(attrs[attrName]); - if (parentGet.literal) { - compare = equals; - } else { - compare = function(a, b) { - return a === b || a !== a && b !== b; - }; - } - parentSet = parentGet.assign || function() { - lastValue = destination[scopeName] = parentGet(scope); - throw $compileMinErr("nonassign", "Expression '{0}' used with directive '{1}' is non-assignable!", attrs[attrName], directive.name); - }; - lastValue = destination[scopeName] = parentGet(scope); - var parentValueWatch = function parentValueWatch(parentValue) { - if (!compare(parentValue, destination[scopeName])) { - if (!compare(parentValue, lastValue)) { - destination[scopeName] = parentValue; - } else { - parentSet(scope, parentValue = destination[scopeName]); - } - } - return lastValue = parentValue; - }; - parentValueWatch.$stateful = true; - var unwatch; - if (definition.collection) { - unwatch = scope.$watchCollection(attrs[attrName], parentValueWatch); - } else { - unwatch = scope.$watch($parse(attrs[attrName], parentValueWatch), null, parentGet.literal); - } - onNewScopeDestroyed = onNewScopeDestroyed || []; - onNewScopeDestroyed.push(unwatch); - break; - - case "&": - parentGet = attrs.hasOwnProperty(attrName) ? $parse(attrs[attrName]) : noop; - if (parentGet === noop && optional) break; - destination[scopeName] = function(locals) { - return parentGet(scope, locals); - }; - break; - } - }); - var destroyBindings = onNewScopeDestroyed ? function destroyBindings() { - for (var i = 0, ii = onNewScopeDestroyed.length; i < ii; ++i) { - onNewScopeDestroyed[i](); - } - } : noop; - if (newScope && destroyBindings !== noop) { - newScope.$on("$destroy", destroyBindings); - return noop; - } - return destroyBindings; - } - } ]; - } - var PREFIX_REGEXP = /^((?:x|data)[\:\-_])/i; - function directiveNormalize(name) { - return camelCase(name.replace(PREFIX_REGEXP, "")); - } - function nodesetLinkingFn(scope, nodeList, rootElement, boundTranscludeFn) {} - function directiveLinkingFn(nodesetLinkingFn, scope, node, rootElement, boundTranscludeFn) {} - function tokenDifference(str1, str2) { - var values = "", tokens1 = str1.split(/\s+/), tokens2 = str2.split(/\s+/); - outer: for (var i = 0; i < tokens1.length; i++) { - var token = tokens1[i]; - for (var j = 0; j < tokens2.length; j++) { - if (token == tokens2[j]) continue outer; - } - values += (values.length > 0 ? " " : "") + token; - } - return values; - } - function removeComments(jqNodes) { - jqNodes = jqLite(jqNodes); - var i = jqNodes.length; - if (i <= 1) { - return jqNodes; - } - while (i--) { - var node = jqNodes[i]; - if (node.nodeType === NODE_TYPE_COMMENT) { - splice.call(jqNodes, i, 1); - } - } - return jqNodes; + return val; + }); } - var $controllerMinErr = minErr("$controller"); - var CNTRL_REG = /^(\S+)(\s+as\s+(\w+))?$/; - function identifierForController(controller, ident) { - if (ident && isString(ident)) return ident; - if (isString(controller)) { - var match = CNTRL_REG.exec(controller); - if (match) return match[3]; + function toDebugString(obj) { + if (typeof obj === "function") { + return obj.toString().replace(/ \{[\s\S]*$/, ""); + } else if (isUndefined(obj)) { + return "undefined"; + } else if (typeof obj !== "string") { + return serializeObject(obj); } + return obj; } - function $ControllerProvider() { - var controllers = {}, globals = false; - this.register = function(name, constructor) { - assertNotHasOwnProperty(name, "controller"); - if (isObject(name)) { - extend(controllers, name); - } else { - controllers[name] = constructor; - } - }; - this.allowGlobals = function() { - globals = true; - }; - this.$get = [ "$injector", "$window", function($injector, $window) { - return function(expression, locals, later, ident) { - var instance, match, constructor, identifier; - later = later === true; - if (ident && isString(ident)) { - identifier = ident; - } - if (isString(expression)) { - match = expression.match(CNTRL_REG); - if (!match) { - throw $controllerMinErr("ctrlfmt", "Badly formed controller string '{0}'. " + "Must match `__name__ as __id__` or `__name__`.", expression); - } - constructor = match[1], identifier = identifier || match[3]; - expression = controllers.hasOwnProperty(constructor) ? controllers[constructor] : getter(locals.$scope, constructor, true) || (globals ? getter($window, constructor, true) : undefined); - assertArgFn(expression, constructor, true); - } - if (later) { - var controllerPrototype = (isArray(expression) ? expression[expression.length - 1] : expression).prototype; - instance = Object.create(controllerPrototype || null); - if (identifier) { - addIdentifier(locals, identifier, instance, constructor || expression.name); - } - var instantiate; - return instantiate = extend(function() { - var result = $injector.invoke(expression, instance, locals, constructor); - if (result !== instance && (isObject(result) || isFunction(result))) { - instance = result; - if (identifier) { - addIdentifier(locals, identifier, instance, constructor || expression.name); - } - } - return instance; - }, { - instance: instance, - identifier: identifier - }); - } - instance = $injector.instantiate(expression, locals, constructor); - if (identifier) { - addIdentifier(locals, identifier, instance, constructor || expression.name); - } - return instance; - }; - function addIdentifier(locals, identifier, instance, name) { - if (!(locals && isObject(locals.$scope))) { - throw minErr("$controller")("noscp", "Cannot export controller '{0}' as '{1}'! No $scope object provided via `locals`.", name, identifier); - } - locals.$scope[identifier] = instance; - } - } ]; - } - function $DocumentProvider() { - this.$get = [ "$window", function(window) { - return jqLite(window.document); - } ]; - } - function $ExceptionHandlerProvider() { - this.$get = [ "$log", function($log) { - return function(exception, cause) { - $log.error.apply($log, arguments); - }; - } ]; - } - var $$ForceReflowProvider = function() { - this.$get = [ "$document", function($document) { - return function(domNode) { - if (domNode) { - if (!domNode.nodeType && domNode instanceof jqLite) { - domNode = domNode[0]; - } - } else { - domNode = $document[0].body; - } - return domNode.offsetWidth + 1; - }; - } ]; - }; - var APPLICATION_JSON = "application/json"; - var CONTENT_TYPE_APPLICATION_JSON = { - "Content-Type": APPLICATION_JSON + ";charset=utf-8" - }; - var JSON_START = /^\[|^\{(?!\{)/; - var JSON_ENDS = { - "[": /]$/, - "{": /}$/ - }; - var JSON_PROTECTION_PREFIX = /^\)\]\}',?\n/; - var $httpMinErr = minErr("$http"); - var $httpMinErrLegacyFn = function(method) { - return function() { - throw $httpMinErr("legacy", "The method `{0}` on the promise returned from `$http` has been disabled.", method); - }; + var version = { + full: "1.4.7", + major: 1, + minor: 4, + dot: 7, + codeName: "dark-luminescence" }; - function serializeValue(v) { - if (isObject(v)) { - return isDate(v) ? v.toISOString() : toJson(v); - } - return v; - } - function $HttpParamSerializerProvider() { - this.$get = function() { - return function ngParamSerializer(params) { - if (!params) return ""; - var parts = []; - forEachSorted(params, function(value, key) { - if (value === null || isUndefined(value)) return; - if (isArray(value)) { - forEach(value, function(v, k) { - parts.push(encodeUriQuery(key) + "=" + encodeUriQuery(serializeValue(v))); - }); - } else { - parts.push(encodeUriQuery(key) + "=" + encodeUriQuery(serializeValue(value))); - } - }); - return parts.join("&"); - }; - }; - } - function $HttpParamSerializerJQLikeProvider() { - this.$get = function() { - return function jQueryLikeParamSerializer(params) { - if (!params) return ""; - var parts = []; - serialize(params, "", true); - return parts.join("&"); - function serialize(toSerialize, prefix, topLevel) { - if (toSerialize === null || isUndefined(toSerialize)) return; - if (isArray(toSerialize)) { - forEach(toSerialize, function(value, index) { - serialize(value, prefix + "[" + (isObject(value) ? index : "") + "]"); - }); - } else if (isObject(toSerialize) && !isDate(toSerialize)) { - forEachSorted(toSerialize, function(value, key) { - serialize(value, prefix + (topLevel ? "" : "[") + key + (topLevel ? "" : "]")); - }); - } else { - parts.push(encodeUriQuery(prefix) + "=" + encodeUriQuery(serializeValue(toSerialize))); - } - } - }; - }; + function publishExternalAPI(angular) { + extend(angular, { + bootstrap: bootstrap, + copy: copy, + extend: extend, + merge: merge, + equals: equals, + element: jqLite, + forEach: forEach, + injector: createInjector, + noop: noop, + bind: bind, + toJson: toJson, + fromJson: fromJson, + identity: identity, + isUndefined: isUndefined, + isDefined: isDefined, + isString: isString, + isFunction: isFunction, + isObject: isObject, + isNumber: isNumber, + isElement: isElement, + isArray: isArray, + version: version, + isDate: isDate, + lowercase: lowercase, + uppercase: uppercase, + callbacks: { + counter: 0 + }, + getTestability: getTestability, + $$minErr: minErr, + $$csp: csp, + reloadWithDebugInfo: reloadWithDebugInfo + }); + angularModule = setupModuleLoader(window); + angularModule("ng", [ "ngLocale" ], [ "$provide", function ngModule($provide) { + $provide.provider({ + $$sanitizeUri: $$SanitizeUriProvider + }); + $provide.provider("$compile", $CompileProvider).directive({ + a: htmlAnchorDirective, + input: inputDirective, + textarea: inputDirective, + form: formDirective, + script: scriptDirective, + select: selectDirective, + style: styleDirective, + option: optionDirective, + ngBind: ngBindDirective, + ngBindHtml: ngBindHtmlDirective, + ngBindTemplate: ngBindTemplateDirective, + ngClass: ngClassDirective, + ngClassEven: ngClassEvenDirective, + ngClassOdd: ngClassOddDirective, + ngCloak: ngCloakDirective, + ngController: ngControllerDirective, + ngForm: ngFormDirective, + ngHide: ngHideDirective, + ngIf: ngIfDirective, + ngInclude: ngIncludeDirective, + ngInit: ngInitDirective, + ngNonBindable: ngNonBindableDirective, + ngPluralize: ngPluralizeDirective, + ngRepeat: ngRepeatDirective, + ngShow: ngShowDirective, + ngStyle: ngStyleDirective, + ngSwitch: ngSwitchDirective, + ngSwitchWhen: ngSwitchWhenDirective, + ngSwitchDefault: ngSwitchDefaultDirective, + ngOptions: ngOptionsDirective, + ngTransclude: ngTranscludeDirective, + ngModel: ngModelDirective, + ngList: ngListDirective, + ngChange: ngChangeDirective, + pattern: patternDirective, + ngPattern: patternDirective, + required: requiredDirective, + ngRequired: requiredDirective, + minlength: minlengthDirective, + ngMinlength: minlengthDirective, + maxlength: maxlengthDirective, + ngMaxlength: maxlengthDirective, + ngValue: ngValueDirective, + ngModelOptions: ngModelOptionsDirective + }).directive({ + ngInclude: ngIncludeFillContentDirective + }).directive(ngAttributeAliasDirectives).directive(ngEventDirectives); + $provide.provider({ + $anchorScroll: $AnchorScrollProvider, + $animate: $AnimateProvider, + $animateCss: $CoreAnimateCssProvider, + $$animateQueue: $$CoreAnimateQueueProvider, + $$AnimateRunner: $$CoreAnimateRunnerProvider, + $browser: $BrowserProvider, + $cacheFactory: $CacheFactoryProvider, + $controller: $ControllerProvider, + $document: $DocumentProvider, + $exceptionHandler: $ExceptionHandlerProvider, + $filter: $FilterProvider, + $$forceReflow: $$ForceReflowProvider, + $interpolate: $InterpolateProvider, + $interval: $IntervalProvider, + $http: $HttpProvider, + $httpParamSerializer: $HttpParamSerializerProvider, + $httpParamSerializerJQLike: $HttpParamSerializerJQLikeProvider, + $httpBackend: $HttpBackendProvider, + $xhrFactory: $xhrFactoryProvider, + $location: $LocationProvider, + $log: $LogProvider, + $parse: $ParseProvider, + $rootScope: $RootScopeProvider, + $q: $QProvider, + $$q: $$QProvider, + $sce: $SceProvider, + $sceDelegate: $SceDelegateProvider, + $sniffer: $SnifferProvider, + $templateCache: $TemplateCacheProvider, + $templateRequest: $TemplateRequestProvider, + $$testability: $$TestabilityProvider, + $timeout: $TimeoutProvider, + $window: $WindowProvider, + $$rAF: $$RAFProvider, + $$jqLite: $$jqLiteProvider, + $$HashMap: $$HashMapProvider, + $$cookieReader: $$CookieReaderProvider + }); + } ]); } - function defaultHttpResponseTransform(data, headers) { - if (isString(data)) { - var tempData = data.replace(JSON_PROTECTION_PREFIX, "").trim(); - if (tempData) { - var contentType = headers("Content-Type"); - if (contentType && contentType.indexOf(APPLICATION_JSON) === 0 || isJsonLike(tempData)) { - data = fromJson(tempData); - } - } - } - return data; + JQLite.expando = "ng339"; + var jqCache = JQLite.cache = {}, jqId = 1, addEventListenerFn = function(element, type, fn) { + element.addEventListener(type, fn, false); + }, removeEventListenerFn = function(element, type, fn) { + element.removeEventListener(type, fn, false); + }; + JQLite._data = function(node) { + return this.cache[node[this.expando]] || {}; + }; + function jqNextId() { + return ++jqId; } - function isJsonLike(str) { - var jsonStart = str.match(JSON_START); - return jsonStart && JSON_ENDS[jsonStart[0]].test(str); + var SPECIAL_CHARS_REGEXP = /([\:\-\_]+(.))/g; + var MOZ_HACK_REGEXP = /^moz([A-Z])/; + var MOUSE_EVENT_MAP = { + mouseleave: "mouseout", + mouseenter: "mouseover" + }; + var jqLiteMinErr = minErr("jqLite"); + function camelCase(name) { + return name.replace(SPECIAL_CHARS_REGEXP, function(_, separator, letter, offset) { + return offset ? letter.toUpperCase() : letter; + }).replace(MOZ_HACK_REGEXP, "Moz$1"); } - function parseHeaders(headers) { - var parsed = createMap(), i; - function fillInParsed(key, val) { - if (key) { - parsed[key] = parsed[key] ? parsed[key] + ", " + val : val; - } - } - if (isString(headers)) { - forEach(headers.split("\n"), function(line) { - i = line.indexOf(":"); - fillInParsed(lowercase(trim(line.substr(0, i))), trim(line.substr(i + 1))); - }); - } else if (isObject(headers)) { - forEach(headers, function(headerVal, headerKey) { - fillInParsed(lowercase(headerKey), trim(headerVal)); - }); - } - return parsed; + var SINGLE_TAG_REGEXP = /^<([\w-]+)\s*\/?>(?:<\/\1>|)$/; + var HTML_REGEXP = /<|&#?\w+;/; + var TAG_NAME_REGEXP = /<([\w:-]+)/; + var XHTML_TAG_REGEXP = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:-]+)[^>]*)\/>/gi; + var wrapMap = { + option: [ 1, '" ], + thead: [ 1, "", "
        " ], + col: [ 2, "", "
        " ], + tr: [ 2, "", "
        " ], + td: [ 3, "", "
        " ], + _default: [ 0, "", "" ] + }; + wrapMap.optgroup = wrapMap.option; + wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead; + wrapMap.th = wrapMap.td; + function jqLiteIsTextNode(html) { + return !HTML_REGEXP.test(html); } - function headersGetter(headers) { - var headersObj; - return function(name) { - if (!headersObj) headersObj = parseHeaders(headers); - if (name) { - var value = headersObj[lowercase(name)]; - if (value === void 0) { - value = null; - } - return value; - } - return headersObj; - }; + function jqLiteAcceptsData(node) { + var nodeType = node.nodeType; + return nodeType === NODE_TYPE_ELEMENT || !nodeType || nodeType === NODE_TYPE_DOCUMENT; } - function transformData(data, headers, status, fns) { - if (isFunction(fns)) { - return fns(data, headers, status); + function jqLiteHasData(node) { + for (var key in jqCache[node.ng339]) { + return true; } - forEach(fns, function(fn) { - data = fn(data, headers, status); - }); - return data; - } - function isSuccess(status) { - return 200 <= status && status < 300; + return false; } - function $HttpProvider() { - var defaults = this.defaults = { - transformResponse: [ defaultHttpResponseTransform ], - transformRequest: [ function(d) { - return isObject(d) && !isFile(d) && !isBlob(d) && !isFormData(d) ? toJson(d) : d; - } ], - headers: { - common: { - Accept: "application/json, text/plain, */*" - }, - post: shallowCopy(CONTENT_TYPE_APPLICATION_JSON), - put: shallowCopy(CONTENT_TYPE_APPLICATION_JSON), - patch: shallowCopy(CONTENT_TYPE_APPLICATION_JSON) - }, - xsrfCookieName: "XSRF-TOKEN", - xsrfHeaderName: "X-XSRF-TOKEN", - paramSerializer: "$httpParamSerializer" - }; - var useApplyAsync = false; - this.useApplyAsync = function(value) { - if (isDefined(value)) { - useApplyAsync = !!value; - return this; + function jqLiteBuildFragment(html, context) { + var tmp, tag, wrap, fragment = context.createDocumentFragment(), nodes = [], i; + if (jqLiteIsTextNode(html)) { + nodes.push(context.createTextNode(html)); + } else { + tmp = tmp || fragment.appendChild(context.createElement("div")); + tag = (TAG_NAME_REGEXP.exec(html) || [ "", "" ])[1].toLowerCase(); + wrap = wrapMap[tag] || wrapMap._default; + tmp.innerHTML = wrap[1] + html.replace(XHTML_TAG_REGEXP, "<$1>") + wrap[2]; + i = wrap[0]; + while (i--) { + tmp = tmp.lastChild; } - return useApplyAsync; - }; - var useLegacyPromise = true; - this.useLegacyPromiseExtensions = function(value) { - if (isDefined(value)) { - useLegacyPromise = !!value; - return this; + nodes = concat(nodes, tmp.childNodes); + tmp = fragment.firstChild; + tmp.textContent = ""; + } + fragment.textContent = ""; + fragment.innerHTML = ""; + forEach(nodes, function(node) { + fragment.appendChild(node); + }); + return fragment; + } + function jqLiteParseHTML(html, context) { + context = context || document; + var parsed; + if (parsed = SINGLE_TAG_REGEXP.exec(html)) { + return [ context.createElement(parsed[1]) ]; + } + if (parsed = jqLiteBuildFragment(html, context)) { + return parsed.childNodes; + } + return []; + } + function JQLite(element) { + if (element instanceof JQLite) { + return element; + } + var argIsString; + if (isString(element)) { + element = trim(element); + argIsString = true; + } + if (!(this instanceof JQLite)) { + if (argIsString && element.charAt(0) != "<") { + throw jqLiteMinErr("nosel", "Looking up elements via selectors is not supported by jqLite! See: http://docs.angularjs.org/api/angular.element"); } - return useLegacyPromise; - }; - var interceptorFactories = this.interceptors = []; - this.$get = [ "$httpBackend", "$$cookieReader", "$cacheFactory", "$rootScope", "$q", "$injector", function($httpBackend, $$cookieReader, $cacheFactory, $rootScope, $q, $injector) { - var defaultCache = $cacheFactory("$http"); - defaults.paramSerializer = isString(defaults.paramSerializer) ? $injector.get(defaults.paramSerializer) : defaults.paramSerializer; - var reversedInterceptors = []; - forEach(interceptorFactories, function(interceptorFactory) { - reversedInterceptors.unshift(isString(interceptorFactory) ? $injector.get(interceptorFactory) : $injector.invoke(interceptorFactory)); - }); - function $http(requestConfig) { - if (!angular.isObject(requestConfig)) { - throw minErr("$http")("badreq", "Http request configuration must be an object. Received: {0}", requestConfig); + return new JQLite(element); + } + if (argIsString) { + jqLiteAddNodes(this, jqLiteParseHTML(element)); + } else { + jqLiteAddNodes(this, element); + } + } + function jqLiteClone(element) { + return element.cloneNode(true); + } + function jqLiteDealoc(element, onlyDescendants) { + if (!onlyDescendants) jqLiteRemoveData(element); + if (element.querySelectorAll) { + var descendants = element.querySelectorAll("*"); + for (var i = 0, l = descendants.length; i < l; i++) { + jqLiteRemoveData(descendants[i]); + } + } + } + function jqLiteOff(element, type, fn, unsupported) { + if (isDefined(unsupported)) throw jqLiteMinErr("offargs", "jqLite#off() does not support the `selector` argument"); + var expandoStore = jqLiteExpandoStore(element); + var events = expandoStore && expandoStore.events; + var handle = expandoStore && expandoStore.handle; + if (!handle) return; + if (!type) { + for (type in events) { + if (type !== "$destroy") { + removeEventListenerFn(element, type, handle); } - var config = extend({ - method: "get", - transformRequest: defaults.transformRequest, - transformResponse: defaults.transformResponse, - paramSerializer: defaults.paramSerializer - }, requestConfig); - config.headers = mergeHeaders(requestConfig); - config.method = uppercase(config.method); - config.paramSerializer = isString(config.paramSerializer) ? $injector.get(config.paramSerializer) : config.paramSerializer; - var serverRequest = function(config) { - var headers = config.headers; - var reqData = transformData(config.data, headersGetter(headers), undefined, config.transformRequest); - if (isUndefined(reqData)) { - forEach(headers, function(value, header) { - if (lowercase(header) === "content-type") { - delete headers[header]; - } - }); - } - if (isUndefined(config.withCredentials) && !isUndefined(defaults.withCredentials)) { - config.withCredentials = defaults.withCredentials; - } - return sendReq(config, reqData).then(transformResponse, transformResponse); - }; - var chain = [ serverRequest, undefined ]; - var promise = $q.when(config); - forEach(reversedInterceptors, function(interceptor) { - if (interceptor.request || interceptor.requestError) { - chain.unshift(interceptor.request, interceptor.requestError); - } - if (interceptor.response || interceptor.responseError) { - chain.push(interceptor.response, interceptor.responseError); + delete events[type]; + } + } else { + forEach(type.split(" "), function(type) { + if (isDefined(fn)) { + var listenerFns = events[type]; + arrayRemove(listenerFns || [], fn); + if (listenerFns && listenerFns.length > 0) { + return; } - }); - while (chain.length) { - var thenFn = chain.shift(); - var rejectFn = chain.shift(); - promise = promise.then(thenFn, rejectFn); } - if (useLegacyPromise) { - promise.success = function(fn) { - assertArgFn(fn, "fn"); - promise.then(function(response) { - fn(response.data, response.status, response.headers, config); - }); - return promise; - }; - promise.error = function(fn) { - assertArgFn(fn, "fn"); - promise.then(null, function(response) { - fn(response.data, response.status, response.headers, config); - }); - return promise; - }; - } else { - promise.success = $httpMinErrLegacyFn("success"); - promise.error = $httpMinErrLegacyFn("error"); + removeEventListenerFn(element, type, handle); + delete events[type]; + }); + } + } + function jqLiteRemoveData(element, name) { + var expandoId = element.ng339; + var expandoStore = expandoId && jqCache[expandoId]; + if (expandoStore) { + if (name) { + delete expandoStore.data[name]; + return; + } + if (expandoStore.handle) { + if (expandoStore.events.$destroy) { + expandoStore.handle({}, "$destroy"); } - return promise; - function transformResponse(response) { - var resp = extend({}, response); - if (!response.data) { - resp.data = response.data; + jqLiteOff(element); + } + delete jqCache[expandoId]; + element.ng339 = undefined; + } + } + function jqLiteExpandoStore(element, createIfNecessary) { + var expandoId = element.ng339, expandoStore = expandoId && jqCache[expandoId]; + if (createIfNecessary && !expandoStore) { + element.ng339 = expandoId = jqNextId(); + expandoStore = jqCache[expandoId] = { + events: {}, + data: {}, + handle: undefined + }; + } + return expandoStore; + } + function jqLiteData(element, key, value) { + if (jqLiteAcceptsData(element)) { + var isSimpleSetter = isDefined(value); + var isSimpleGetter = !isSimpleSetter && key && !isObject(key); + var massGetter = !key; + var expandoStore = jqLiteExpandoStore(element, !isSimpleGetter); + var data = expandoStore && expandoStore.data; + if (isSimpleSetter) { + data[key] = value; + } else { + if (massGetter) { + return data; + } else { + if (isSimpleGetter) { + return data && data[key]; } else { - resp.data = transformData(response.data, response.headers, response.status, config.transformResponse); + extend(data, key); } - return isSuccess(response.status) ? resp : $q.reject(resp); - } - function executeHeaderFns(headers, config) { - var headerContent, processedHeaders = {}; - forEach(headers, function(headerFn, header) { - if (isFunction(headerFn)) { - headerContent = headerFn(config); - if (headerContent != null) { - processedHeaders[header] = headerContent; - } - } else { - processedHeaders[header] = headerFn; - } - }); - return processedHeaders; } - function mergeHeaders(config) { - var defHeaders = defaults.headers, reqHeaders = extend({}, config.headers), defHeaderName, lowercaseDefHeaderName, reqHeaderName; - defHeaders = extend({}, defHeaders.common, defHeaders[lowercase(config.method)]); - defaultHeadersIteration: for (defHeaderName in defHeaders) { - lowercaseDefHeaderName = lowercase(defHeaderName); - for (reqHeaderName in reqHeaders) { - if (lowercase(reqHeaderName) === lowercaseDefHeaderName) { - continue defaultHeadersIteration; - } - } - reqHeaders[defHeaderName] = defHeaders[defHeaderName]; - } - return executeHeaderFns(reqHeaders, shallowCopy(config)); - } - } - $http.pendingRequests = []; - createShortMethods("get", "delete", "head", "jsonp"); - createShortMethodsWithData("post", "put", "patch"); - $http.defaults = defaults; - return $http; - function createShortMethods(names) { - forEach(arguments, function(name) { - $http[name] = function(url, config) { - return $http(extend({}, config || {}, { - method: name, - url: url - })); - }; - }); - } - function createShortMethodsWithData(name) { - forEach(arguments, function(name) { - $http[name] = function(url, data, config) { - return $http(extend({}, config || {}, { - method: name, - url: url, - data: data - })); - }; - }); - } - function sendReq(config, reqData) { - var deferred = $q.defer(), promise = deferred.promise, cache, cachedResp, reqHeaders = config.headers, url = buildUrl(config.url, config.paramSerializer(config.params)); - $http.pendingRequests.push(config); - promise.then(removePendingReq, removePendingReq); - if ((config.cache || defaults.cache) && config.cache !== false && (config.method === "GET" || config.method === "JSONP")) { - cache = isObject(config.cache) ? config.cache : isObject(defaults.cache) ? defaults.cache : defaultCache; - } - if (cache) { - cachedResp = cache.get(url); - if (isDefined(cachedResp)) { - if (isPromiseLike(cachedResp)) { - cachedResp.then(resolvePromiseWithResult, resolvePromiseWithResult); - } else { - if (isArray(cachedResp)) { - resolvePromise(cachedResp[1], cachedResp[0], shallowCopy(cachedResp[2]), cachedResp[3]); - } else { - resolvePromise(cachedResp, 200, {}, "OK"); - } - } - } else { - cache.put(url, promise); - } - } - if (isUndefined(cachedResp)) { - var xsrfValue = urlIsSameOrigin(config.url) ? $$cookieReader()[config.xsrfCookieName || defaults.xsrfCookieName] : undefined; - if (xsrfValue) { - reqHeaders[config.xsrfHeaderName || defaults.xsrfHeaderName] = xsrfValue; - } - $httpBackend(config.method, url, reqData, done, reqHeaders, config.timeout, config.withCredentials, config.responseType); - } - return promise; - function done(status, response, headersString, statusText) { - if (cache) { - if (isSuccess(status)) { - cache.put(url, [ status, response, parseHeaders(headersString), statusText ]); - } else { - cache.remove(url); - } - } - function resolveHttpPromise() { - resolvePromise(response, status, headersString, statusText); - } - if (useApplyAsync) { - $rootScope.$applyAsync(resolveHttpPromise); - } else { - resolveHttpPromise(); - if (!$rootScope.$$phase) $rootScope.$apply(); - } - } - function resolvePromise(response, status, headers, statusText) { - status = status >= -1 ? status : 0; - (isSuccess(status) ? deferred.resolve : deferred.reject)({ - data: response, - status: status, - headers: headersGetter(headers), - config: config, - statusText: statusText - }); - } - function resolvePromiseWithResult(result) { - resolvePromise(result.data, result.status, shallowCopy(result.headers()), result.statusText); - } - function removePendingReq() { - var idx = $http.pendingRequests.indexOf(config); - if (idx !== -1) $http.pendingRequests.splice(idx, 1); - } - } - function buildUrl(url, serializedParams) { - if (serializedParams.length > 0) { - url += (url.indexOf("?") == -1 ? "?" : "&") + serializedParams; - } - return url; } - } ]; + } } - function createXhr() { - return new window.XMLHttpRequest(); + function jqLiteHasClass(element, selector) { + if (!element.getAttribute) return false; + return (" " + (element.getAttribute("class") || "") + " ").replace(/[\n\t]/g, " ").indexOf(" " + selector + " ") > -1; } - function $HttpBackendProvider() { - this.$get = [ "$browser", "$window", "$document", function($browser, $window, $document) { - return createHttpBackend($browser, createXhr, $browser.defer, $window.angular.callbacks, $document[0]); - } ]; + function jqLiteRemoveClass(element, cssClasses) { + if (cssClasses && element.setAttribute) { + forEach(cssClasses.split(" "), function(cssClass) { + element.setAttribute("class", trim((" " + (element.getAttribute("class") || "") + " ").replace(/[\n\t]/g, " ").replace(" " + trim(cssClass) + " ", " "))); + }); + } } - function createHttpBackend($browser, createXhr, $browserDefer, callbacks, rawDocument) { - return function(method, url, post, callback, headers, timeout, withCredentials, responseType) { - $browser.$$incOutstandingRequestCount(); - url = url || $browser.url(); - if (lowercase(method) == "jsonp") { - var callbackId = "_" + (callbacks.counter++).toString(36); - callbacks[callbackId] = function(data) { - callbacks[callbackId].data = data; - callbacks[callbackId].called = true; - }; - var jsonpDone = jsonpReq(url.replace("JSON_CALLBACK", "angular.callbacks." + callbackId), callbackId, function(status, text) { - completeRequest(callback, status, callbacks[callbackId].data, "", text); - callbacks[callbackId] = noop; - }); - } else { - var xhr = createXhr(); - xhr.open(method, url, true); - forEach(headers, function(value, key) { - if (isDefined(value)) { - xhr.setRequestHeader(key, value); - } - }); - xhr.onload = function requestLoaded() { - var statusText = xhr.statusText || ""; - var response = "response" in xhr ? xhr.response : xhr.responseText; - var status = xhr.status === 1223 ? 204 : xhr.status; - if (status === 0) { - status = response ? 200 : urlResolve(url).protocol == "file" ? 404 : 0; - } - completeRequest(callback, status, response, xhr.getAllResponseHeaders(), statusText); - }; - var requestError = function() { - completeRequest(callback, -1, null, null, ""); - }; - xhr.onerror = requestError; - xhr.onabort = requestError; - if (withCredentials) { - xhr.withCredentials = true; + function jqLiteAddClass(element, cssClasses) { + if (cssClasses && element.setAttribute) { + var existingClasses = (" " + (element.getAttribute("class") || "") + " ").replace(/[\n\t]/g, " "); + forEach(cssClasses.split(" "), function(cssClass) { + cssClass = trim(cssClass); + if (existingClasses.indexOf(" " + cssClass + " ") === -1) { + existingClasses += cssClass + " "; } - if (responseType) { - try { - xhr.responseType = responseType; - } catch (e) { - if (responseType !== "json") { - throw e; + }); + element.setAttribute("class", trim(existingClasses)); + } + } + function jqLiteAddNodes(root, elements) { + if (elements) { + if (elements.nodeType) { + root[root.length++] = elements; + } else { + var length = elements.length; + if (typeof length === "number" && elements.window !== elements) { + if (length) { + for (var i = 0; i < length; i++) { + root[root.length++] = elements[i]; } } + } else { + root[root.length++] = elements; } - xhr.send(isUndefined(post) ? null : post); - } - if (timeout > 0) { - var timeoutId = $browserDefer(timeoutRequest, timeout); - } else if (isPromiseLike(timeout)) { - timeout.then(timeoutRequest); - } - function timeoutRequest() { - jsonpDone && jsonpDone(); - xhr && xhr.abort(); - } - function completeRequest(callback, status, response, headersString, statusText) { - if (isDefined(timeoutId)) { - $browserDefer.cancel(timeoutId); - } - jsonpDone = xhr = null; - callback(status, response, headersString, statusText); - $browser.$$completeOutstandingRequest(noop); } - }; - function jsonpReq(url, callbackId, done) { - var script = rawDocument.createElement("script"), callback = null; - script.type = "text/javascript"; - script.src = url; - script.async = true; - callback = function(event) { - removeEventListenerFn(script, "load", callback); - removeEventListenerFn(script, "error", callback); - rawDocument.body.removeChild(script); - script = null; - var status = -1; - var text = "unknown"; - if (event) { - if (event.type === "load" && !callbacks[callbackId].called) { - event = { - type: "error" - }; - } - text = event.type; - status = event.type === "error" ? 404 : 200; - } - if (done) { - done(status, text); - } - }; - addEventListenerFn(script, "load", callback); - addEventListenerFn(script, "error", callback); - rawDocument.body.appendChild(script); - return callback; } } - var $interpolateMinErr = angular.$interpolateMinErr = minErr("$interpolate"); - $interpolateMinErr.throwNoconcat = function(text) { - throw $interpolateMinErr("noconcat", "Error while interpolating: {0}\nStrict Contextual Escaping disallows " + "interpolations that concatenate multiple expressions when a trusted value is " + "required. See http://docs.angularjs.org/api/ng.$sce", text); - }; - $interpolateMinErr.interr = function(text, err) { - return $interpolateMinErr("interr", "Can't interpolate: {0}\n{1}", text, err.toString()); - }; - function $InterpolateProvider() { - var startSymbol = "{{"; - var endSymbol = "}}"; - this.startSymbol = function(value) { - if (value) { - startSymbol = value; - return this; - } else { - return startSymbol; + function jqLiteController(element, name) { + return jqLiteInheritedData(element, "$" + (name || "ngController") + "Controller"); + } + function jqLiteInheritedData(element, name, value) { + if (element.nodeType == NODE_TYPE_DOCUMENT) { + element = element.documentElement; + } + var names = isArray(name) ? name : [ name ]; + while (element) { + for (var i = 0, ii = names.length; i < ii; i++) { + if (isDefined(value = jqLite.data(element, names[i]))) return value; } - }; - this.endSymbol = function(value) { - if (value) { - endSymbol = value; - return this; - } else { - return endSymbol; + element = element.parentNode || element.nodeType === NODE_TYPE_DOCUMENT_FRAGMENT && element.host; + } + } + function jqLiteEmpty(element) { + jqLiteDealoc(element, true); + while (element.firstChild) { + element.removeChild(element.firstChild); + } + } + function jqLiteRemove(element, keepData) { + if (!keepData) jqLiteDealoc(element); + var parent = element.parentNode; + if (parent) parent.removeChild(element); + } + function jqLiteDocumentLoaded(action, win) { + win = win || window; + if (win.document.readyState === "complete") { + win.setTimeout(action); + } else { + jqLite(win).on("load", action); + } + } + var JQLitePrototype = JQLite.prototype = { + ready: function(fn) { + var fired = false; + function trigger() { + if (fired) return; + fired = true; + fn(); } - }; - this.$get = [ "$parse", "$exceptionHandler", "$sce", function($parse, $exceptionHandler, $sce) { - var startSymbolLength = startSymbol.length, endSymbolLength = endSymbol.length, escapedStartRegexp = new RegExp(startSymbol.replace(/./g, escape), "g"), escapedEndRegexp = new RegExp(endSymbol.replace(/./g, escape), "g"); - function escape(ch) { - return "\\\\\\" + ch; + if (document.readyState === "complete") { + setTimeout(trigger); + } else { + this.on("DOMContentLoaded", trigger); + JQLite(window).on("load", trigger); } - function unescapeText(text) { - return text.replace(escapedStartRegexp, startSymbol).replace(escapedEndRegexp, endSymbol); + }, + toString: function() { + var value = []; + forEach(this, function(e) { + value.push("" + e); + }); + return "[" + value.join(", ") + "]"; + }, + eq: function(index) { + return index >= 0 ? jqLite(this[index]) : jqLite(this[this.length + index]); + }, + length: 0, + push: push, + sort: [].sort, + splice: [].splice + }; + var BOOLEAN_ATTR = {}; + forEach("multiple,selected,checked,disabled,readOnly,required,open".split(","), function(value) { + BOOLEAN_ATTR[lowercase(value)] = value; + }); + var BOOLEAN_ELEMENTS = {}; + forEach("input,select,option,textarea,button,form,details".split(","), function(value) { + BOOLEAN_ELEMENTS[value] = true; + }); + var ALIASED_ATTR = { + ngMinlength: "minlength", + ngMaxlength: "maxlength", + ngMin: "min", + ngMax: "max", + ngPattern: "pattern" + }; + function getBooleanAttrName(element, name) { + var booleanAttr = BOOLEAN_ATTR[name.toLowerCase()]; + return booleanAttr && BOOLEAN_ELEMENTS[nodeName_(element)] && booleanAttr; + } + function getAliasedAttrName(name) { + return ALIASED_ATTR[name]; + } + forEach({ + data: jqLiteData, + removeData: jqLiteRemoveData, + hasData: jqLiteHasData + }, function(fn, name) { + JQLite[name] = fn; + }); + forEach({ + data: jqLiteData, + inheritedData: jqLiteInheritedData, + scope: function(element) { + return jqLite.data(element, "$scope") || jqLiteInheritedData(element.parentNode || element, [ "$isolateScope", "$scope" ]); + }, + isolateScope: function(element) { + return jqLite.data(element, "$isolateScope") || jqLite.data(element, "$isolateScopeNoTemplate"); + }, + controller: jqLiteController, + injector: function(element) { + return jqLiteInheritedData(element, "$injector"); + }, + removeAttr: function(element, name) { + element.removeAttribute(name); + }, + hasClass: jqLiteHasClass, + css: function(element, name, value) { + name = camelCase(name); + if (isDefined(value)) { + element.style[name] = value; + } else { + return element.style[name]; } - function stringify(value) { - if (value == null) { - return ""; - } - switch (typeof value) { - case "string": - break; - - case "number": - value = "" + value; - break; - - default: - value = toJson(value); - } - return value; + }, + attr: function(element, name, value) { + var nodeType = element.nodeType; + if (nodeType === NODE_TYPE_TEXT || nodeType === NODE_TYPE_ATTRIBUTE || nodeType === NODE_TYPE_COMMENT) { + return; } - function $interpolate(text, mustHaveExpression, trustedContext, allOrNothing) { - allOrNothing = !!allOrNothing; - var startIndex, endIndex, index = 0, expressions = [], parseFns = [], textLength = text.length, exp, concat = [], expressionPositions = []; - while (index < textLength) { - if ((startIndex = text.indexOf(startSymbol, index)) != -1 && (endIndex = text.indexOf(endSymbol, startIndex + startSymbolLength)) != -1) { - if (index !== startIndex) { - concat.push(unescapeText(text.substring(index, startIndex))); - } - exp = text.substring(startIndex + startSymbolLength, endIndex); - expressions.push(exp); - parseFns.push($parse(exp, parseStringifyInterceptor)); - index = endIndex + endSymbolLength; - expressionPositions.push(concat.length); - concat.push(""); + var lowercasedName = lowercase(name); + if (BOOLEAN_ATTR[lowercasedName]) { + if (isDefined(value)) { + if (!!value) { + element[name] = true; + element.setAttribute(name, lowercasedName); } else { - if (index !== textLength) { - concat.push(unescapeText(text.substring(index))); - } - break; + element[name] = false; + element.removeAttribute(lowercasedName); } + } else { + return element[name] || (element.attributes.getNamedItem(name) || noop).specified ? lowercasedName : undefined; } - if (trustedContext && concat.length > 1) { - $interpolateMinErr.throwNoconcat(text); + } else if (isDefined(value)) { + element.setAttribute(name, value); + } else if (element.getAttribute) { + var ret = element.getAttribute(name, 2); + return ret === null ? undefined : ret; + } + }, + prop: function(element, name, value) { + if (isDefined(value)) { + element[name] = value; + } else { + return element[name]; + } + }, + text: function() { + getText.$dv = ""; + return getText; + function getText(element, value) { + if (isUndefined(value)) { + var nodeType = element.nodeType; + return nodeType === NODE_TYPE_ELEMENT || nodeType === NODE_TYPE_TEXT ? element.textContent : ""; } - if (!mustHaveExpression || expressions.length) { - var compute = function(values) { - for (var i = 0, ii = expressions.length; i < ii; i++) { - if (allOrNothing && isUndefined(values[i])) return; - concat[expressionPositions[i]] = values[i]; - } - return concat.join(""); - }; - var getValue = function(value) { - return trustedContext ? $sce.getTrusted(trustedContext, value) : $sce.valueOf(value); - }; - return extend(function interpolationFn(context) { - var i = 0; - var ii = expressions.length; - var values = new Array(ii); - try { - for (;i < ii; i++) { - values[i] = parseFns[i](context); - } - return compute(values); - } catch (err) { - $exceptionHandler($interpolateMinErr.interr(text, err)); - } - }, { - exp: text, - expressions: expressions, - $$watchDelegate: function(scope, listener) { - var lastValue; - return scope.$watchGroup(parseFns, function interpolateFnWatcher(values, oldValues) { - var currValue = compute(values); - if (isFunction(listener)) { - listener.call(this, currValue, values !== oldValues ? lastValue : currValue, scope); - } - lastValue = currValue; - }); + element.textContent = value; + } + }(), + val: function(element, value) { + if (isUndefined(value)) { + if (element.multiple && nodeName_(element) === "select") { + var result = []; + forEach(element.options, function(option) { + if (option.selected) { + result.push(option.value || option.text); } }); + return result.length === 0 ? null : result; } - function parseStringifyInterceptor(value) { - try { - value = getValue(value); - return allOrNothing && !isDefined(value) ? value : stringify(value); - } catch (err) { - $exceptionHandler($interpolateMinErr.interr(text, err)); - } - } + return element.value; } - $interpolate.startSymbol = function() { - return startSymbol; - }; - $interpolate.endSymbol = function() { - return endSymbol; - }; - return $interpolate; - } ]; - } - function $IntervalProvider() { - this.$get = [ "$rootScope", "$window", "$q", "$$q", function($rootScope, $window, $q, $$q) { - var intervals = {}; - function interval(fn, delay, count, invokeApply) { - var hasParams = arguments.length > 4, args = hasParams ? sliceArgs(arguments, 4) : [], setInterval = $window.setInterval, clearInterval = $window.clearInterval, iteration = 0, skipApply = isDefined(invokeApply) && !invokeApply, deferred = (skipApply ? $$q : $q).defer(), promise = deferred.promise; - count = isDefined(count) ? count : 0; - promise.then(null, null, !hasParams ? fn : function() { - fn.apply(null, args); - }); - promise.$$intervalId = setInterval(function tick() { - deferred.notify(iteration++); - if (count > 0 && iteration >= count) { - deferred.resolve(iteration); - clearInterval(promise.$$intervalId); - delete intervals[promise.$$intervalId]; - } - if (!skipApply) $rootScope.$apply(); - }, delay); - intervals[promise.$$intervalId] = deferred; - return promise; - } - interval.cancel = function(promise) { - if (promise && promise.$$intervalId in intervals) { - intervals[promise.$$intervalId].reject("canceled"); - $window.clearInterval(promise.$$intervalId); - delete intervals[promise.$$intervalId]; - return true; - } - return false; - }; - return interval; - } ]; - } - var PATH_MATCH = /^([^\?#]*)(\?([^#]*))?(#(.*))?$/, DEFAULT_PORTS = { - http: 80, - https: 443, - ftp: 21 - }; - var $locationMinErr = minErr("$location"); - function encodePath(path) { - var segments = path.split("/"), i = segments.length; - while (i--) { - segments[i] = encodeUriSegment(segments[i]); - } - return segments.join("/"); - } - function parseAbsoluteUrl(absoluteUrl, locationObj) { - var parsedUrl = urlResolve(absoluteUrl); - locationObj.$$protocol = parsedUrl.protocol; - locationObj.$$host = parsedUrl.hostname; - locationObj.$$port = toInt(parsedUrl.port) || DEFAULT_PORTS[parsedUrl.protocol] || null; - } - function parseAppUrl(relativeUrl, locationObj) { - var prefixed = relativeUrl.charAt(0) !== "/"; - if (prefixed) { - relativeUrl = "/" + relativeUrl; - } - var match = urlResolve(relativeUrl); - locationObj.$$path = decodeURIComponent(prefixed && match.pathname.charAt(0) === "/" ? match.pathname.substring(1) : match.pathname); - locationObj.$$search = parseKeyValue(match.search); - locationObj.$$hash = decodeURIComponent(match.hash); - if (locationObj.$$path && locationObj.$$path.charAt(0) != "/") { - locationObj.$$path = "/" + locationObj.$$path; - } - } - function beginsWith(begin, whole) { - if (whole.indexOf(begin) === 0) { - return whole.substr(begin.length); - } - } - function stripHash(url) { - var index = url.indexOf("#"); - return index == -1 ? url : url.substr(0, index); - } - function trimEmptyHash(url) { - return url.replace(/(#.+)|#$/, "$1"); - } - function stripFile(url) { - return url.substr(0, stripHash(url).lastIndexOf("/") + 1); - } - function serverBase(url) { - return url.substring(0, url.indexOf("/", url.indexOf("//") + 2)); - } - function LocationHtml5Url(appBase, appBaseNoFile, basePrefix) { - this.$$html5 = true; - basePrefix = basePrefix || ""; - parseAbsoluteUrl(appBase, this); - this.$$parse = function(url) { - var pathUrl = beginsWith(appBaseNoFile, url); - if (!isString(pathUrl)) { - throw $locationMinErr("ipthprfx", 'Invalid url "{0}", missing path prefix "{1}".', url, appBaseNoFile); - } - parseAppUrl(pathUrl, this); - if (!this.$$path) { - this.$$path = "/"; - } - this.$$compose(); - }; - this.$$compose = function() { - var search = toKeyValue(this.$$search), hash = this.$$hash ? "#" + encodeUriSegment(this.$$hash) : ""; - this.$$url = encodePath(this.$$path) + (search ? "?" + search : "") + hash; - this.$$absUrl = appBaseNoFile + this.$$url.substr(1); - }; - this.$$parseLinkUrl = function(url, relHref) { - if (relHref && relHref[0] === "#") { - this.hash(relHref.slice(1)); - return true; + element.value = value; + }, + html: function(element, value) { + if (isUndefined(value)) { + return element.innerHTML; } - var appUrl, prevAppUrl; - var rewrittenUrl; - if (isDefined(appUrl = beginsWith(appBase, url))) { - prevAppUrl = appUrl; - if (isDefined(appUrl = beginsWith(basePrefix, appUrl))) { - rewrittenUrl = appBaseNoFile + (beginsWith("/", appUrl) || appUrl); + jqLiteDealoc(element, true); + element.innerHTML = value; + }, + empty: jqLiteEmpty + }, function(fn, name) { + JQLite.prototype[name] = function(arg1, arg2) { + var i, key; + var nodeCount = this.length; + if (fn !== jqLiteEmpty && isUndefined(fn.length == 2 && (fn !== jqLiteHasClass && fn !== jqLiteController) ? arg1 : arg2)) { + if (isObject(arg1)) { + for (i = 0; i < nodeCount; i++) { + if (fn === jqLiteData) { + fn(this[i], arg1); + } else { + for (key in arg1) { + fn(this[i], key, arg1[key]); + } + } + } + return this; } else { - rewrittenUrl = appBase + prevAppUrl; + var value = fn.$dv; + var jj = isUndefined(value) ? Math.min(nodeCount, 1) : nodeCount; + for (var j = 0; j < jj; j++) { + var nodeValue = fn(this[j], arg1, arg2); + value = value ? value + nodeValue : nodeValue; + } + return value; } - } else if (isDefined(appUrl = beginsWith(appBaseNoFile, url))) { - rewrittenUrl = appBaseNoFile + appUrl; - } else if (appBaseNoFile == url + "/") { - rewrittenUrl = appBaseNoFile; - } - if (rewrittenUrl) { - this.$$parse(rewrittenUrl); + } else { + for (i = 0; i < nodeCount; i++) { + fn(this[i], arg1, arg2); + } + return this; } - return !!rewrittenUrl; }; - } - function LocationHashbangUrl(appBase, appBaseNoFile, hashPrefix) { - parseAbsoluteUrl(appBase, this); - this.$$parse = function(url) { - var withoutBaseUrl = beginsWith(appBase, url) || beginsWith(appBaseNoFile, url); - var withoutHashUrl; - if (!isUndefined(withoutBaseUrl) && withoutBaseUrl.charAt(0) === "#") { - withoutHashUrl = beginsWith(hashPrefix, withoutBaseUrl); - if (isUndefined(withoutHashUrl)) { - withoutHashUrl = withoutBaseUrl; - } - } else { - if (this.$$html5) { - withoutHashUrl = withoutBaseUrl; - } else { - withoutHashUrl = ""; - if (isUndefined(withoutBaseUrl)) { - appBase = url; - this.replace(); + }); + function createEventHandler(element, events) { + var eventHandler = function(event, type) { + event.isDefaultPrevented = function() { + return event.defaultPrevented; + }; + var eventFns = events[type || event.type]; + var eventFnsLength = eventFns ? eventFns.length : 0; + if (!eventFnsLength) return; + if (isUndefined(event.immediatePropagationStopped)) { + var originalStopImmediatePropagation = event.stopImmediatePropagation; + event.stopImmediatePropagation = function() { + event.immediatePropagationStopped = true; + if (event.stopPropagation) { + event.stopPropagation(); } - } + if (originalStopImmediatePropagation) { + originalStopImmediatePropagation.call(event); + } + }; } - parseAppUrl(withoutHashUrl, this); - this.$$path = removeWindowsDriveName(this.$$path, withoutHashUrl, appBase); - this.$$compose(); - function removeWindowsDriveName(path, url, base) { - var windowsFilePathExp = /^\/[A-Z]:(\/.*)/; - var firstPathSegmentMatch; - if (url.indexOf(base) === 0) { - url = url.replace(base, ""); - } - if (windowsFilePathExp.exec(url)) { - return path; - } - firstPathSegmentMatch = windowsFilePathExp.exec(path); - return firstPathSegmentMatch ? firstPathSegmentMatch[1] : path; + event.isImmediatePropagationStopped = function() { + return event.immediatePropagationStopped === true; + }; + if (eventFnsLength > 1) { + eventFns = shallowCopy(eventFns); } - }; - this.$$compose = function() { - var search = toKeyValue(this.$$search), hash = this.$$hash ? "#" + encodeUriSegment(this.$$hash) : ""; - this.$$url = encodePath(this.$$path) + (search ? "?" + search : "") + hash; - this.$$absUrl = appBase + (this.$$url ? hashPrefix + this.$$url : ""); - }; - this.$$parseLinkUrl = function(url, relHref) { - if (stripHash(appBase) == stripHash(url)) { - this.$$parse(url); - return true; + for (var i = 0; i < eventFnsLength; i++) { + if (!event.isImmediatePropagationStopped()) { + eventFns[i].call(element, event); + } } - return false; }; + eventHandler.elem = element; + return eventHandler; } - function LocationHashbangInHtml5Url(appBase, appBaseNoFile, hashPrefix) { - this.$$html5 = true; - LocationHashbangUrl.apply(this, arguments); - this.$$parseLinkUrl = function(url, relHref) { - if (relHref && relHref[0] === "#") { - this.hash(relHref.slice(1)); - return true; + forEach({ + removeData: jqLiteRemoveData, + on: function jqLiteOn(element, type, fn, unsupported) { + if (isDefined(unsupported)) throw jqLiteMinErr("onargs", "jqLite#on() does not support the `selector` or `eventData` parameters"); + if (!jqLiteAcceptsData(element)) { + return; } - var rewrittenUrl; - var appUrl; - if (appBase == stripHash(url)) { - rewrittenUrl = url; - } else if (appUrl = beginsWith(appBaseNoFile, url)) { - rewrittenUrl = appBase + hashPrefix + appUrl; - } else if (appBaseNoFile === url + "/") { - rewrittenUrl = appBaseNoFile; + var expandoStore = jqLiteExpandoStore(element, true); + var events = expandoStore.events; + var handle = expandoStore.handle; + if (!handle) { + handle = expandoStore.handle = createEventHandler(element, events); } - if (rewrittenUrl) { - this.$$parse(rewrittenUrl); - } - return !!rewrittenUrl; - }; - this.$$compose = function() { - var search = toKeyValue(this.$$search), hash = this.$$hash ? "#" + encodeUriSegment(this.$$hash) : ""; - this.$$url = encodePath(this.$$path) + (search ? "?" + search : "") + hash; - this.$$absUrl = appBase + hashPrefix + this.$$url; - }; - } - var locationPrototype = { - $$html5: false, - $$replace: false, - absUrl: locationGetter("$$absUrl"), - url: function(url) { - if (isUndefined(url)) { - return this.$$url; + var types = type.indexOf(" ") >= 0 ? type.split(" ") : [ type ]; + var i = types.length; + while (i--) { + type = types[i]; + var eventFns = events[type]; + if (!eventFns) { + events[type] = []; + if (type === "mouseenter" || type === "mouseleave") { + jqLiteOn(element, MOUSE_EVENT_MAP[type], function(event) { + var target = this, related = event.relatedTarget; + if (!related || related !== target && !target.contains(related)) { + handle(event, type); + } + }); + } else { + if (type !== "$destroy") { + addEventListenerFn(element, type, handle); + } + } + eventFns = events[type]; + } + eventFns.push(fn); } - var match = PATH_MATCH.exec(url); - if (match[1] || url === "") this.path(decodeURIComponent(match[1])); - if (match[2] || match[1] || url === "") this.search(match[3] || ""); - this.hash(match[5] || ""); - return this; }, - protocol: locationGetter("$$protocol"), - host: locationGetter("$$host"), - port: locationGetter("$$port"), - path: locationGetterSetter("$$path", function(path) { - path = path !== null ? path.toString() : ""; - return path.charAt(0) == "/" ? path : "/" + path; - }), - search: function(search, paramValue) { - switch (arguments.length) { - case 0: - return this.$$search; - - case 1: - if (isString(search) || isNumber(search)) { - search = search.toString(); - this.$$search = parseKeyValue(search); - } else if (isObject(search)) { - search = copy(search, {}); - forEach(search, function(value, key) { - if (value == null) delete search[key]; - }); - this.$$search = search; + off: jqLiteOff, + one: function(element, type, fn) { + element = jqLite(element); + element.on(type, function onFn() { + element.off(type, fn); + element.off(type, onFn); + }); + element.on(type, fn); + }, + replaceWith: function(element, replaceNode) { + var index, parent = element.parentNode; + jqLiteDealoc(element); + forEach(new JQLite(replaceNode), function(node) { + if (index) { + parent.insertBefore(node, index.nextSibling); } else { - throw $locationMinErr("isrcharg", "The first argument of the `$location#search()` call must be a string or an object."); + parent.replaceChild(node, element); } - break; - - default: - if (isUndefined(paramValue) || paramValue === null) { - delete this.$$search[search]; - } else { - this.$$search[search] = paramValue; + index = node; + }); + }, + children: function(element) { + var children = []; + forEach(element.childNodes, function(element) { + if (element.nodeType === NODE_TYPE_ELEMENT) { + children.push(element); } - } - this.$$compose(); - return this; + }); + return children; }, - hash: locationGetterSetter("$$hash", function(hash) { - return hash !== null ? hash.toString() : ""; - }), - replace: function() { - this.$$replace = true; - return this; - } - }; - forEach([ LocationHashbangInHtml5Url, LocationHashbangUrl, LocationHtml5Url ], function(Location) { - Location.prototype = Object.create(locationPrototype); - Location.prototype.state = function(state) { - if (!arguments.length) { - return this.$$state; + contents: function(element) { + return element.contentDocument || element.childNodes || []; + }, + append: function(element, node) { + var nodeType = element.nodeType; + if (nodeType !== NODE_TYPE_ELEMENT && nodeType !== NODE_TYPE_DOCUMENT_FRAGMENT) return; + node = new JQLite(node); + for (var i = 0, ii = node.length; i < ii; i++) { + var child = node[i]; + element.appendChild(child); } - if (Location !== LocationHtml5Url || !this.$$html5) { - throw $locationMinErr("nostate", "History API state support is available only " + "in HTML5 mode and only in browsers supporting HTML5 History API"); + }, + prepend: function(element, node) { + if (element.nodeType === NODE_TYPE_ELEMENT) { + var index = element.firstChild; + forEach(new JQLite(node), function(child) { + element.insertBefore(child, index); + }); } - this.$$state = isUndefined(state) ? null : state; - return this; - }; - }); - function locationGetter(property) { - return function() { - return this[property]; - }; - } - function locationGetterSetter(property, preprocess) { - return function(value) { - if (isUndefined(value)) { - return this[property]; + }, + wrap: function(element, wrapNode) { + wrapNode = jqLite(wrapNode).eq(0).clone()[0]; + var parent = element.parentNode; + if (parent) { + parent.replaceChild(wrapNode, element); } - this[property] = preprocess(value); - this.$$compose(); - return this; - }; - } - function $LocationProvider() { - var hashPrefix = "", html5Mode = { - enabled: false, - requireBase: true, - rewriteLinks: true - }; - this.hashPrefix = function(prefix) { - if (isDefined(prefix)) { - hashPrefix = prefix; - return this; - } else { - return hashPrefix; + wrapNode.appendChild(element); + }, + remove: jqLiteRemove, + detach: function(element) { + jqLiteRemove(element, true); + }, + after: function(element, newElement) { + var index = element, parent = element.parentNode; + newElement = new JQLite(newElement); + for (var i = 0, ii = newElement.length; i < ii; i++) { + var node = newElement[i]; + parent.insertBefore(node, index.nextSibling); + index = node; } - }; - this.html5Mode = function(mode) { - if (isBoolean(mode)) { - html5Mode.enabled = mode; - return this; - } else if (isObject(mode)) { - if (isBoolean(mode.enabled)) { - html5Mode.enabled = mode.enabled; - } - if (isBoolean(mode.requireBase)) { - html5Mode.requireBase = mode.requireBase; - } - if (isBoolean(mode.rewriteLinks)) { - html5Mode.rewriteLinks = mode.rewriteLinks; - } - return this; - } else { - return html5Mode; + }, + addClass: jqLiteAddClass, + removeClass: jqLiteRemoveClass, + toggleClass: function(element, selector, condition) { + if (selector) { + forEach(selector.split(" "), function(className) { + var classCondition = condition; + if (isUndefined(classCondition)) { + classCondition = !jqLiteHasClass(element, className); + } + (classCondition ? jqLiteAddClass : jqLiteRemoveClass)(element, className); + }); } - }; - this.$get = [ "$rootScope", "$browser", "$sniffer", "$rootElement", "$window", function($rootScope, $browser, $sniffer, $rootElement, $window) { - var $location, LocationMode, baseHref = $browser.baseHref(), initialUrl = $browser.url(), appBase; - if (html5Mode.enabled) { - if (!baseHref && html5Mode.requireBase) { - throw $locationMinErr("nobase", "$location in HTML5 mode requires a tag to be present!"); - } - appBase = serverBase(initialUrl) + (baseHref || "/"); - LocationMode = $sniffer.history ? LocationHtml5Url : LocationHashbangInHtml5Url; + }, + parent: function(element) { + var parent = element.parentNode; + return parent && parent.nodeType !== NODE_TYPE_DOCUMENT_FRAGMENT ? parent : null; + }, + next: function(element) { + return element.nextElementSibling; + }, + find: function(element, selector) { + if (element.getElementsByTagName) { + return element.getElementsByTagName(selector); } else { - appBase = stripHash(initialUrl); - LocationMode = LocationHashbangUrl; - } - var appBaseNoFile = stripFile(appBase); - $location = new LocationMode(appBase, appBaseNoFile, "#" + hashPrefix); - $location.$$parseLinkUrl(initialUrl, initialUrl); - $location.$$state = $browser.state(); - var IGNORE_URI_REGEXP = /^\s*(javascript|mailto):/i; - function setBrowserUrlWithFallback(url, replace, state) { - var oldUrl = $location.url(); - var oldState = $location.$$state; - try { - $browser.url(url, replace, state); - $location.$$state = $browser.state(); - } catch (e) { - $location.url(oldUrl); - $location.$$state = oldState; - throw e; - } + return []; } - $rootElement.on("click", function(event) { - if (!html5Mode.rewriteLinks || event.ctrlKey || event.metaKey || event.shiftKey || event.which == 2 || event.button == 2) return; - var elm = jqLite(event.target); - while (nodeName_(elm[0]) !== "a") { - if (elm[0] === $rootElement[0] || !(elm = elm.parent())[0]) return; - } - var absHref = elm.prop("href"); - var relHref = elm.attr("href") || elm.attr("xlink:href"); - if (isObject(absHref) && absHref.toString() === "[object SVGAnimatedString]") { - absHref = urlResolve(absHref.animVal).href; - } - if (IGNORE_URI_REGEXP.test(absHref)) return; - if (absHref && !elm.attr("target") && !event.isDefaultPrevented()) { - if ($location.$$parseLinkUrl(absHref, relHref)) { - event.preventDefault(); - if ($location.absUrl() != $browser.url()) { - $rootScope.$apply(); - $window.angular["ff-684208-preventDefault"] = true; - } - } - } - }); - if (trimEmptyHash($location.absUrl()) != trimEmptyHash(initialUrl)) { - $browser.url($location.absUrl(), true); - } - var initializing = true; - $browser.onUrlChange(function(newUrl, newState) { - if (isUndefined(beginsWith(appBaseNoFile, newUrl))) { - $window.location.href = newUrl; - return; + }, + clone: jqLiteClone, + triggerHandler: function(element, event, extraParameters) { + var dummyEvent, eventFnsCopy, handlerArgs; + var eventName = event.type || event; + var expandoStore = jqLiteExpandoStore(element); + var events = expandoStore && expandoStore.events; + var eventFns = events && events[eventName]; + if (eventFns) { + dummyEvent = { + preventDefault: function() { + this.defaultPrevented = true; + }, + isDefaultPrevented: function() { + return this.defaultPrevented === true; + }, + stopImmediatePropagation: function() { + this.immediatePropagationStopped = true; + }, + isImmediatePropagationStopped: function() { + return this.immediatePropagationStopped === true; + }, + stopPropagation: noop, + type: eventName, + target: element + }; + if (event.type) { + dummyEvent = extend(dummyEvent, event); } - $rootScope.$evalAsync(function() { - var oldUrl = $location.absUrl(); - var oldState = $location.$$state; - var defaultPrevented; - $location.$$parse(newUrl); - $location.$$state = newState; - defaultPrevented = $rootScope.$broadcast("$locationChangeStart", newUrl, oldUrl, newState, oldState).defaultPrevented; - if ($location.absUrl() !== newUrl) return; - if (defaultPrevented) { - $location.$$parse(oldUrl); - $location.$$state = oldState; - setBrowserUrlWithFallback(oldUrl, false, oldState); - } else { - initializing = false; - afterLocationChange(oldUrl, oldState); + eventFnsCopy = shallowCopy(eventFns); + handlerArgs = extraParameters ? [ dummyEvent ].concat(extraParameters) : [ dummyEvent ]; + forEach(eventFnsCopy, function(fn) { + if (!dummyEvent.isImmediatePropagationStopped()) { + fn.apply(element, handlerArgs); } }); - if (!$rootScope.$$phase) $rootScope.$digest(); - }); - $rootScope.$watch(function $locationWatch() { - var oldUrl = trimEmptyHash($browser.url()); - var newUrl = trimEmptyHash($location.absUrl()); - var oldState = $browser.state(); - var currentReplace = $location.$$replace; - var urlOrStateChanged = oldUrl !== newUrl || $location.$$html5 && $sniffer.history && oldState !== $location.$$state; - if (initializing || urlOrStateChanged) { - initializing = false; - $rootScope.$evalAsync(function() { - var newUrl = $location.absUrl(); - var defaultPrevented = $rootScope.$broadcast("$locationChangeStart", newUrl, oldUrl, $location.$$state, oldState).defaultPrevented; - if ($location.absUrl() !== newUrl) return; - if (defaultPrevented) { - $location.$$parse(oldUrl); - $location.$$state = oldState; - } else { - if (urlOrStateChanged) { - setBrowserUrlWithFallback(newUrl, currentReplace, oldState === $location.$$state ? null : $location.$$state); - } - afterLocationChange(oldUrl, oldState); - } - }); - } - $location.$$replace = false; - }); - return $location; - function afterLocationChange(oldUrl, oldState) { - $rootScope.$broadcast("$locationChangeSuccess", $location.absUrl(), oldUrl, $location.$$state, oldState); - } - } ]; - } - function $LogProvider() { - var debug = true, self = this; - this.debugEnabled = function(flag) { - if (isDefined(flag)) { - debug = flag; - return this; - } else { - return debug; } - }; - this.$get = [ "$window", function($window) { - return { - log: consoleLog("log"), - info: consoleLog("info"), - warn: consoleLog("warn"), - error: consoleLog("error"), - debug: function() { - var fn = consoleLog("debug"); - return function() { - if (debug) { - fn.apply(self, arguments); - } - }; - }() - }; - function formatError(arg) { - if (arg instanceof Error) { - if (arg.stack) { - arg = arg.message && arg.stack.indexOf(arg.message) === -1 ? "Error: " + arg.message + "\n" + arg.stack : arg.stack; - } else if (arg.sourceURL) { - arg = arg.message + "\n" + arg.sourceURL + ":" + arg.line; + } + }, function(fn, name) { + JQLite.prototype[name] = function(arg1, arg2, arg3) { + var value; + for (var i = 0, ii = this.length; i < ii; i++) { + if (isUndefined(value)) { + value = fn(this[i], arg1, arg2, arg3); + if (isDefined(value)) { + value = jqLite(value); } + } else { + jqLiteAddNodes(value, fn(this[i], arg1, arg2, arg3)); } - return arg; } - function consoleLog(type) { - var console = $window.console || {}, logFn = console[type] || console.log || noop, hasApply = false; - try { - hasApply = !!logFn.apply; - } catch (e) {} - if (hasApply) { - return function() { - var args = []; - forEach(arguments, function(arg) { - args.push(formatError(arg)); - }); - return logFn.apply(console, args); - }; + return isDefined(value) ? value : this; + }; + JQLite.prototype.bind = JQLite.prototype.on; + JQLite.prototype.unbind = JQLite.prototype.off; + }); + function $$jqLiteProvider() { + this.$get = function $$jqLite() { + return extend(JQLite, { + hasClass: function(node, classes) { + if (node.attr) node = node[0]; + return jqLiteHasClass(node, classes); + }, + addClass: function(node, classes) { + if (node.attr) node = node[0]; + return jqLiteAddClass(node, classes); + }, + removeClass: function(node, classes) { + if (node.attr) node = node[0]; + return jqLiteRemoveClass(node, classes); } - return function(arg1, arg2) { - logFn(arg1, arg2 == null ? "" : arg2); - }; - } - } ]; - } - var $parseMinErr = minErr("$parse"); - function ensureSafeMemberName(name, fullExpression) { - name = isObject(name) && name.toString ? name.toString() : name; - if (name === "__defineGetter__" || name === "__defineSetter__" || name === "__lookupGetter__" || name === "__lookupSetter__" || name === "__proto__") { - throw $parseMinErr("isecfld", "Attempting to access a disallowed field in Angular expressions! " + "Expression: {0}", fullExpression); - } - return name; + }); + }; } - function ensureSafeObject(obj, fullExpression) { - if (obj) { - if (obj.constructor === obj) { - throw $parseMinErr("isecfn", "Referencing Function in Angular expressions is disallowed! Expression: {0}", fullExpression); - } else if (obj.window === obj) { - throw $parseMinErr("isecwindow", "Referencing the Window in Angular expressions is disallowed! Expression: {0}", fullExpression); - } else if (obj.children && (obj.nodeName || obj.prop && obj.attr && obj.find)) { - throw $parseMinErr("isecdom", "Referencing DOM nodes in Angular expressions is disallowed! Expression: {0}", fullExpression); - } else if (obj === Object) { - throw $parseMinErr("isecobj", "Referencing Object in Angular expressions is disallowed! Expression: {0}", fullExpression); + function hashKey(obj, nextUidFn) { + var key = obj && obj.$$hashKey; + if (key) { + if (typeof key === "function") { + key = obj.$$hashKey(); } + return key; } - return obj; + var objType = typeof obj; + if (objType == "function" || objType == "object" && obj !== null) { + key = obj.$$hashKey = objType + ":" + (nextUidFn || nextUid)(); + } else { + key = objType + ":" + obj; + } + return key; } - var CALL = Function.prototype.call; - var APPLY = Function.prototype.apply; - var BIND = Function.prototype.bind; - function ensureSafeFunction(obj, fullExpression) { - if (obj) { - if (obj.constructor === obj) { - throw $parseMinErr("isecfn", "Referencing Function in Angular expressions is disallowed! Expression: {0}", fullExpression); - } else if (obj === CALL || obj === APPLY || obj === BIND) { - throw $parseMinErr("isecff", "Referencing call, apply or bind in Angular expressions is disallowed! Expression: {0}", fullExpression); - } + function HashMap(array, isolatedUid) { + if (isolatedUid) { + var uid = 0; + this.nextUid = function() { + return ++uid; + }; } + forEach(array, this.put, this); } - var OPERATORS = createMap(); - forEach("+ - * / % === !== == != < > <= >= && || ! = |".split(" "), function(operator) { - OPERATORS[operator] = true; - }); - var ESCAPE = { - n: "\n", - f: "\f", - r: "\r", - t: " ", - v: " ", - "'": "'", - '"': '"' - }; - var Lexer = function(options) { - this.options = options; - }; - Lexer.prototype = { - constructor: Lexer, - lex: function(text) { - this.text = text; - this.index = 0; - this.tokens = []; - while (this.index < this.text.length) { - var ch = this.text.charAt(this.index); - if (ch === '"' || ch === "'") { - this.readString(ch); - } else if (this.isNumber(ch) || ch === "." && this.isNumber(this.peek())) { - this.readNumber(); - } else if (this.isIdent(ch)) { - this.readIdent(); - } else if (this.is(ch, "(){}[].,;:?")) { - this.tokens.push({ - index: this.index, - text: ch - }); - this.index++; - } else if (this.isWhitespace(ch)) { - this.index++; - } else { - var ch2 = ch + this.peek(); - var ch3 = ch2 + this.peek(2); - var op1 = OPERATORS[ch]; - var op2 = OPERATORS[ch2]; - var op3 = OPERATORS[ch3]; - if (op1 || op2 || op3) { - var token = op3 ? ch3 : op2 ? ch2 : ch; - this.tokens.push({ - index: this.index, - text: token, - operator: true - }); - this.index += token.length; - } else { - this.throwError("Unexpected next character ", this.index, this.index + 1); - } - } - } - return this.tokens; - }, - is: function(ch, chars) { - return chars.indexOf(ch) !== -1; - }, - peek: function(i) { - var num = i || 1; - return this.index + num < this.text.length ? this.text.charAt(this.index + num) : false; - }, - isNumber: function(ch) { - return "0" <= ch && ch <= "9" && typeof ch === "string"; - }, - isWhitespace: function(ch) { - return ch === " " || ch === "\r" || ch === " " || ch === "\n" || ch === " " || ch === " "; - }, - isIdent: function(ch) { - return "a" <= ch && ch <= "z" || "A" <= ch && ch <= "Z" || "_" === ch || ch === "$"; - }, - isExpOperator: function(ch) { - return ch === "-" || ch === "+" || this.isNumber(ch); - }, - throwError: function(error, start, end) { - end = end || this.index; - var colStr = isDefined(start) ? "s " + start + "-" + this.index + " [" + this.text.substring(start, end) + "]" : " " + end; - throw $parseMinErr("lexerr", "Lexer Error: {0} at column{1} in expression [{2}].", error, colStr, this.text); - }, - readNumber: function() { - var number = ""; - var start = this.index; - while (this.index < this.text.length) { - var ch = lowercase(this.text.charAt(this.index)); - if (ch == "." || this.isNumber(ch)) { - number += ch; - } else { - var peekCh = this.peek(); - if (ch == "e" && this.isExpOperator(peekCh)) { - number += ch; - } else if (this.isExpOperator(ch) && peekCh && this.isNumber(peekCh) && number.charAt(number.length - 1) == "e") { - number += ch; - } else if (this.isExpOperator(ch) && (!peekCh || !this.isNumber(peekCh)) && number.charAt(number.length - 1) == "e") { - this.throwError("Invalid exponent"); - } else { - break; - } - } - this.index++; - } - this.tokens.push({ - index: start, - text: number, - constant: true, - value: Number(number) - }); + HashMap.prototype = { + put: function(key, value) { + this[hashKey(key, this.nextUid)] = value; }, - readIdent: function() { - var start = this.index; - while (this.index < this.text.length) { - var ch = this.text.charAt(this.index); - if (!(this.isIdent(ch) || this.isNumber(ch))) { - break; - } - this.index++; - } - this.tokens.push({ - index: start, - text: this.text.slice(start, this.index), - identifier: true - }); + get: function(key) { + return this[hashKey(key, this.nextUid)]; }, - readString: function(quote) { - var start = this.index; - this.index++; - var string = ""; - var rawString = quote; - var escape = false; - while (this.index < this.text.length) { - var ch = this.text.charAt(this.index); - rawString += ch; - if (escape) { - if (ch === "u") { - var hex = this.text.substring(this.index + 1, this.index + 5); - if (!hex.match(/[\da-f]{4}/i)) { - this.throwError("Invalid unicode escape [\\u" + hex + "]"); + remove: function(key) { + var value = this[key = hashKey(key, this.nextUid)]; + delete this[key]; + return value; + } + }; + var $$HashMapProvider = [ function() { + this.$get = [ function() { + return HashMap; + } ]; + } ]; + var FN_ARGS = /^[^\(]*\(\s*([^\)]*)\)/m; + var FN_ARG_SPLIT = /,/; + var FN_ARG = /^\s*(_?)(\S+?)\1\s*$/; + var STRIP_COMMENTS = /((\/\/.*$)|(\/\*[\s\S]*?\*\/))/gm; + var $injectorMinErr = minErr("$injector"); + function anonFn(fn) { + var fnText = fn.toString().replace(STRIP_COMMENTS, ""), args = fnText.match(FN_ARGS); + if (args) { + return "function(" + (args[1] || "").replace(/[\s\r\n]+/, " ") + ")"; + } + return "fn"; + } + function annotate(fn, strictDi, name) { + var $inject, fnText, argDecl, last; + if (typeof fn === "function") { + if (!($inject = fn.$inject)) { + $inject = []; + if (fn.length) { + if (strictDi) { + if (!isString(name) || !name) { + name = fn.name || anonFn(fn); } - this.index += 4; - string += String.fromCharCode(parseInt(hex, 16)); - } else { - var rep = ESCAPE[ch]; - string = string + (rep || ch); + throw $injectorMinErr("strictdi", "{0} is not using explicit annotation and cannot be invoked in strict mode", name); } - escape = false; - } else if (ch === "\\") { - escape = true; - } else if (ch === quote) { - this.index++; - this.tokens.push({ - index: start, - text: rawString, - constant: true, - value: string + fnText = fn.toString().replace(STRIP_COMMENTS, ""); + argDecl = fnText.match(FN_ARGS); + forEach(argDecl[1].split(FN_ARG_SPLIT), function(arg) { + arg.replace(FN_ARG, function(all, underscore, name) { + $inject.push(name); + }); }); - return; - } else { - string += ch; } - this.index++; + fn.$inject = $inject; } - this.throwError("Unterminated quote", start); + } else if (isArray(fn)) { + last = fn.length - 1; + assertArgFn(fn[last], "fn"); + $inject = fn.slice(0, last); + } else { + assertArgFn(fn, "fn", true); } - }; - var AST = function(lexer, options) { - this.lexer = lexer; - this.options = options; - }; - AST.Program = "Program"; - AST.ExpressionStatement = "ExpressionStatement"; - AST.AssignmentExpression = "AssignmentExpression"; - AST.ConditionalExpression = "ConditionalExpression"; - AST.LogicalExpression = "LogicalExpression"; - AST.BinaryExpression = "BinaryExpression"; - AST.UnaryExpression = "UnaryExpression"; - AST.CallExpression = "CallExpression"; - AST.MemberExpression = "MemberExpression"; - AST.Identifier = "Identifier"; - AST.Literal = "Literal"; - AST.ArrayExpression = "ArrayExpression"; - AST.Property = "Property"; - AST.ObjectExpression = "ObjectExpression"; - AST.ThisExpression = "ThisExpression"; - AST.NGValueParameter = "NGValueParameter"; - AST.prototype = { - ast: function(text) { - this.text = text; - this.tokens = this.lexer.lex(text); - var value = this.program(); - if (this.tokens.length !== 0) { - this.throwError("is an unexpected token", this.tokens[0]); + return $inject; + } + function createInjector(modulesToLoad, strictDi) { + strictDi = strictDi === true; + var INSTANTIATING = {}, providerSuffix = "Provider", path = [], loadedModules = new HashMap([], true), providerCache = { + $provide: { + provider: supportObject(provider), + factory: supportObject(factory), + service: supportObject(service), + value: supportObject(value), + constant: supportObject(constant), + decorator: decorator } - return value; - }, - program: function() { - var body = []; - while (true) { - if (this.tokens.length > 0 && !this.peek("}", ")", ";", "]")) body.push(this.expressionStatement()); - if (!this.expect(";")) { - return { - type: AST.Program, - body: body - }; - } + }, providerInjector = providerCache.$injector = createInternalInjector(providerCache, function(serviceName, caller) { + if (angular.isString(caller)) { + path.push(caller); } - }, - expressionStatement: function() { - return { - type: AST.ExpressionStatement, - expression: this.filterChain() - }; - }, - filterChain: function() { - var left = this.expression(); - var token; - while (token = this.expect("|")) { - left = this.filter(left); + throw $injectorMinErr("unpr", "Unknown provider: {0}", path.join(" <- ")); + }), instanceCache = {}, instanceInjector = instanceCache.$injector = createInternalInjector(instanceCache, function(serviceName, caller) { + var provider = providerInjector.get(serviceName + providerSuffix, caller); + return instanceInjector.invoke(provider.$get, provider, undefined, serviceName); + }); + forEach(loadModules(modulesToLoad), function(fn) { + if (fn) instanceInjector.invoke(fn); + }); + return instanceInjector; + function supportObject(delegate) { + return function(key, value) { + if (isObject(key)) { + forEach(key, reverseParams(delegate)); + } else { + return delegate(key, value); + } + }; + } + function provider(name, provider_) { + assertNotHasOwnProperty(name, "service"); + if (isFunction(provider_) || isArray(provider_)) { + provider_ = providerInjector.instantiate(provider_); } - return left; - }, - expression: function() { - return this.assignment(); - }, - assignment: function() { - var result = this.ternary(); - if (this.expect("=")) { - result = { - type: AST.AssignmentExpression, - left: result, - right: this.assignment(), - operator: "=" - }; + if (!provider_.$get) { + throw $injectorMinErr("pget", "Provider '{0}' must define $get factory method.", name); } - return result; - }, - ternary: function() { - var test = this.logicalOR(); - var alternate; - var consequent; - if (this.expect("?")) { - alternate = this.expression(); - if (this.consume(":")) { - consequent = this.expression(); - return { - type: AST.ConditionalExpression, - test: test, - alternate: alternate, - consequent: consequent - }; + return providerCache[name + providerSuffix] = provider_; + } + function enforceReturnValue(name, factory) { + return function enforcedReturnValue() { + var result = instanceInjector.invoke(factory, this); + if (isUndefined(result)) { + throw $injectorMinErr("undef", "Provider '{0}' must return a value from $get factory method.", name); + } + return result; + }; + } + function factory(name, factoryFn, enforce) { + return provider(name, { + $get: enforce !== false ? enforceReturnValue(name, factoryFn) : factoryFn + }); + } + function service(name, constructor) { + return factory(name, [ "$injector", function($injector) { + return $injector.instantiate(constructor); + } ]); + } + function value(name, val) { + return factory(name, valueFn(val), false); + } + function constant(name, value) { + assertNotHasOwnProperty(name, "constant"); + providerCache[name] = value; + instanceCache[name] = value; + } + function decorator(serviceName, decorFn) { + var origProvider = providerInjector.get(serviceName + providerSuffix), orig$get = origProvider.$get; + origProvider.$get = function() { + var origInstance = instanceInjector.invoke(orig$get, origProvider); + return instanceInjector.invoke(decorFn, null, { + $delegate: origInstance + }); + }; + } + function loadModules(modulesToLoad) { + assertArg(isUndefined(modulesToLoad) || isArray(modulesToLoad), "modulesToLoad", "not an array"); + var runBlocks = [], moduleFn; + forEach(modulesToLoad, function(module) { + if (loadedModules.get(module)) return; + loadedModules.put(module, true); + function runInvokeQueue(queue) { + var i, ii; + for (i = 0, ii = queue.length; i < ii; i++) { + var invokeArgs = queue[i], provider = providerInjector.get(invokeArgs[0]); + provider[invokeArgs[1]].apply(provider, invokeArgs[2]); + } + } + try { + if (isString(module)) { + moduleFn = angularModule(module); + runBlocks = runBlocks.concat(loadModules(moduleFn.requires)).concat(moduleFn._runBlocks); + runInvokeQueue(moduleFn._invokeQueue); + runInvokeQueue(moduleFn._configBlocks); + } else if (isFunction(module)) { + runBlocks.push(providerInjector.invoke(module)); + } else if (isArray(module)) { + runBlocks.push(providerInjector.invoke(module)); + } else { + assertArgFn(module, "module"); + } + } catch (e) { + if (isArray(module)) { + module = module[module.length - 1]; + } + if (e.message && e.stack && e.stack.indexOf(e.message) == -1) { + e = e.message + "\n" + e.stack; + } + throw $injectorMinErr("modulerr", "Failed to instantiate module {0} due to:\n{1}", module, e.stack || e.message || e); + } + }); + return runBlocks; + } + function createInternalInjector(cache, factory) { + function getService(serviceName, caller) { + if (cache.hasOwnProperty(serviceName)) { + if (cache[serviceName] === INSTANTIATING) { + throw $injectorMinErr("cdep", "Circular dependency found: {0}", serviceName + " <- " + path.join(" <- ")); + } + return cache[serviceName]; + } else { + try { + path.unshift(serviceName); + cache[serviceName] = INSTANTIATING; + return cache[serviceName] = factory(serviceName, caller); + } catch (err) { + if (cache[serviceName] === INSTANTIATING) { + delete cache[serviceName]; + } + throw err; + } finally { + path.shift(); + } } } - return test; - }, - logicalOR: function() { - var left = this.logicalAND(); - while (this.expect("||")) { - left = { - type: AST.LogicalExpression, - operator: "||", - left: left, - right: this.logicalAND() - }; - } - return left; - }, - logicalAND: function() { - var left = this.equality(); - while (this.expect("&&")) { - left = { - type: AST.LogicalExpression, - operator: "&&", - left: left, - right: this.equality() - }; + function invoke(fn, self, locals, serviceName) { + if (typeof locals === "string") { + serviceName = locals; + locals = null; + } + var args = [], $inject = createInjector.$$annotate(fn, strictDi, serviceName), length, i, key; + for (i = 0, length = $inject.length; i < length; i++) { + key = $inject[i]; + if (typeof key !== "string") { + throw $injectorMinErr("itkn", "Incorrect injection token! Expected service name as string, got {0}", key); + } + args.push(locals && locals.hasOwnProperty(key) ? locals[key] : getService(key, serviceName)); + } + if (isArray(fn)) { + fn = fn[length]; + } + return fn.apply(self, args); } - return left; - }, - equality: function() { - var left = this.relational(); - var token; - while (token = this.expect("==", "!=", "===", "!==")) { - left = { - type: AST.BinaryExpression, - operator: token.text, - left: left, - right: this.relational() - }; + function instantiate(Type, locals, serviceName) { + var instance = Object.create((isArray(Type) ? Type[Type.length - 1] : Type).prototype || null); + var returnedValue = invoke(Type, instance, locals, serviceName); + return isObject(returnedValue) || isFunction(returnedValue) ? returnedValue : instance; } - return left; - }, - relational: function() { - var left = this.additive(); - var token; - while (token = this.expect("<", ">", "<=", ">=")) { - left = { - type: AST.BinaryExpression, - operator: token.text, - left: left, - right: this.additive() - }; + return { + invoke: invoke, + instantiate: instantiate, + get: getService, + annotate: createInjector.$$annotate, + has: function(name) { + return providerCache.hasOwnProperty(name + providerSuffix) || cache.hasOwnProperty(name); + } + }; + } + } + createInjector.$$annotate = annotate; + function $AnchorScrollProvider() { + var autoScrollingEnabled = true; + this.disableAutoScrolling = function() { + autoScrollingEnabled = false; + }; + this.$get = [ "$window", "$location", "$rootScope", function($window, $location, $rootScope) { + var document = $window.document; + function getFirstAnchor(list) { + var result = null; + Array.prototype.some.call(list, function(element) { + if (nodeName_(element) === "a") { + result = element; + return true; + } + }); + return result; } - return left; - }, - additive: function() { - var left = this.multiplicative(); - var token; - while (token = this.expect("+", "-")) { - left = { - type: AST.BinaryExpression, - operator: token.text, - left: left, - right: this.multiplicative() - }; - } - return left; - }, - multiplicative: function() { - var left = this.unary(); - var token; - while (token = this.expect("*", "/", "%")) { - left = { - type: AST.BinaryExpression, - operator: token.text, - left: left, - right: this.unary() - }; - } - return left; - }, - unary: function() { - var token; - if (token = this.expect("+", "-", "!")) { - return { - type: AST.UnaryExpression, - operator: token.text, - prefix: true, - argument: this.unary() - }; - } else { - return this.primary(); - } - }, - primary: function() { - var primary; - if (this.expect("(")) { - primary = this.filterChain(); - this.consume(")"); - } else if (this.expect("[")) { - primary = this.arrayDeclaration(); - } else if (this.expect("{")) { - primary = this.object(); - } else if (this.constants.hasOwnProperty(this.peek().text)) { - primary = copy(this.constants[this.consume().text]); - } else if (this.peek().identifier) { - primary = this.identifier(); - } else if (this.peek().constant) { - primary = this.constant(); - } else { - this.throwError("not a primary expression", this.peek()); + function getYOffset() { + var offset = scroll.yOffset; + if (isFunction(offset)) { + offset = offset(); + } else if (isElement(offset)) { + var elem = offset[0]; + var style = $window.getComputedStyle(elem); + if (style.position !== "fixed") { + offset = 0; + } else { + offset = elem.getBoundingClientRect().bottom; + } + } else if (!isNumber(offset)) { + offset = 0; + } + return offset; } - var next; - while (next = this.expect("(", "[", ".")) { - if (next.text === "(") { - primary = { - type: AST.CallExpression, - callee: primary, - arguments: this.parseArguments() - }; - this.consume(")"); - } else if (next.text === "[") { - primary = { - type: AST.MemberExpression, - object: primary, - property: this.expression(), - computed: true - }; - this.consume("]"); - } else if (next.text === ".") { - primary = { - type: AST.MemberExpression, - object: primary, - property: this.identifier(), - computed: false - }; + function scrollTo(elem) { + if (elem) { + elem.scrollIntoView(); + var offset = getYOffset(); + if (offset) { + var elemTop = elem.getBoundingClientRect().top; + $window.scrollBy(0, elemTop - offset); + } } else { - this.throwError("IMPOSSIBLE"); + $window.scrollTo(0, 0); } } - return primary; - }, - filter: function(baseExpression) { - var args = [ baseExpression ]; - var result = { - type: AST.CallExpression, - callee: this.identifier(), - arguments: args, - filter: true - }; - while (this.expect(":")) { - args.push(this.expression()); + function scroll(hash) { + hash = isString(hash) ? hash : $location.hash(); + var elm; + if (!hash) scrollTo(null); else if (elm = document.getElementById(hash)) scrollTo(elm); else if (elm = getFirstAnchor(document.getElementsByName(hash))) scrollTo(elm); else if (hash === "top") scrollTo(null); } - return result; - }, - parseArguments: function() { - var args = []; - if (this.peekToken().text !== ")") { - do { - args.push(this.expression()); - } while (this.expect(",")); + if (autoScrollingEnabled) { + $rootScope.$watch(function autoScrollWatch() { + return $location.hash(); + }, function autoScrollWatchAction(newVal, oldVal) { + if (newVal === oldVal && newVal === "") return; + jqLiteDocumentLoaded(function() { + $rootScope.$evalAsync(scroll); + }); + }); } - return args; - }, - identifier: function() { - var token = this.consume(); - if (!token.identifier) { - this.throwError("is not a valid identifier", token); + return scroll; + } ]; + } + var $animateMinErr = minErr("$animate"); + var ELEMENT_NODE = 1; + var NG_ANIMATE_CLASSNAME = "ng-animate"; + function mergeClasses(a, b) { + if (!a && !b) return ""; + if (!a) return b; + if (!b) return a; + if (isArray(a)) a = a.join(" "); + if (isArray(b)) b = b.join(" "); + return a + " " + b; + } + function extractElementNode(element) { + for (var i = 0; i < element.length; i++) { + var elm = element[i]; + if (elm.nodeType === ELEMENT_NODE) { + return elm; } - return { - type: AST.Identifier, - name: token.text + } + } + function splitClasses(classes) { + if (isString(classes)) { + classes = classes.split(" "); + } + var obj = createMap(); + forEach(classes, function(klass) { + if (klass.length) { + obj[klass] = true; + } + }); + return obj; + } + function prepareAnimateOptions(options) { + return isObject(options) ? options : {}; + } + var $$CoreAnimateRunnerProvider = function() { + this.$get = [ "$q", "$$rAF", function($q, $$rAF) { + function AnimateRunner() {} + AnimateRunner.all = noop; + AnimateRunner.chain = noop; + AnimateRunner.prototype = { + end: noop, + cancel: noop, + resume: noop, + pause: noop, + complete: noop, + then: function(pass, fail) { + return $q(function(resolve) { + $$rAF(function() { + resolve(); + }); + }).then(pass, fail); + } }; - }, - constant: function() { + return AnimateRunner; + } ]; + }; + var $$CoreAnimateQueueProvider = function() { + var postDigestQueue = new HashMap(); + var postDigestElements = []; + this.$get = [ "$$AnimateRunner", "$rootScope", function($$AnimateRunner, $rootScope) { return { - type: AST.Literal, - value: this.consume().value - }; - }, - arrayDeclaration: function() { - var elements = []; - if (this.peekToken().text !== "]") { - do { - if (this.peek("]")) { - break; + enabled: noop, + on: noop, + off: noop, + pin: noop, + push: function(element, event, options, domOperation) { + domOperation && domOperation(); + options = options || {}; + options.from && element.css(options.from); + options.to && element.css(options.to); + if (options.addClass || options.removeClass) { + addRemoveClassesPostDigest(element, options.addClass, options.removeClass); } - elements.push(this.expression()); - } while (this.expect(",")); - } - this.consume("]"); - return { - type: AST.ArrayExpression, - elements: elements + return new $$AnimateRunner(); + } }; - }, - object: function() { - var properties = [], property; - if (this.peekToken().text !== "}") { - do { - if (this.peek("}")) { - break; - } - property = { - type: AST.Property, - kind: "init" - }; - if (this.peek().constant) { - property.key = this.constant(); - } else if (this.peek().identifier) { - property.key = this.identifier(); - } else { - this.throwError("invalid key", this.peek()); - } - this.consume(":"); - property.value = this.expression(); - properties.push(property); - } while (this.expect(",")); - } - this.consume("}"); - return { - type: AST.ObjectExpression, - properties: properties - }; - }, - throwError: function(msg, token) { - throw $parseMinErr("syntax", "Syntax Error: Token '{0}' {1} at column {2} of the expression [{3}] starting at [{4}].", token.text, msg, token.index + 1, this.text, this.text.substring(token.index)); - }, - consume: function(e1) { - if (this.tokens.length === 0) { - throw $parseMinErr("ueoe", "Unexpected end of expression: {0}", this.text); - } - var token = this.expect(e1); - if (!token) { - this.throwError("is unexpected, expecting [" + e1 + "]", this.peek()); - } - return token; - }, - peekToken: function() { - if (this.tokens.length === 0) { - throw $parseMinErr("ueoe", "Unexpected end of expression: {0}", this.text); - } - return this.tokens[0]; - }, - peek: function(e1, e2, e3, e4) { - return this.peekAhead(0, e1, e2, e3, e4); - }, - peekAhead: function(i, e1, e2, e3, e4) { - if (this.tokens.length > i) { - var token = this.tokens[i]; - var t = token.text; - if (t === e1 || t === e2 || t === e3 || t === e4 || !e1 && !e2 && !e3 && !e4) { - return token; + function updateData(data, classes, value) { + var changed = false; + if (classes) { + classes = isString(classes) ? classes.split(" ") : isArray(classes) ? classes : []; + forEach(classes, function(className) { + if (className) { + changed = true; + data[className] = value; + } + }); } + return changed; } - return false; - }, - expect: function(e1, e2, e3, e4) { - var token = this.peek(e1, e2, e3, e4); - if (token) { - this.tokens.shift(); - return token; + function handleCSSClassChanges() { + forEach(postDigestElements, function(element) { + var data = postDigestQueue.get(element); + if (data) { + var existing = splitClasses(element.attr("class")); + var toAdd = ""; + var toRemove = ""; + forEach(data, function(status, className) { + var hasClass = !!existing[className]; + if (status !== hasClass) { + if (status) { + toAdd += (toAdd.length ? " " : "") + className; + } else { + toRemove += (toRemove.length ? " " : "") + className; + } + } + }); + forEach(element, function(elm) { + toAdd && jqLiteAddClass(elm, toAdd); + toRemove && jqLiteRemoveClass(elm, toRemove); + }); + postDigestQueue.remove(element); + } + }); + postDigestElements.length = 0; } - return false; - }, - constants: { - "true": { - type: AST.Literal, - value: true - }, - "false": { - type: AST.Literal, - value: false - }, - "null": { - type: AST.Literal, - value: null - }, - undefined: { - type: AST.Literal, - value: undefined - }, - "this": { - type: AST.ThisExpression + function addRemoveClassesPostDigest(element, add, remove) { + var data = postDigestQueue.get(element) || {}; + var classesAdded = updateData(data, add, true); + var classesRemoved = updateData(data, remove, false); + if (classesAdded || classesRemoved) { + postDigestQueue.put(element, data); + postDigestElements.push(element); + if (postDigestElements.length === 1) { + $rootScope.$$postDigest(handleCSSClassChanges); + } + } } - } + } ]; }; - function ifDefined(v, d) { - return typeof v !== "undefined" ? v : d; - } - function plusFn(l, r) { - if (typeof l === "undefined") return r; - if (typeof r === "undefined") return l; - return l + r; - } - function isStateless($filter, filterName) { - var fn = $filter(filterName); - return !fn.$stateful; - } - function findConstantAndWatchExpressions(ast, $filter) { - var allConstants; - var argsToWatch; - switch (ast.type) { - case AST.Program: - allConstants = true; - forEach(ast.body, function(expr) { - findConstantAndWatchExpressions(expr.expression, $filter); - allConstants = allConstants && expr.expression.constant; - }); - ast.constant = allConstants; - break; - - case AST.Literal: - ast.constant = true; - ast.toWatch = []; - break; - - case AST.UnaryExpression: - findConstantAndWatchExpressions(ast.argument, $filter); - ast.constant = ast.argument.constant; - ast.toWatch = ast.argument.toWatch; - break; - - case AST.BinaryExpression: - findConstantAndWatchExpressions(ast.left, $filter); - findConstantAndWatchExpressions(ast.right, $filter); - ast.constant = ast.left.constant && ast.right.constant; - ast.toWatch = ast.left.toWatch.concat(ast.right.toWatch); - break; - - case AST.LogicalExpression: - findConstantAndWatchExpressions(ast.left, $filter); - findConstantAndWatchExpressions(ast.right, $filter); - ast.constant = ast.left.constant && ast.right.constant; - ast.toWatch = ast.constant ? [] : [ ast ]; - break; - - case AST.ConditionalExpression: - findConstantAndWatchExpressions(ast.test, $filter); - findConstantAndWatchExpressions(ast.alternate, $filter); - findConstantAndWatchExpressions(ast.consequent, $filter); - ast.constant = ast.test.constant && ast.alternate.constant && ast.consequent.constant; - ast.toWatch = ast.constant ? [] : [ ast ]; - break; - - case AST.Identifier: - ast.constant = false; - ast.toWatch = [ ast ]; - break; - - case AST.MemberExpression: - findConstantAndWatchExpressions(ast.object, $filter); - if (ast.computed) { - findConstantAndWatchExpressions(ast.property, $filter); + var $AnimateProvider = [ "$provide", function($provide) { + var provider = this; + this.$$registeredAnimations = Object.create(null); + this.register = function(name, factory) { + if (name && name.charAt(0) !== ".") { + throw $animateMinErr("notcsel", "Expecting class selector starting with '.' got '{0}'.", name); } - ast.constant = ast.object.constant && (!ast.computed || ast.property.constant); - ast.toWatch = [ ast ]; - break; - - case AST.CallExpression: - allConstants = ast.filter ? isStateless($filter, ast.callee.name) : false; - argsToWatch = []; - forEach(ast.arguments, function(expr) { - findConstantAndWatchExpressions(expr, $filter); - allConstants = allConstants && expr.constant; - if (!expr.constant) { - argsToWatch.push.apply(argsToWatch, expr.toWatch); - } - }); - ast.constant = allConstants; - ast.toWatch = ast.filter && isStateless($filter, ast.callee.name) ? argsToWatch : [ ast ]; - break; - - case AST.AssignmentExpression: - findConstantAndWatchExpressions(ast.left, $filter); - findConstantAndWatchExpressions(ast.right, $filter); - ast.constant = ast.left.constant && ast.right.constant; - ast.toWatch = [ ast ]; - break; - - case AST.ArrayExpression: - allConstants = true; - argsToWatch = []; - forEach(ast.elements, function(expr) { - findConstantAndWatchExpressions(expr, $filter); - allConstants = allConstants && expr.constant; - if (!expr.constant) { - argsToWatch.push.apply(argsToWatch, expr.toWatch); + var key = name + "-animation"; + provider.$$registeredAnimations[name.substr(1)] = key; + $provide.factory(key, factory); + }; + this.classNameFilter = function(expression) { + if (arguments.length === 1) { + this.$$classNameFilter = expression instanceof RegExp ? expression : null; + if (this.$$classNameFilter) { + var reservedRegex = new RegExp("(\\s+|\\/)" + NG_ANIMATE_CLASSNAME + "(\\s+|\\/)"); + if (reservedRegex.test(this.$$classNameFilter.toString())) { + throw $animateMinErr("nongcls", '$animateProvider.classNameFilter(regex) prohibits accepting a regex value which matches/contains the "{0}" CSS class.', NG_ANIMATE_CLASSNAME); + } } - }); - ast.constant = allConstants; - ast.toWatch = argsToWatch; - break; - - case AST.ObjectExpression: - allConstants = true; - argsToWatch = []; - forEach(ast.properties, function(property) { - findConstantAndWatchExpressions(property.value, $filter); - allConstants = allConstants && property.value.constant; - if (!property.value.constant) { - argsToWatch.push.apply(argsToWatch, property.value.toWatch); + } + return this.$$classNameFilter; + }; + this.$get = [ "$$animateQueue", function($$animateQueue) { + function domInsert(element, parentElement, afterElement) { + if (afterElement) { + var afterNode = extractElementNode(afterElement); + if (afterNode && !afterNode.parentNode && !afterNode.previousElementSibling) { + afterElement = null; + } } - }); - ast.constant = allConstants; - ast.toWatch = argsToWatch; - break; - - case AST.ThisExpression: - ast.constant = false; - ast.toWatch = []; - break; - } - } - function getInputs(body) { - if (body.length != 1) return; - var lastExpression = body[0].expression; - var candidate = lastExpression.toWatch; - if (candidate.length !== 1) return candidate; - return candidate[0] !== lastExpression ? candidate : undefined; - } - function isAssignable(ast) { - return ast.type === AST.Identifier || ast.type === AST.MemberExpression; - } - function assignableAST(ast) { - if (ast.body.length === 1 && isAssignable(ast.body[0].expression)) { + afterElement ? afterElement.after(element) : parentElement.prepend(element); + } return { - type: AST.AssignmentExpression, - left: ast.body[0].expression, - right: { - type: AST.NGValueParameter + on: $$animateQueue.on, + off: $$animateQueue.off, + pin: $$animateQueue.pin, + enabled: $$animateQueue.enabled, + cancel: function(runner) { + runner.end && runner.end(); }, - operator: "=" + enter: function(element, parent, after, options) { + parent = parent && jqLite(parent); + after = after && jqLite(after); + parent = parent || after.parent(); + domInsert(element, parent, after); + return $$animateQueue.push(element, "enter", prepareAnimateOptions(options)); + }, + move: function(element, parent, after, options) { + parent = parent && jqLite(parent); + after = after && jqLite(after); + parent = parent || after.parent(); + domInsert(element, parent, after); + return $$animateQueue.push(element, "move", prepareAnimateOptions(options)); + }, + leave: function(element, options) { + return $$animateQueue.push(element, "leave", prepareAnimateOptions(options), function() { + element.remove(); + }); + }, + addClass: function(element, className, options) { + options = prepareAnimateOptions(options); + options.addClass = mergeClasses(options.addclass, className); + return $$animateQueue.push(element, "addClass", options); + }, + removeClass: function(element, className, options) { + options = prepareAnimateOptions(options); + options.removeClass = mergeClasses(options.removeClass, className); + return $$animateQueue.push(element, "removeClass", options); + }, + setClass: function(element, add, remove, options) { + options = prepareAnimateOptions(options); + options.addClass = mergeClasses(options.addClass, add); + options.removeClass = mergeClasses(options.removeClass, remove); + return $$animateQueue.push(element, "setClass", options); + }, + animate: function(element, from, to, className, options) { + options = prepareAnimateOptions(options); + options.from = options.from ? extend(options.from, from) : from; + options.to = options.to ? extend(options.to, to) : to; + className = className || "ng-inline-animate"; + options.tempClasses = mergeClasses(options.tempClasses, className); + return $$animateQueue.push(element, "animate", options); + } }; - } - } - function isLiteral(ast) { - return ast.body.length === 0 || ast.body.length === 1 && (ast.body[0].expression.type === AST.Literal || ast.body[0].expression.type === AST.ArrayExpression || ast.body[0].expression.type === AST.ObjectExpression); - } - function isConstant(ast) { - return ast.constant; - } - function ASTCompiler(astBuilder, $filter) { - this.astBuilder = astBuilder; - this.$filter = $filter; - } - ASTCompiler.prototype = { - compile: function(expression, expensiveChecks) { - var self = this; - var ast = this.astBuilder.ast(expression); - this.state = { - nextId: 0, - filters: {}, - expensiveChecks: expensiveChecks, - fn: { - vars: [], - body: [], - own: {} + } ]; + } ]; + var $CoreAnimateCssProvider = function() { + this.$get = [ "$$rAF", "$q", function($$rAF, $q) { + var RAFPromise = function() {}; + RAFPromise.prototype = { + done: function(cancel) { + this.defer && this.defer[cancel === true ? "reject" : "resolve"](); }, - assign: { - vars: [], - body: [], - own: {} + end: function() { + this.done(); }, - inputs: [] + cancel: function() { + this.done(true); + }, + getPromise: function() { + if (!this.defer) { + this.defer = $q.defer(); + } + return this.defer.promise; + }, + then: function(f1, f2) { + return this.getPromise().then(f1, f2); + }, + "catch": function(f1) { + return this.getPromise()["catch"](f1); + }, + "finally": function(f1) { + return this.getPromise()["finally"](f1); + } }; - findConstantAndWatchExpressions(ast, self.$filter); - var extra = ""; - var assignable; - this.stage = "assign"; - if (assignable = assignableAST(ast)) { - this.state.computing = "assign"; - var result = this.nextId(); - this.recurse(assignable, result); - this.return_(result); - extra = "fn.assign=" + this.generateFunction("assign", "s,v,l"); - } - var toWatch = getInputs(ast.body); - self.stage = "inputs"; - forEach(toWatch, function(watch, key) { - var fnKey = "fn" + key; - self.state[fnKey] = { - vars: [], - body: [], - own: {} + return function(element, options) { + if (options.cleanupStyles) { + options.from = options.to = null; + } + if (options.from) { + element.css(options.from); + options.from = null; + } + var closed, runner = new RAFPromise(); + return { + start: run, + end: run }; - self.state.computing = fnKey; - var intoId = self.nextId(); - self.recurse(watch, intoId); - self.return_(intoId); - self.state.inputs.push(fnKey); - watch.watchId = key; - }); - this.state.computing = "fn"; - this.stage = "main"; - this.recurse(ast); - var fnString = '"' + this.USE + " " + this.STRICT + '";\n' + this.filterPrefix() + "var fn=" + this.generateFunction("fn", "s,l,a,i") + extra + this.watchFns() + "return fn;"; - var fn = new Function("$filter", "ensureSafeMemberName", "ensureSafeObject", "ensureSafeFunction", "ifDefined", "plus", "text", fnString)(this.$filter, ensureSafeMemberName, ensureSafeObject, ensureSafeFunction, ifDefined, plusFn, expression); - this.state = this.stage = undefined; - fn.literal = isLiteral(ast); - fn.constant = isConstant(ast); - return fn; - }, - USE: "use", - STRICT: "strict", - watchFns: function() { - var result = []; - var fns = this.state.inputs; - var self = this; - forEach(fns, function(name) { - result.push("var " + name + "=" + self.generateFunction(name, "s")); - }); - if (fns.length) { - result.push("fn.inputs=[" + fns.join(",") + "];"); - } - return result.join(""); - }, - generateFunction: function(name, params) { - return "function(" + params + "){" + this.varsPrefix(name) + this.body(name) + "};"; - }, - filterPrefix: function() { - var parts = []; - var self = this; - forEach(this.state.filters, function(id, filter) { - parts.push(id + "=$filter(" + self.escape(filter) + ")"); - }); - if (parts.length) return "var " + parts.join(",") + ";"; - return ""; - }, - varsPrefix: function(section) { - return this.state[section].vars.length ? "var " + this.state[section].vars.join(",") + ";" : ""; - }, - body: function(section) { - return this.state[section].body.join(""); - }, - recurse: function(ast, intoId, nameId, recursionFn, create, skipWatchIdCheck) { - var left, right, self = this, args, expression; - recursionFn = recursionFn || noop; - if (!skipWatchIdCheck && isDefined(ast.watchId)) { - intoId = intoId || this.nextId(); - this.if_("i", this.lazyAssign(intoId, this.computedMember("i", ast.watchId)), this.lazyRecurse(ast, intoId, nameId, recursionFn, create, true)); - return; - } - switch (ast.type) { - case AST.Program: - forEach(ast.body, function(expression, pos) { - self.recurse(expression.expression, undefined, undefined, function(expr) { - right = expr; + function run() { + $$rAF(function() { + close(); + if (!closed) { + runner.done(); + } + closed = true; }); - if (pos !== ast.body.length - 1) { - self.current().body.push(right, ";"); - } else { - self.return_(right); + return runner; + } + function close() { + if (options.addClass) { + element.addClass(options.addClass); + options.addClass = null; + } + if (options.removeClass) { + element.removeClass(options.removeClass); + options.removeClass = null; + } + if (options.to) { + element.css(options.to); + options.to = null; } - }); - break; - - case AST.Literal: - expression = this.escape(ast.value); - this.assign(intoId, expression); - recursionFn(expression); - break; - - case AST.UnaryExpression: - this.recurse(ast.argument, undefined, undefined, function(expr) { - right = expr; - }); - expression = ast.operator + "(" + this.ifDefined(right, 0) + ")"; - this.assign(intoId, expression); - recursionFn(expression); - break; - - case AST.BinaryExpression: - this.recurse(ast.left, undefined, undefined, function(expr) { - left = expr; - }); - this.recurse(ast.right, undefined, undefined, function(expr) { - right = expr; - }); - if (ast.operator === "+") { - expression = this.plus(left, right); - } else if (ast.operator === "-") { - expression = this.ifDefined(left, 0) + ast.operator + this.ifDefined(right, 0); - } else { - expression = "(" + left + ")" + ast.operator + "(" + right + ")"; - } - this.assign(intoId, expression); - recursionFn(expression); - break; - - case AST.LogicalExpression: - intoId = intoId || this.nextId(); - self.recurse(ast.left, intoId); - self.if_(ast.operator === "&&" ? intoId : self.not(intoId), self.lazyRecurse(ast.right, intoId)); - recursionFn(intoId); - break; - - case AST.ConditionalExpression: - intoId = intoId || this.nextId(); - self.recurse(ast.test, intoId); - self.if_(intoId, self.lazyRecurse(ast.alternate, intoId), self.lazyRecurse(ast.consequent, intoId)); - recursionFn(intoId); - break; - - case AST.Identifier: - intoId = intoId || this.nextId(); - if (nameId) { - nameId.context = self.stage === "inputs" ? "s" : this.assign(this.nextId(), this.getHasOwnProperty("l", ast.name) + "?l:s"); - nameId.computed = false; - nameId.name = ast.name; - } - ensureSafeMemberName(ast.name); - self.if_(self.stage === "inputs" || self.not(self.getHasOwnProperty("l", ast.name)), function() { - self.if_(self.stage === "inputs" || "s", function() { - if (create && create !== 1) { - self.if_(self.not(self.nonComputedMember("s", ast.name)), self.lazyAssign(self.nonComputedMember("s", ast.name), "{}")); - } - self.assign(intoId, self.nonComputedMember("s", ast.name)); - }); - }, intoId && self.lazyAssign(intoId, self.nonComputedMember("l", ast.name))); - if (self.state.expensiveChecks || isPossiblyDangerousMemberName(ast.name)) { - self.addEnsureSafeObject(intoId); } - recursionFn(intoId); - break; - - case AST.MemberExpression: - left = nameId && (nameId.context = this.nextId()) || this.nextId(); - intoId = intoId || this.nextId(); - self.recurse(ast.object, left, undefined, function() { - self.if_(self.notNull(left), function() { - if (ast.computed) { - right = self.nextId(); - self.recurse(ast.property, right); - self.addEnsureSafeMemberName(right); - if (create && create !== 1) { - self.if_(self.not(self.computedMember(left, right)), self.lazyAssign(self.computedMember(left, right), "{}")); - } - expression = self.ensureSafeObject(self.computedMember(left, right)); - self.assign(intoId, expression); - if (nameId) { - nameId.computed = true; - nameId.name = right; - } - } else { - ensureSafeMemberName(ast.property.name); - if (create && create !== 1) { - self.if_(self.not(self.nonComputedMember(left, ast.property.name)), self.lazyAssign(self.nonComputedMember(left, ast.property.name), "{}")); - } - expression = self.nonComputedMember(left, ast.property.name); - if (self.state.expensiveChecks || isPossiblyDangerousMemberName(ast.property.name)) { - expression = self.ensureSafeObject(expression); - } - self.assign(intoId, expression); - if (nameId) { - nameId.computed = false; - nameId.name = ast.property.name; - } + }; + } ]; + }; + function Browser(window, document, $log, $sniffer) { + var self = this, rawDocument = document[0], location = window.location, history = window.history, setTimeout = window.setTimeout, clearTimeout = window.clearTimeout, pendingDeferIds = {}; + self.isMock = false; + var outstandingRequestCount = 0; + var outstandingRequestCallbacks = []; + self.$$completeOutstandingRequest = completeOutstandingRequest; + self.$$incOutstandingRequestCount = function() { + outstandingRequestCount++; + }; + function completeOutstandingRequest(fn) { + try { + fn.apply(null, sliceArgs(arguments, 1)); + } finally { + outstandingRequestCount--; + if (outstandingRequestCount === 0) { + while (outstandingRequestCallbacks.length) { + try { + outstandingRequestCallbacks.pop()(); + } catch (e) { + $log.error(e); } - }, function() { - self.assign(intoId, "undefined"); - }); - recursionFn(intoId); - }, !!create); - break; - - case AST.CallExpression: - intoId = intoId || this.nextId(); - if (ast.filter) { - right = self.filter(ast.callee.name); - args = []; - forEach(ast.arguments, function(expr) { - var argument = self.nextId(); - self.recurse(expr, argument); - args.push(argument); - }); - expression = right + "(" + args.join(",") + ")"; - self.assign(intoId, expression); - recursionFn(intoId); - } else { - right = self.nextId(); - left = {}; - args = []; - self.recurse(ast.callee, right, left, function() { - self.if_(self.notNull(right), function() { - self.addEnsureSafeFunction(right); - forEach(ast.arguments, function(expr) { - self.recurse(expr, self.nextId(), undefined, function(argument) { - args.push(self.ensureSafeObject(argument)); - }); - }); - if (left.name) { - if (!self.state.expensiveChecks) { - self.addEnsureSafeObject(left.context); - } - expression = self.member(left.context, left.name, left.computed) + "(" + args.join(",") + ")"; - } else { - expression = right + "(" + args.join(",") + ")"; - } - expression = self.ensureSafeObject(expression); - self.assign(intoId, expression); - }, function() { - self.assign(intoId, "undefined"); - }); - recursionFn(intoId); - }); - } - break; - - case AST.AssignmentExpression: - right = this.nextId(); - left = {}; - if (!isAssignable(ast.left)) { - throw $parseMinErr("lval", "Trying to assing a value to a non l-value"); + } } - this.recurse(ast.left, undefined, left, function() { - self.if_(self.notNull(left.context), function() { - self.recurse(ast.right, right); - self.addEnsureSafeObject(self.member(left.context, left.name, left.computed)); - expression = self.member(left.context, left.name, left.computed) + ast.operator + right; - self.assign(intoId, expression); - recursionFn(intoId || expression); - }); - }, 1); - break; - - case AST.ArrayExpression: - args = []; - forEach(ast.elements, function(expr) { - self.recurse(expr, self.nextId(), undefined, function(argument) { - args.push(argument); - }); - }); - expression = "[" + args.join(",") + "]"; - this.assign(intoId, expression); - recursionFn(expression); - break; - - case AST.ObjectExpression: - args = []; - forEach(ast.properties, function(property) { - self.recurse(property.value, self.nextId(), undefined, function(expr) { - args.push(self.escape(property.key.type === AST.Identifier ? property.key.name : "" + property.key.value) + ":" + expr); - }); - }); - expression = "{" + args.join(",") + "}"; - this.assign(intoId, expression); - recursionFn(expression); - break; - - case AST.ThisExpression: - this.assign(intoId, "s"); - recursionFn("s"); - break; - - case AST.NGValueParameter: - this.assign(intoId, "v"); - recursionFn("v"); - break; } - }, - getHasOwnProperty: function(element, property) { - var key = element + "." + property; - var own = this.current().own; - if (!own.hasOwnProperty(key)) { - own[key] = this.nextId(false, element + "&&(" + this.escape(property) + " in " + element + ")"); + } + function getHash(url) { + var index = url.indexOf("#"); + return index === -1 ? "" : url.substr(index); + } + self.notifyWhenNoOutstandingRequests = function(callback) { + if (outstandingRequestCount === 0) { + callback(); + } else { + outstandingRequestCallbacks.push(callback); } - return own[key]; - }, - assign: function(id, value) { - if (!id) return; - this.current().body.push(id, "=", value, ";"); - return id; - }, - filter: function(filterName) { - if (!this.state.filters.hasOwnProperty(filterName)) { - this.state.filters[filterName] = this.nextId(true); + }; + var cachedState, lastHistoryState, lastBrowserUrl = location.href, baseElement = document.find("base"), pendingLocation = null; + cacheState(); + lastHistoryState = cachedState; + self.url = function(url, replace, state) { + if (isUndefined(state)) { + state = null; } - return this.state.filters[filterName]; - }, - ifDefined: function(id, defaultValue) { - return "ifDefined(" + id + "," + this.escape(defaultValue) + ")"; - }, - plus: function(left, right) { - return "plus(" + left + "," + right + ")"; - }, - return_: function(id) { - this.current().body.push("return ", id, ";"); - }, - if_: function(test, alternate, consequent) { - if (test === true) { - alternate(); - } else { - var body = this.current().body; - body.push("if(", test, "){"); - alternate(); - body.push("}"); - if (consequent) { - body.push("else{"); - consequent(); - body.push("}"); + if (location !== window.location) location = window.location; + if (history !== window.history) history = window.history; + if (url) { + var sameState = lastHistoryState === state; + if (lastBrowserUrl === url && (!$sniffer.history || sameState)) { + return self; } + var sameBase = lastBrowserUrl && stripHash(lastBrowserUrl) === stripHash(url); + lastBrowserUrl = url; + lastHistoryState = state; + if ($sniffer.history && (!sameBase || !sameState)) { + history[replace ? "replaceState" : "pushState"](state, "", url); + cacheState(); + lastHistoryState = cachedState; + } else { + if (!sameBase || pendingLocation) { + pendingLocation = url; + } + if (replace) { + location.replace(url); + } else if (!sameBase) { + location.href = url; + } else { + location.hash = getHash(url); + } + if (location.href !== url) { + pendingLocation = url; + } + } + return self; + } else { + return pendingLocation || location.href.replace(/%27/g, "'"); } - }, - not: function(expression) { - return "!(" + expression + ")"; - }, - notNull: function(expression) { - return expression + "!=null"; - }, - nonComputedMember: function(left, right) { - return left + "." + right; - }, - computedMember: function(left, right) { - return left + "[" + right + "]"; - }, - member: function(left, right, computed) { - if (computed) return this.computedMember(left, right); - return this.nonComputedMember(left, right); - }, - addEnsureSafeObject: function(item) { - this.current().body.push(this.ensureSafeObject(item), ";"); - }, - addEnsureSafeMemberName: function(item) { - this.current().body.push(this.ensureSafeMemberName(item), ";"); - }, - addEnsureSafeFunction: function(item) { - this.current().body.push(this.ensureSafeFunction(item), ";"); - }, - ensureSafeObject: function(item) { - return "ensureSafeObject(" + item + ",text)"; - }, - ensureSafeMemberName: function(item) { - return "ensureSafeMemberName(" + item + ",text)"; - }, - ensureSafeFunction: function(item) { - return "ensureSafeFunction(" + item + ",text)"; - }, - lazyRecurse: function(ast, intoId, nameId, recursionFn, create, skipWatchIdCheck) { - var self = this; - return function() { - self.recurse(ast, intoId, nameId, recursionFn, create, skipWatchIdCheck); - }; - }, - lazyAssign: function(id, value) { - var self = this; - return function() { - self.assign(id, value); - }; - }, - stringEscapeRegex: /[^ a-zA-Z0-9]/g, - stringEscapeFn: function(c) { - return "\\u" + ("0000" + c.charCodeAt(0).toString(16)).slice(-4); - }, - escape: function(value) { - if (isString(value)) return "'" + value.replace(this.stringEscapeRegex, this.stringEscapeFn) + "'"; - if (isNumber(value)) return value.toString(); - if (value === true) return "true"; - if (value === false) return "false"; - if (value === null) return "null"; - if (typeof value === "undefined") return "undefined"; - throw $parseMinErr("esc", "IMPOSSIBLE"); - }, - nextId: function(skip, init) { - var id = "v" + this.state.nextId++; - if (!skip) { - this.current().vars.push(id + (init ? "=" + init : "")); - } - return id; - }, - current: function() { - return this.state[this.state.computing]; + }; + self.state = function() { + return cachedState; + }; + var urlChangeListeners = [], urlChangeInit = false; + function cacheStateAndFireUrlChange() { + pendingLocation = null; + cacheState(); + fireUrlChange(); } - }; - function ASTInterpreter(astBuilder, $filter) { - this.astBuilder = astBuilder; - this.$filter = $filter; - } - ASTInterpreter.prototype = { - compile: function(expression, expensiveChecks) { - var self = this; - var ast = this.astBuilder.ast(expression); - this.expression = expression; - this.expensiveChecks = expensiveChecks; - findConstantAndWatchExpressions(ast, self.$filter); - var assignable; - var assign; - if (assignable = assignableAST(ast)) { - assign = this.recurse(assignable); + function getCurrentState() { + try { + return history.state; + } catch (e) {} + } + var lastCachedState = null; + function cacheState() { + cachedState = getCurrentState(); + cachedState = isUndefined(cachedState) ? null : cachedState; + if (equals(cachedState, lastCachedState)) { + cachedState = lastCachedState; } - var toWatch = getInputs(ast.body); - var inputs; - if (toWatch) { - inputs = []; - forEach(toWatch, function(watch, key) { - var input = self.recurse(watch); - watch.input = input; - inputs.push(input); - watch.watchId = key; - }); + lastCachedState = cachedState; + } + function fireUrlChange() { + if (lastBrowserUrl === self.url() && lastHistoryState === cachedState) { + return; } - var expressions = []; - forEach(ast.body, function(expression) { - expressions.push(self.recurse(expression.expression)); + lastBrowserUrl = self.url(); + lastHistoryState = cachedState; + forEach(urlChangeListeners, function(listener) { + listener(self.url(), cachedState); }); - var fn = ast.body.length === 0 ? function() {} : ast.body.length === 1 ? expressions[0] : function(scope, locals) { - var lastValue; - forEach(expressions, function(exp) { - lastValue = exp(scope, locals); - }); - return lastValue; - }; - if (assign) { - fn.assign = function(scope, value, locals) { - return assign(scope, locals, value); - }; - } - if (inputs) { - fn.inputs = inputs; + } + self.onUrlChange = function(callback) { + if (!urlChangeInit) { + if ($sniffer.history) jqLite(window).on("popstate", cacheStateAndFireUrlChange); + jqLite(window).on("hashchange", cacheStateAndFireUrlChange); + urlChangeInit = true; } - fn.literal = isLiteral(ast); - fn.constant = isConstant(ast); - return fn; - }, - recurse: function(ast, context, create) { - var left, right, self = this, args, expression; - if (ast.input) { - return this.inputs(ast.input, ast.watchId); + urlChangeListeners.push(callback); + return callback; + }; + self.$$applicationDestroyed = function() { + jqLite(window).off("hashchange popstate", cacheStateAndFireUrlChange); + }; + self.$$checkUrlChange = fireUrlChange; + self.baseHref = function() { + var href = baseElement.attr("href"); + return href ? href.replace(/^(https?\:)?\/\/[^\/]*/, "") : ""; + }; + self.defer = function(fn, delay) { + var timeoutId; + outstandingRequestCount++; + timeoutId = setTimeout(function() { + delete pendingDeferIds[timeoutId]; + completeOutstandingRequest(fn); + }, delay || 0); + pendingDeferIds[timeoutId] = true; + return timeoutId; + }; + self.defer.cancel = function(deferId) { + if (pendingDeferIds[deferId]) { + delete pendingDeferIds[deferId]; + clearTimeout(deferId); + completeOutstandingRequest(noop); + return true; } - switch (ast.type) { - case AST.Literal: - return this.value(ast.value, context); - - case AST.UnaryExpression: - right = this.recurse(ast.argument); - return this["unary" + ast.operator](right, context); - - case AST.BinaryExpression: - left = this.recurse(ast.left); - right = this.recurse(ast.right); - return this["binary" + ast.operator](left, right, context); - - case AST.LogicalExpression: - left = this.recurse(ast.left); - right = this.recurse(ast.right); - return this["binary" + ast.operator](left, right, context); - - case AST.ConditionalExpression: - return this["ternary?:"](this.recurse(ast.test), this.recurse(ast.alternate), this.recurse(ast.consequent), context); - - case AST.Identifier: - ensureSafeMemberName(ast.name, self.expression); - return self.identifier(ast.name, self.expensiveChecks || isPossiblyDangerousMemberName(ast.name), context, create, self.expression); - - case AST.MemberExpression: - left = this.recurse(ast.object, false, !!create); - if (!ast.computed) { - ensureSafeMemberName(ast.property.name, self.expression); - right = ast.property.name; + return false; + }; + } + function $BrowserProvider() { + this.$get = [ "$window", "$log", "$sniffer", "$document", function($window, $log, $sniffer, $document) { + return new Browser($window, $document, $log, $sniffer); + } ]; + } + function $CacheFactoryProvider() { + this.$get = function() { + var caches = {}; + function cacheFactory(cacheId, options) { + if (cacheId in caches) { + throw minErr("$cacheFactory")("iid", "CacheId '{0}' is already taken!", cacheId); } - if (ast.computed) right = this.recurse(ast.property); - return ast.computed ? this.computedMember(left, right, context, create, self.expression) : this.nonComputedMember(left, right, self.expensiveChecks, context, create, self.expression); - - case AST.CallExpression: - args = []; - forEach(ast.arguments, function(expr) { - args.push(self.recurse(expr)); - }); - if (ast.filter) right = this.$filter(ast.callee.name); - if (!ast.filter) right = this.recurse(ast.callee, true); - return ast.filter ? function(scope, locals, assign, inputs) { - var values = []; - for (var i = 0; i < args.length; ++i) { - values.push(args[i](scope, locals, assign, inputs)); - } - var value = right.apply(undefined, values, inputs); - return context ? { - context: undefined, - name: undefined, - value: value - } : value; - } : function(scope, locals, assign, inputs) { - var rhs = right(scope, locals, assign, inputs); - var value; - if (rhs.value != null) { - ensureSafeObject(rhs.context, self.expression); - ensureSafeFunction(rhs.value, self.expression); - var values = []; - for (var i = 0; i < args.length; ++i) { - values.push(ensureSafeObject(args[i](scope, locals, assign, inputs), self.expression)); + var size = 0, stats = extend({}, options, { + id: cacheId + }), data = {}, capacity = options && options.capacity || Number.MAX_VALUE, lruHash = {}, freshEnd = null, staleEnd = null; + return caches[cacheId] = { + put: function(key, value) { + if (isUndefined(value)) return; + if (capacity < Number.MAX_VALUE) { + var lruEntry = lruHash[key] || (lruHash[key] = { + key: key + }); + refresh(lruEntry); } - value = ensureSafeObject(rhs.value.apply(rhs.context, values), self.expression); + if (!(key in data)) size++; + data[key] = value; + if (size > capacity) { + this.remove(staleEnd.key); + } + return value; + }, + get: function(key) { + if (capacity < Number.MAX_VALUE) { + var lruEntry = lruHash[key]; + if (!lruEntry) return; + refresh(lruEntry); + } + return data[key]; + }, + remove: function(key) { + if (capacity < Number.MAX_VALUE) { + var lruEntry = lruHash[key]; + if (!lruEntry) return; + if (lruEntry == freshEnd) freshEnd = lruEntry.p; + if (lruEntry == staleEnd) staleEnd = lruEntry.n; + link(lruEntry.n, lruEntry.p); + delete lruHash[key]; + } + delete data[key]; + size--; + }, + removeAll: function() { + data = {}; + size = 0; + lruHash = {}; + freshEnd = staleEnd = null; + }, + destroy: function() { + data = null; + stats = null; + lruHash = null; + delete caches[cacheId]; + }, + info: function() { + return extend({}, stats, { + size: size + }); } - return context ? { - value: value - } : value; - }; - - case AST.AssignmentExpression: - left = this.recurse(ast.left, true, 1); - right = this.recurse(ast.right); - return function(scope, locals, assign, inputs) { - var lhs = left(scope, locals, assign, inputs); - var rhs = right(scope, locals, assign, inputs); - ensureSafeObject(lhs.value, self.expression); - lhs.context[lhs.name] = rhs; - return context ? { - value: rhs - } : rhs; }; - - case AST.ArrayExpression: - args = []; - forEach(ast.elements, function(expr) { - args.push(self.recurse(expr)); - }); - return function(scope, locals, assign, inputs) { - var value = []; - for (var i = 0; i < args.length; ++i) { - value.push(args[i](scope, locals, assign, inputs)); + function refresh(entry) { + if (entry != freshEnd) { + if (!staleEnd) { + staleEnd = entry; + } else if (staleEnd == entry) { + staleEnd = entry.n; + } + link(entry.n, entry.p); + link(entry, freshEnd); + freshEnd = entry; + freshEnd.n = null; } - return context ? { - value: value - } : value; - }; - - case AST.ObjectExpression: - args = []; - forEach(ast.properties, function(property) { - args.push({ - key: property.key.type === AST.Identifier ? property.key.name : "" + property.key.value, - value: self.recurse(property.value) - }); - }); - return function(scope, locals, assign, inputs) { - var value = {}; - for (var i = 0; i < args.length; ++i) { - value[args[i].key] = args[i].value(scope, locals, assign, inputs); + } + function link(nextEntry, prevEntry) { + if (nextEntry != prevEntry) { + if (nextEntry) nextEntry.p = prevEntry; + if (prevEntry) prevEntry.n = nextEntry; } - return context ? { - value: value - } : value; - }; - - case AST.ThisExpression: - return function(scope) { - return context ? { - value: scope - } : scope; - }; - - case AST.NGValueParameter: - return function(scope, locals, assign, inputs) { - return context ? { - value: assign - } : assign; - }; + } } - }, - "unary+": function(argument, context) { - return function(scope, locals, assign, inputs) { - var arg = argument(scope, locals, assign, inputs); - if (isDefined(arg)) { - arg = +arg; - } else { - arg = 0; + cacheFactory.info = function() { + var info = {}; + forEach(caches, function(cache, cacheId) { + info[cacheId] = cache.info(); + }); + return info; + }; + cacheFactory.get = function(cacheId) { + return caches[cacheId]; + }; + return cacheFactory; + }; + } + function $TemplateCacheProvider() { + this.$get = [ "$cacheFactory", function($cacheFactory) { + return $cacheFactory("templates"); + } ]; + } + var $compileMinErr = minErr("$compile"); + $CompileProvider.$inject = [ "$provide", "$$sanitizeUriProvider" ]; + function $CompileProvider($provide, $$sanitizeUriProvider) { + var hasDirectives = {}, Suffix = "Directive", COMMENT_DIRECTIVE_REGEXP = /^\s*directive\:\s*([\w\-]+)\s+(.*)$/, CLASS_DIRECTIVE_REGEXP = /(([\w\-]+)(?:\:([^;]+))?;?)/, ALL_OR_NOTHING_ATTRS = makeMap("ngSrc,ngSrcset,src,srcset"), REQUIRE_PREFIX_REGEXP = /^(?:(\^\^?)?(\?)?(\^\^?)?)?/; + var EVENT_HANDLER_ATTR_REGEXP = /^(on[a-z]+|formaction)$/; + function parseIsolateBindings(scope, directiveName, isController) { + var LOCAL_REGEXP = /^\s*([@&]|=(\*?))(\??)\s*(\w*)\s*$/; + var bindings = {}; + forEach(scope, function(definition, scopeName) { + var match = definition.match(LOCAL_REGEXP); + if (!match) { + throw $compileMinErr("iscp", "Invalid {3} for directive '{0}'." + " Definition: {... {1}: '{2}' ...}", directiveName, scopeName, definition, isController ? "controller bindings definition" : "isolate scope definition"); } - return context ? { - value: arg - } : arg; + bindings[scopeName] = { + mode: match[1][0], + collection: match[2] === "*", + optional: match[3] === "?", + attrName: match[4] || scopeName + }; + }); + return bindings; + } + function parseDirectiveBindings(directive, directiveName) { + var bindings = { + isolateScope: null, + bindToController: null }; - }, - "unary-": function(argument, context) { - return function(scope, locals, assign, inputs) { - var arg = argument(scope, locals, assign, inputs); - if (isDefined(arg)) { - arg = -arg; + if (isObject(directive.scope)) { + if (directive.bindToController === true) { + bindings.bindToController = parseIsolateBindings(directive.scope, directiveName, true); + bindings.isolateScope = {}; } else { - arg = 0; + bindings.isolateScope = parseIsolateBindings(directive.scope, directiveName, false); } - return context ? { - value: arg - } : arg; - }; - }, - "unary!": function(argument, context) { - return function(scope, locals, assign, inputs) { - var arg = !argument(scope, locals, assign, inputs); - return context ? { - value: arg - } : arg; - }; - }, - "binary+": function(left, right, context) { - return function(scope, locals, assign, inputs) { - var lhs = left(scope, locals, assign, inputs); - var rhs = right(scope, locals, assign, inputs); - var arg = plusFn(lhs, rhs); - return context ? { - value: arg - } : arg; - }; - }, - "binary-": function(left, right, context) { - return function(scope, locals, assign, inputs) { - var lhs = left(scope, locals, assign, inputs); - var rhs = right(scope, locals, assign, inputs); - var arg = (isDefined(lhs) ? lhs : 0) - (isDefined(rhs) ? rhs : 0); - return context ? { - value: arg - } : arg; - }; - }, - "binary*": function(left, right, context) { - return function(scope, locals, assign, inputs) { - var arg = left(scope, locals, assign, inputs) * right(scope, locals, assign, inputs); - return context ? { - value: arg - } : arg; - }; - }, - "binary/": function(left, right, context) { - return function(scope, locals, assign, inputs) { - var arg = left(scope, locals, assign, inputs) / right(scope, locals, assign, inputs); - return context ? { - value: arg - } : arg; - }; - }, - "binary%": function(left, right, context) { - return function(scope, locals, assign, inputs) { - var arg = left(scope, locals, assign, inputs) % right(scope, locals, assign, inputs); - return context ? { - value: arg - } : arg; - }; - }, - "binary===": function(left, right, context) { - return function(scope, locals, assign, inputs) { - var arg = left(scope, locals, assign, inputs) === right(scope, locals, assign, inputs); - return context ? { - value: arg - } : arg; - }; - }, - "binary!==": function(left, right, context) { - return function(scope, locals, assign, inputs) { - var arg = left(scope, locals, assign, inputs) !== right(scope, locals, assign, inputs); - return context ? { - value: arg - } : arg; - }; - }, - "binary==": function(left, right, context) { - return function(scope, locals, assign, inputs) { - var arg = left(scope, locals, assign, inputs) == right(scope, locals, assign, inputs); - return context ? { - value: arg - } : arg; - }; - }, - "binary!=": function(left, right, context) { - return function(scope, locals, assign, inputs) { - var arg = left(scope, locals, assign, inputs) != right(scope, locals, assign, inputs); - return context ? { - value: arg - } : arg; - }; - }, - "binary<": function(left, right, context) { - return function(scope, locals, assign, inputs) { - var arg = left(scope, locals, assign, inputs) < right(scope, locals, assign, inputs); - return context ? { - value: arg - } : arg; - }; - }, - "binary>": function(left, right, context) { - return function(scope, locals, assign, inputs) { - var arg = left(scope, locals, assign, inputs) > right(scope, locals, assign, inputs); - return context ? { - value: arg - } : arg; - }; - }, - "binary<=": function(left, right, context) { - return function(scope, locals, assign, inputs) { - var arg = left(scope, locals, assign, inputs) <= right(scope, locals, assign, inputs); - return context ? { - value: arg - } : arg; - }; - }, - "binary>=": function(left, right, context) { - return function(scope, locals, assign, inputs) { - var arg = left(scope, locals, assign, inputs) >= right(scope, locals, assign, inputs); - return context ? { - value: arg - } : arg; - }; - }, - "binary&&": function(left, right, context) { - return function(scope, locals, assign, inputs) { - var arg = left(scope, locals, assign, inputs) && right(scope, locals, assign, inputs); - return context ? { - value: arg - } : arg; - }; - }, - "binary||": function(left, right, context) { - return function(scope, locals, assign, inputs) { - var arg = left(scope, locals, assign, inputs) || right(scope, locals, assign, inputs); - return context ? { - value: arg - } : arg; - }; - }, - "ternary?:": function(test, alternate, consequent, context) { - return function(scope, locals, assign, inputs) { - var arg = test(scope, locals, assign, inputs) ? alternate(scope, locals, assign, inputs) : consequent(scope, locals, assign, inputs); - return context ? { - value: arg - } : arg; - }; - }, - value: function(value, context) { - return function() { - return context ? { - context: undefined, - name: undefined, - value: value - } : value; - }; - }, - identifier: function(name, expensiveChecks, context, create, expression) { - return function(scope, locals, assign, inputs) { - var base = locals && name in locals ? locals : scope; - if (create && create !== 1 && base && !base[name]) { - base[name] = {}; - } - var value = base ? base[name] : undefined; - if (expensiveChecks) { - ensureSafeObject(value, expression); - } - if (context) { - return { - context: base, - name: name, - value: value - }; - } else { - return value; - } - }; - }, - computedMember: function(left, right, context, create, expression) { - return function(scope, locals, assign, inputs) { - var lhs = left(scope, locals, assign, inputs); - var rhs; - var value; - if (lhs != null) { - rhs = right(scope, locals, assign, inputs); - ensureSafeMemberName(rhs, expression); - if (create && create !== 1 && lhs && !lhs[rhs]) { - lhs[rhs] = {}; - } - value = lhs[rhs]; - ensureSafeObject(value, expression); - } - if (context) { - return { - context: lhs, - name: rhs, - value: value - }; - } else { - return value; - } - }; - }, - nonComputedMember: function(left, right, expensiveChecks, context, create, expression) { - return function(scope, locals, assign, inputs) { - var lhs = left(scope, locals, assign, inputs); - if (create && create !== 1 && lhs && !lhs[right]) { - lhs[right] = {}; - } - var value = lhs != null ? lhs[right] : undefined; - if (expensiveChecks || isPossiblyDangerousMemberName(right)) { - ensureSafeObject(value, expression); - } - if (context) { - return { - context: lhs, - name: right, - value: value - }; - } else { - return value; + } + if (isObject(directive.bindToController)) { + bindings.bindToController = parseIsolateBindings(directive.bindToController, directiveName, true); + } + if (isObject(bindings.bindToController)) { + var controller = directive.controller; + var controllerAs = directive.controllerAs; + if (!controller) { + throw $compileMinErr("noctrl", "Cannot bind to controller without directive '{0}'s controller.", directiveName); + } else if (!identifierForController(controller, controllerAs)) { + throw $compileMinErr("noident", "Cannot bind to controller without identifier for directive '{0}'.", directiveName); } - }; - }, - inputs: function(input, watchId) { - return function(scope, value, locals, inputs) { - if (inputs) return inputs[watchId]; - return input(scope, value, locals); - }; + } + return bindings; } - }; - var Parser = function(lexer, $filter, options) { - this.lexer = lexer; - this.$filter = $filter; - this.options = options; - this.ast = new AST(this.lexer); - this.astCompiler = options.csp ? new ASTInterpreter(this.ast, $filter) : new ASTCompiler(this.ast, $filter); - }; - Parser.prototype = { - constructor: Parser, - parse: function(text) { - return this.astCompiler.compile(text, this.options.expensiveChecks); + function assertValidDirectiveName(name) { + var letter = name.charAt(0); + if (!letter || letter !== lowercase(letter)) { + throw $compileMinErr("baddir", "Directive name '{0}' is invalid. The first character must be a lowercase letter", name); + } + if (name !== name.trim()) { + throw $compileMinErr("baddir", "Directive name '{0}' is invalid. The name should not contain leading or trailing whitespaces", name); + } } - }; - var getterFnCacheDefault = createMap(); - var getterFnCacheExpensive = createMap(); - function isPossiblyDangerousMemberName(name) { - return name == "constructor"; - } - var objectValueOf = Object.prototype.valueOf; - function getValueOf(value) { - return isFunction(value.valueOf) ? value.valueOf() : objectValueOf.call(value); - } - function $ParseProvider() { - var cacheDefault = createMap(); - var cacheExpensive = createMap(); - this.$get = [ "$filter", function($filter) { - var noUnsafeEval = csp().noUnsafeEval; - var $parseOptions = { - csp: noUnsafeEval, - expensiveChecks: false - }, $parseOptionsExpensive = { - csp: noUnsafeEval, - expensiveChecks: true - }; - return function $parse(exp, interceptorFn, expensiveChecks) { - var parsedExpression, oneTime, cacheKey; - switch (typeof exp) { - case "string": - exp = exp.trim(); - cacheKey = exp; - var cache = expensiveChecks ? cacheExpensive : cacheDefault; - parsedExpression = cache[cacheKey]; - if (!parsedExpression) { - if (exp.charAt(0) === ":" && exp.charAt(1) === ":") { - oneTime = true; - exp = exp.substring(2); - } - var parseOptions = expensiveChecks ? $parseOptionsExpensive : $parseOptions; - var lexer = new Lexer(parseOptions); - var parser = new Parser(lexer, $filter, parseOptions); - parsedExpression = parser.parse(exp); - if (parsedExpression.constant) { - parsedExpression.$$watchDelegate = constantWatchDelegate; - } else if (oneTime) { - parsedExpression.$$watchDelegate = parsedExpression.literal ? oneTimeLiteralWatchDelegate : oneTimeWatchDelegate; - } else if (parsedExpression.inputs) { - parsedExpression.$$watchDelegate = inputsWatchDelegate; - } - cache[cacheKey] = parsedExpression; + this.directive = function registerDirective(name, directiveFactory) { + assertNotHasOwnProperty(name, "directive"); + if (isString(name)) { + assertValidDirectiveName(name); + assertArg(directiveFactory, "directiveFactory"); + if (!hasDirectives.hasOwnProperty(name)) { + hasDirectives[name] = []; + $provide.factory(name + Suffix, [ "$injector", "$exceptionHandler", function($injector, $exceptionHandler) { + var directives = []; + forEach(hasDirectives[name], function(directiveFactory, index) { + try { + var directive = $injector.invoke(directiveFactory); + if (isFunction(directive)) { + directive = { + compile: valueFn(directive) + }; + } else if (!directive.compile && directive.link) { + directive.compile = valueFn(directive.link); + } + directive.priority = directive.priority || 0; + directive.index = index; + directive.name = directive.name || name; + directive.require = directive.require || directive.controller && directive.name; + directive.restrict = directive.restrict || "EA"; + var bindings = directive.$$bindings = parseDirectiveBindings(directive, directive.name); + if (isObject(bindings.isolateScope)) { + directive.$$isolateBindings = bindings.isolateScope; + } + directive.$$moduleName = directiveFactory.$$moduleName; + directives.push(directive); + } catch (e) { + $exceptionHandler(e); + } + }); + return directives; + } ]); + } + hasDirectives[name].push(directiveFactory); + } else { + forEach(name, reverseParams(registerDirective)); + } + return this; + }; + this.aHrefSanitizationWhitelist = function(regexp) { + if (isDefined(regexp)) { + $$sanitizeUriProvider.aHrefSanitizationWhitelist(regexp); + return this; + } else { + return $$sanitizeUriProvider.aHrefSanitizationWhitelist(); + } + }; + this.imgSrcSanitizationWhitelist = function(regexp) { + if (isDefined(regexp)) { + $$sanitizeUriProvider.imgSrcSanitizationWhitelist(regexp); + return this; + } else { + return $$sanitizeUriProvider.imgSrcSanitizationWhitelist(); + } + }; + var debugInfoEnabled = true; + this.debugInfoEnabled = function(enabled) { + if (isDefined(enabled)) { + debugInfoEnabled = enabled; + return this; + } + return debugInfoEnabled; + }; + this.$get = [ "$injector", "$interpolate", "$exceptionHandler", "$templateRequest", "$parse", "$controller", "$rootScope", "$document", "$sce", "$animate", "$$sanitizeUri", function($injector, $interpolate, $exceptionHandler, $templateRequest, $parse, $controller, $rootScope, $document, $sce, $animate, $$sanitizeUri) { + var Attributes = function(element, attributesToCopy) { + if (attributesToCopy) { + var keys = Object.keys(attributesToCopy); + var i, l, key; + for (i = 0, l = keys.length; i < l; i++) { + key = keys[i]; + this[key] = attributesToCopy[key]; } - return addInterceptor(parsedExpression, interceptorFn); - - case "function": - return addInterceptor(exp, interceptorFn); - - default: - return noop; + } else { + this.$attr = {}; } + this.$$element = element; }; - function expressionInputDirtyCheck(newValue, oldValueOfValue) { - if (newValue == null || oldValueOfValue == null) { - return newValue === oldValueOfValue; - } - if (typeof newValue === "object") { - newValue = getValueOf(newValue); - if (typeof newValue === "object") { - return false; + Attributes.prototype = { + $normalize: directiveNormalize, + $addClass: function(classVal) { + if (classVal && classVal.length > 0) { + $animate.addClass(this.$$element, classVal); } - } - return newValue === oldValueOfValue || newValue !== newValue && oldValueOfValue !== oldValueOfValue; - } - function inputsWatchDelegate(scope, listener, objectEquality, parsedExpression, prettyPrintExpression) { - var inputExpressions = parsedExpression.inputs; - var lastResult; - if (inputExpressions.length === 1) { - var oldInputValueOf = expressionInputDirtyCheck; - inputExpressions = inputExpressions[0]; - return scope.$watch(function expressionInputWatch(scope) { - var newInputValue = inputExpressions(scope); - if (!expressionInputDirtyCheck(newInputValue, oldInputValueOf)) { - lastResult = parsedExpression(scope, undefined, undefined, [ newInputValue ]); - oldInputValueOf = newInputValue && getValueOf(newInputValue); - } - return lastResult; - }, listener, objectEquality, prettyPrintExpression); - } - var oldInputValueOfValues = []; - var oldInputValues = []; - for (var i = 0, ii = inputExpressions.length; i < ii; i++) { - oldInputValueOfValues[i] = expressionInputDirtyCheck; - oldInputValues[i] = null; - } - return scope.$watch(function expressionInputsWatch(scope) { - var changed = false; - for (var i = 0, ii = inputExpressions.length; i < ii; i++) { - var newInputValue = inputExpressions[i](scope); - if (changed || (changed = !expressionInputDirtyCheck(newInputValue, oldInputValueOfValues[i]))) { - oldInputValues[i] = newInputValue; - oldInputValueOfValues[i] = newInputValue && getValueOf(newInputValue); - } + }, + $removeClass: function(classVal) { + if (classVal && classVal.length > 0) { + $animate.removeClass(this.$$element, classVal); } - if (changed) { - lastResult = parsedExpression(scope, undefined, undefined, oldInputValues); + }, + $updateClass: function(newClasses, oldClasses) { + var toAdd = tokenDifference(newClasses, oldClasses); + if (toAdd && toAdd.length) { + $animate.addClass(this.$$element, toAdd); } - return lastResult; - }, listener, objectEquality, prettyPrintExpression); - } - function oneTimeWatchDelegate(scope, listener, objectEquality, parsedExpression) { - var unwatch, lastValue; - return unwatch = scope.$watch(function oneTimeWatch(scope) { - return parsedExpression(scope); - }, function oneTimeListener(value, old, scope) { - lastValue = value; - if (isFunction(listener)) { - listener.apply(this, arguments); + var toRemove = tokenDifference(oldClasses, newClasses); + if (toRemove && toRemove.length) { + $animate.removeClass(this.$$element, toRemove); } - if (isDefined(value)) { - scope.$$postDigest(function() { - if (isDefined(lastValue)) { - unwatch(); - } - }); + }, + $set: function(key, value, writeAttr, attrName) { + var node = this.$$element[0], booleanKey = getBooleanAttrName(node, key), aliasedKey = getAliasedAttrName(key), observer = key, nodeName; + if (booleanKey) { + this.$$element.prop(key, value); + attrName = booleanKey; + } else if (aliasedKey) { + this[aliasedKey] = value; + observer = aliasedKey; } - }, objectEquality); - } - function oneTimeLiteralWatchDelegate(scope, listener, objectEquality, parsedExpression) { - var unwatch, lastValue; - return unwatch = scope.$watch(function oneTimeWatch(scope) { - return parsedExpression(scope); - }, function oneTimeListener(value, old, scope) { - lastValue = value; - if (isFunction(listener)) { - listener.call(this, value, old, scope); + this[key] = value; + if (attrName) { + this.$attr[key] = attrName; + } else { + attrName = this.$attr[key]; + if (!attrName) { + this.$attr[key] = attrName = snake_case(key, "-"); + } } - if (isAllDefined(value)) { - scope.$$postDigest(function() { - if (isAllDefined(lastValue)) unwatch(); - }); + nodeName = nodeName_(this.$$element); + if (nodeName === "a" && key === "href" || nodeName === "img" && key === "src") { + this[key] = value = $$sanitizeUri(value, key === "src"); + } else if (nodeName === "img" && key === "srcset") { + var result = ""; + var trimmedSrcset = trim(value); + var srcPattern = /(\s+\d+x\s*,|\s+\d+w\s*,|\s+,|,\s+)/; + var pattern = /\s/.test(trimmedSrcset) ? srcPattern : /(,)/; + var rawUris = trimmedSrcset.split(pattern); + var nbrUrisWith2parts = Math.floor(rawUris.length / 2); + for (var i = 0; i < nbrUrisWith2parts; i++) { + var innerIdx = i * 2; + result += $$sanitizeUri(trim(rawUris[innerIdx]), true); + result += " " + trim(rawUris[innerIdx + 1]); + } + var lastTuple = trim(rawUris[i * 2]).split(/\s/); + result += $$sanitizeUri(trim(lastTuple[0]), true); + if (lastTuple.length === 2) { + result += " " + trim(lastTuple[1]); + } + this[key] = value = result; } - }, objectEquality); - function isAllDefined(value) { - var allDefined = true; - forEach(value, function(val) { - if (!isDefined(val)) allDefined = false; + if (writeAttr !== false) { + if (value === null || isUndefined(value)) { + this.$$element.removeAttr(attrName); + } else { + this.$$element.attr(attrName, value); + } + } + var $$observers = this.$$observers; + $$observers && forEach($$observers[observer], function(fn) { + try { + fn(value); + } catch (e) { + $exceptionHandler(e); + } }); - return allDefined; + }, + $observe: function(key, fn) { + var attrs = this, $$observers = attrs.$$observers || (attrs.$$observers = createMap()), listeners = $$observers[key] || ($$observers[key] = []); + listeners.push(fn); + $rootScope.$evalAsync(function() { + if (!listeners.$$inter && attrs.hasOwnProperty(key) && !isUndefined(attrs[key])) { + fn(attrs[key]); + } + }); + return function() { + arrayRemove(listeners, fn); + }; } + }; + function safeAddClass($element, className) { + try { + $element.addClass(className); + } catch (e) {} } - function constantWatchDelegate(scope, listener, objectEquality, parsedExpression) { - var unwatch; - return unwatch = scope.$watch(function constantWatch(scope) { - return parsedExpression(scope); - }, function constantListener(value, old, scope) { - if (isFunction(listener)) { - listener.apply(this, arguments); - } - unwatch(); - }, objectEquality); - } - function addInterceptor(parsedExpression, interceptorFn) { - if (!interceptorFn) return parsedExpression; - var watchDelegate = parsedExpression.$$watchDelegate; - var regularWatch = watchDelegate !== oneTimeLiteralWatchDelegate && watchDelegate !== oneTimeWatchDelegate; - var fn = regularWatch ? function regularInterceptedExpression(scope, locals, assign, inputs) { - var value = parsedExpression(scope, locals, assign, inputs); - return interceptorFn(value, scope, locals); - } : function oneTimeInterceptedExpression(scope, locals, assign, inputs) { - var value = parsedExpression(scope, locals, assign, inputs); - var result = interceptorFn(value, scope, locals); - return isDefined(value) ? result : value; - }; - if (parsedExpression.$$watchDelegate && parsedExpression.$$watchDelegate !== inputsWatchDelegate) { - fn.$$watchDelegate = parsedExpression.$$watchDelegate; - } else if (!interceptorFn.$stateful) { - fn.$$watchDelegate = inputsWatchDelegate; - fn.inputs = parsedExpression.inputs ? parsedExpression.inputs : [ parsedExpression ]; + var startSymbol = $interpolate.startSymbol(), endSymbol = $interpolate.endSymbol(), denormalizeTemplate = startSymbol == "{{" || endSymbol == "}}" ? identity : function denormalizeTemplate(template) { + return template.replace(/\{\{/g, startSymbol).replace(/}}/g, endSymbol); + }, NG_ATTR_BINDING = /^ngAttr[A-Z]/; + compile.$$addBindingInfo = debugInfoEnabled ? function $$addBindingInfo($element, binding) { + var bindings = $element.data("$binding") || []; + if (isArray(binding)) { + bindings = bindings.concat(binding); + } else { + bindings.push(binding); } - return fn; - } - } ]; - } - function $QProvider() { - this.$get = [ "$rootScope", "$exceptionHandler", function($rootScope, $exceptionHandler) { - return qFactory(function(callback) { - $rootScope.$evalAsync(callback); - }, $exceptionHandler); - } ]; - } - function $$QProvider() { - this.$get = [ "$browser", "$exceptionHandler", function($browser, $exceptionHandler) { - return qFactory(function(callback) { - $browser.defer(callback); - }, $exceptionHandler); - } ]; - } - function qFactory(nextTick, exceptionHandler) { - var $qMinErr = minErr("$q", TypeError); - function callOnce(self, resolveFn, rejectFn) { - var called = false; - function wrap(fn) { - return function(value) { - if (called) return; - called = true; - fn.call(self, value); - }; - } - return [ wrap(resolveFn), wrap(rejectFn) ]; - } - var defer = function() { - return new Deferred(); - }; - function Promise() { - this.$$state = { - status: 0 - }; - } - extend(Promise.prototype, { - then: function(onFulfilled, onRejected, progressBack) { - if (isUndefined(onFulfilled) && isUndefined(onRejected) && isUndefined(progressBack)) { - return this; + $element.data("$binding", bindings); + } : noop; + compile.$$addBindingClass = debugInfoEnabled ? function $$addBindingClass($element) { + safeAddClass($element, "ng-binding"); + } : noop; + compile.$$addScopeInfo = debugInfoEnabled ? function $$addScopeInfo($element, scope, isolated, noTemplate) { + var dataName = isolated ? noTemplate ? "$isolateScopeNoTemplate" : "$isolateScope" : "$scope"; + $element.data(dataName, scope); + } : noop; + compile.$$addScopeClass = debugInfoEnabled ? function $$addScopeClass($element, isolated) { + safeAddClass($element, isolated ? "ng-isolate-scope" : "ng-scope"); + } : noop; + return compile; + function compile($compileNodes, transcludeFn, maxPriority, ignoreDirective, previousCompileContext) { + if (!($compileNodes instanceof jqLite)) { + $compileNodes = jqLite($compileNodes); } - var result = new Deferred(); - this.$$state.pending = this.$$state.pending || []; - this.$$state.pending.push([ result, onFulfilled, onRejected, progressBack ]); - if (this.$$state.status > 0) scheduleProcessQueue(this.$$state); - return result.promise; - }, - "catch": function(callback) { - return this.then(null, callback); - }, - "finally": function(callback, progressBack) { - return this.then(function(value) { - return handleCallback(value, true, callback); - }, function(error) { - return handleCallback(error, false, callback); - }, progressBack); - } - }); - function simpleBind(context, fn) { - return function(value) { - fn.call(context, value); - }; - } - function processQueue(state) { - var fn, deferred, pending; - pending = state.pending; - state.processScheduled = false; - state.pending = undefined; - for (var i = 0, ii = pending.length; i < ii; ++i) { - deferred = pending[i][0]; - fn = pending[i][state.status]; - try { - if (isFunction(fn)) { - deferred.resolve(fn(state.value)); - } else if (state.status === 1) { - deferred.resolve(state.value); + forEach($compileNodes, function(node, index) { + if (node.nodeType == NODE_TYPE_TEXT && node.nodeValue.match(/\S+/)) { + $compileNodes[index] = jqLite(node).wrap("").parent()[0]; + } + }); + var compositeLinkFn = compileNodes($compileNodes, transcludeFn, $compileNodes, maxPriority, ignoreDirective, previousCompileContext); + compile.$$addScopeClass($compileNodes); + var namespace = null; + return function publicLinkFn(scope, cloneConnectFn, options) { + assertArg(scope, "scope"); + options = options || {}; + var parentBoundTranscludeFn = options.parentBoundTranscludeFn, transcludeControllers = options.transcludeControllers, futureParentElement = options.futureParentElement; + if (parentBoundTranscludeFn && parentBoundTranscludeFn.$$boundTransclude) { + parentBoundTranscludeFn = parentBoundTranscludeFn.$$boundTransclude; + } + if (!namespace) { + namespace = detectNamespaceForChildElements(futureParentElement); + } + var $linkNode; + if (namespace !== "html") { + $linkNode = jqLite(wrapTemplate(namespace, jqLite("
        ").append($compileNodes).html())); + } else if (cloneConnectFn) { + $linkNode = JQLitePrototype.clone.call($compileNodes); } else { - deferred.reject(state.value); + $linkNode = $compileNodes; } - } catch (e) { - deferred.reject(e); - exceptionHandler(e); - } + if (transcludeControllers) { + for (var controllerName in transcludeControllers) { + $linkNode.data("$" + controllerName + "Controller", transcludeControllers[controllerName].instance); + } + } + compile.$$addScopeInfo($linkNode, scope); + if (cloneConnectFn) cloneConnectFn($linkNode, scope); + if (compositeLinkFn) compositeLinkFn(scope, $linkNode, $linkNode, parentBoundTranscludeFn); + return $linkNode; + }; } - } - function scheduleProcessQueue(state) { - if (state.processScheduled || !state.pending) return; - state.processScheduled = true; - nextTick(function() { - processQueue(state); - }); - } - function Deferred() { - this.promise = new Promise(); - this.resolve = simpleBind(this, this.resolve); - this.reject = simpleBind(this, this.reject); - this.notify = simpleBind(this, this.notify); - } - extend(Deferred.prototype, { - resolve: function(val) { - if (this.promise.$$state.status) return; - if (val === this.promise) { - this.$$reject($qMinErr("qcycle", "Expected promise to be resolved with value other than itself '{0}'", val)); + function detectNamespaceForChildElements(parentElement) { + var node = parentElement && parentElement[0]; + if (!node) { + return "html"; } else { - this.$$resolve(val); + return nodeName_(node) !== "foreignobject" && node.toString().match(/SVG/) ? "svg" : "html"; } - }, - $$resolve: function(val) { - var then, fns; - fns = callOnce(this, this.$$resolve, this.$$reject); - try { - if (isObject(val) || isFunction(val)) then = val && val.then; - if (isFunction(then)) { - this.promise.$$state.status = -1; - then.call(val, fns[0], fns[1], this.notify); - } else { - this.promise.$$state.value = val; - this.promise.$$state.status = 1; - scheduleProcessQueue(this.promise.$$state); + } + function compileNodes(nodeList, transcludeFn, $rootElement, maxPriority, ignoreDirective, previousCompileContext) { + var linkFns = [], attrs, directives, nodeLinkFn, childNodes, childLinkFn, linkFnFound, nodeLinkFnFound; + for (var i = 0; i < nodeList.length; i++) { + attrs = new Attributes(); + directives = collectDirectives(nodeList[i], [], attrs, i === 0 ? maxPriority : undefined, ignoreDirective); + nodeLinkFn = directives.length ? applyDirectivesToNode(directives, nodeList[i], attrs, transcludeFn, $rootElement, null, [], [], previousCompileContext) : null; + if (nodeLinkFn && nodeLinkFn.scope) { + compile.$$addScopeClass(attrs.$$element); } - } catch (e) { - fns[1](e); - exceptionHandler(e); + childLinkFn = nodeLinkFn && nodeLinkFn.terminal || !(childNodes = nodeList[i].childNodes) || !childNodes.length ? null : compileNodes(childNodes, nodeLinkFn ? (nodeLinkFn.transcludeOnThisElement || !nodeLinkFn.templateOnThisElement) && nodeLinkFn.transclude : transcludeFn); + if (nodeLinkFn || childLinkFn) { + linkFns.push(i, nodeLinkFn, childLinkFn); + linkFnFound = true; + nodeLinkFnFound = nodeLinkFnFound || nodeLinkFn; + } + previousCompileContext = null; } - }, - reject: function(reason) { - if (this.promise.$$state.status) return; - this.$$reject(reason); - }, - $$reject: function(reason) { - this.promise.$$state.value = reason; - this.promise.$$state.status = 2; - scheduleProcessQueue(this.promise.$$state); - }, - notify: function(progress) { - var callbacks = this.promise.$$state.pending; - if (this.promise.$$state.status <= 0 && callbacks && callbacks.length) { - nextTick(function() { - var callback, result; - for (var i = 0, ii = callbacks.length; i < ii; i++) { - result = callbacks[i][0]; - callback = callbacks[i][3]; - try { - result.notify(isFunction(callback) ? callback(progress) : progress); - } catch (e) { - exceptionHandler(e); + return linkFnFound ? compositeLinkFn : null; + function compositeLinkFn(scope, nodeList, $rootElement, parentBoundTranscludeFn) { + var nodeLinkFn, childLinkFn, node, childScope, i, ii, idx, childBoundTranscludeFn; + var stableNodeList; + if (nodeLinkFnFound) { + var nodeListLength = nodeList.length; + stableNodeList = new Array(nodeListLength); + for (i = 0; i < linkFns.length; i += 3) { + idx = linkFns[i]; + stableNodeList[idx] = nodeList[idx]; + } + } else { + stableNodeList = nodeList; + } + for (i = 0, ii = linkFns.length; i < ii; ) { + node = stableNodeList[linkFns[i++]]; + nodeLinkFn = linkFns[i++]; + childLinkFn = linkFns[i++]; + if (nodeLinkFn) { + if (nodeLinkFn.scope) { + childScope = scope.$new(); + compile.$$addScopeInfo(jqLite(node), childScope); + var destroyBindings = nodeLinkFn.$$destroyBindings; + if (destroyBindings) { + nodeLinkFn.$$destroyBindings = null; + childScope.$on("$destroyed", destroyBindings); + } + } else { + childScope = scope; + } + if (nodeLinkFn.transcludeOnThisElement) { + childBoundTranscludeFn = createBoundTranscludeFn(scope, nodeLinkFn.transclude, parentBoundTranscludeFn); + } else if (!nodeLinkFn.templateOnThisElement && parentBoundTranscludeFn) { + childBoundTranscludeFn = parentBoundTranscludeFn; + } else if (!parentBoundTranscludeFn && transcludeFn) { + childBoundTranscludeFn = createBoundTranscludeFn(scope, transcludeFn); + } else { + childBoundTranscludeFn = null; } + nodeLinkFn(childLinkFn, childScope, node, $rootElement, childBoundTranscludeFn, nodeLinkFn); + } else if (childLinkFn) { + childLinkFn(scope, node.childNodes, undefined, parentBoundTranscludeFn); } - }); + } } } - }); - var reject = function(reason) { - var result = new Deferred(); - result.reject(reason); - return result.promise; - }; - var makePromise = function makePromise(value, resolved) { - var result = new Deferred(); - if (resolved) { - result.resolve(value); - } else { - result.reject(value); - } - return result.promise; - }; - var handleCallback = function handleCallback(value, isResolved, callback) { - var callbackOutput = null; - try { - if (isFunction(callback)) callbackOutput = callback(); - } catch (e) { - return makePromise(e, false); - } - if (isPromiseLike(callbackOutput)) { - return callbackOutput.then(function() { - return makePromise(value, isResolved); - }, function(error) { - return makePromise(error, false); - }); - } else { - return makePromise(value, isResolved); - } - }; - var when = function(value, callback, errback, progressBack) { - var result = new Deferred(); - result.resolve(value); - return result.promise.then(callback, errback, progressBack); - }; - var resolve = when; - function all(promises) { - var deferred = new Deferred(), counter = 0, results = isArray(promises) ? [] : {}; - forEach(promises, function(promise, key) { - counter++; - when(promise).then(function(value) { - if (results.hasOwnProperty(key)) return; - results[key] = value; - if (!--counter) deferred.resolve(results); - }, function(reason) { - if (results.hasOwnProperty(key)) return; - deferred.reject(reason); - }); - }); - if (counter === 0) { - deferred.resolve(results); - } - return deferred.promise; - } - var $Q = function Q(resolver) { - if (!isFunction(resolver)) { - throw $qMinErr("norslvr", "Expected resolverFn, got '{0}'", resolver); + function createBoundTranscludeFn(scope, transcludeFn, previousBoundTranscludeFn) { + var boundTranscludeFn = function(transcludedScope, cloneFn, controllers, futureParentElement, containingScope) { + if (!transcludedScope) { + transcludedScope = scope.$new(false, containingScope); + transcludedScope.$$transcluded = true; + } + return transcludeFn(transcludedScope, cloneFn, { + parentBoundTranscludeFn: previousBoundTranscludeFn, + transcludeControllers: controllers, + futureParentElement: futureParentElement + }); + }; + return boundTranscludeFn; } - if (!(this instanceof Q)) { - return new Q(resolver); + function collectDirectives(node, directives, attrs, maxPriority, ignoreDirective) { + var nodeType = node.nodeType, attrsMap = attrs.$attr, match, className; + switch (nodeType) { + case NODE_TYPE_ELEMENT: + addDirective(directives, directiveNormalize(nodeName_(node)), "E", maxPriority, ignoreDirective); + for (var attr, name, nName, ngAttrName, value, isNgAttr, nAttrs = node.attributes, j = 0, jj = nAttrs && nAttrs.length; j < jj; j++) { + var attrStartName = false; + var attrEndName = false; + attr = nAttrs[j]; + name = attr.name; + value = trim(attr.value); + ngAttrName = directiveNormalize(name); + if (isNgAttr = NG_ATTR_BINDING.test(ngAttrName)) { + name = name.replace(PREFIX_REGEXP, "").substr(8).replace(/_(.)/g, function(match, letter) { + return letter.toUpperCase(); + }); + } + var directiveNName = ngAttrName.replace(/(Start|End)$/, ""); + if (directiveIsMultiElement(directiveNName)) { + if (ngAttrName === directiveNName + "Start") { + attrStartName = name; + attrEndName = name.substr(0, name.length - 5) + "end"; + name = name.substr(0, name.length - 6); + } + } + nName = directiveNormalize(name.toLowerCase()); + attrsMap[nName] = name; + if (isNgAttr || !attrs.hasOwnProperty(nName)) { + attrs[nName] = value; + if (getBooleanAttrName(node, nName)) { + attrs[nName] = true; + } + } + addAttrInterpolateDirective(node, directives, value, nName, isNgAttr); + addDirective(directives, nName, "A", maxPriority, ignoreDirective, attrStartName, attrEndName); + } + className = node.className; + if (isObject(className)) { + className = className.animVal; + } + if (isString(className) && className !== "") { + while (match = CLASS_DIRECTIVE_REGEXP.exec(className)) { + nName = directiveNormalize(match[2]); + if (addDirective(directives, nName, "C", maxPriority, ignoreDirective)) { + attrs[nName] = trim(match[3]); + } + className = className.substr(match.index + match[0].length); + } + } + break; + + case NODE_TYPE_TEXT: + if (msie === 11) { + while (node.parentNode && node.nextSibling && node.nextSibling.nodeType === NODE_TYPE_TEXT) { + node.nodeValue = node.nodeValue + node.nextSibling.nodeValue; + node.parentNode.removeChild(node.nextSibling); + } + } + addTextInterpolateDirective(directives, node.nodeValue); + break; + + case NODE_TYPE_COMMENT: + try { + match = COMMENT_DIRECTIVE_REGEXP.exec(node.nodeValue); + if (match) { + nName = directiveNormalize(match[1]); + if (addDirective(directives, nName, "M", maxPriority, ignoreDirective)) { + attrs[nName] = trim(match[2]); + } + } + } catch (e) {} + break; + } + directives.sort(byPriority); + return directives; } - var deferred = new Deferred(); - function resolveFn(value) { - deferred.resolve(value); + function groupScan(node, attrStart, attrEnd) { + var nodes = []; + var depth = 0; + if (attrStart && node.hasAttribute && node.hasAttribute(attrStart)) { + do { + if (!node) { + throw $compileMinErr("uterdir", "Unterminated attribute, found '{0}' but no matching '{1}' found.", attrStart, attrEnd); + } + if (node.nodeType == NODE_TYPE_ELEMENT) { + if (node.hasAttribute(attrStart)) depth++; + if (node.hasAttribute(attrEnd)) depth--; + } + nodes.push(node); + node = node.nextSibling; + } while (depth > 0); + } else { + nodes.push(node); + } + return jqLite(nodes); } - function rejectFn(reason) { - deferred.reject(reason); + function groupElementsLinkFnWrapper(linkFn, attrStart, attrEnd) { + return function(scope, element, attrs, controllers, transcludeFn) { + element = groupScan(element[0], attrStart, attrEnd); + return linkFn(scope, element, attrs, controllers, transcludeFn); + }; } - resolver(resolveFn, rejectFn); - return deferred.promise; - }; - $Q.defer = defer; - $Q.reject = reject; - $Q.when = when; - $Q.resolve = resolve; - $Q.all = all; - return $Q; - } - function $$RAFProvider() { - this.$get = [ "$window", "$timeout", function($window, $timeout) { - var requestAnimationFrame = $window.requestAnimationFrame || $window.webkitRequestAnimationFrame; - var cancelAnimationFrame = $window.cancelAnimationFrame || $window.webkitCancelAnimationFrame || $window.webkitCancelRequestAnimationFrame; - var rafSupported = !!requestAnimationFrame; - var raf = rafSupported ? function(fn) { - var id = requestAnimationFrame(fn); - return function() { - cancelAnimationFrame(id); - }; - } : function(fn) { - var timer = $timeout(fn, 16.66, false); - return function() { - $timeout.cancel(timer); - }; - }; - raf.supported = rafSupported; - return raf; - } ]; - } - function $RootScopeProvider() { - var TTL = 10; - var $rootScopeMinErr = minErr("$rootScope"); - var lastDirtyWatch = null; - var applyAsyncId = null; - this.digestTtl = function(value) { - if (arguments.length) { - TTL = value; - } - return TTL; - }; - function createChildScopeClass(parent) { - function ChildScope() { - this.$$watchers = this.$$nextSibling = this.$$childHead = this.$$childTail = null; - this.$$listeners = {}; - this.$$listenerCount = {}; - this.$$watchersCount = 0; - this.$id = nextUid(); - this.$$ChildScope = null; - } - ChildScope.prototype = parent; - return ChildScope; - } - this.$get = [ "$injector", "$exceptionHandler", "$parse", "$browser", function($injector, $exceptionHandler, $parse, $browser) { - function destroyChildScope($event) { - $event.currentScope.$$destroyed = true; - } - function Scope() { - this.$id = nextUid(); - this.$$phase = this.$parent = this.$$watchers = this.$$nextSibling = this.$$prevSibling = this.$$childHead = this.$$childTail = null; - this.$root = this; - this.$$destroyed = false; - this.$$listeners = {}; - this.$$listenerCount = {}; - this.$$watchersCount = 0; - this.$$isolateBindings = null; - } - Scope.prototype = { - constructor: Scope, - $new: function(isolate, parent) { - var child; - parent = parent || this; - if (isolate) { - child = new Scope(); - child.$root = this.$root; - } else { - if (!this.$$ChildScope) { - this.$$ChildScope = createChildScopeClass(this); - } - child = new this.$$ChildScope(); - } - child.$parent = parent; - child.$$prevSibling = parent.$$childTail; - if (parent.$$childHead) { - parent.$$childTail.$$nextSibling = child; - parent.$$childTail = child; - } else { - parent.$$childHead = parent.$$childTail = child; - } - if (isolate || parent != this) child.$on("$destroy", destroyChildScope); - return child; - }, - $watch: function(watchExp, listener, objectEquality, prettyPrintExpression) { - var get = $parse(watchExp); - if (get.$$watchDelegate) { - return get.$$watchDelegate(this, listener, objectEquality, get, watchExp); - } - var scope = this, array = scope.$$watchers, watcher = { - fn: listener, - last: initWatchVal, - get: get, - exp: prettyPrintExpression || watchExp, - eq: !!objectEquality - }; - lastDirtyWatch = null; - if (!isFunction(listener)) { - watcher.fn = noop; + function applyDirectivesToNode(directives, compileNode, templateAttrs, transcludeFn, jqCollection, originalReplaceDirective, preLinkFns, postLinkFns, previousCompileContext) { + previousCompileContext = previousCompileContext || {}; + var terminalPriority = -Number.MAX_VALUE, newScopeDirective = previousCompileContext.newScopeDirective, controllerDirectives = previousCompileContext.controllerDirectives, newIsolateScopeDirective = previousCompileContext.newIsolateScopeDirective, templateDirective = previousCompileContext.templateDirective, nonTlbTranscludeDirective = previousCompileContext.nonTlbTranscludeDirective, hasTranscludeDirective = false, hasTemplate = false, hasElementTranscludeDirective = previousCompileContext.hasElementTranscludeDirective, $compileNode = templateAttrs.$$element = jqLite(compileNode), directive, directiveName, $template, replaceDirective = originalReplaceDirective, childTranscludeFn = transcludeFn, linkFn, directiveValue; + for (var i = 0, ii = directives.length; i < ii; i++) { + directive = directives[i]; + var attrStart = directive.$$start; + var attrEnd = directive.$$end; + if (attrStart) { + $compileNode = groupScan(compileNode, attrStart, attrEnd); } - if (!array) { - array = scope.$$watchers = []; + $template = undefined; + if (terminalPriority > directive.priority) { + break; } - array.unshift(watcher); - incrementWatchersCount(this, 1); - return function deregisterWatch() { - if (arrayRemove(array, watcher) >= 0) { - incrementWatchersCount(scope, -1); + if (directiveValue = directive.scope) { + if (!directive.templateUrl) { + if (isObject(directiveValue)) { + assertNoDuplicate("new/isolated scope", newIsolateScopeDirective || newScopeDirective, directive, $compileNode); + newIsolateScopeDirective = directive; + } else { + assertNoDuplicate("new/isolated scope", newIsolateScopeDirective, directive, $compileNode); + } } - lastDirtyWatch = null; - }; - }, - $watchGroup: function(watchExpressions, listener) { - var oldValues = new Array(watchExpressions.length); - var newValues = new Array(watchExpressions.length); - var deregisterFns = []; - var self = this; - var changeReactionScheduled = false; - var firstRun = true; - if (!watchExpressions.length) { - var shouldCall = true; - self.$evalAsync(function() { - if (shouldCall) listener(newValues, newValues, self); - }); - return function deregisterWatchGroup() { - shouldCall = false; - }; + newScopeDirective = newScopeDirective || directive; } - if (watchExpressions.length === 1) { - return this.$watch(watchExpressions[0], function watchGroupAction(value, oldValue, scope) { - newValues[0] = value; - oldValues[0] = oldValue; - listener(newValues, value === oldValue ? newValues : oldValues, scope); - }); + directiveName = directive.name; + if (!directive.templateUrl && directive.controller) { + directiveValue = directive.controller; + controllerDirectives = controllerDirectives || createMap(); + assertNoDuplicate("'" + directiveName + "' controller", controllerDirectives[directiveName], directive, $compileNode); + controllerDirectives[directiveName] = directive; } - forEach(watchExpressions, function(expr, i) { - var unwatchFn = self.$watch(expr, function watchGroupSubAction(value, oldValue) { - newValues[i] = value; - oldValues[i] = oldValue; - if (!changeReactionScheduled) { - changeReactionScheduled = true; - self.$evalAsync(watchGroupAction); - } - }); - deregisterFns.push(unwatchFn); - }); - function watchGroupAction() { - changeReactionScheduled = false; - if (firstRun) { - firstRun = false; - listener(newValues, newValues, self); + if (directiveValue = directive.transclude) { + hasTranscludeDirective = true; + if (!directive.$$tlb) { + assertNoDuplicate("transclusion", nonTlbTranscludeDirective, directive, $compileNode); + nonTlbTranscludeDirective = directive; + } + if (directiveValue == "element") { + hasElementTranscludeDirective = true; + terminalPriority = directive.priority; + $template = $compileNode; + $compileNode = templateAttrs.$$element = jqLite(document.createComment(" " + directiveName + ": " + templateAttrs[directiveName] + " ")); + compileNode = $compileNode[0]; + replaceWith(jqCollection, sliceArgs($template), compileNode); + childTranscludeFn = compile($template, transcludeFn, terminalPriority, replaceDirective && replaceDirective.name, { + nonTlbTranscludeDirective: nonTlbTranscludeDirective + }); } else { - listener(newValues, oldValues, self); + $template = jqLite(jqLiteClone(compileNode)).contents(); + $compileNode.empty(); + childTranscludeFn = compile($template, transcludeFn); } } - return function deregisterWatchGroup() { - while (deregisterFns.length) { - deregisterFns.shift()(); - } - }; - }, - $watchCollection: function(obj, listener) { - $watchCollectionInterceptor.$stateful = true; - var self = this; - var newValue; - var oldValue; - var veryOldValue; - var trackVeryOldValue = listener.length > 1; - var changeDetected = 0; - var changeDetector = $parse(obj, $watchCollectionInterceptor); - var internalArray = []; - var internalObject = {}; - var initRun = true; - var oldLength = 0; - function $watchCollectionInterceptor(_value) { - newValue = _value; - var newLength, key, bothNaN, newItem, oldItem; - if (isUndefined(newValue)) return; - if (!isObject(newValue)) { - if (oldValue !== newValue) { - oldValue = newValue; - changeDetected++; + if (directive.template) { + hasTemplate = true; + assertNoDuplicate("template", templateDirective, directive, $compileNode); + templateDirective = directive; + directiveValue = isFunction(directive.template) ? directive.template($compileNode, templateAttrs) : directive.template; + directiveValue = denormalizeTemplate(directiveValue); + if (directive.replace) { + replaceDirective = directive; + if (jqLiteIsTextNode(directiveValue)) { + $template = []; + } else { + $template = removeComments(wrapTemplate(directive.templateNamespace, trim(directiveValue))); } - } else if (isArrayLike(newValue)) { - if (oldValue !== internalArray) { - oldValue = internalArray; - oldLength = oldValue.length = 0; - changeDetected++; + compileNode = $template[0]; + if ($template.length != 1 || compileNode.nodeType !== NODE_TYPE_ELEMENT) { + throw $compileMinErr("tplrt", "Template for directive '{0}' must have exactly one root element. {1}", directiveName, ""); } - newLength = newValue.length; - if (oldLength !== newLength) { - changeDetected++; - oldValue.length = oldLength = newLength; - } - for (var i = 0; i < newLength; i++) { - oldItem = oldValue[i]; - newItem = newValue[i]; - bothNaN = oldItem !== oldItem && newItem !== newItem; - if (!bothNaN && oldItem !== newItem) { - changeDetected++; - oldValue[i] = newItem; - } + replaceWith(jqCollection, $compileNode, compileNode); + var newTemplateAttrs = { + $attr: {} + }; + var templateDirectives = collectDirectives(compileNode, [], newTemplateAttrs); + var unprocessedDirectives = directives.splice(i + 1, directives.length - (i + 1)); + if (newIsolateScopeDirective) { + markDirectivesAsIsolate(templateDirectives); } + directives = directives.concat(templateDirectives).concat(unprocessedDirectives); + mergeTemplateAttributes(templateAttrs, newTemplateAttrs); + ii = directives.length; } else { - if (oldValue !== internalObject) { - oldValue = internalObject = {}; - oldLength = 0; - changeDetected++; - } - newLength = 0; - for (key in newValue) { - if (hasOwnProperty.call(newValue, key)) { - newLength++; - newItem = newValue[key]; - oldItem = oldValue[key]; - if (key in oldValue) { - bothNaN = oldItem !== oldItem && newItem !== newItem; - if (!bothNaN && oldItem !== newItem) { - changeDetected++; - oldValue[key] = newItem; - } - } else { - oldLength++; - oldValue[key] = newItem; - changeDetected++; - } - } - } - if (oldLength > newLength) { - changeDetected++; - for (key in oldValue) { - if (!hasOwnProperty.call(newValue, key)) { - oldLength--; - delete oldValue[key]; - } - } - } + $compileNode.html(directiveValue); } - return changeDetected; } - function $watchCollectionAction() { - if (initRun) { - initRun = false; - listener(newValue, newValue, self); - } else { - listener(newValue, veryOldValue, self); + if (directive.templateUrl) { + hasTemplate = true; + assertNoDuplicate("template", templateDirective, directive, $compileNode); + templateDirective = directive; + if (directive.replace) { + replaceDirective = directive; } - if (trackVeryOldValue) { - if (!isObject(newValue)) { - veryOldValue = newValue; - } else if (isArrayLike(newValue)) { - veryOldValue = new Array(newValue.length); - for (var i = 0; i < newValue.length; i++) { - veryOldValue[i] = newValue[i]; - } - } else { - veryOldValue = {}; - for (var key in newValue) { - if (hasOwnProperty.call(newValue, key)) { - veryOldValue[key] = newValue[key]; - } - } + nodeLinkFn = compileTemplateUrl(directives.splice(i, directives.length - i), $compileNode, templateAttrs, jqCollection, hasTranscludeDirective && childTranscludeFn, preLinkFns, postLinkFns, { + controllerDirectives: controllerDirectives, + newScopeDirective: newScopeDirective !== directive && newScopeDirective, + newIsolateScopeDirective: newIsolateScopeDirective, + templateDirective: templateDirective, + nonTlbTranscludeDirective: nonTlbTranscludeDirective + }); + ii = directives.length; + } else if (directive.compile) { + try { + linkFn = directive.compile($compileNode, templateAttrs, childTranscludeFn); + if (isFunction(linkFn)) { + addLinkFns(null, linkFn, attrStart, attrEnd); + } else if (linkFn) { + addLinkFns(linkFn.pre, linkFn.post, attrStart, attrEnd); } + } catch (e) { + $exceptionHandler(e, startingTag($compileNode)); } } - return this.$watch(changeDetector, $watchCollectionAction); - }, - $digest: function() { - var watch, value, last, watchers, length, dirty, ttl = TTL, next, current, target = this, watchLog = [], logIdx, logMsg, asyncTask; - beginPhase("$digest"); - $browser.$$checkUrlChange(); - if (this === $rootScope && applyAsyncId !== null) { - $browser.defer.cancel(applyAsyncId); - flushApplyAsync(); + if (directive.terminal) { + nodeLinkFn.terminal = true; + terminalPriority = Math.max(terminalPriority, directive.priority); } - lastDirtyWatch = null; - do { - dirty = false; - current = target; - while (asyncQueue.length) { - try { - asyncTask = asyncQueue.shift(); - asyncTask.scope.$eval(asyncTask.expression, asyncTask.locals); - } catch (e) { - $exceptionHandler(e); - } - lastDirtyWatch = null; + } + nodeLinkFn.scope = newScopeDirective && newScopeDirective.scope === true; + nodeLinkFn.transcludeOnThisElement = hasTranscludeDirective; + nodeLinkFn.templateOnThisElement = hasTemplate; + nodeLinkFn.transclude = childTranscludeFn; + previousCompileContext.hasElementTranscludeDirective = hasElementTranscludeDirective; + return nodeLinkFn; + function addLinkFns(pre, post, attrStart, attrEnd) { + if (pre) { + if (attrStart) pre = groupElementsLinkFnWrapper(pre, attrStart, attrEnd); + pre.require = directive.require; + pre.directiveName = directiveName; + if (newIsolateScopeDirective === directive || directive.$$isolateScope) { + pre = cloneAndAnnotateFn(pre, { + isolateScope: true + }); } - traverseScopesLoop: do { - if (watchers = current.$$watchers) { - length = watchers.length; - while (length--) { - try { - watch = watchers[length]; - if (watch) { - if ((value = watch.get(current)) !== (last = watch.last) && !(watch.eq ? equals(value, last) : typeof value === "number" && typeof last === "number" && isNaN(value) && isNaN(last))) { - dirty = true; - lastDirtyWatch = watch; - watch.last = watch.eq ? copy(value, null) : value; - watch.fn(value, last === initWatchVal ? value : last, current); - if (ttl < 5) { - logIdx = 4 - ttl; - if (!watchLog[logIdx]) watchLog[logIdx] = []; - watchLog[logIdx].push({ - msg: isFunction(watch.exp) ? "fn: " + (watch.exp.name || watch.exp.toString()) : watch.exp, - newVal: value, - oldVal: last - }); - } - } else if (watch === lastDirtyWatch) { - dirty = false; - break traverseScopesLoop; - } - } - } catch (e) { - $exceptionHandler(e); - } - } - } - if (!(next = current.$$watchersCount && current.$$childHead || current !== target && current.$$nextSibling)) { - while (current !== target && !(next = current.$$nextSibling)) { - current = current.$parent; - } - } - } while (current = next); - if ((dirty || asyncQueue.length) && !ttl--) { - clearPhase(); - throw $rootScopeMinErr("infdig", "{0} $digest() iterations reached. Aborting!\n" + "Watchers fired in the last 5 iterations: {1}", TTL, watchLog); + preLinkFns.push(pre); + } + if (post) { + if (attrStart) post = groupElementsLinkFnWrapper(post, attrStart, attrEnd); + post.require = directive.require; + post.directiveName = directiveName; + if (newIsolateScopeDirective === directive || directive.$$isolateScope) { + post = cloneAndAnnotateFn(post, { + isolateScope: true + }); } - } while (dirty || asyncQueue.length); - clearPhase(); - while (postDigestQueue.length) { - try { - postDigestQueue.shift()(); - } catch (e) { - $exceptionHandler(e); + postLinkFns.push(post); + } + } + function getControllers(directiveName, require, $element, elementControllers) { + var value; + if (isString(require)) { + var match = require.match(REQUIRE_PREFIX_REGEXP); + var name = require.substring(match[0].length); + var inheritType = match[1] || match[3]; + var optional = match[2] === "?"; + if (inheritType === "^^") { + $element = $element.parent(); + } else { + value = elementControllers && elementControllers[name]; + value = value && value.instance; + } + if (!value) { + var dataName = "$" + name + "Controller"; + value = inheritType ? $element.inheritedData(dataName) : $element.data(dataName); + } + if (!value && !optional) { + throw $compileMinErr("ctreq", "Controller '{0}', required by directive '{1}', can't be found!", name, directiveName); + } + } else if (isArray(require)) { + value = []; + for (var i = 0, ii = require.length; i < ii; i++) { + value[i] = getControllers(directiveName, require[i], $element, elementControllers); } } - }, - $destroy: function() { - if (this.$$destroyed) return; - var parent = this.$parent; - this.$broadcast("$destroy"); - this.$$destroyed = true; - if (this === $rootScope) { - $browser.$$applicationDestroyed(); + return value || null; + } + function setupControllers($element, attrs, transcludeFn, controllerDirectives, isolateScope, scope) { + var elementControllers = createMap(); + for (var controllerKey in controllerDirectives) { + var directive = controllerDirectives[controllerKey]; + var locals = { + $scope: directive === newIsolateScopeDirective || directive.$$isolateScope ? isolateScope : scope, + $element: $element, + $attrs: attrs, + $transclude: transcludeFn + }; + var controller = directive.controller; + if (controller == "@") { + controller = attrs[directive.name]; + } + var controllerInstance = $controller(controller, locals, true, directive.controllerAs); + elementControllers[directive.name] = controllerInstance; + if (!hasElementTranscludeDirective) { + $element.data("$" + directive.name + "Controller", controllerInstance.instance); + } } - incrementWatchersCount(this, -this.$$watchersCount); - for (var eventName in this.$$listenerCount) { - decrementListenerCount(this, this.$$listenerCount[eventName], eventName); + return elementControllers; + } + function nodeLinkFn(childLinkFn, scope, linkNode, $rootElement, boundTranscludeFn, thisLinkFn) { + var i, ii, linkFn, controller, isolateScope, elementControllers, transcludeFn, $element, attrs; + if (compileNode === linkNode) { + attrs = templateAttrs; + $element = templateAttrs.$$element; + } else { + $element = jqLite(linkNode); + attrs = new Attributes($element, templateAttrs); } - if (parent && parent.$$childHead == this) parent.$$childHead = this.$$nextSibling; - if (parent && parent.$$childTail == this) parent.$$childTail = this.$$prevSibling; - if (this.$$prevSibling) this.$$prevSibling.$$nextSibling = this.$$nextSibling; - if (this.$$nextSibling) this.$$nextSibling.$$prevSibling = this.$$prevSibling; - this.$destroy = this.$digest = this.$apply = this.$evalAsync = this.$applyAsync = noop; - this.$on = this.$watch = this.$watchGroup = function() { - return noop; - }; - this.$$listeners = {}; - this.$parent = this.$$nextSibling = this.$$prevSibling = this.$$childHead = this.$$childTail = this.$root = this.$$watchers = null; - }, - $eval: function(expr, locals) { - return $parse(expr)(this, locals); - }, - $evalAsync: function(expr, locals) { - if (!$rootScope.$$phase && !asyncQueue.length) { - $browser.defer(function() { - if (asyncQueue.length) { - $rootScope.$digest(); - } - }); + if (newIsolateScopeDirective) { + isolateScope = scope.$new(true); } - asyncQueue.push({ - scope: this, - expression: expr, - locals: locals - }); - }, - $$postDigest: function(fn) { - postDigestQueue.push(fn); - }, - $apply: function(expr) { - try { - beginPhase("$apply"); - try { - return this.$eval(expr); - } finally { - clearPhase(); - } - } catch (e) { - $exceptionHandler(e); - } finally { - try { - $rootScope.$digest(); - } catch (e) { - $exceptionHandler(e); - throw e; - } + if (boundTranscludeFn) { + transcludeFn = controllersBoundTransclude; + transcludeFn.$$boundTransclude = boundTranscludeFn; } - }, - $applyAsync: function(expr) { - var scope = this; - expr && applyAsyncQueue.push($applyAsyncExpression); - scheduleApplyAsync(); - function $applyAsyncExpression() { - scope.$eval(expr); + if (controllerDirectives) { + elementControllers = setupControllers($element, attrs, transcludeFn, controllerDirectives, isolateScope, scope); } - }, - $on: function(name, listener) { - var namedListeners = this.$$listeners[name]; - if (!namedListeners) { - this.$$listeners[name] = namedListeners = []; + if (newIsolateScopeDirective) { + compile.$$addScopeInfo($element, isolateScope, true, !(templateDirective && (templateDirective === newIsolateScopeDirective || templateDirective === newIsolateScopeDirective.$$originalDirective))); + compile.$$addScopeClass($element, true); + isolateScope.$$isolateBindings = newIsolateScopeDirective.$$isolateBindings; + initializeDirectiveBindings(scope, attrs, isolateScope, isolateScope.$$isolateBindings, newIsolateScopeDirective, isolateScope); } - namedListeners.push(listener); - var current = this; - do { - if (!current.$$listenerCount[name]) { - current.$$listenerCount[name] = 0; - } - current.$$listenerCount[name]++; - } while (current = current.$parent); - var self = this; - return function() { - var indexOfListener = namedListeners.indexOf(listener); - if (indexOfListener !== -1) { - namedListeners[indexOfListener] = null; - decrementListenerCount(self, 1, name); - } - }; - }, - $emit: function(name, args) { - var empty = [], namedListeners, scope = this, stopPropagation = false, event = { - name: name, - targetScope: scope, - stopPropagation: function() { - stopPropagation = true; - }, - preventDefault: function() { - event.defaultPrevented = true; - }, - defaultPrevented: false - }, listenerArgs = concat([ event ], arguments, 1), i, length; - do { - namedListeners = scope.$$listeners[name] || empty; - event.currentScope = scope; - for (i = 0, length = namedListeners.length; i < length; i++) { - if (!namedListeners[i]) { - namedListeners.splice(i, 1); - i--; - length--; - continue; - } - try { - namedListeners[i].apply(null, listenerArgs); - } catch (e) { - $exceptionHandler(e); - } - } - if (stopPropagation) { - event.currentScope = null; - return event; - } - scope = scope.$parent; - } while (scope); - event.currentScope = null; - return event; - }, - $broadcast: function(name, args) { - var target = this, current = target, next = target, event = { - name: name, - targetScope: target, - preventDefault: function() { - event.defaultPrevented = true; - }, - defaultPrevented: false - }; - if (!target.$$listenerCount[name]) return event; - var listenerArgs = concat([ event ], arguments, 1), listeners, i, length; - while (current = next) { - event.currentScope = current; - listeners = current.$$listeners[name] || []; - for (i = 0, length = listeners.length; i < length; i++) { - if (!listeners[i]) { - listeners.splice(i, 1); - i--; - length--; - continue; - } - try { - listeners[i].apply(null, listenerArgs); - } catch (e) { - $exceptionHandler(e); + if (elementControllers) { + var scopeDirective = newIsolateScopeDirective || newScopeDirective; + var bindings; + var controllerForBindings; + if (scopeDirective && elementControllers[scopeDirective.name]) { + bindings = scopeDirective.$$bindings.bindToController; + controller = elementControllers[scopeDirective.name]; + if (controller && controller.identifier && bindings) { + controllerForBindings = controller; + thisLinkFn.$$destroyBindings = initializeDirectiveBindings(scope, attrs, controller.instance, bindings, scopeDirective); } } - if (!(next = current.$$listenerCount[name] && current.$$childHead || current !== target && current.$$nextSibling)) { - while (current !== target && !(next = current.$$nextSibling)) { - current = current.$parent; + for (i in elementControllers) { + controller = elementControllers[i]; + var controllerResult = controller(); + if (controllerResult !== controller.instance) { + controller.instance = controllerResult; + $element.data("$" + i + "Controller", controllerResult); + if (controller === controllerForBindings) { + thisLinkFn.$$destroyBindings(); + thisLinkFn.$$destroyBindings = initializeDirectiveBindings(scope, attrs, controllerResult, bindings, scopeDirective); + } } } } - event.currentScope = null; - return event; - } - }; - var $rootScope = new Scope(); - var asyncQueue = $rootScope.$$asyncQueue = []; - var postDigestQueue = $rootScope.$$postDigestQueue = []; - var applyAsyncQueue = $rootScope.$$applyAsyncQueue = []; - return $rootScope; - function beginPhase(phase) { - if ($rootScope.$$phase) { - throw $rootScopeMinErr("inprog", "{0} already in progress", $rootScope.$$phase); - } - $rootScope.$$phase = phase; - } - function clearPhase() { - $rootScope.$$phase = null; - } - function incrementWatchersCount(current, count) { - do { - current.$$watchersCount += count; - } while (current = current.$parent); - } - function decrementListenerCount(current, count, name) { - do { - current.$$listenerCount[name] -= count; - if (current.$$listenerCount[name] === 0) { - delete current.$$listenerCount[name]; + for (i = 0, ii = preLinkFns.length; i < ii; i++) { + linkFn = preLinkFns[i]; + invokeLinkFn(linkFn, linkFn.isolateScope ? isolateScope : scope, $element, attrs, linkFn.require && getControllers(linkFn.directiveName, linkFn.require, $element, elementControllers), transcludeFn); } - } while (current = current.$parent); - } - function initWatchVal() {} - function flushApplyAsync() { - while (applyAsyncQueue.length) { - try { - applyAsyncQueue.shift()(); - } catch (e) { - $exceptionHandler(e); + var scopeToChild = scope; + if (newIsolateScopeDirective && (newIsolateScopeDirective.template || newIsolateScopeDirective.templateUrl === null)) { + scopeToChild = isolateScope; + } + childLinkFn && childLinkFn(scopeToChild, linkNode.childNodes, undefined, boundTranscludeFn); + for (i = postLinkFns.length - 1; i >= 0; i--) { + linkFn = postLinkFns[i]; + invokeLinkFn(linkFn, linkFn.isolateScope ? isolateScope : scope, $element, attrs, linkFn.require && getControllers(linkFn.directiveName, linkFn.require, $element, elementControllers), transcludeFn); + } + function controllersBoundTransclude(scope, cloneAttachFn, futureParentElement) { + var transcludeControllers; + if (!isScope(scope)) { + futureParentElement = cloneAttachFn; + cloneAttachFn = scope; + scope = undefined; + } + if (hasElementTranscludeDirective) { + transcludeControllers = elementControllers; + } + if (!futureParentElement) { + futureParentElement = hasElementTranscludeDirective ? $element.parent() : $element; + } + return boundTranscludeFn(scope, cloneAttachFn, transcludeControllers, futureParentElement, scopeToChild); } } - applyAsyncId = null; } - function scheduleApplyAsync() { - if (applyAsyncId === null) { - applyAsyncId = $browser.defer(function() { - $rootScope.$apply(flushApplyAsync); + function markDirectivesAsIsolate(directives) { + for (var j = 0, jj = directives.length; j < jj; j++) { + directives[j] = inherit(directives[j], { + $$isolateScope: true }); } } - } ]; - } - function $$SanitizeUriProvider() { - var aHrefSanitizationWhitelist = /^\s*(https?|ftp|mailto|tel|file):/, imgSrcSanitizationWhitelist = /^\s*((https?|ftp|file|blob):|data:image\/)/; - this.aHrefSanitizationWhitelist = function(regexp) { - if (isDefined(regexp)) { - aHrefSanitizationWhitelist = regexp; - return this; - } - return aHrefSanitizationWhitelist; - }; - this.imgSrcSanitizationWhitelist = function(regexp) { - if (isDefined(regexp)) { - imgSrcSanitizationWhitelist = regexp; - return this; - } - return imgSrcSanitizationWhitelist; - }; - this.$get = function() { - return function sanitizeUri(uri, isImage) { - var regex = isImage ? imgSrcSanitizationWhitelist : aHrefSanitizationWhitelist; - var normalizedVal; - normalizedVal = urlResolve(uri).href; - if (normalizedVal !== "" && !normalizedVal.match(regex)) { - return "unsafe:" + normalizedVal; - } - return uri; - }; - }; - } - var $sceMinErr = minErr("$sce"); - var SCE_CONTEXTS = { - HTML: "html", - CSS: "css", - URL: "url", - RESOURCE_URL: "resourceUrl", - JS: "js" - }; - function adjustMatcher(matcher) { - if (matcher === "self") { - return matcher; - } else if (isString(matcher)) { - if (matcher.indexOf("***") > -1) { - throw $sceMinErr("iwcard", "Illegal sequence *** in string matcher. String: {0}", matcher); - } - matcher = escapeForRegexp(matcher).replace("\\*\\*", ".*").replace("\\*", "[^:/.?&;]*"); - return new RegExp("^" + matcher + "$"); - } else if (isRegExp(matcher)) { - return new RegExp("^" + matcher.source + "$"); - } else { - throw $sceMinErr("imatcher", 'Matchers may only be "self", string patterns or RegExp objects'); - } - } - function adjustMatchers(matchers) { - var adjustedMatchers = []; - if (isDefined(matchers)) { - forEach(matchers, function(matcher) { - adjustedMatchers.push(adjustMatcher(matcher)); - }); - } - return adjustedMatchers; - } - function $SceDelegateProvider() { - this.SCE_CONTEXTS = SCE_CONTEXTS; - var resourceUrlWhitelist = [ "self" ], resourceUrlBlacklist = []; - this.resourceUrlWhitelist = function(value) { - if (arguments.length) { - resourceUrlWhitelist = adjustMatchers(value); - } - return resourceUrlWhitelist; - }; - this.resourceUrlBlacklist = function(value) { - if (arguments.length) { - resourceUrlBlacklist = adjustMatchers(value); - } - return resourceUrlBlacklist; - }; - this.$get = [ "$injector", function($injector) { - var htmlSanitizer = function htmlSanitizer(html) { - throw $sceMinErr("unsafe", "Attempting to use an unsafe value in a safe context."); - }; - if ($injector.has("$sanitize")) { - htmlSanitizer = $injector.get("$sanitize"); - } - function matchUrl(matcher, parsedUrl) { - if (matcher === "self") { - return urlIsSameOrigin(parsedUrl); - } else { - return !!matcher.exec(parsedUrl.href); + function addDirective(tDirectives, name, location, maxPriority, ignoreDirective, startAttrName, endAttrName) { + if (name === ignoreDirective) return null; + var match = null; + if (hasDirectives.hasOwnProperty(name)) { + for (var directive, directives = $injector.get(name + Suffix), i = 0, ii = directives.length; i < ii; i++) { + try { + directive = directives[i]; + if ((isUndefined(maxPriority) || maxPriority > directive.priority) && directive.restrict.indexOf(location) != -1) { + if (startAttrName) { + directive = inherit(directive, { + $$start: startAttrName, + $$end: endAttrName + }); + } + tDirectives.push(directive); + match = directive; + } + } catch (e) { + $exceptionHandler(e); + } + } } + return match; } - function isResourceUrlAllowedByPolicy(url) { - var parsedUrl = urlResolve(url.toString()); - var i, n, allowed = false; - for (i = 0, n = resourceUrlWhitelist.length; i < n; i++) { - if (matchUrl(resourceUrlWhitelist[i], parsedUrl)) { - allowed = true; - break; + function directiveIsMultiElement(name) { + if (hasDirectives.hasOwnProperty(name)) { + for (var directive, directives = $injector.get(name + Suffix), i = 0, ii = directives.length; i < ii; i++) { + directive = directives[i]; + if (directive.multiElement) { + return true; + } } } - if (allowed) { - for (i = 0, n = resourceUrlBlacklist.length; i < n; i++) { - if (matchUrl(resourceUrlBlacklist[i], parsedUrl)) { - allowed = false; - break; + return false; + } + function mergeTemplateAttributes(dst, src) { + var srcAttr = src.$attr, dstAttr = dst.$attr, $element = dst.$$element; + forEach(dst, function(value, key) { + if (key.charAt(0) != "$") { + if (src[key] && src[key] !== value) { + value += (key === "style" ? ";" : " ") + src[key]; } + dst.$set(key, value, true, srcAttr[key]); } - } - return allowed; + }); + forEach(src, function(value, key) { + if (key == "class") { + safeAddClass($element, value); + dst["class"] = (dst["class"] ? dst["class"] + " " : "") + value; + } else if (key == "style") { + $element.attr("style", $element.attr("style") + ";" + value); + dst["style"] = (dst["style"] ? dst["style"] + ";" : "") + value; + } else if (key.charAt(0) != "$" && !dst.hasOwnProperty(key)) { + dst[key] = value; + dstAttr[key] = srcAttr[key]; + } + }); } - function generateHolderType(Base) { - var holderType = function TrustedValueHolderType(trustedValue) { - this.$$unwrapTrustedValue = function() { - return trustedValue; - }; - }; - if (Base) { - holderType.prototype = new Base(); - } - holderType.prototype.valueOf = function sceValueOf() { - return this.$$unwrapTrustedValue(); - }; - holderType.prototype.toString = function sceToString() { - return this.$$unwrapTrustedValue().toString(); + function compileTemplateUrl(directives, $compileNode, tAttrs, $rootElement, childTranscludeFn, preLinkFns, postLinkFns, previousCompileContext) { + var linkQueue = [], afterTemplateNodeLinkFn, afterTemplateChildLinkFn, beforeTemplateCompileNode = $compileNode[0], origAsyncDirective = directives.shift(), derivedSyncDirective = inherit(origAsyncDirective, { + templateUrl: null, + transclude: null, + replace: null, + $$originalDirective: origAsyncDirective + }), templateUrl = isFunction(origAsyncDirective.templateUrl) ? origAsyncDirective.templateUrl($compileNode, tAttrs) : origAsyncDirective.templateUrl, templateNamespace = origAsyncDirective.templateNamespace; + $compileNode.empty(); + $templateRequest(templateUrl).then(function(content) { + var compileNode, tempTemplateAttrs, $template, childBoundTranscludeFn; + content = denormalizeTemplate(content); + if (origAsyncDirective.replace) { + if (jqLiteIsTextNode(content)) { + $template = []; + } else { + $template = removeComments(wrapTemplate(templateNamespace, trim(content))); + } + compileNode = $template[0]; + if ($template.length != 1 || compileNode.nodeType !== NODE_TYPE_ELEMENT) { + throw $compileMinErr("tplrt", "Template for directive '{0}' must have exactly one root element. {1}", origAsyncDirective.name, templateUrl); + } + tempTemplateAttrs = { + $attr: {} + }; + replaceWith($rootElement, $compileNode, compileNode); + var templateDirectives = collectDirectives(compileNode, [], tempTemplateAttrs); + if (isObject(origAsyncDirective.scope)) { + markDirectivesAsIsolate(templateDirectives); + } + directives = templateDirectives.concat(directives); + mergeTemplateAttributes(tAttrs, tempTemplateAttrs); + } else { + compileNode = beforeTemplateCompileNode; + $compileNode.html(content); + } + directives.unshift(derivedSyncDirective); + afterTemplateNodeLinkFn = applyDirectivesToNode(directives, compileNode, tAttrs, childTranscludeFn, $compileNode, origAsyncDirective, preLinkFns, postLinkFns, previousCompileContext); + forEach($rootElement, function(node, i) { + if (node == compileNode) { + $rootElement[i] = $compileNode[0]; + } + }); + afterTemplateChildLinkFn = compileNodes($compileNode[0].childNodes, childTranscludeFn); + while (linkQueue.length) { + var scope = linkQueue.shift(), beforeTemplateLinkNode = linkQueue.shift(), linkRootElement = linkQueue.shift(), boundTranscludeFn = linkQueue.shift(), linkNode = $compileNode[0]; + if (scope.$$destroyed) continue; + if (beforeTemplateLinkNode !== beforeTemplateCompileNode) { + var oldClasses = beforeTemplateLinkNode.className; + if (!(previousCompileContext.hasElementTranscludeDirective && origAsyncDirective.replace)) { + linkNode = jqLiteClone(compileNode); + } + replaceWith(linkRootElement, jqLite(beforeTemplateLinkNode), linkNode); + safeAddClass(jqLite(linkNode), oldClasses); + } + if (afterTemplateNodeLinkFn.transcludeOnThisElement) { + childBoundTranscludeFn = createBoundTranscludeFn(scope, afterTemplateNodeLinkFn.transclude, boundTranscludeFn); + } else { + childBoundTranscludeFn = boundTranscludeFn; + } + afterTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, linkNode, $rootElement, childBoundTranscludeFn, afterTemplateNodeLinkFn); + } + linkQueue = null; + }); + return function delayedNodeLinkFn(ignoreChildLinkFn, scope, node, rootElement, boundTranscludeFn) { + var childBoundTranscludeFn = boundTranscludeFn; + if (scope.$$destroyed) return; + if (linkQueue) { + linkQueue.push(scope, node, rootElement, childBoundTranscludeFn); + } else { + if (afterTemplateNodeLinkFn.transcludeOnThisElement) { + childBoundTranscludeFn = createBoundTranscludeFn(scope, afterTemplateNodeLinkFn.transclude, boundTranscludeFn); + } + afterTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, node, rootElement, childBoundTranscludeFn, afterTemplateNodeLinkFn); + } }; - return holderType; } - var trustedValueHolderBase = generateHolderType(), byType = {}; - byType[SCE_CONTEXTS.HTML] = generateHolderType(trustedValueHolderBase); - byType[SCE_CONTEXTS.CSS] = generateHolderType(trustedValueHolderBase); - byType[SCE_CONTEXTS.URL] = generateHolderType(trustedValueHolderBase); - byType[SCE_CONTEXTS.JS] = generateHolderType(trustedValueHolderBase); - byType[SCE_CONTEXTS.RESOURCE_URL] = generateHolderType(byType[SCE_CONTEXTS.URL]); - function trustAs(type, trustedValue) { - var Constructor = byType.hasOwnProperty(type) ? byType[type] : null; - if (!Constructor) { - throw $sceMinErr("icontext", "Attempted to trust a value in invalid context. Context: {0}; Value: {1}", type, trustedValue); + function byPriority(a, b) { + var diff = b.priority - a.priority; + if (diff !== 0) return diff; + if (a.name !== b.name) return a.name < b.name ? -1 : 1; + return a.index - b.index; + } + function assertNoDuplicate(what, previousDirective, directive, element) { + function wrapModuleNameIfDefined(moduleName) { + return moduleName ? " (module: " + moduleName + ")" : ""; } - if (trustedValue === null || isUndefined(trustedValue) || trustedValue === "") { - return trustedValue; + if (previousDirective) { + throw $compileMinErr("multidir", "Multiple directives [{0}{1}, {2}{3}] asking for {4} on: {5}", previousDirective.name, wrapModuleNameIfDefined(previousDirective.$$moduleName), directive.name, wrapModuleNameIfDefined(directive.$$moduleName), what, startingTag(element)); } - if (typeof trustedValue !== "string") { - throw $sceMinErr("itype", "Attempted to trust a non-string value in a content requiring a string: Context: {0}", type); - } - return new Constructor(trustedValue); } - function valueOf(maybeTrusted) { - if (maybeTrusted instanceof trustedValueHolderBase) { - return maybeTrusted.$$unwrapTrustedValue(); - } else { - return maybeTrusted; + function addTextInterpolateDirective(directives, text) { + var interpolateFn = $interpolate(text, true); + if (interpolateFn) { + directives.push({ + priority: 0, + compile: function textInterpolateCompileFn(templateNode) { + var templateNodeParent = templateNode.parent(), hasCompileParent = !!templateNodeParent.length; + if (hasCompileParent) compile.$$addBindingClass(templateNodeParent); + return function textInterpolateLinkFn(scope, node) { + var parent = node.parent(); + if (!hasCompileParent) compile.$$addBindingClass(parent); + compile.$$addBindingInfo(parent, interpolateFn.expressions); + scope.$watch(interpolateFn, function interpolateFnWatchAction(value) { + node[0].nodeValue = value; + }); + }; + } + }); } } - function getTrusted(type, maybeTrusted) { - if (maybeTrusted === null || isUndefined(maybeTrusted) || maybeTrusted === "") { - return maybeTrusted; + function wrapTemplate(type, template) { + type = lowercase(type || "html"); + switch (type) { + case "svg": + case "math": + var wrapper = document.createElement("div"); + wrapper.innerHTML = "<" + type + ">" + template + ""; + return wrapper.childNodes[0].childNodes; + + default: + return template; } - var constructor = byType.hasOwnProperty(type) ? byType[type] : null; - if (constructor && maybeTrusted instanceof constructor) { - return maybeTrusted.$$unwrapTrustedValue(); + } + function getTrustedContext(node, attrNormalizedName) { + if (attrNormalizedName == "srcdoc") { + return $sce.HTML; } - if (type === SCE_CONTEXTS.RESOURCE_URL) { - if (isResourceUrlAllowedByPolicy(maybeTrusted)) { - return maybeTrusted; - } else { - throw $sceMinErr("insecurl", "Blocked loading resource from url not allowed by $sceDelegate policy. URL: {0}", maybeTrusted.toString()); - } - } else if (type === SCE_CONTEXTS.HTML) { - return htmlSanitizer(maybeTrusted); + var tag = nodeName_(node); + if (attrNormalizedName == "xlinkHref" || tag == "form" && attrNormalizedName == "action" || tag != "img" && (attrNormalizedName == "src" || attrNormalizedName == "ngSrc")) { + return $sce.RESOURCE_URL; } - throw $sceMinErr("unsafe", "Attempting to use an unsafe value in a safe context."); - } - return { - trustAs: trustAs, - getTrusted: getTrusted, - valueOf: valueOf - }; - } ]; - } - function $SceProvider() { - var enabled = true; - this.enabled = function(value) { - if (arguments.length) { - enabled = !!value; - } - return enabled; - }; - this.$get = [ "$parse", "$sceDelegate", function($parse, $sceDelegate) { - if (enabled && msie < 8) { - throw $sceMinErr("iequirks", "Strict Contextual Escaping does not support Internet Explorer version < 11 in quirks " + "mode. You can fix this by adding the text to the top of your HTML " + "document. See http://docs.angularjs.org/api/ng.$sce for more information."); - } - var sce = shallowCopy(SCE_CONTEXTS); - sce.isEnabled = function() { - return enabled; - }; - sce.trustAs = $sceDelegate.trustAs; - sce.getTrusted = $sceDelegate.getTrusted; - sce.valueOf = $sceDelegate.valueOf; - if (!enabled) { - sce.trustAs = sce.getTrusted = function(type, value) { - return value; - }; - sce.valueOf = identity; } - sce.parseAs = function sceParseAs(type, expr) { - var parsed = $parse(expr); - if (parsed.literal && parsed.constant) { - return parsed; - } else { - return $parse(expr, function(value) { - return sce.getTrusted(type, value); - }); + function addAttrInterpolateDirective(node, directives, value, name, allOrNothing) { + var trustedContext = getTrustedContext(node, name); + allOrNothing = ALL_OR_NOTHING_ATTRS[name] || allOrNothing; + var interpolateFn = $interpolate(value, true, trustedContext, allOrNothing); + if (!interpolateFn) return; + if (name === "multiple" && nodeName_(node) === "select") { + throw $compileMinErr("selmulti", "Binding to the 'multiple' attribute is not supported. Element: {0}", startingTag(node)); } - }; - var parse = sce.parseAs, getTrusted = sce.getTrusted, trustAs = sce.trustAs; - forEach(SCE_CONTEXTS, function(enumValue, name) { - var lName = lowercase(name); - sce[camelCase("parse_as_" + lName)] = function(expr) { - return parse(enumValue, expr); - }; - sce[camelCase("get_trusted_" + lName)] = function(value) { - return getTrusted(enumValue, value); - }; - sce[camelCase("trust_as_" + lName)] = function(value) { - return trustAs(enumValue, value); - }; - }); - return sce; - } ]; - } - function $SnifferProvider() { - this.$get = [ "$window", "$document", function($window, $document) { - var eventSupport = {}, android = toInt((/android (\d+)/.exec(lowercase(($window.navigator || {}).userAgent)) || [])[1]), boxee = /Boxee/i.test(($window.navigator || {}).userAgent), document = $document[0] || {}, vendorPrefix, vendorRegex = /^(Moz|webkit|ms)(?=[A-Z])/, bodyStyle = document.body && document.body.style, transitions = false, animations = false, match; - if (bodyStyle) { - for (var prop in bodyStyle) { - if (match = vendorRegex.exec(prop)) { - vendorPrefix = match[0]; - vendorPrefix = vendorPrefix.substr(0, 1).toUpperCase() + vendorPrefix.substr(1); - break; + directives.push({ + priority: 100, + compile: function() { + return { + pre: function attrInterpolatePreLinkFn(scope, element, attr) { + var $$observers = attr.$$observers || (attr.$$observers = createMap()); + if (EVENT_HANDLER_ATTR_REGEXP.test(name)) { + throw $compileMinErr("nodomevents", "Interpolations for HTML DOM event attributes are disallowed. Please use the " + "ng- versions (such as ng-click instead of onclick) instead."); + } + var newValue = attr[name]; + if (newValue !== value) { + interpolateFn = newValue && $interpolate(newValue, true, trustedContext, allOrNothing); + value = newValue; + } + if (!interpolateFn) return; + attr[name] = interpolateFn(scope); + ($$observers[name] || ($$observers[name] = [])).$$inter = true; + (attr.$$observers && attr.$$observers[name].$$scope || scope).$watch(interpolateFn, function interpolateFnWatchAction(newValue, oldValue) { + if (name === "class" && newValue != oldValue) { + attr.$updateClass(newValue, oldValue); + } else { + attr.$set(name, newValue); + } + }); + } + }; } - } - if (!vendorPrefix) { - vendorPrefix = "WebkitOpacity" in bodyStyle && "webkit"; - } - transitions = !!("transition" in bodyStyle || vendorPrefix + "Transition" in bodyStyle); - animations = !!("animation" in bodyStyle || vendorPrefix + "Animation" in bodyStyle); - if (android && (!transitions || !animations)) { - transitions = isString(bodyStyle.webkitTransition); - animations = isString(bodyStyle.webkitAnimation); - } + }); } - return { - history: !!($window.history && $window.history.pushState && !(android < 4) && !boxee), - hasEvent: function(event) { - if (event === "input" && msie <= 11) return false; - if (isUndefined(eventSupport[event])) { - var divElm = document.createElement("div"); - eventSupport[event] = "on" + event in divElm; + function replaceWith($rootElement, elementsToRemove, newNode) { + var firstElementToRemove = elementsToRemove[0], removeCount = elementsToRemove.length, parent = firstElementToRemove.parentNode, i, ii; + if ($rootElement) { + for (i = 0, ii = $rootElement.length; i < ii; i++) { + if ($rootElement[i] == firstElementToRemove) { + $rootElement[i++] = newNode; + for (var j = i, j2 = j + removeCount - 1, jj = $rootElement.length; j < jj; j++, + j2++) { + if (j2 < jj) { + $rootElement[j] = $rootElement[j2]; + } else { + delete $rootElement[j]; + } + } + $rootElement.length -= removeCount - 1; + if ($rootElement.context === firstElementToRemove) { + $rootElement.context = newNode; + } + break; + } } - return eventSupport[event]; - }, - csp: csp(), - vendorPrefix: vendorPrefix, - transitions: transitions, - animations: animations, - android: android - }; - } ]; - } - var $compileMinErr = minErr("$compile"); - function $TemplateRequestProvider() { - this.$get = [ "$templateCache", "$http", "$q", "$sce", function($templateCache, $http, $q, $sce) { - function handleRequestFn(tpl, ignoreRequestError) { - handleRequestFn.totalPendingRequests++; - if (!isString(tpl) || !$templateCache.get(tpl)) { - tpl = $sce.getTrustedResourceUrl(tpl); } - var transformResponse = $http.defaults && $http.defaults.transformResponse; - if (isArray(transformResponse)) { - transformResponse = transformResponse.filter(function(transformer) { - return transformer !== defaultHttpResponseTransform; - }); - } else if (transformResponse === defaultHttpResponseTransform) { - transformResponse = null; + if (parent) { + parent.replaceChild(newNode, firstElementToRemove); } - var httpOptions = { - cache: $templateCache, - transformResponse: transformResponse - }; - return $http.get(tpl, httpOptions)["finally"](function() { - handleRequestFn.totalPendingRequests--; - }).then(function(response) { - $templateCache.put(tpl, response.data); - return response.data; - }, handleError); - function handleError(resp) { - if (!ignoreRequestError) { - throw $compileMinErr("tpload", "Failed to load template: {0} (HTTP status: {1} {2})", tpl, resp.status, resp.statusText); + var fragment = document.createDocumentFragment(); + fragment.appendChild(firstElementToRemove); + if (jqLite.hasData(firstElementToRemove)) { + jqLite(newNode).data(jqLite(firstElementToRemove).data()); + if (!jQuery) { + delete jqLite.cache[firstElementToRemove[jqLite.expando]]; + } else { + skipDestroyOnNextJQueryCleanData = true; + jQuery.cleanData([ firstElementToRemove ]); } - return $q.reject(resp); } + for (var k = 1, kk = elementsToRemove.length; k < kk; k++) { + var element = elementsToRemove[k]; + jqLite(element).remove(); + fragment.appendChild(element); + delete elementsToRemove[k]; + } + elementsToRemove[0] = newNode; + elementsToRemove.length = 1; } - handleRequestFn.totalPendingRequests = 0; - return handleRequestFn; - } ]; - } - function $$TestabilityProvider() { - this.$get = [ "$rootScope", "$browser", "$location", function($rootScope, $browser, $location) { - var testability = {}; - testability.findBindings = function(element, expression, opt_exactMatch) { - var bindings = element.getElementsByClassName("ng-binding"); - var matches = []; - forEach(bindings, function(binding) { - var dataBinding = angular.element(binding).data("$binding"); - if (dataBinding) { - forEach(dataBinding, function(bindingName) { - if (opt_exactMatch) { - var matcher = new RegExp("(^|\\s)" + escapeForRegexp(expression) + "(\\s|\\||$)"); - if (matcher.test(bindingName)) { - matches.push(binding); - } - } else { - if (bindingName.indexOf(expression) != -1) { - matches.push(binding); - } + function cloneAndAnnotateFn(fn, annotation) { + return extend(function() { + return fn.apply(null, arguments); + }, fn, annotation); + } + function invokeLinkFn(linkFn, scope, $element, attrs, controllers, transcludeFn) { + try { + linkFn(scope, $element, attrs, controllers, transcludeFn); + } catch (e) { + $exceptionHandler(e, startingTag($element)); + } + } + function initializeDirectiveBindings(scope, attrs, destination, bindings, directive, newScope) { + var onNewScopeDestroyed; + forEach(bindings, function(definition, scopeName) { + var attrName = definition.attrName, optional = definition.optional, mode = definition.mode, lastValue, parentGet, parentSet, compare; + switch (mode) { + case "@": + if (!optional && !hasOwnProperty.call(attrs, attrName)) { + destination[scopeName] = attrs[attrName] = void 0; + } + attrs.$observe(attrName, function(value) { + if (isString(value)) { + destination[scopeName] = value; } }); + attrs.$$observers[attrName].$$scope = scope; + if (isString(attrs[attrName])) { + destination[scopeName] = $interpolate(attrs[attrName])(scope); + } + break; + + case "=": + if (!hasOwnProperty.call(attrs, attrName)) { + if (optional) break; + attrs[attrName] = void 0; + } + if (optional && !attrs[attrName]) break; + parentGet = $parse(attrs[attrName]); + if (parentGet.literal) { + compare = equals; + } else { + compare = function(a, b) { + return a === b || a !== a && b !== b; + }; + } + parentSet = parentGet.assign || function() { + lastValue = destination[scopeName] = parentGet(scope); + throw $compileMinErr("nonassign", "Expression '{0}' used with directive '{1}' is non-assignable!", attrs[attrName], directive.name); + }; + lastValue = destination[scopeName] = parentGet(scope); + var parentValueWatch = function parentValueWatch(parentValue) { + if (!compare(parentValue, destination[scopeName])) { + if (!compare(parentValue, lastValue)) { + destination[scopeName] = parentValue; + } else { + parentSet(scope, parentValue = destination[scopeName]); + } + } + return lastValue = parentValue; + }; + parentValueWatch.$stateful = true; + var unwatch; + if (definition.collection) { + unwatch = scope.$watchCollection(attrs[attrName], parentValueWatch); + } else { + unwatch = scope.$watch($parse(attrs[attrName], parentValueWatch), null, parentGet.literal); + } + onNewScopeDestroyed = onNewScopeDestroyed || []; + onNewScopeDestroyed.push(unwatch); + break; + + case "&": + parentGet = attrs.hasOwnProperty(attrName) ? $parse(attrs[attrName]) : noop; + if (parentGet === noop && optional) break; + destination[scopeName] = function(locals) { + return parentGet(scope, locals); + }; + break; } }); - return matches; - }; - testability.findModels = function(element, expression, opt_exactMatch) { - var prefixes = [ "ng-", "data-ng-", "ng\\:" ]; - for (var p = 0; p < prefixes.length; ++p) { - var attributeEquals = opt_exactMatch ? "=" : "*="; - var selector = "[" + prefixes[p] + "model" + attributeEquals + '"' + expression + '"]'; - var elements = element.querySelectorAll(selector); - if (elements.length) { - return elements; + var destroyBindings = onNewScopeDestroyed ? function destroyBindings() { + for (var i = 0, ii = onNewScopeDestroyed.length; i < ii; ++i) { + onNewScopeDestroyed[i](); } + } : noop; + if (newScope && destroyBindings !== noop) { + newScope.$on("$destroy", destroyBindings); + return noop; } - }; - testability.getLocation = function() { - return $location.url(); - }; - testability.setLocation = function(url) { - if (url !== $location.url()) { - $location.url(url); - $rootScope.$digest(); - } - }; - testability.whenStable = function(callback) { - $browser.notifyWhenNoOutstandingRequests(callback); - }; - return testability; - } ]; - } - function $TimeoutProvider() { - this.$get = [ "$rootScope", "$browser", "$q", "$$q", "$exceptionHandler", function($rootScope, $browser, $q, $$q, $exceptionHandler) { - var deferreds = {}; - function timeout(fn, delay, invokeApply) { - if (!isFunction(fn)) { - invokeApply = delay; - delay = fn; - fn = noop; - } - var args = sliceArgs(arguments, 3), skipApply = isDefined(invokeApply) && !invokeApply, deferred = (skipApply ? $$q : $q).defer(), promise = deferred.promise, timeoutId; - timeoutId = $browser.defer(function() { - try { - deferred.resolve(fn.apply(null, args)); - } catch (e) { - deferred.reject(e); - $exceptionHandler(e); - } finally { - delete deferreds[promise.$$timeoutId]; - } - if (!skipApply) $rootScope.$apply(); - }, delay); - promise.$$timeoutId = timeoutId; - deferreds[timeoutId] = deferred; - return promise; + return destroyBindings; } - timeout.cancel = function(promise) { - if (promise && promise.$$timeoutId in deferreds) { - deferreds[promise.$$timeoutId].reject("canceled"); - delete deferreds[promise.$$timeoutId]; - return $browser.defer.cancel(promise.$$timeoutId); - } - return false; - }; - return timeout; } ]; } - var urlParsingNode = document.createElement("a"); - var originUrl = urlResolve(window.location.href); - function urlResolve(url) { - var href = url; - if (msie) { - urlParsingNode.setAttribute("href", href); - href = urlParsingNode.href; - } - urlParsingNode.setAttribute("href", href); - return { - href: urlParsingNode.href, - protocol: urlParsingNode.protocol ? urlParsingNode.protocol.replace(/:$/, "") : "", - host: urlParsingNode.host, - search: urlParsingNode.search ? urlParsingNode.search.replace(/^\?/, "") : "", - hash: urlParsingNode.hash ? urlParsingNode.hash.replace(/^#/, "") : "", - hostname: urlParsingNode.hostname, - port: urlParsingNode.port, - pathname: urlParsingNode.pathname.charAt(0) === "/" ? urlParsingNode.pathname : "/" + urlParsingNode.pathname - }; - } - function urlIsSameOrigin(requestUrl) { - var parsed = isString(requestUrl) ? urlResolve(requestUrl) : requestUrl; - return parsed.protocol === originUrl.protocol && parsed.host === originUrl.host; - } - function $WindowProvider() { - this.$get = valueFn(window); + var PREFIX_REGEXP = /^((?:x|data)[\:\-_])/i; + function directiveNormalize(name) { + return camelCase(name.replace(PREFIX_REGEXP, "")); } - function $$CookieReader($document) { - var rawDocument = $document[0] || {}; - var lastCookies = {}; - var lastCookieString = ""; - function safeDecodeURIComponent(str) { - try { - return decodeURIComponent(str); - } catch (e) { - return str; + function nodesetLinkingFn(scope, nodeList, rootElement, boundTranscludeFn) {} + function directiveLinkingFn(nodesetLinkingFn, scope, node, rootElement, boundTranscludeFn) {} + function tokenDifference(str1, str2) { + var values = "", tokens1 = str1.split(/\s+/), tokens2 = str2.split(/\s+/); + outer: for (var i = 0; i < tokens1.length; i++) { + var token = tokens1[i]; + for (var j = 0; j < tokens2.length; j++) { + if (token == tokens2[j]) continue outer; } + values += (values.length > 0 ? " " : "") + token; } - return function() { - var cookieArray, cookie, i, index, name; - var currentCookieString = rawDocument.cookie || ""; - if (currentCookieString !== lastCookieString) { - lastCookieString = currentCookieString; - cookieArray = lastCookieString.split("; "); - lastCookies = {}; - for (i = 0; i < cookieArray.length; i++) { - cookie = cookieArray[i]; - index = cookie.indexOf("="); - if (index > 0) { - name = safeDecodeURIComponent(cookie.substring(0, index)); - if (isUndefined(lastCookies[name])) { - lastCookies[name] = safeDecodeURIComponent(cookie.substring(index + 1)); - } - } - } - } - return lastCookies; - }; - } - $$CookieReader.$inject = [ "$document" ]; - function $$CookieReaderProvider() { - this.$get = $$CookieReader; + return values; } - $FilterProvider.$inject = [ "$provide" ]; - function $FilterProvider($provide) { - var suffix = "Filter"; - function register(name, factory) { - if (isObject(name)) { - var filters = {}; - forEach(name, function(filter, key) { - filters[key] = register(key, filter); - }); - return filters; - } else { - return $provide.factory(name + suffix, factory); + function removeComments(jqNodes) { + jqNodes = jqLite(jqNodes); + var i = jqNodes.length; + if (i <= 1) { + return jqNodes; + } + while (i--) { + var node = jqNodes[i]; + if (node.nodeType === NODE_TYPE_COMMENT) { + splice.call(jqNodes, i, 1); } } - this.register = register; - this.$get = [ "$injector", function($injector) { - return function(name) { - return $injector.get(name + suffix); - }; - } ]; - register("currency", currencyFilter); - register("date", dateFilter); - register("filter", filterFilter); - register("json", jsonFilter); - register("limitTo", limitToFilter); - register("lowercase", lowercaseFilter); - register("number", numberFilter); - register("orderBy", orderByFilter); - register("uppercase", uppercaseFilter); + return jqNodes; } - function filterFilter() { - return function(array, expression, comparator) { - if (!isArrayLike(array)) { - if (array == null) { - return array; - } else { - throw minErr("filter")("notarray", "Expected array but received: {0}", array); - } - } - var expressionType = getTypeForFilter(expression); - var predicateFn; - var matchAgainstAnyProp; - switch (expressionType) { - case "function": - predicateFn = expression; - break; - - case "boolean": - case "null": - case "number": - case "string": - matchAgainstAnyProp = true; - - case "object": - predicateFn = createPredicateFn(expression, comparator, matchAgainstAnyProp); - break; - - default: - return array; + var $controllerMinErr = minErr("$controller"); + var CNTRL_REG = /^(\S+)(\s+as\s+(\w+))?$/; + function identifierForController(controller, ident) { + if (ident && isString(ident)) return ident; + if (isString(controller)) { + var match = CNTRL_REG.exec(controller); + if (match) return match[3]; + } + } + function $ControllerProvider() { + var controllers = {}, globals = false; + this.register = function(name, constructor) { + assertNotHasOwnProperty(name, "controller"); + if (isObject(name)) { + extend(controllers, name); + } else { + controllers[name] = constructor; } - return Array.prototype.filter.call(array, predicateFn); }; - } - function createPredicateFn(expression, comparator, matchAgainstAnyProp) { - var shouldMatchPrimitives = isObject(expression) && "$" in expression; - var predicateFn; - if (comparator === true) { - comparator = equals; - } else if (!isFunction(comparator)) { - comparator = function(actual, expected) { - if (isUndefined(actual)) { - return false; + this.allowGlobals = function() { + globals = true; + }; + this.$get = [ "$injector", "$window", function($injector, $window) { + return function(expression, locals, later, ident) { + var instance, match, constructor, identifier; + later = later === true; + if (ident && isString(ident)) { + identifier = ident; } - if (actual === null || expected === null) { - return actual === expected; + if (isString(expression)) { + match = expression.match(CNTRL_REG); + if (!match) { + throw $controllerMinErr("ctrlfmt", "Badly formed controller string '{0}'. " + "Must match `__name__ as __id__` or `__name__`.", expression); + } + constructor = match[1], identifier = identifier || match[3]; + expression = controllers.hasOwnProperty(constructor) ? controllers[constructor] : getter(locals.$scope, constructor, true) || (globals ? getter($window, constructor, true) : undefined); + assertArgFn(expression, constructor, true); } - if (isObject(expected) || isObject(actual) && !hasCustomToString(actual)) { - return false; + if (later) { + var controllerPrototype = (isArray(expression) ? expression[expression.length - 1] : expression).prototype; + instance = Object.create(controllerPrototype || null); + if (identifier) { + addIdentifier(locals, identifier, instance, constructor || expression.name); + } + var instantiate; + return instantiate = extend(function() { + var result = $injector.invoke(expression, instance, locals, constructor); + if (result !== instance && (isObject(result) || isFunction(result))) { + instance = result; + if (identifier) { + addIdentifier(locals, identifier, instance, constructor || expression.name); + } + } + return instance; + }, { + instance: instance, + identifier: identifier + }); } - actual = lowercase("" + actual); - expected = lowercase("" + expected); - return actual.indexOf(expected) !== -1; + instance = $injector.instantiate(expression, locals, constructor); + if (identifier) { + addIdentifier(locals, identifier, instance, constructor || expression.name); + } + return instance; }; - } - predicateFn = function(item) { - if (shouldMatchPrimitives && !isObject(item)) { - return deepCompare(item, expression.$, comparator, false); + function addIdentifier(locals, identifier, instance, name) { + if (!(locals && isObject(locals.$scope))) { + throw minErr("$controller")("noscp", "Cannot export controller '{0}' as '{1}'! No $scope object provided via `locals`.", name, identifier); + } + locals.$scope[identifier] = instance; } - return deepCompare(item, expression, comparator, matchAgainstAnyProp); - }; - return predicateFn; + } ]; } - function deepCompare(actual, expected, comparator, matchAgainstAnyProp, dontMatchWholeObject) { - var actualType = getTypeForFilter(actual); - var expectedType = getTypeForFilter(expected); - if (expectedType === "string" && expected.charAt(0) === "!") { - return !deepCompare(actual, expected.substring(1), comparator, matchAgainstAnyProp); - } else if (isArray(actual)) { - return actual.some(function(item) { - return deepCompare(item, expected, comparator, matchAgainstAnyProp); - }); - } - switch (actualType) { - case "object": - var key; - if (matchAgainstAnyProp) { - for (key in actual) { - if (key.charAt(0) !== "$" && deepCompare(actual[key], expected, comparator, true)) { - return true; - } - } - return dontMatchWholeObject ? false : deepCompare(actual, expected, comparator, false); - } else if (expectedType === "object") { - for (key in expected) { - var expectedVal = expected[key]; - if (isFunction(expectedVal) || isUndefined(expectedVal)) { - continue; - } - var matchAnyProperty = key === "$"; - var actualVal = matchAnyProperty ? actual : actual[key]; - if (!deepCompare(actualVal, expectedVal, comparator, matchAnyProperty, matchAnyProperty)) { - return false; + function $DocumentProvider() { + this.$get = [ "$window", function(window) { + return jqLite(window.document); + } ]; + } + function $ExceptionHandlerProvider() { + this.$get = [ "$log", function($log) { + return function(exception, cause) { + $log.error.apply($log, arguments); + }; + } ]; + } + var $$ForceReflowProvider = function() { + this.$get = [ "$document", function($document) { + return function(domNode) { + if (domNode) { + if (!domNode.nodeType && domNode instanceof jqLite) { + domNode = domNode[0]; } + } else { + domNode = $document[0].body; } - return true; - } else { - return comparator(actual, expected); - } - break; - - case "function": - return false; - - default: - return comparator(actual, expected); + return domNode.offsetWidth + 1; + }; + } ]; + }; + var APPLICATION_JSON = "application/json"; + var CONTENT_TYPE_APPLICATION_JSON = { + "Content-Type": APPLICATION_JSON + ";charset=utf-8" + }; + var JSON_START = /^\[|^\{(?!\{)/; + var JSON_ENDS = { + "[": /]$/, + "{": /}$/ + }; + var JSON_PROTECTION_PREFIX = /^\)\]\}',?\n/; + var $httpMinErr = minErr("$http"); + var $httpMinErrLegacyFn = function(method) { + return function() { + throw $httpMinErr("legacy", "The method `{0}` on the promise returned from `$http` has been disabled.", method); + }; + }; + function serializeValue(v) { + if (isObject(v)) { + return isDate(v) ? v.toISOString() : toJson(v); } + return v; } - function getTypeForFilter(val) { - return val === null ? "null" : typeof val; - } - currencyFilter.$inject = [ "$locale" ]; - function currencyFilter($locale) { - var formats = $locale.NUMBER_FORMATS; - return function(amount, currencySymbol, fractionSize) { - if (isUndefined(currencySymbol)) { - currencySymbol = formats.CURRENCY_SYM; - } - if (isUndefined(fractionSize)) { - fractionSize = formats.PATTERNS[1].maxFrac; - } - return amount == null ? amount : formatNumber(amount, formats.PATTERNS[1], formats.GROUP_SEP, formats.DECIMAL_SEP, fractionSize).replace(/\u00A4/g, currencySymbol); + function $HttpParamSerializerProvider() { + this.$get = function() { + return function ngParamSerializer(params) { + if (!params) return ""; + var parts = []; + forEachSorted(params, function(value, key) { + if (value === null || isUndefined(value)) return; + if (isArray(value)) { + forEach(value, function(v, k) { + parts.push(encodeUriQuery(key) + "=" + encodeUriQuery(serializeValue(v))); + }); + } else { + parts.push(encodeUriQuery(key) + "=" + encodeUriQuery(serializeValue(value))); + } + }); + return parts.join("&"); + }; }; } - numberFilter.$inject = [ "$locale" ]; - function numberFilter($locale) { - var formats = $locale.NUMBER_FORMATS; - return function(number, fractionSize) { - return number == null ? number : formatNumber(number, formats.PATTERNS[0], formats.GROUP_SEP, formats.DECIMAL_SEP, fractionSize); - }; - } - var DECIMAL_SEP = "."; - function formatNumber(number, pattern, groupSep, decimalSep, fractionSize) { - if (isObject(number)) return ""; - var isNegative = number < 0; - number = Math.abs(number); - var isInfinity = number === Infinity; - if (!isInfinity && !isFinite(number)) return ""; - var numStr = number + "", formatedText = "", hasExponent = false, parts = []; - if (isInfinity) formatedText = "∞"; - if (!isInfinity && numStr.indexOf("e") !== -1) { - var match = numStr.match(/([\d\.]+)e(-?)(\d+)/); - if (match && match[2] == "-" && match[3] > fractionSize + 1) { - number = 0; - } else { - formatedText = numStr; - hasExponent = true; - } - } - if (!isInfinity && !hasExponent) { - var fractionLen = (numStr.split(DECIMAL_SEP)[1] || "").length; - if (isUndefined(fractionSize)) { - fractionSize = Math.min(Math.max(pattern.minFrac, fractionLen), pattern.maxFrac); - } - number = +(Math.round(+(number.toString() + "e" + fractionSize)).toString() + "e" + -fractionSize); - var fraction = ("" + number).split(DECIMAL_SEP); - var whole = fraction[0]; - fraction = fraction[1] || ""; - var i, pos = 0, lgroup = pattern.lgSize, group = pattern.gSize; - if (whole.length >= lgroup + group) { - pos = whole.length - lgroup; - for (i = 0; i < pos; i++) { - if ((pos - i) % group === 0 && i !== 0) { - formatedText += groupSep; + function $HttpParamSerializerJQLikeProvider() { + this.$get = function() { + return function jQueryLikeParamSerializer(params) { + if (!params) return ""; + var parts = []; + serialize(params, "", true); + return parts.join("&"); + function serialize(toSerialize, prefix, topLevel) { + if (toSerialize === null || isUndefined(toSerialize)) return; + if (isArray(toSerialize)) { + forEach(toSerialize, function(value, index) { + serialize(value, prefix + "[" + (isObject(value) ? index : "") + "]"); + }); + } else if (isObject(toSerialize) && !isDate(toSerialize)) { + forEachSorted(toSerialize, function(value, key) { + serialize(value, prefix + (topLevel ? "" : "[") + key + (topLevel ? "" : "]")); + }); + } else { + parts.push(encodeUriQuery(prefix) + "=" + encodeUriQuery(serializeValue(toSerialize))); } - formatedText += whole.charAt(i); } - } - for (i = pos; i < whole.length; i++) { - if ((whole.length - i) % lgroup === 0 && i !== 0) { - formatedText += groupSep; + }; + }; + } + function defaultHttpResponseTransform(data, headers) { + if (isString(data)) { + var tempData = data.replace(JSON_PROTECTION_PREFIX, "").trim(); + if (tempData) { + var contentType = headers("Content-Type"); + if (contentType && contentType.indexOf(APPLICATION_JSON) === 0 || isJsonLike(tempData)) { + data = fromJson(tempData); } - formatedText += whole.charAt(i); - } - while (fraction.length < fractionSize) { - fraction += "0"; - } - if (fractionSize && fractionSize !== "0") formatedText += decimalSep + fraction.substr(0, fractionSize); - } else { - if (fractionSize > 0 && number < 1) { - formatedText = number.toFixed(fractionSize); - number = parseFloat(formatedText); } } - if (number === 0) { - isNegative = false; - } - parts.push(isNegative ? pattern.negPre : pattern.posPre, formatedText, isNegative ? pattern.negSuf : pattern.posSuf); - return parts.join(""); + return data; } - function padNumber(num, digits, trim) { - var neg = ""; - if (num < 0) { - neg = "-"; - num = -num; + function isJsonLike(str) { + var jsonStart = str.match(JSON_START); + return jsonStart && JSON_ENDS[jsonStart[0]].test(str); + } + function parseHeaders(headers) { + var parsed = createMap(), i; + function fillInParsed(key, val) { + if (key) { + parsed[key] = parsed[key] ? parsed[key] + ", " + val : val; + } } - num = "" + num; - while (num.length < digits) num = "0" + num; - if (trim) { - num = num.substr(num.length - digits); + if (isString(headers)) { + forEach(headers.split("\n"), function(line) { + i = line.indexOf(":"); + fillInParsed(lowercase(trim(line.substr(0, i))), trim(line.substr(i + 1))); + }); + } else if (isObject(headers)) { + forEach(headers, function(headerVal, headerKey) { + fillInParsed(lowercase(headerKey), trim(headerVal)); + }); } - return neg + num; + return parsed; } - function dateGetter(name, size, offset, trim) { - offset = offset || 0; - return function(date) { - var value = date["get" + name](); - if (offset > 0 || value > -offset) { - value += offset; + function headersGetter(headers) { + var headersObj; + return function(name) { + if (!headersObj) headersObj = parseHeaders(headers); + if (name) { + var value = headersObj[lowercase(name)]; + if (value === void 0) { + value = null; + } + return value; } - if (value === 0 && offset == -12) value = 12; - return padNumber(value, size, trim); - }; - } - function dateStrGetter(name, shortForm) { - return function(date, formats) { - var value = date["get" + name](); - var get = uppercase(shortForm ? "SHORT" + name : name); - return formats[get][value]; + return headersObj; }; } - function timeZoneGetter(date, formats, offset) { - var zone = -1 * offset; - var paddedZone = zone >= 0 ? "+" : ""; - paddedZone += padNumber(Math[zone > 0 ? "floor" : "ceil"](zone / 60), 2) + padNumber(Math.abs(zone % 60), 2); - return paddedZone; - } - function getFirstThursdayOfYear(year) { - var dayOfWeekOnFirst = new Date(year, 0, 1).getDay(); - return new Date(year, 0, (dayOfWeekOnFirst <= 4 ? 5 : 12) - dayOfWeekOnFirst); + function transformData(data, headers, status, fns) { + if (isFunction(fns)) { + return fns(data, headers, status); + } + forEach(fns, function(fn) { + data = fn(data, headers, status); + }); + return data; } - function getThursdayThisWeek(datetime) { - return new Date(datetime.getFullYear(), datetime.getMonth(), datetime.getDate() + (4 - datetime.getDay())); + function isSuccess(status) { + return 200 <= status && status < 300; } - function weekGetter(size) { - return function(date) { - var firstThurs = getFirstThursdayOfYear(date.getFullYear()), thisThurs = getThursdayThisWeek(date); - var diff = +thisThurs - +firstThurs, result = 1 + Math.round(diff / 6048e5); - return padNumber(result, size); + function $HttpProvider() { + var defaults = this.defaults = { + transformResponse: [ defaultHttpResponseTransform ], + transformRequest: [ function(d) { + return isObject(d) && !isFile(d) && !isBlob(d) && !isFormData(d) ? toJson(d) : d; + } ], + headers: { + common: { + Accept: "application/json, text/plain, */*" + }, + post: shallowCopy(CONTENT_TYPE_APPLICATION_JSON), + put: shallowCopy(CONTENT_TYPE_APPLICATION_JSON), + patch: shallowCopy(CONTENT_TYPE_APPLICATION_JSON) + }, + xsrfCookieName: "XSRF-TOKEN", + xsrfHeaderName: "X-XSRF-TOKEN", + paramSerializer: "$httpParamSerializer" }; - } - function ampmGetter(date, formats) { - return date.getHours() < 12 ? formats.AMPMS[0] : formats.AMPMS[1]; - } - function eraGetter(date, formats) { - return date.getFullYear() <= 0 ? formats.ERAS[0] : formats.ERAS[1]; - } - function longEraGetter(date, formats) { - return date.getFullYear() <= 0 ? formats.ERANAMES[0] : formats.ERANAMES[1]; - } - var DATE_FORMATS = { - yyyy: dateGetter("FullYear", 4), - yy: dateGetter("FullYear", 2, 0, true), - y: dateGetter("FullYear", 1), - MMMM: dateStrGetter("Month"), - MMM: dateStrGetter("Month", true), - MM: dateGetter("Month", 2, 1), - M: dateGetter("Month", 1, 1), - dd: dateGetter("Date", 2), - d: dateGetter("Date", 1), - HH: dateGetter("Hours", 2), - H: dateGetter("Hours", 1), - hh: dateGetter("Hours", 2, -12), - h: dateGetter("Hours", 1, -12), - mm: dateGetter("Minutes", 2), - m: dateGetter("Minutes", 1), - ss: dateGetter("Seconds", 2), - s: dateGetter("Seconds", 1), - sss: dateGetter("Milliseconds", 3), - EEEE: dateStrGetter("Day"), - EEE: dateStrGetter("Day", true), - a: ampmGetter, - Z: timeZoneGetter, - ww: weekGetter(2), - w: weekGetter(1), - G: eraGetter, - GG: eraGetter, - GGG: eraGetter, - GGGG: longEraGetter - }; - var DATE_FORMATS_SPLIT = /((?:[^yMdHhmsaZEwG']+)|(?:'(?:[^']|'')*')|(?:E+|y+|M+|d+|H+|h+|m+|s+|a|Z|G+|w+))(.*)/, NUMBER_STRING = /^\-?\d+$/; - dateFilter.$inject = [ "$locale" ]; - function dateFilter($locale) { - var R_ISO8601_STR = /^(\d{4})-?(\d\d)-?(\d\d)(?:T(\d\d)(?::?(\d\d)(?::?(\d\d)(?:\.(\d+))?)?)?(Z|([+-])(\d\d):?(\d\d))?)?$/; - function jsonStringToDate(string) { - var match; - if (match = string.match(R_ISO8601_STR)) { - var date = new Date(0), tzHour = 0, tzMin = 0, dateSetter = match[8] ? date.setUTCFullYear : date.setFullYear, timeSetter = match[8] ? date.setUTCHours : date.setHours; - if (match[9]) { - tzHour = toInt(match[9] + match[10]); - tzMin = toInt(match[9] + match[11]); - } - dateSetter.call(date, toInt(match[1]), toInt(match[2]) - 1, toInt(match[3])); - var h = toInt(match[4] || 0) - tzHour; - var m = toInt(match[5] || 0) - tzMin; - var s = toInt(match[6] || 0); - var ms = Math.round(parseFloat("0." + (match[7] || 0)) * 1e3); - timeSetter.call(date, h, m, s, ms); - return date; + var useApplyAsync = false; + this.useApplyAsync = function(value) { + if (isDefined(value)) { + useApplyAsync = !!value; + return this; } - return string; - } - return function(date, format, timezone) { - var text = "", parts = [], fn, match; - format = format || "mediumDate"; - format = $locale.DATETIME_FORMATS[format] || format; - if (isString(date)) { - date = NUMBER_STRING.test(date) ? toInt(date) : jsonStringToDate(date); - } - if (isNumber(date)) { - date = new Date(date); - } - if (!isDate(date) || !isFinite(date.getTime())) { - return date; - } - while (format) { - match = DATE_FORMATS_SPLIT.exec(format); - if (match) { - parts = concat(parts, match, 1); - format = parts.pop(); - } else { - parts.push(format); - format = null; - } - } - var dateTimezoneOffset = date.getTimezoneOffset(); - if (timezone) { - dateTimezoneOffset = timezoneToOffset(timezone, date.getTimezoneOffset()); - date = convertTimezoneToLocal(date, timezone, true); - } - forEach(parts, function(value) { - fn = DATE_FORMATS[value]; - text += fn ? fn(date, $locale.DATETIME_FORMATS, dateTimezoneOffset) : value.replace(/(^'|'$)/g, "").replace(/''/g, "'"); - }); - return text; - }; - } - function jsonFilter() { - return function(object, spacing) { - if (isUndefined(spacing)) { - spacing = 2; - } - return toJson(object, spacing); + return useApplyAsync; }; - } - var lowercaseFilter = valueFn(lowercase); - var uppercaseFilter = valueFn(uppercase); - function limitToFilter() { - return function(input, limit, begin) { - if (Math.abs(Number(limit)) === Infinity) { - limit = Number(limit); - } else { - limit = toInt(limit); - } - if (isNaN(limit)) return input; - if (isNumber(input)) input = input.toString(); - if (!isArray(input) && !isString(input)) return input; - begin = !begin || isNaN(begin) ? 0 : toInt(begin); - begin = begin < 0 && begin >= -input.length ? input.length + begin : begin; - if (limit >= 0) { - return input.slice(begin, begin + limit); - } else { - if (begin === 0) { - return input.slice(limit, input.length); - } else { - return input.slice(Math.max(0, begin + limit), begin); - } + var useLegacyPromise = true; + this.useLegacyPromiseExtensions = function(value) { + if (isDefined(value)) { + useLegacyPromise = !!value; + return this; } + return useLegacyPromise; }; - } - orderByFilter.$inject = [ "$parse" ]; - function orderByFilter($parse) { - return function(array, sortPredicate, reverseOrder) { - if (!isArrayLike(array)) return array; - if (!isArray(sortPredicate)) { - sortPredicate = [ sortPredicate ]; - } - if (sortPredicate.length === 0) { - sortPredicate = [ "+" ]; - } - var predicates = processPredicates(sortPredicate, reverseOrder); - predicates.push({ - get: function() { - return {}; - }, - descending: reverseOrder ? -1 : 1 - }); - var compareValues = Array.prototype.map.call(array, getComparisonObject); - compareValues.sort(doComparison); - array = compareValues.map(function(item) { - return item.value; + var interceptorFactories = this.interceptors = []; + this.$get = [ "$httpBackend", "$$cookieReader", "$cacheFactory", "$rootScope", "$q", "$injector", function($httpBackend, $$cookieReader, $cacheFactory, $rootScope, $q, $injector) { + var defaultCache = $cacheFactory("$http"); + defaults.paramSerializer = isString(defaults.paramSerializer) ? $injector.get(defaults.paramSerializer) : defaults.paramSerializer; + var reversedInterceptors = []; + forEach(interceptorFactories, function(interceptorFactory) { + reversedInterceptors.unshift(isString(interceptorFactory) ? $injector.get(interceptorFactory) : $injector.invoke(interceptorFactory)); }); - return array; - function getComparisonObject(value, index) { - return { - value: value, - predicateValues: predicates.map(function(predicate) { - return getPredicateValue(predicate.get(value), index); - }) + function $http(requestConfig) { + if (!angular.isObject(requestConfig)) { + throw minErr("$http")("badreq", "Http request configuration must be an object. Received: {0}", requestConfig); + } + var config = extend({ + method: "get", + transformRequest: defaults.transformRequest, + transformResponse: defaults.transformResponse, + paramSerializer: defaults.paramSerializer + }, requestConfig); + config.headers = mergeHeaders(requestConfig); + config.method = uppercase(config.method); + config.paramSerializer = isString(config.paramSerializer) ? $injector.get(config.paramSerializer) : config.paramSerializer; + var serverRequest = function(config) { + var headers = config.headers; + var reqData = transformData(config.data, headersGetter(headers), undefined, config.transformRequest); + if (isUndefined(reqData)) { + forEach(headers, function(value, header) { + if (lowercase(header) === "content-type") { + delete headers[header]; + } + }); + } + if (isUndefined(config.withCredentials) && !isUndefined(defaults.withCredentials)) { + config.withCredentials = defaults.withCredentials; + } + return sendReq(config, reqData).then(transformResponse, transformResponse); }; - } - function doComparison(v1, v2) { - var result = 0; - for (var index = 0, length = predicates.length; index < length; ++index) { - result = compare(v1.predicateValues[index], v2.predicateValues[index]) * predicates[index].descending; - if (result) break; + var chain = [ serverRequest, undefined ]; + var promise = $q.when(config); + forEach(reversedInterceptors, function(interceptor) { + if (interceptor.request || interceptor.requestError) { + chain.unshift(interceptor.request, interceptor.requestError); + } + if (interceptor.response || interceptor.responseError) { + chain.push(interceptor.response, interceptor.responseError); + } + }); + while (chain.length) { + var thenFn = chain.shift(); + var rejectFn = chain.shift(); + promise = promise.then(thenFn, rejectFn); } - return result; - } - }; - function processPredicates(sortPredicate, reverseOrder) { - reverseOrder = reverseOrder ? -1 : 1; - return sortPredicate.map(function(predicate) { - var descending = 1, get = identity; - if (isFunction(predicate)) { - get = predicate; - } else if (isString(predicate)) { - if (predicate.charAt(0) == "+" || predicate.charAt(0) == "-") { - descending = predicate.charAt(0) == "-" ? -1 : 1; - predicate = predicate.substring(1); + if (useLegacyPromise) { + promise.success = function(fn) { + assertArgFn(fn, "fn"); + promise.then(function(response) { + fn(response.data, response.status, response.headers, config); + }); + return promise; + }; + promise.error = function(fn) { + assertArgFn(fn, "fn"); + promise.then(null, function(response) { + fn(response.data, response.status, response.headers, config); + }); + return promise; + }; + } else { + promise.success = $httpMinErrLegacyFn("success"); + promise.error = $httpMinErrLegacyFn("error"); + } + return promise; + function transformResponse(response) { + var resp = extend({}, response); + if (!response.data) { + resp.data = response.data; + } else { + resp.data = transformData(response.data, response.headers, response.status, config.transformResponse); } - if (predicate !== "") { - get = $parse(predicate); - if (get.constant) { - var key = get(); - get = function(value) { - return value[key]; - }; + return isSuccess(response.status) ? resp : $q.reject(resp); + } + function executeHeaderFns(headers, config) { + var headerContent, processedHeaders = {}; + forEach(headers, function(headerFn, header) { + if (isFunction(headerFn)) { + headerContent = headerFn(config); + if (headerContent != null) { + processedHeaders[header] = headerContent; + } + } else { + processedHeaders[header] = headerFn; + } + }); + return processedHeaders; + } + function mergeHeaders(config) { + var defHeaders = defaults.headers, reqHeaders = extend({}, config.headers), defHeaderName, lowercaseDefHeaderName, reqHeaderName; + defHeaders = extend({}, defHeaders.common, defHeaders[lowercase(config.method)]); + defaultHeadersIteration: for (defHeaderName in defHeaders) { + lowercaseDefHeaderName = lowercase(defHeaderName); + for (reqHeaderName in reqHeaders) { + if (lowercase(reqHeaderName) === lowercaseDefHeaderName) { + continue defaultHeadersIteration; + } } + reqHeaders[defHeaderName] = defHeaders[defHeaderName]; } + return executeHeaderFns(reqHeaders, shallowCopy(config)); } - return { - get: get, - descending: descending * reverseOrder - }; - }); - } - function isPrimitive(value) { - switch (typeof value) { - case "number": - case "boolean": - case "string": - return true; - - default: - return false; } - } - function objectValue(value, index) { - if (typeof value.valueOf === "function") { - value = value.valueOf(); - if (isPrimitive(value)) return value; + $http.pendingRequests = []; + createShortMethods("get", "delete", "head", "jsonp"); + createShortMethodsWithData("post", "put", "patch"); + $http.defaults = defaults; + return $http; + function createShortMethods(names) { + forEach(arguments, function(name) { + $http[name] = function(url, config) { + return $http(extend({}, config || {}, { + method: name, + url: url + })); + }; + }); } - if (hasCustomToString(value)) { - value = value.toString(); - if (isPrimitive(value)) return value; + function createShortMethodsWithData(name) { + forEach(arguments, function(name) { + $http[name] = function(url, data, config) { + return $http(extend({}, config || {}, { + method: name, + url: url, + data: data + })); + }; + }); } - return index; - } - function getPredicateValue(value, index) { - var type = typeof value; - if (value === null) { - type = "string"; - value = "null"; - } else if (type === "string") { - value = value.toLowerCase(); - } else if (type === "object") { - value = objectValue(value, index); + function sendReq(config, reqData) { + var deferred = $q.defer(), promise = deferred.promise, cache, cachedResp, reqHeaders = config.headers, url = buildUrl(config.url, config.paramSerializer(config.params)); + $http.pendingRequests.push(config); + promise.then(removePendingReq, removePendingReq); + if ((config.cache || defaults.cache) && config.cache !== false && (config.method === "GET" || config.method === "JSONP")) { + cache = isObject(config.cache) ? config.cache : isObject(defaults.cache) ? defaults.cache : defaultCache; + } + if (cache) { + cachedResp = cache.get(url); + if (isDefined(cachedResp)) { + if (isPromiseLike(cachedResp)) { + cachedResp.then(resolvePromiseWithResult, resolvePromiseWithResult); + } else { + if (isArray(cachedResp)) { + resolvePromise(cachedResp[1], cachedResp[0], shallowCopy(cachedResp[2]), cachedResp[3]); + } else { + resolvePromise(cachedResp, 200, {}, "OK"); + } + } + } else { + cache.put(url, promise); + } + } + if (isUndefined(cachedResp)) { + var xsrfValue = urlIsSameOrigin(config.url) ? $$cookieReader()[config.xsrfCookieName || defaults.xsrfCookieName] : undefined; + if (xsrfValue) { + reqHeaders[config.xsrfHeaderName || defaults.xsrfHeaderName] = xsrfValue; + } + $httpBackend(config.method, url, reqData, done, reqHeaders, config.timeout, config.withCredentials, config.responseType); + } + return promise; + function done(status, response, headersString, statusText) { + if (cache) { + if (isSuccess(status)) { + cache.put(url, [ status, response, parseHeaders(headersString), statusText ]); + } else { + cache.remove(url); + } + } + function resolveHttpPromise() { + resolvePromise(response, status, headersString, statusText); + } + if (useApplyAsync) { + $rootScope.$applyAsync(resolveHttpPromise); + } else { + resolveHttpPromise(); + if (!$rootScope.$$phase) $rootScope.$apply(); + } + } + function resolvePromise(response, status, headers, statusText) { + status = status >= -1 ? status : 0; + (isSuccess(status) ? deferred.resolve : deferred.reject)({ + data: response, + status: status, + headers: headersGetter(headers), + config: config, + statusText: statusText + }); + } + function resolvePromiseWithResult(result) { + resolvePromise(result.data, result.status, shallowCopy(result.headers()), result.statusText); + } + function removePendingReq() { + var idx = $http.pendingRequests.indexOf(config); + if (idx !== -1) $http.pendingRequests.splice(idx, 1); + } } - return { - value: value, - type: type - }; - } - function compare(v1, v2) { - var result = 0; - if (v1.type === v2.type) { - if (v1.value !== v2.value) { - result = v1.value < v2.value ? -1 : 1; + function buildUrl(url, serializedParams) { + if (serializedParams.length > 0) { + url += (url.indexOf("?") == -1 ? "?" : "&") + serializedParams; } - } else { - result = v1.type < v2.type ? -1 : 1; + return url; } - return result; - } + } ]; } - function ngDirective(directive) { - if (isFunction(directive)) { - directive = { - link: directive + function $xhrFactoryProvider() { + this.$get = function() { + return function createXhr() { + return new window.XMLHttpRequest(); }; - } - directive.restrict = directive.restrict || "AC"; - return valueFn(directive); + }; } - var htmlAnchorDirective = valueFn({ - restrict: "E", - compile: function(element, attr) { - if (!attr.href && !attr.xlinkHref) { - return function(scope, element) { - if (element[0].nodeName.toLowerCase() !== "a") return; - var href = toString.call(element.prop("href")) === "[object SVGAnimatedString]" ? "xlink:href" : "href"; - element.on("click", function(event) { - if (!element.attr(href)) { - event.preventDefault(); - } - }); + function $HttpBackendProvider() { + this.$get = [ "$browser", "$window", "$document", "$xhrFactory", function($browser, $window, $document, $xhrFactory) { + return createHttpBackend($browser, $xhrFactory, $browser.defer, $window.angular.callbacks, $document[0]); + } ]; + } + function createHttpBackend($browser, createXhr, $browserDefer, callbacks, rawDocument) { + return function(method, url, post, callback, headers, timeout, withCredentials, responseType) { + $browser.$$incOutstandingRequestCount(); + url = url || $browser.url(); + if (lowercase(method) == "jsonp") { + var callbackId = "_" + (callbacks.counter++).toString(36); + callbacks[callbackId] = function(data) { + callbacks[callbackId].data = data; + callbacks[callbackId].called = true; + }; + var jsonpDone = jsonpReq(url.replace("JSON_CALLBACK", "angular.callbacks." + callbackId), callbackId, function(status, text) { + completeRequest(callback, status, callbacks[callbackId].data, "", text); + callbacks[callbackId] = noop; + }); + } else { + var xhr = createXhr(method, url); + xhr.open(method, url, true); + forEach(headers, function(value, key) { + if (isDefined(value)) { + xhr.setRequestHeader(key, value); + } + }); + xhr.onload = function requestLoaded() { + var statusText = xhr.statusText || ""; + var response = "response" in xhr ? xhr.response : xhr.responseText; + var status = xhr.status === 1223 ? 204 : xhr.status; + if (status === 0) { + status = response ? 200 : urlResolve(url).protocol == "file" ? 404 : 0; + } + completeRequest(callback, status, response, xhr.getAllResponseHeaders(), statusText); + }; + var requestError = function() { + completeRequest(callback, -1, null, null, ""); }; + xhr.onerror = requestError; + xhr.onabort = requestError; + if (withCredentials) { + xhr.withCredentials = true; + } + if (responseType) { + try { + xhr.responseType = responseType; + } catch (e) { + if (responseType !== "json") { + throw e; + } + } + } + xhr.send(isUndefined(post) ? null : post); } - } - }); - var ngAttributeAliasDirectives = {}; - forEach(BOOLEAN_ATTR, function(propName, attrName) { - if (propName == "multiple") return; - function defaultLinkFn(scope, element, attr) { - scope.$watch(attr[normalized], function ngBooleanAttrWatchAction(value) { - attr.$set(attrName, !!value); - }); - } - var normalized = directiveNormalize("ng-" + attrName); - var linkFn = defaultLinkFn; - if (propName === "checked") { - linkFn = function(scope, element, attr) { - if (attr.ngModel !== attr[normalized]) { - defaultLinkFn(scope, element, attr); + if (timeout > 0) { + var timeoutId = $browserDefer(timeoutRequest, timeout); + } else if (isPromiseLike(timeout)) { + timeout.then(timeoutRequest); + } + function timeoutRequest() { + jsonpDone && jsonpDone(); + xhr && xhr.abort(); + } + function completeRequest(callback, status, response, headersString, statusText) { + if (isDefined(timeoutId)) { + $browserDefer.cancel(timeoutId); } - }; - } - ngAttributeAliasDirectives[normalized] = function() { - return { - restrict: "A", - priority: 100, - link: linkFn - }; + jsonpDone = xhr = null; + callback(status, response, headersString, statusText); + $browser.$$completeOutstandingRequest(noop); + } }; - }); - forEach(ALIASED_ATTR, function(htmlAttr, ngAttr) { - ngAttributeAliasDirectives[ngAttr] = function() { - return { - priority: 100, - link: function(scope, element, attr) { - if (ngAttr === "ngPattern" && attr.ngPattern.charAt(0) == "/") { - var match = attr.ngPattern.match(REGEX_STRING_REGEXP); - if (match) { - attr.$set("ngPattern", new RegExp(match[1], match[2])); - return; - } + function jsonpReq(url, callbackId, done) { + var script = rawDocument.createElement("script"), callback = null; + script.type = "text/javascript"; + script.src = url; + script.async = true; + callback = function(event) { + removeEventListenerFn(script, "load", callback); + removeEventListenerFn(script, "error", callback); + rawDocument.body.removeChild(script); + script = null; + var status = -1; + var text = "unknown"; + if (event) { + if (event.type === "load" && !callbacks[callbackId].called) { + event = { + type: "error" + }; } - scope.$watch(attr[ngAttr], function ngAttrAliasWatchAction(value) { - attr.$set(ngAttr, value); - }); + text = event.type; + status = event.type === "error" ? 404 : 200; + } + if (done) { + done(status, text); } }; - }; - }); - forEach([ "src", "srcset", "href" ], function(attrName) { - var normalized = directiveNormalize("ng-" + attrName); - ngAttributeAliasDirectives[normalized] = function() { - return { - priority: 99, - link: function(scope, element, attr) { - var propName = attrName, name = attrName; - if (attrName === "href" && toString.call(element.prop("href")) === "[object SVGAnimatedString]") { - name = "xlinkHref"; - attr.$attr[name] = "xlink:href"; - propName = null; - } - attr.$observe(normalized, function(value) { - if (!value) { - if (attrName === "href") { - attr.$set(name, null); - } - return; - } - attr.$set(name, value); - if (msie && propName) element.prop(propName, attr[name]); - }); - } - }; - }; - }); - var nullFormCtrl = { - $addControl: noop, - $$renameControl: nullFormRenameControl, - $removeControl: noop, - $setValidity: noop, - $setDirty: noop, - $setPristine: noop, - $setSubmitted: noop - }, SUBMITTED_CLASS = "ng-submitted"; - function nullFormRenameControl(control, name) { - control.$name = name; + addEventListenerFn(script, "load", callback); + addEventListenerFn(script, "error", callback); + rawDocument.body.appendChild(script); + return callback; + } } - FormController.$inject = [ "$element", "$attrs", "$scope", "$animate", "$interpolate" ]; - function FormController(element, attrs, $scope, $animate, $interpolate) { - var form = this, controls = []; - form.$error = {}; - form.$$success = {}; - form.$pending = undefined; - form.$name = $interpolate(attrs.name || attrs.ngForm || "")($scope); - form.$dirty = false; - form.$pristine = true; - form.$valid = true; - form.$invalid = false; - form.$submitted = false; - form.$$parentForm = nullFormCtrl; - form.$rollbackViewValue = function() { - forEach(controls, function(control) { - control.$rollbackViewValue(); - }); - }; - form.$commitViewValue = function() { - forEach(controls, function(control) { - control.$commitViewValue(); - }); - }; - form.$addControl = function(control) { - assertNotHasOwnProperty(control.$name, "input"); - controls.push(control); - if (control.$name) { - form[control.$name] = control; + var $interpolateMinErr = angular.$interpolateMinErr = minErr("$interpolate"); + $interpolateMinErr.throwNoconcat = function(text) { + throw $interpolateMinErr("noconcat", "Error while interpolating: {0}\nStrict Contextual Escaping disallows " + "interpolations that concatenate multiple expressions when a trusted value is " + "required. See http://docs.angularjs.org/api/ng.$sce", text); + }; + $interpolateMinErr.interr = function(text, err) { + return $interpolateMinErr("interr", "Can't interpolate: {0}\n{1}", text, err.toString()); + }; + function $InterpolateProvider() { + var startSymbol = "{{"; + var endSymbol = "}}"; + this.startSymbol = function(value) { + if (value) { + startSymbol = value; + return this; + } else { + return startSymbol; } - control.$$parentForm = form; }; - form.$$renameControl = function(control, newName) { - var oldName = control.$name; - if (form[oldName] === control) { - delete form[oldName]; + this.endSymbol = function(value) { + if (value) { + endSymbol = value; + return this; + } else { + return endSymbol; } - form[newName] = control; - control.$name = newName; }; - form.$removeControl = function(control) { - if (control.$name && form[control.$name] === control) { - delete form[control.$name]; + this.$get = [ "$parse", "$exceptionHandler", "$sce", function($parse, $exceptionHandler, $sce) { + var startSymbolLength = startSymbol.length, endSymbolLength = endSymbol.length, escapedStartRegexp = new RegExp(startSymbol.replace(/./g, escape), "g"), escapedEndRegexp = new RegExp(endSymbol.replace(/./g, escape), "g"); + function escape(ch) { + return "\\\\\\" + ch; } - forEach(form.$pending, function(value, name) { - form.$setValidity(name, null, control); - }); - forEach(form.$error, function(value, name) { - form.$setValidity(name, null, control); - }); - forEach(form.$$success, function(value, name) { - form.$setValidity(name, null, control); - }); - arrayRemove(controls, control); - control.$$parentForm = nullFormCtrl; - }; - addSetValidityMethod({ - ctrl: this, - $element: element, - set: function(object, property, controller) { - var list = object[property]; - if (!list) { - object[property] = [ controller ]; - } else { - var index = list.indexOf(controller); - if (index === -1) { - list.push(controller); - } - } - }, - unset: function(object, property, controller) { - var list = object[property]; - if (!list) { - return; + function unescapeText(text) { + return text.replace(escapedStartRegexp, startSymbol).replace(escapedEndRegexp, endSymbol); + } + function stringify(value) { + if (value == null) { + return ""; } - arrayRemove(list, controller); - if (list.length === 0) { - delete object[property]; + switch (typeof value) { + case "string": + break; + + case "number": + value = "" + value; + break; + + default: + value = toJson(value); } - }, - $animate: $animate - }); - form.$setDirty = function() { - $animate.removeClass(element, PRISTINE_CLASS); - $animate.addClass(element, DIRTY_CLASS); - form.$dirty = true; - form.$pristine = false; - form.$$parentForm.$setDirty(); - }; - form.$setPristine = function() { - $animate.setClass(element, PRISTINE_CLASS, DIRTY_CLASS + " " + SUBMITTED_CLASS); - form.$dirty = false; - form.$pristine = true; - form.$submitted = false; - forEach(controls, function(control) { - control.$setPristine(); - }); - }; - form.$setUntouched = function() { - forEach(controls, function(control) { - control.$setUntouched(); - }); - }; - form.$setSubmitted = function() { - $animate.addClass(element, SUBMITTED_CLASS); - form.$submitted = true; - form.$$parentForm.$setSubmitted(); - }; - } - var formDirectiveFactory = function(isNgForm) { - return [ "$timeout", "$parse", function($timeout, $parse) { - var formDirective = { - name: "form", - restrict: isNgForm ? "EAC" : "E", - require: [ "form", "^^?form" ], - controller: FormController, - compile: function ngFormCompile(formElement, attr) { - formElement.addClass(PRISTINE_CLASS).addClass(VALID_CLASS); - var nameAttr = attr.name ? "name" : isNgForm && attr.ngForm ? "ngForm" : false; - return { - pre: function ngFormPreLink(scope, formElement, attr, ctrls) { - var controller = ctrls[0]; - if (!("action" in attr)) { - var handleFormSubmission = function(event) { - scope.$apply(function() { - controller.$commitViewValue(); - controller.$setSubmitted(); - }); - event.preventDefault(); - }; - addEventListenerFn(formElement[0], "submit", handleFormSubmission); - formElement.on("$destroy", function() { - $timeout(function() { - removeEventListenerFn(formElement[0], "submit", handleFormSubmission); - }, 0, false); - }); - } - var parentFormCtrl = ctrls[1] || controller.$$parentForm; - parentFormCtrl.$addControl(controller); - var setter = nameAttr ? getSetter(controller.$name) : noop; - if (nameAttr) { - setter(scope, controller); - attr.$observe(nameAttr, function(newValue) { - if (controller.$name === newValue) return; - setter(scope, undefined); - controller.$$parentForm.$$renameControl(controller, newValue); - setter = getSetter(controller.$name); - setter(scope, controller); - }); - } - formElement.on("$destroy", function() { - controller.$$parentForm.$removeControl(controller); - setter(scope, undefined); - extend(controller, nullFormCtrl); - }); + return value; + } + function $interpolate(text, mustHaveExpression, trustedContext, allOrNothing) { + allOrNothing = !!allOrNothing; + var startIndex, endIndex, index = 0, expressions = [], parseFns = [], textLength = text.length, exp, concat = [], expressionPositions = []; + while (index < textLength) { + if ((startIndex = text.indexOf(startSymbol, index)) != -1 && (endIndex = text.indexOf(endSymbol, startIndex + startSymbolLength)) != -1) { + if (index !== startIndex) { + concat.push(unescapeText(text.substring(index, startIndex))); } - }; + exp = text.substring(startIndex + startSymbolLength, endIndex); + expressions.push(exp); + parseFns.push($parse(exp, parseStringifyInterceptor)); + index = endIndex + endSymbolLength; + expressionPositions.push(concat.length); + concat.push(""); + } else { + if (index !== textLength) { + concat.push(unescapeText(text.substring(index))); + } + break; + } } - }; - return formDirective; - function getSetter(expression) { - if (expression === "") { - return $parse('this[""]').assign; + if (trustedContext && concat.length > 1) { + $interpolateMinErr.throwNoconcat(text); + } + if (!mustHaveExpression || expressions.length) { + var compute = function(values) { + for (var i = 0, ii = expressions.length; i < ii; i++) { + if (allOrNothing && isUndefined(values[i])) return; + concat[expressionPositions[i]] = values[i]; + } + return concat.join(""); + }; + var getValue = function(value) { + return trustedContext ? $sce.getTrusted(trustedContext, value) : $sce.valueOf(value); + }; + return extend(function interpolationFn(context) { + var i = 0; + var ii = expressions.length; + var values = new Array(ii); + try { + for (;i < ii; i++) { + values[i] = parseFns[i](context); + } + return compute(values); + } catch (err) { + $exceptionHandler($interpolateMinErr.interr(text, err)); + } + }, { + exp: text, + expressions: expressions, + $$watchDelegate: function(scope, listener) { + var lastValue; + return scope.$watchGroup(parseFns, function interpolateFnWatcher(values, oldValues) { + var currValue = compute(values); + if (isFunction(listener)) { + listener.call(this, currValue, values !== oldValues ? lastValue : currValue, scope); + } + lastValue = currValue; + }); + } + }); + } + function parseStringifyInterceptor(value) { + try { + value = getValue(value); + return allOrNothing && !isDefined(value) ? value : stringify(value); + } catch (err) { + $exceptionHandler($interpolateMinErr.interr(text, err)); + } } - return $parse(expression).assign || noop; } + $interpolate.startSymbol = function() { + return startSymbol; + }; + $interpolate.endSymbol = function() { + return endSymbol; + }; + return $interpolate; } ]; - }; - var formDirective = formDirectiveFactory(); - var ngFormDirective = formDirectiveFactory(true); - var ISO_DATE_REGEXP = /\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d:[0-5]\d\.\d+([+-][0-2]\d:[0-5]\d|Z)/; - var URL_REGEXP = /^(ftp|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?$/; - var EMAIL_REGEXP = /^[a-z0-9!#$%&'*+\/=?^_`{|}~.-]+@[a-z0-9]([a-z0-9-]*[a-z0-9])?(\.[a-z0-9]([a-z0-9-]*[a-z0-9])?)*$/i; - var NUMBER_REGEXP = /^\s*(\-|\+)?(\d+|(\d*(\.\d*)))([eE][+-]?\d+)?\s*$/; - var DATE_REGEXP = /^(\d{4})-(\d{2})-(\d{2})$/; - var DATETIMELOCAL_REGEXP = /^(\d{4})-(\d\d)-(\d\d)T(\d\d):(\d\d)(?::(\d\d)(\.\d{1,3})?)?$/; - var WEEK_REGEXP = /^(\d{4})-W(\d\d)$/; - var MONTH_REGEXP = /^(\d{4})-(\d\d)$/; - var TIME_REGEXP = /^(\d\d):(\d\d)(?::(\d\d)(\.\d{1,3})?)?$/; - var inputType = { - text: textInputType, - date: createDateInputType("date", DATE_REGEXP, createDateParser(DATE_REGEXP, [ "yyyy", "MM", "dd" ]), "yyyy-MM-dd"), - "datetime-local": createDateInputType("datetimelocal", DATETIMELOCAL_REGEXP, createDateParser(DATETIMELOCAL_REGEXP, [ "yyyy", "MM", "dd", "HH", "mm", "ss", "sss" ]), "yyyy-MM-ddTHH:mm:ss.sss"), - time: createDateInputType("time", TIME_REGEXP, createDateParser(TIME_REGEXP, [ "HH", "mm", "ss", "sss" ]), "HH:mm:ss.sss"), - week: createDateInputType("week", WEEK_REGEXP, weekParser, "yyyy-Www"), - month: createDateInputType("month", MONTH_REGEXP, createDateParser(MONTH_REGEXP, [ "yyyy", "MM" ]), "yyyy-MM"), - number: numberInputType, - url: urlInputType, - email: emailInputType, - radio: radioInputType, - checkbox: checkboxInputType, - hidden: noop, - button: noop, - submit: noop, - reset: noop, - file: noop - }; - function stringBasedInputType(ctrl) { - ctrl.$formatters.push(function(value) { - return ctrl.$isEmpty(value) ? value : value.toString(); - }); - } - function textInputType(scope, element, attr, ctrl, $sniffer, $browser) { - baseInputType(scope, element, attr, ctrl, $sniffer, $browser); - stringBasedInputType(ctrl); } - function baseInputType(scope, element, attr, ctrl, $sniffer, $browser) { - var type = lowercase(element[0].type); - if (!$sniffer.android) { - var composing = false; - element.on("compositionstart", function(data) { - composing = true; - }); - element.on("compositionend", function() { - composing = false; - listener(); - }); - } - var listener = function(ev) { - if (timeout) { - $browser.defer.cancel(timeout); - timeout = null; - } - if (composing) return; - var value = element.val(), event = ev && ev.type; - if (type !== "password" && (!attr.ngTrim || attr.ngTrim !== "false")) { - value = trim(value); - } - if (ctrl.$viewValue !== value || value === "" && ctrl.$$hasNativeValidators) { - ctrl.$setViewValue(value, event); + function $IntervalProvider() { + this.$get = [ "$rootScope", "$window", "$q", "$$q", function($rootScope, $window, $q, $$q) { + var intervals = {}; + function interval(fn, delay, count, invokeApply) { + var hasParams = arguments.length > 4, args = hasParams ? sliceArgs(arguments, 4) : [], setInterval = $window.setInterval, clearInterval = $window.clearInterval, iteration = 0, skipApply = isDefined(invokeApply) && !invokeApply, deferred = (skipApply ? $$q : $q).defer(), promise = deferred.promise; + count = isDefined(count) ? count : 0; + promise.then(null, null, !hasParams ? fn : function() { + fn.apply(null, args); + }); + promise.$$intervalId = setInterval(function tick() { + deferred.notify(iteration++); + if (count > 0 && iteration >= count) { + deferred.resolve(iteration); + clearInterval(promise.$$intervalId); + delete intervals[promise.$$intervalId]; + } + if (!skipApply) $rootScope.$apply(); + }, delay); + intervals[promise.$$intervalId] = deferred; + return promise; } - }; - if ($sniffer.hasEvent("input")) { - element.on("input", listener); - } else { - var timeout; - var deferListener = function(ev, input, origValue) { - if (!timeout) { - timeout = $browser.defer(function() { - timeout = null; - if (!input || input.value !== origValue) { - listener(ev); - } - }); + interval.cancel = function(promise) { + if (promise && promise.$$intervalId in intervals) { + intervals[promise.$$intervalId].reject("canceled"); + $window.clearInterval(promise.$$intervalId); + delete intervals[promise.$$intervalId]; + return true; } + return false; }; - element.on("keydown", function(event) { - var key = event.keyCode; - if (key === 91 || 15 < key && key < 19 || 37 <= key && key <= 40) return; - deferListener(event, this, this.value); - }); - if ($sniffer.hasEvent("paste")) { - element.on("paste cut", deferListener); - } + return interval; + } ]; + } + var PATH_MATCH = /^([^\?#]*)(\?([^#]*))?(#(.*))?$/, DEFAULT_PORTS = { + http: 80, + https: 443, + ftp: 21 + }; + var $locationMinErr = minErr("$location"); + function encodePath(path) { + var segments = path.split("/"), i = segments.length; + while (i--) { + segments[i] = encodeUriSegment(segments[i]); } - element.on("change", listener); - ctrl.$render = function() { - var value = ctrl.$isEmpty(ctrl.$viewValue) ? "" : ctrl.$viewValue; - if (element.val() !== value) { - element.val(value); - } - }; + return segments.join("/"); } - function weekParser(isoWeek, existingDate) { - if (isDate(isoWeek)) { - return isoWeek; + function parseAbsoluteUrl(absoluteUrl, locationObj) { + var parsedUrl = urlResolve(absoluteUrl); + locationObj.$$protocol = parsedUrl.protocol; + locationObj.$$host = parsedUrl.hostname; + locationObj.$$port = toInt(parsedUrl.port) || DEFAULT_PORTS[parsedUrl.protocol] || null; + } + function parseAppUrl(relativeUrl, locationObj) { + var prefixed = relativeUrl.charAt(0) !== "/"; + if (prefixed) { + relativeUrl = "/" + relativeUrl; } - if (isString(isoWeek)) { - WEEK_REGEXP.lastIndex = 0; - var parts = WEEK_REGEXP.exec(isoWeek); - if (parts) { - var year = +parts[1], week = +parts[2], hours = 0, minutes = 0, seconds = 0, milliseconds = 0, firstThurs = getFirstThursdayOfYear(year), addDays = (week - 1) * 7; - if (existingDate) { - hours = existingDate.getHours(); - minutes = existingDate.getMinutes(); - seconds = existingDate.getSeconds(); - milliseconds = existingDate.getMilliseconds(); - } - return new Date(year, 0, firstThurs.getDate() + addDays, hours, minutes, seconds, milliseconds); - } + var match = urlResolve(relativeUrl); + locationObj.$$path = decodeURIComponent(prefixed && match.pathname.charAt(0) === "/" ? match.pathname.substring(1) : match.pathname); + locationObj.$$search = parseKeyValue(match.search); + locationObj.$$hash = decodeURIComponent(match.hash); + if (locationObj.$$path && locationObj.$$path.charAt(0) != "/") { + locationObj.$$path = "/" + locationObj.$$path; } - return NaN; } - function createDateParser(regexp, mapping) { - return function(iso, date) { - var parts, map; - if (isDate(iso)) { - return iso; + function beginsWith(begin, whole) { + if (whole.indexOf(begin) === 0) { + return whole.substr(begin.length); + } + } + function stripHash(url) { + var index = url.indexOf("#"); + return index == -1 ? url : url.substr(0, index); + } + function trimEmptyHash(url) { + return url.replace(/(#.+)|#$/, "$1"); + } + function stripFile(url) { + return url.substr(0, stripHash(url).lastIndexOf("/") + 1); + } + function serverBase(url) { + return url.substring(0, url.indexOf("/", url.indexOf("//") + 2)); + } + function LocationHtml5Url(appBase, appBaseNoFile, basePrefix) { + this.$$html5 = true; + basePrefix = basePrefix || ""; + parseAbsoluteUrl(appBase, this); + this.$$parse = function(url) { + var pathUrl = beginsWith(appBaseNoFile, url); + if (!isString(pathUrl)) { + throw $locationMinErr("ipthprfx", 'Invalid url "{0}", missing path prefix "{1}".', url, appBaseNoFile); } - if (isString(iso)) { - if (iso.charAt(0) == '"' && iso.charAt(iso.length - 1) == '"') { - iso = iso.substring(1, iso.length - 1); - } - if (ISO_DATE_REGEXP.test(iso)) { - return new Date(iso); - } - regexp.lastIndex = 0; - parts = regexp.exec(iso); - if (parts) { - parts.shift(); - if (date) { - map = { - yyyy: date.getFullYear(), - MM: date.getMonth() + 1, - dd: date.getDate(), - HH: date.getHours(), - mm: date.getMinutes(), - ss: date.getSeconds(), - sss: date.getMilliseconds() / 1e3 - }; - } else { - map = { - yyyy: 1970, - MM: 1, - dd: 1, - HH: 0, - mm: 0, - ss: 0, - sss: 0 - }; - } - forEach(parts, function(part, index) { - if (index < mapping.length) { - map[mapping[index]] = +part; - } - }); - return new Date(map.yyyy, map.MM - 1, map.dd, map.HH, map.mm, map.ss || 0, map.sss * 1e3 || 0); - } + parseAppUrl(pathUrl, this); + if (!this.$$path) { + this.$$path = "/"; } - return NaN; + this.$$compose(); }; - } - function createDateInputType(type, regexp, parseDate, format) { - return function dynamicDateInputType(scope, element, attr, ctrl, $sniffer, $browser, $filter) { - badInputChecker(scope, element, attr, ctrl); - baseInputType(scope, element, attr, ctrl, $sniffer, $browser); - var timezone = ctrl && ctrl.$options && ctrl.$options.timezone; - var previousDate; - ctrl.$$parserName = type; - ctrl.$parsers.push(function(value) { - if (ctrl.$isEmpty(value)) return null; - if (regexp.test(value)) { - var parsedDate = parseDate(value, previousDate); - if (timezone) { - parsedDate = convertTimezoneToLocal(parsedDate, timezone); - } - return parsedDate; - } - return undefined; - }); - ctrl.$formatters.push(function(value) { - if (value && !isDate(value)) { - throw ngModelMinErr("datefmt", "Expected `{0}` to be a date", value); - } - if (isValidDate(value)) { - previousDate = value; - if (previousDate && timezone) { - previousDate = convertTimezoneToLocal(previousDate, timezone, true); - } - return $filter("date")(value, format, timezone); + this.$$compose = function() { + var search = toKeyValue(this.$$search), hash = this.$$hash ? "#" + encodeUriSegment(this.$$hash) : ""; + this.$$url = encodePath(this.$$path) + (search ? "?" + search : "") + hash; + this.$$absUrl = appBaseNoFile + this.$$url.substr(1); + }; + this.$$parseLinkUrl = function(url, relHref) { + if (relHref && relHref[0] === "#") { + this.hash(relHref.slice(1)); + return true; + } + var appUrl, prevAppUrl; + var rewrittenUrl; + if (isDefined(appUrl = beginsWith(appBase, url))) { + prevAppUrl = appUrl; + if (isDefined(appUrl = beginsWith(basePrefix, appUrl))) { + rewrittenUrl = appBaseNoFile + (beginsWith("/", appUrl) || appUrl); } else { - previousDate = null; - return ""; + rewrittenUrl = appBase + prevAppUrl; } - }); - if (isDefined(attr.min) || attr.ngMin) { - var minVal; - ctrl.$validators.min = function(value) { - return !isValidDate(value) || isUndefined(minVal) || parseDate(value) >= minVal; - }; - attr.$observe("min", function(val) { - minVal = parseObservedDateValue(val); - ctrl.$validate(); - }); - } - if (isDefined(attr.max) || attr.ngMax) { - var maxVal; - ctrl.$validators.max = function(value) { - return !isValidDate(value) || isUndefined(maxVal) || parseDate(value) <= maxVal; - }; - attr.$observe("max", function(val) { - maxVal = parseObservedDateValue(val); - ctrl.$validate(); - }); - } - function isValidDate(value) { - return value && !(value.getTime && value.getTime() !== value.getTime()); + } else if (isDefined(appUrl = beginsWith(appBaseNoFile, url))) { + rewrittenUrl = appBaseNoFile + appUrl; + } else if (appBaseNoFile == url + "/") { + rewrittenUrl = appBaseNoFile; } - function parseObservedDateValue(val) { - return isDefined(val) && !isDate(val) ? parseDate(val) || undefined : val; + if (rewrittenUrl) { + this.$$parse(rewrittenUrl); } + return !!rewrittenUrl; }; } - function badInputChecker(scope, element, attr, ctrl) { - var node = element[0]; - var nativeValidation = ctrl.$$hasNativeValidators = isObject(node.validity); - if (nativeValidation) { - ctrl.$parsers.push(function(value) { - var validity = element.prop(VALIDITY_STATE_PROPERTY) || {}; - return validity.badInput && !validity.typeMismatch ? undefined : value; - }); - } - } - function numberInputType(scope, element, attr, ctrl, $sniffer, $browser) { - badInputChecker(scope, element, attr, ctrl); - baseInputType(scope, element, attr, ctrl, $sniffer, $browser); - ctrl.$$parserName = "number"; - ctrl.$parsers.push(function(value) { - if (ctrl.$isEmpty(value)) return null; - if (NUMBER_REGEXP.test(value)) return parseFloat(value); - return undefined; - }); - ctrl.$formatters.push(function(value) { - if (!ctrl.$isEmpty(value)) { - if (!isNumber(value)) { - throw ngModelMinErr("numfmt", "Expected `{0}` to be a number", value); + function LocationHashbangUrl(appBase, appBaseNoFile, hashPrefix) { + parseAbsoluteUrl(appBase, this); + this.$$parse = function(url) { + var withoutBaseUrl = beginsWith(appBase, url) || beginsWith(appBaseNoFile, url); + var withoutHashUrl; + if (!isUndefined(withoutBaseUrl) && withoutBaseUrl.charAt(0) === "#") { + withoutHashUrl = beginsWith(hashPrefix, withoutBaseUrl); + if (isUndefined(withoutHashUrl)) { + withoutHashUrl = withoutBaseUrl; + } + } else { + if (this.$$html5) { + withoutHashUrl = withoutBaseUrl; + } else { + withoutHashUrl = ""; + if (isUndefined(withoutBaseUrl)) { + appBase = url; + this.replace(); + } } - value = value.toString(); } - return value; - }); - if (isDefined(attr.min) || attr.ngMin) { - var minVal; - ctrl.$validators.min = function(value) { - return ctrl.$isEmpty(value) || isUndefined(minVal) || value >= minVal; - }; - attr.$observe("min", function(val) { - if (isDefined(val) && !isNumber(val)) { - val = parseFloat(val, 10); + parseAppUrl(withoutHashUrl, this); + this.$$path = removeWindowsDriveName(this.$$path, withoutHashUrl, appBase); + this.$$compose(); + function removeWindowsDriveName(path, url, base) { + var windowsFilePathExp = /^\/[A-Z]:(\/.*)/; + var firstPathSegmentMatch; + if (url.indexOf(base) === 0) { + url = url.replace(base, ""); } - minVal = isNumber(val) && !isNaN(val) ? val : undefined; - ctrl.$validate(); - }); - } - if (isDefined(attr.max) || attr.ngMax) { - var maxVal; - ctrl.$validators.max = function(value) { - return ctrl.$isEmpty(value) || isUndefined(maxVal) || value <= maxVal; - }; - attr.$observe("max", function(val) { - if (isDefined(val) && !isNumber(val)) { - val = parseFloat(val, 10); + if (windowsFilePathExp.exec(url)) { + return path; } - maxVal = isNumber(val) && !isNaN(val) ? val : undefined; - ctrl.$validate(); - }); - } - } - function urlInputType(scope, element, attr, ctrl, $sniffer, $browser) { - baseInputType(scope, element, attr, ctrl, $sniffer, $browser); - stringBasedInputType(ctrl); - ctrl.$$parserName = "url"; - ctrl.$validators.url = function(modelValue, viewValue) { - var value = modelValue || viewValue; - return ctrl.$isEmpty(value) || URL_REGEXP.test(value); - }; - } - function emailInputType(scope, element, attr, ctrl, $sniffer, $browser) { - baseInputType(scope, element, attr, ctrl, $sniffer, $browser); - stringBasedInputType(ctrl); - ctrl.$$parserName = "email"; - ctrl.$validators.email = function(modelValue, viewValue) { - var value = modelValue || viewValue; - return ctrl.$isEmpty(value) || EMAIL_REGEXP.test(value); - }; - } - function radioInputType(scope, element, attr, ctrl) { - if (isUndefined(attr.name)) { - element.attr("name", nextUid()); - } - var listener = function(ev) { - if (element[0].checked) { - ctrl.$setViewValue(attr.value, ev && ev.type); + firstPathSegmentMatch = windowsFilePathExp.exec(path); + return firstPathSegmentMatch ? firstPathSegmentMatch[1] : path; } }; - element.on("click", listener); - ctrl.$render = function() { - var value = attr.value; - element[0].checked = value == ctrl.$viewValue; + this.$$compose = function() { + var search = toKeyValue(this.$$search), hash = this.$$hash ? "#" + encodeUriSegment(this.$$hash) : ""; + this.$$url = encodePath(this.$$path) + (search ? "?" + search : "") + hash; + this.$$absUrl = appBase + (this.$$url ? hashPrefix + this.$$url : ""); }; - attr.$observe("value", ctrl.$render); - } - function parseConstantExpr($parse, context, name, expression, fallback) { - var parseFn; - if (isDefined(expression)) { - parseFn = $parse(expression); - if (!parseFn.constant) { - throw ngModelMinErr("constexpr", "Expected constant expression for `{0}`, but saw " + "`{1}`.", name, expression); + this.$$parseLinkUrl = function(url, relHref) { + if (stripHash(appBase) == stripHash(url)) { + this.$$parse(url); + return true; } - return parseFn(context); - } - return fallback; + return false; + }; } - function checkboxInputType(scope, element, attr, ctrl, $sniffer, $browser, $filter, $parse) { - var trueValue = parseConstantExpr($parse, scope, "ngTrueValue", attr.ngTrueValue, true); - var falseValue = parseConstantExpr($parse, scope, "ngFalseValue", attr.ngFalseValue, false); - var listener = function(ev) { - ctrl.$setViewValue(element[0].checked, ev && ev.type); - }; - element.on("click", listener); - ctrl.$render = function() { - element[0].checked = ctrl.$viewValue; + function LocationHashbangInHtml5Url(appBase, appBaseNoFile, hashPrefix) { + this.$$html5 = true; + LocationHashbangUrl.apply(this, arguments); + this.$$parseLinkUrl = function(url, relHref) { + if (relHref && relHref[0] === "#") { + this.hash(relHref.slice(1)); + return true; + } + var rewrittenUrl; + var appUrl; + if (appBase == stripHash(url)) { + rewrittenUrl = url; + } else if (appUrl = beginsWith(appBaseNoFile, url)) { + rewrittenUrl = appBase + hashPrefix + appUrl; + } else if (appBaseNoFile === url + "/") { + rewrittenUrl = appBaseNoFile; + } + if (rewrittenUrl) { + this.$$parse(rewrittenUrl); + } + return !!rewrittenUrl; }; - ctrl.$isEmpty = function(value) { - return value === false; + this.$$compose = function() { + var search = toKeyValue(this.$$search), hash = this.$$hash ? "#" + encodeUriSegment(this.$$hash) : ""; + this.$$url = encodePath(this.$$path) + (search ? "?" + search : "") + hash; + this.$$absUrl = appBase + hashPrefix + this.$$url; }; - ctrl.$formatters.push(function(value) { - return equals(value, trueValue); - }); - ctrl.$parsers.push(function(value) { - return value ? trueValue : falseValue; - }); } - var inputDirective = [ "$browser", "$sniffer", "$filter", "$parse", function($browser, $sniffer, $filter, $parse) { - return { - restrict: "E", - require: [ "?ngModel" ], - link: { - pre: function(scope, element, attr, ctrls) { - if (ctrls[0]) { - (inputType[lowercase(attr.type)] || inputType.text)(scope, element, attr, ctrls[0], $sniffer, $browser, $filter, $parse); - } - } + var locationPrototype = { + $$html5: false, + $$replace: false, + absUrl: locationGetter("$$absUrl"), + url: function(url) { + if (isUndefined(url)) { + return this.$$url; } - }; - } ]; - var CONSTANT_VALUE_REGEXP = /^(true|false|\d+)$/; - var ngValueDirective = function() { - return { - restrict: "A", - priority: 100, - compile: function(tpl, tplAttr) { - if (CONSTANT_VALUE_REGEXP.test(tplAttr.ngValue)) { - return function ngValueConstantLink(scope, elm, attr) { - attr.$set("value", scope.$eval(attr.ngValue)); - }; + var match = PATH_MATCH.exec(url); + if (match[1] || url === "") this.path(decodeURIComponent(match[1])); + if (match[2] || match[1] || url === "") this.search(match[3] || ""); + this.hash(match[5] || ""); + return this; + }, + protocol: locationGetter("$$protocol"), + host: locationGetter("$$host"), + port: locationGetter("$$port"), + path: locationGetterSetter("$$path", function(path) { + path = path !== null ? path.toString() : ""; + return path.charAt(0) == "/" ? path : "/" + path; + }), + search: function(search, paramValue) { + switch (arguments.length) { + case 0: + return this.$$search; + + case 1: + if (isString(search) || isNumber(search)) { + search = search.toString(); + this.$$search = parseKeyValue(search); + } else if (isObject(search)) { + search = copy(search, {}); + forEach(search, function(value, key) { + if (value == null) delete search[key]; + }); + this.$$search = search; } else { - return function ngValueLink(scope, elm, attr) { - scope.$watch(attr.ngValue, function valueWatchAction(value) { - attr.$set("value", value); - }); - }; + throw $locationMinErr("isrcharg", "The first argument of the `$location#search()` call must be a string or an object."); + } + break; + + default: + if (isUndefined(paramValue) || paramValue === null) { + delete this.$$search[search]; + } else { + this.$$search[search] = paramValue; } } - }; + this.$$compose(); + return this; + }, + hash: locationGetterSetter("$$hash", function(hash) { + return hash !== null ? hash.toString() : ""; + }), + replace: function() { + this.$$replace = true; + return this; + } }; - var ngBindDirective = [ "$compile", function($compile) { - return { - restrict: "AC", - compile: function ngBindCompile(templateElement) { - $compile.$$addBindingClass(templateElement); - return function ngBindLink(scope, element, attr) { - $compile.$$addBindingInfo(element, attr.ngBind); - element = element[0]; - scope.$watch(attr.ngBind, function ngBindWatchAction(value) { - element.textContent = isUndefined(value) ? "" : value; - }); - }; + forEach([ LocationHashbangInHtml5Url, LocationHashbangUrl, LocationHtml5Url ], function(Location) { + Location.prototype = Object.create(locationPrototype); + Location.prototype.state = function(state) { + if (!arguments.length) { + return this.$$state; } + if (Location !== LocationHtml5Url || !this.$$html5) { + throw $locationMinErr("nostate", "History API state support is available only " + "in HTML5 mode and only in browsers supporting HTML5 History API"); + } + this.$$state = isUndefined(state) ? null : state; + return this; }; - } ]; - var ngBindTemplateDirective = [ "$interpolate", "$compile", function($interpolate, $compile) { - return { - compile: function ngBindTemplateCompile(templateElement) { - $compile.$$addBindingClass(templateElement); - return function ngBindTemplateLink(scope, element, attr) { - var interpolateFn = $interpolate(element.attr(attr.$attr.ngBindTemplate)); - $compile.$$addBindingInfo(element, interpolateFn.expressions); - element = element[0]; - attr.$observe("ngBindTemplate", function(value) { - element.textContent = isUndefined(value) ? "" : value; - }); - }; + }); + function locationGetter(property) { + return function() { + return this[property]; + }; + } + function locationGetterSetter(property, preprocess) { + return function(value) { + if (isUndefined(value)) { + return this[property]; } + this[property] = preprocess(value); + this.$$compose(); + return this; }; - } ]; - var ngBindHtmlDirective = [ "$sce", "$parse", "$compile", function($sce, $parse, $compile) { - return { - restrict: "A", - compile: function ngBindHtmlCompile(tElement, tAttrs) { - var ngBindHtmlGetter = $parse(tAttrs.ngBindHtml); - var ngBindHtmlWatch = $parse(tAttrs.ngBindHtml, function getStringValue(value) { - return (value || "").toString(); - }); - $compile.$$addBindingClass(tElement); - return function ngBindHtmlLink(scope, element, attr) { - $compile.$$addBindingInfo(element, attr.ngBindHtml); - scope.$watch(ngBindHtmlWatch, function ngBindHtmlWatchAction() { - element.html($sce.getTrustedHtml(ngBindHtmlGetter(scope)) || ""); - }); - }; + } + function $LocationProvider() { + var hashPrefix = "", html5Mode = { + enabled: false, + requireBase: true, + rewriteLinks: true + }; + this.hashPrefix = function(prefix) { + if (isDefined(prefix)) { + hashPrefix = prefix; + return this; + } else { + return hashPrefix; } }; - } ]; - var ngChangeDirective = valueFn({ - restrict: "A", - require: "ngModel", - link: function(scope, element, attr, ctrl) { - ctrl.$viewChangeListeners.push(function() { - scope.$eval(attr.ngChange); - }); - } - }); - function classDirective(name, selector) { - name = "ngClass" + name; - return [ "$animate", function($animate) { - return { - restrict: "AC", - link: function(scope, element, attr) { - var oldVal; - scope.$watch(attr[name], ngClassWatchAction, true); - attr.$observe("class", function(value) { - ngClassWatchAction(scope.$eval(attr[name])); - }); - if (name !== "ngClass") { - scope.$watch("$index", function($index, old$index) { - var mod = $index & 1; - if (mod !== (old$index & 1)) { - var classes = arrayClasses(scope.$eval(attr[name])); - mod === selector ? addClasses(classes) : removeClasses(classes); - } - }); - } - function addClasses(classes) { - var newClasses = digestClassCounts(classes, 1); - attr.$addClass(newClasses); - } - function removeClasses(classes) { - var newClasses = digestClassCounts(classes, -1); - attr.$removeClass(newClasses); - } - function digestClassCounts(classes, count) { - var classCounts = element.data("$classCounts") || createMap(); - var classesToUpdate = []; - forEach(classes, function(className) { - if (count > 0 || classCounts[className]) { - classCounts[className] = (classCounts[className] || 0) + count; - if (classCounts[className] === +(count > 0)) { - classesToUpdate.push(className); - } - } - }); - element.data("$classCounts", classCounts); - return classesToUpdate.join(" "); - } - function updateClasses(oldClasses, newClasses) { - var toAdd = arrayDifference(newClasses, oldClasses); - var toRemove = arrayDifference(oldClasses, newClasses); - toAdd = digestClassCounts(toAdd, 1); - toRemove = digestClassCounts(toRemove, -1); - if (toAdd && toAdd.length) { - $animate.addClass(element, toAdd); - } - if (toRemove && toRemove.length) { - $animate.removeClass(element, toRemove); - } - } - function ngClassWatchAction(newVal) { - if (selector === true || scope.$index % 2 === selector) { - var newClasses = arrayClasses(newVal || []); - if (!oldVal) { - addClasses(newClasses); - } else if (!equals(newVal, oldVal)) { - var oldClasses = arrayClasses(oldVal); - updateClasses(oldClasses, newClasses); - } - } - oldVal = shallowCopy(newVal); - } + this.html5Mode = function(mode) { + if (isBoolean(mode)) { + html5Mode.enabled = mode; + return this; + } else if (isObject(mode)) { + if (isBoolean(mode.enabled)) { + html5Mode.enabled = mode.enabled; } - }; - function arrayDifference(tokens1, tokens2) { - var values = []; - outer: for (var i = 0; i < tokens1.length; i++) { - var token = tokens1[i]; - for (var j = 0; j < tokens2.length; j++) { - if (token == tokens2[j]) continue outer; + if (isBoolean(mode.requireBase)) { + html5Mode.requireBase = mode.requireBase; + } + if (isBoolean(mode.rewriteLinks)) { + html5Mode.rewriteLinks = mode.rewriteLinks; + } + return this; + } else { + return html5Mode; + } + }; + this.$get = [ "$rootScope", "$browser", "$sniffer", "$rootElement", "$window", function($rootScope, $browser, $sniffer, $rootElement, $window) { + var $location, LocationMode, baseHref = $browser.baseHref(), initialUrl = $browser.url(), appBase; + if (html5Mode.enabled) { + if (!baseHref && html5Mode.requireBase) { + throw $locationMinErr("nobase", "$location in HTML5 mode requires a tag to be present!"); + } + appBase = serverBase(initialUrl) + (baseHref || "/"); + LocationMode = $sniffer.history ? LocationHtml5Url : LocationHashbangInHtml5Url; + } else { + appBase = stripHash(initialUrl); + LocationMode = LocationHashbangUrl; + } + var appBaseNoFile = stripFile(appBase); + $location = new LocationMode(appBase, appBaseNoFile, "#" + hashPrefix); + $location.$$parseLinkUrl(initialUrl, initialUrl); + $location.$$state = $browser.state(); + var IGNORE_URI_REGEXP = /^\s*(javascript|mailto):/i; + function setBrowserUrlWithFallback(url, replace, state) { + var oldUrl = $location.url(); + var oldState = $location.$$state; + try { + $browser.url(url, replace, state); + $location.$$state = $browser.state(); + } catch (e) { + $location.url(oldUrl); + $location.$$state = oldState; + throw e; + } + } + $rootElement.on("click", function(event) { + if (!html5Mode.rewriteLinks || event.ctrlKey || event.metaKey || event.shiftKey || event.which == 2 || event.button == 2) return; + var elm = jqLite(event.target); + while (nodeName_(elm[0]) !== "a") { + if (elm[0] === $rootElement[0] || !(elm = elm.parent())[0]) return; + } + var absHref = elm.prop("href"); + var relHref = elm.attr("href") || elm.attr("xlink:href"); + if (isObject(absHref) && absHref.toString() === "[object SVGAnimatedString]") { + absHref = urlResolve(absHref.animVal).href; + } + if (IGNORE_URI_REGEXP.test(absHref)) return; + if (absHref && !elm.attr("target") && !event.isDefaultPrevented()) { + if ($location.$$parseLinkUrl(absHref, relHref)) { + event.preventDefault(); + if ($location.absUrl() != $browser.url()) { + $rootScope.$apply(); + $window.angular["ff-684208-preventDefault"] = true; + } } - values.push(token); } - return values; + }); + if (trimEmptyHash($location.absUrl()) != trimEmptyHash(initialUrl)) { + $browser.url($location.absUrl(), true); } - function arrayClasses(classVal) { - var classes = []; - if (isArray(classVal)) { - forEach(classVal, function(v) { - classes = classes.concat(arrayClasses(v)); - }); - return classes; - } else if (isString(classVal)) { - return classVal.split(" "); - } else if (isObject(classVal)) { - forEach(classVal, function(v, k) { - if (v) { - classes = classes.concat(k.split(" ")); + var initializing = true; + $browser.onUrlChange(function(newUrl, newState) { + if (isUndefined(beginsWith(appBaseNoFile, newUrl))) { + $window.location.href = newUrl; + return; + } + $rootScope.$evalAsync(function() { + var oldUrl = $location.absUrl(); + var oldState = $location.$$state; + var defaultPrevented; + $location.$$parse(newUrl); + $location.$$state = newState; + defaultPrevented = $rootScope.$broadcast("$locationChangeStart", newUrl, oldUrl, newState, oldState).defaultPrevented; + if ($location.absUrl() !== newUrl) return; + if (defaultPrevented) { + $location.$$parse(oldUrl); + $location.$$state = oldState; + setBrowserUrlWithFallback(oldUrl, false, oldState); + } else { + initializing = false; + afterLocationChange(oldUrl, oldState); + } + }); + if (!$rootScope.$$phase) $rootScope.$digest(); + }); + $rootScope.$watch(function $locationWatch() { + var oldUrl = trimEmptyHash($browser.url()); + var newUrl = trimEmptyHash($location.absUrl()); + var oldState = $browser.state(); + var currentReplace = $location.$$replace; + var urlOrStateChanged = oldUrl !== newUrl || $location.$$html5 && $sniffer.history && oldState !== $location.$$state; + if (initializing || urlOrStateChanged) { + initializing = false; + $rootScope.$evalAsync(function() { + var newUrl = $location.absUrl(); + var defaultPrevented = $rootScope.$broadcast("$locationChangeStart", newUrl, oldUrl, $location.$$state, oldState).defaultPrevented; + if ($location.absUrl() !== newUrl) return; + if (defaultPrevented) { + $location.$$parse(oldUrl); + $location.$$state = oldState; + } else { + if (urlOrStateChanged) { + setBrowserUrlWithFallback(newUrl, currentReplace, oldState === $location.$$state ? null : $location.$$state); + } + afterLocationChange(oldUrl, oldState); } }); - return classes; } - return classVal; + $location.$$replace = false; + }); + return $location; + function afterLocationChange(oldUrl, oldState) { + $rootScope.$broadcast("$locationChangeSuccess", $location.absUrl(), oldUrl, $location.$$state, oldState); } } ]; } - var ngClassDirective = classDirective("", true); - var ngClassOddDirective = classDirective("Odd", 0); - var ngClassEvenDirective = classDirective("Even", 1); - var ngCloakDirective = ngDirective({ - compile: function(element, attr) { - attr.$set("ngCloak", undefined); - element.removeClass("ng-cloak"); - } - }); - var ngControllerDirective = [ function() { - return { - restrict: "A", - scope: true, - controller: "@", - priority: 500 + function $LogProvider() { + var debug = true, self = this; + this.debugEnabled = function(flag) { + if (isDefined(flag)) { + debug = flag; + return this; + } else { + return debug; + } }; - } ]; - var ngEventDirectives = {}; - var forceAsyncEvents = { - blur: true, - focus: true - }; - forEach("click dblclick mousedown mouseup mouseover mouseout mousemove mouseenter mouseleave keydown keyup keypress submit focus blur copy cut paste".split(" "), function(eventName) { - var directiveName = directiveNormalize("ng-" + eventName); - ngEventDirectives[directiveName] = [ "$parse", "$rootScope", function($parse, $rootScope) { + this.$get = [ "$window", function($window) { return { - restrict: "A", - compile: function($element, attr) { - var fn = $parse(attr[directiveName], null, true); - return function ngEventHandler(scope, element) { - element.on(eventName, function(event) { - var callback = function() { - fn(scope, { - $event: event - }); - }; - if (forceAsyncEvents[eventName] && $rootScope.$$phase) { - scope.$evalAsync(callback); - } else { - scope.$apply(callback); - } + log: consoleLog("log"), + info: consoleLog("info"), + warn: consoleLog("warn"), + error: consoleLog("error"), + debug: function() { + var fn = consoleLog("debug"); + return function() { + if (debug) { + fn.apply(self, arguments); + } + }; + }() + }; + function formatError(arg) { + if (arg instanceof Error) { + if (arg.stack) { + arg = arg.message && arg.stack.indexOf(arg.message) === -1 ? "Error: " + arg.message + "\n" + arg.stack : arg.stack; + } else if (arg.sourceURL) { + arg = arg.message + "\n" + arg.sourceURL + ":" + arg.line; + } + } + return arg; + } + function consoleLog(type) { + var console = $window.console || {}, logFn = console[type] || console.log || noop, hasApply = false; + try { + hasApply = !!logFn.apply; + } catch (e) {} + if (hasApply) { + return function() { + var args = []; + forEach(arguments, function(arg) { + args.push(formatError(arg)); }); + return logFn.apply(console, args); }; } - }; + return function(arg1, arg2) { + logFn(arg1, arg2 == null ? "" : arg2); + }; + } } ]; - }); - var ngIfDirective = [ "$animate", function($animate) { - return { - multiElement: true, - transclude: "element", - priority: 600, - terminal: true, - restrict: "A", - $$tlb: true, - link: function($scope, $element, $attr, ctrl, $transclude) { - var block, childScope, previousElements; - $scope.$watch($attr.ngIf, function ngIfWatchAction(value) { - if (value) { - if (!childScope) { - $transclude(function(clone, newScope) { - childScope = newScope; - clone[clone.length++] = document.createComment(" end ngIf: " + $attr.ngIf + " "); - block = { - clone: clone - }; - $animate.enter(clone, $element.parent(), $element); - }); - } - } else { - if (previousElements) { - previousElements.remove(); - previousElements = null; - } - if (childScope) { - childScope.$destroy(); - childScope = null; - } - if (block) { - previousElements = getBlockNodes(block.clone); - $animate.leave(previousElements).then(function() { - previousElements = null; - }); - block = null; - } - } - }); + } + var $parseMinErr = minErr("$parse"); + function ensureSafeMemberName(name, fullExpression) { + if (name === "__defineGetter__" || name === "__defineSetter__" || name === "__lookupGetter__" || name === "__lookupSetter__" || name === "__proto__") { + throw $parseMinErr("isecfld", "Attempting to access a disallowed field in Angular expressions! " + "Expression: {0}", fullExpression); + } + return name; + } + function getStringValue(name, fullExpression) { + name = name + ""; + if (!isString(name)) { + throw $parseMinErr("iseccst", "Cannot convert object to primitive value! " + "Expression: {0}", fullExpression); + } + return name; + } + function ensureSafeObject(obj, fullExpression) { + if (obj) { + if (obj.constructor === obj) { + throw $parseMinErr("isecfn", "Referencing Function in Angular expressions is disallowed! Expression: {0}", fullExpression); + } else if (obj.window === obj) { + throw $parseMinErr("isecwindow", "Referencing the Window in Angular expressions is disallowed! Expression: {0}", fullExpression); + } else if (obj.children && (obj.nodeName || obj.prop && obj.attr && obj.find)) { + throw $parseMinErr("isecdom", "Referencing DOM nodes in Angular expressions is disallowed! Expression: {0}", fullExpression); + } else if (obj === Object) { + throw $parseMinErr("isecobj", "Referencing Object in Angular expressions is disallowed! Expression: {0}", fullExpression); } - }; - } ]; - var ngIncludeDirective = [ "$templateRequest", "$anchorScroll", "$animate", function($templateRequest, $anchorScroll, $animate) { - return { - restrict: "ECA", - priority: 400, - terminal: true, - transclude: "element", - controller: angular.noop, - compile: function(element, attr) { - var srcExp = attr.ngInclude || attr.src, onloadExp = attr.onload || "", autoScrollExp = attr.autoscroll; - return function(scope, $element, $attr, ctrl, $transclude) { - var changeCounter = 0, currentScope, previousElement, currentElement; - var cleanupLastIncludeContent = function() { - if (previousElement) { - previousElement.remove(); - previousElement = null; - } - if (currentScope) { - currentScope.$destroy(); - currentScope = null; - } - if (currentElement) { - $animate.leave(currentElement).then(function() { - previousElement = null; - }); - previousElement = currentElement; - currentElement = null; - } - }; - scope.$watch(srcExp, function ngIncludeWatchAction(src) { - var afterAnimation = function() { - if (isDefined(autoScrollExp) && (!autoScrollExp || scope.$eval(autoScrollExp))) { - $anchorScroll(); - } - }; - var thisChangeId = ++changeCounter; - if (src) { - $templateRequest(src, true).then(function(response) { - if (thisChangeId !== changeCounter) return; - var newScope = scope.$new(); - ctrl.template = response; - var clone = $transclude(newScope, function(clone) { - cleanupLastIncludeContent(); - $animate.enter(clone, null, $element).then(afterAnimation); - }); - currentScope = newScope; - currentElement = clone; - currentScope.$emit("$includeContentLoaded", src); - scope.$eval(onloadExp); - }, function() { - if (thisChangeId === changeCounter) { - cleanupLastIncludeContent(); - scope.$emit("$includeContentError", src); - } - }); - scope.$emit("$includeContentRequested", src); - } else { - cleanupLastIncludeContent(); - ctrl.template = null; - } - }); - }; + } + return obj; + } + var CALL = Function.prototype.call; + var APPLY = Function.prototype.apply; + var BIND = Function.prototype.bind; + function ensureSafeFunction(obj, fullExpression) { + if (obj) { + if (obj.constructor === obj) { + throw $parseMinErr("isecfn", "Referencing Function in Angular expressions is disallowed! Expression: {0}", fullExpression); + } else if (obj === CALL || obj === APPLY || obj === BIND) { + throw $parseMinErr("isecff", "Referencing call, apply or bind in Angular expressions is disallowed! Expression: {0}", fullExpression); } - }; - } ]; - var ngIncludeFillContentDirective = [ "$compile", function($compile) { - return { - restrict: "ECA", - priority: -400, - require: "ngInclude", - link: function(scope, $element, $attr, ctrl) { - if (/SVG/.test($element[0].toString())) { - $element.empty(); - $compile(jqLiteBuildFragment(ctrl.template, document).childNodes)(scope, function namespaceAdaptedClone(clone) { - $element.append(clone); - }, { - futureParentElement: $element - }); - return; - } - $element.html(ctrl.template); - $compile($element.contents())(scope); + } + } + function ensureSafeAssignContext(obj, fullExpression) { + if (obj) { + if (obj === 0..constructor || obj === false.constructor || obj === "".constructor || obj === {}.constructor || obj === [].constructor || obj === Function.constructor) { + throw $parseMinErr("isecaf", "Assigning to a constructor is disallowed! Expression: {0}", fullExpression); } - }; - } ]; - var ngInitDirective = ngDirective({ - priority: 450, - compile: function() { - return { - pre: function(scope, element, attrs) { - scope.$eval(attrs.ngInit); - } - }; } + } + var OPERATORS = createMap(); + forEach("+ - * / % === !== == != < > <= >= && || ! = |".split(" "), function(operator) { + OPERATORS[operator] = true; }); - var ngListDirective = function() { - return { - restrict: "A", - priority: 100, - require: "ngModel", - link: function(scope, element, attr, ctrl) { - var ngList = element.attr(attr.$attr.ngList) || ", "; - var trimValues = attr.ngTrim !== "false"; - var separator = trimValues ? trim(ngList) : ngList; - var parse = function(viewValue) { - if (isUndefined(viewValue)) return; - var list = []; - if (viewValue) { - forEach(viewValue.split(separator), function(value) { - if (value) list.push(trimValues ? trim(value) : value); + var ESCAPE = { + n: "\n", + f: "\f", + r: "\r", + t: " ", + v: " ", + "'": "'", + '"': '"' + }; + var Lexer = function(options) { + this.options = options; + }; + Lexer.prototype = { + constructor: Lexer, + lex: function(text) { + this.text = text; + this.index = 0; + this.tokens = []; + while (this.index < this.text.length) { + var ch = this.text.charAt(this.index); + if (ch === '"' || ch === "'") { + this.readString(ch); + } else if (this.isNumber(ch) || ch === "." && this.isNumber(this.peek())) { + this.readNumber(); + } else if (this.isIdent(ch)) { + this.readIdent(); + } else if (this.is(ch, "(){}[].,;:?")) { + this.tokens.push({ + index: this.index, + text: ch + }); + this.index++; + } else if (this.isWhitespace(ch)) { + this.index++; + } else { + var ch2 = ch + this.peek(); + var ch3 = ch2 + this.peek(2); + var op1 = OPERATORS[ch]; + var op2 = OPERATORS[ch2]; + var op3 = OPERATORS[ch3]; + if (op1 || op2 || op3) { + var token = op3 ? ch3 : op2 ? ch2 : ch; + this.tokens.push({ + index: this.index, + text: token, + operator: true }); + this.index += token.length; + } else { + this.throwError("Unexpected next character ", this.index, this.index + 1); } - return list; - }; - ctrl.$parsers.push(parse); - ctrl.$formatters.push(function(value) { - if (isArray(value)) { - return value.join(ngList); - } - return undefined; - }); - ctrl.$isEmpty = function(value) { - return !value || !value.length; - }; + } } - }; - }; - var VALID_CLASS = "ng-valid", INVALID_CLASS = "ng-invalid", PRISTINE_CLASS = "ng-pristine", DIRTY_CLASS = "ng-dirty", UNTOUCHED_CLASS = "ng-untouched", TOUCHED_CLASS = "ng-touched", PENDING_CLASS = "ng-pending"; - var ngModelMinErr = minErr("ngModel"); - var NgModelController = [ "$scope", "$exceptionHandler", "$attrs", "$element", "$parse", "$animate", "$timeout", "$rootScope", "$q", "$interpolate", function($scope, $exceptionHandler, $attr, $element, $parse, $animate, $timeout, $rootScope, $q, $interpolate) { - this.$viewValue = Number.NaN; - this.$modelValue = Number.NaN; - this.$$rawModelValue = undefined; - this.$validators = {}; - this.$asyncValidators = {}; - this.$parsers = []; - this.$formatters = []; - this.$viewChangeListeners = []; - this.$untouched = true; - this.$touched = false; - this.$pristine = true; - this.$dirty = false; - this.$valid = true; - this.$invalid = false; - this.$error = {}; - this.$$success = {}; - this.$pending = undefined; - this.$name = $interpolate($attr.name || "", false)($scope); - this.$$parentForm = nullFormCtrl; - var parsedNgModel = $parse($attr.ngModel), parsedNgModelAssign = parsedNgModel.assign, ngModelGet = parsedNgModel, ngModelSet = parsedNgModelAssign, pendingDebounce = null, parserValid, ctrl = this; - this.$$setOptions = function(options) { - ctrl.$options = options; - if (options && options.getterSetter) { - var invokeModelGetter = $parse($attr.ngModel + "()"), invokeModelSetter = $parse($attr.ngModel + "($$$p)"); - ngModelGet = function($scope) { - var modelValue = parsedNgModel($scope); - if (isFunction(modelValue)) { - modelValue = invokeModelGetter($scope); - } - return modelValue; - }; - ngModelSet = function($scope, newValue) { - if (isFunction(parsedNgModel($scope))) { - invokeModelSetter($scope, { - $$$p: ctrl.$modelValue - }); - } else { - parsedNgModelAssign($scope, ctrl.$modelValue); - } - }; - } else if (!parsedNgModel.assign) { - throw ngModelMinErr("nonassign", "Expression '{0}' is non-assignable. Element: {1}", $attr.ngModel, startingTag($element)); - } - }; - this.$render = noop; - this.$isEmpty = function(value) { - return isUndefined(value) || value === "" || value === null || value !== value; - }; - var currentValidationRunId = 0; - addSetValidityMethod({ - ctrl: this, - $element: $element, - set: function(object, property) { - object[property] = true; - }, - unset: function(object, property) { - delete object[property]; - }, - $animate: $animate - }); - this.$setPristine = function() { - ctrl.$dirty = false; - ctrl.$pristine = true; - $animate.removeClass($element, DIRTY_CLASS); - $animate.addClass($element, PRISTINE_CLASS); - }; - this.$setDirty = function() { - ctrl.$dirty = true; - ctrl.$pristine = false; - $animate.removeClass($element, PRISTINE_CLASS); - $animate.addClass($element, DIRTY_CLASS); - ctrl.$$parentForm.$setDirty(); - }; - this.$setUntouched = function() { - ctrl.$touched = false; - ctrl.$untouched = true; - $animate.setClass($element, UNTOUCHED_CLASS, TOUCHED_CLASS); - }; - this.$setTouched = function() { - ctrl.$touched = true; - ctrl.$untouched = false; - $animate.setClass($element, TOUCHED_CLASS, UNTOUCHED_CLASS); - }; - this.$rollbackViewValue = function() { - $timeout.cancel(pendingDebounce); - ctrl.$viewValue = ctrl.$$lastCommittedViewValue; - ctrl.$render(); - }; - this.$validate = function() { - if (isNumber(ctrl.$modelValue) && isNaN(ctrl.$modelValue)) { - return; - } - var viewValue = ctrl.$$lastCommittedViewValue; - var modelValue = ctrl.$$rawModelValue; - var prevValid = ctrl.$valid; - var prevModelValue = ctrl.$modelValue; - var allowInvalid = ctrl.$options && ctrl.$options.allowInvalid; - ctrl.$$runValidators(modelValue, viewValue, function(allValid) { - if (!allowInvalid && prevValid !== allValid) { - ctrl.$modelValue = allValid ? modelValue : undefined; - if (ctrl.$modelValue !== prevModelValue) { - ctrl.$$writeModelToScope(); - } - } - }); - }; - this.$$runValidators = function(modelValue, viewValue, doneCallback) { - currentValidationRunId++; - var localValidationRunId = currentValidationRunId; - if (!processParseErrors()) { - validationDone(false); - return; - } - if (!processSyncValidators()) { - validationDone(false); - return; - } - processAsyncValidators(); - function processParseErrors() { - var errorKey = ctrl.$$parserName || "parse"; - if (isUndefined(parserValid)) { - setValidity(errorKey, null); + return this.tokens; + }, + is: function(ch, chars) { + return chars.indexOf(ch) !== -1; + }, + peek: function(i) { + var num = i || 1; + return this.index + num < this.text.length ? this.text.charAt(this.index + num) : false; + }, + isNumber: function(ch) { + return "0" <= ch && ch <= "9" && typeof ch === "string"; + }, + isWhitespace: function(ch) { + return ch === " " || ch === "\r" || ch === " " || ch === "\n" || ch === " " || ch === " "; + }, + isIdent: function(ch) { + return "a" <= ch && ch <= "z" || "A" <= ch && ch <= "Z" || "_" === ch || ch === "$"; + }, + isExpOperator: function(ch) { + return ch === "-" || ch === "+" || this.isNumber(ch); + }, + throwError: function(error, start, end) { + end = end || this.index; + var colStr = isDefined(start) ? "s " + start + "-" + this.index + " [" + this.text.substring(start, end) + "]" : " " + end; + throw $parseMinErr("lexerr", "Lexer Error: {0} at column{1} in expression [{2}].", error, colStr, this.text); + }, + readNumber: function() { + var number = ""; + var start = this.index; + while (this.index < this.text.length) { + var ch = lowercase(this.text.charAt(this.index)); + if (ch == "." || this.isNumber(ch)) { + number += ch; } else { - if (!parserValid) { - forEach(ctrl.$validators, function(v, name) { - setValidity(name, null); - }); - forEach(ctrl.$asyncValidators, function(v, name) { - setValidity(name, null); - }); + var peekCh = this.peek(); + if (ch == "e" && this.isExpOperator(peekCh)) { + number += ch; + } else if (this.isExpOperator(ch) && peekCh && this.isNumber(peekCh) && number.charAt(number.length - 1) == "e") { + number += ch; + } else if (this.isExpOperator(ch) && (!peekCh || !this.isNumber(peekCh)) && number.charAt(number.length - 1) == "e") { + this.throwError("Invalid exponent"); + } else { + break; } - setValidity(errorKey, parserValid); - return parserValid; } - return true; + this.index++; } - function processSyncValidators() { - var syncValidatorsValid = true; - forEach(ctrl.$validators, function(validator, name) { - var result = validator(modelValue, viewValue); - syncValidatorsValid = syncValidatorsValid && result; - setValidity(name, result); - }); - if (!syncValidatorsValid) { - forEach(ctrl.$asyncValidators, function(v, name) { - setValidity(name, null); - }); - return false; + this.tokens.push({ + index: start, + text: number, + constant: true, + value: Number(number) + }); + }, + readIdent: function() { + var start = this.index; + while (this.index < this.text.length) { + var ch = this.text.charAt(this.index); + if (!(this.isIdent(ch) || this.isNumber(ch))) { + break; } - return true; + this.index++; } - function processAsyncValidators() { - var validatorPromises = []; - var allValid = true; - forEach(ctrl.$asyncValidators, function(validator, name) { - var promise = validator(modelValue, viewValue); - if (!isPromiseLike(promise)) { - throw ngModelMinErr("$asyncValidators", "Expected asynchronous validator to return a promise but got '{0}' instead.", promise); + this.tokens.push({ + index: start, + text: this.text.slice(start, this.index), + identifier: true + }); + }, + readString: function(quote) { + var start = this.index; + this.index++; + var string = ""; + var rawString = quote; + var escape = false; + while (this.index < this.text.length) { + var ch = this.text.charAt(this.index); + rawString += ch; + if (escape) { + if (ch === "u") { + var hex = this.text.substring(this.index + 1, this.index + 5); + if (!hex.match(/[\da-f]{4}/i)) { + this.throwError("Invalid unicode escape [\\u" + hex + "]"); + } + this.index += 4; + string += String.fromCharCode(parseInt(hex, 16)); + } else { + var rep = ESCAPE[ch]; + string = string + (rep || ch); } - setValidity(name, undefined); - validatorPromises.push(promise.then(function() { - setValidity(name, true); - }, function(error) { - allValid = false; - setValidity(name, false); - })); - }); - if (!validatorPromises.length) { - validationDone(true); + escape = false; + } else if (ch === "\\") { + escape = true; + } else if (ch === quote) { + this.index++; + this.tokens.push({ + index: start, + text: rawString, + constant: true, + value: string + }); + return; } else { - $q.all(validatorPromises).then(function() { - validationDone(allValid); - }, noop); + string += ch; } + this.index++; } - function setValidity(name, isValid) { - if (localValidationRunId === currentValidationRunId) { - ctrl.$setValidity(name, isValid); - } + this.throwError("Unterminated quote", start); + } + }; + var AST = function(lexer, options) { + this.lexer = lexer; + this.options = options; + }; + AST.Program = "Program"; + AST.ExpressionStatement = "ExpressionStatement"; + AST.AssignmentExpression = "AssignmentExpression"; + AST.ConditionalExpression = "ConditionalExpression"; + AST.LogicalExpression = "LogicalExpression"; + AST.BinaryExpression = "BinaryExpression"; + AST.UnaryExpression = "UnaryExpression"; + AST.CallExpression = "CallExpression"; + AST.MemberExpression = "MemberExpression"; + AST.Identifier = "Identifier"; + AST.Literal = "Literal"; + AST.ArrayExpression = "ArrayExpression"; + AST.Property = "Property"; + AST.ObjectExpression = "ObjectExpression"; + AST.ThisExpression = "ThisExpression"; + AST.NGValueParameter = "NGValueParameter"; + AST.prototype = { + ast: function(text) { + this.text = text; + this.tokens = this.lexer.lex(text); + var value = this.program(); + if (this.tokens.length !== 0) { + this.throwError("is an unexpected token", this.tokens[0]); } - function validationDone(allValid) { - if (localValidationRunId === currentValidationRunId) { - doneCallback(allValid); + return value; + }, + program: function() { + var body = []; + while (true) { + if (this.tokens.length > 0 && !this.peek("}", ")", ";", "]")) body.push(this.expressionStatement()); + if (!this.expect(";")) { + return { + type: AST.Program, + body: body + }; } } - }; - this.$commitViewValue = function() { - var viewValue = ctrl.$viewValue; - $timeout.cancel(pendingDebounce); - if (ctrl.$$lastCommittedViewValue === viewValue && (viewValue !== "" || !ctrl.$$hasNativeValidators)) { - return; + }, + expressionStatement: function() { + return { + type: AST.ExpressionStatement, + expression: this.filterChain() + }; + }, + filterChain: function() { + var left = this.expression(); + var token; + while (token = this.expect("|")) { + left = this.filter(left); } - ctrl.$$lastCommittedViewValue = viewValue; - if (ctrl.$pristine) { - this.$setDirty(); + return left; + }, + expression: function() { + return this.assignment(); + }, + assignment: function() { + var result = this.ternary(); + if (this.expect("=")) { + result = { + type: AST.AssignmentExpression, + left: result, + right: this.assignment(), + operator: "=" + }; } - this.$$parseAndValidate(); - }; - this.$$parseAndValidate = function() { - var viewValue = ctrl.$$lastCommittedViewValue; - var modelValue = viewValue; - parserValid = isUndefined(modelValue) ? undefined : true; - if (parserValid) { - for (var i = 0; i < ctrl.$parsers.length; i++) { - modelValue = ctrl.$parsers[i](modelValue); - if (isUndefined(modelValue)) { - parserValid = false; - break; - } + return result; + }, + ternary: function() { + var test = this.logicalOR(); + var alternate; + var consequent; + if (this.expect("?")) { + alternate = this.expression(); + if (this.consume(":")) { + consequent = this.expression(); + return { + type: AST.ConditionalExpression, + test: test, + alternate: alternate, + consequent: consequent + }; } } - if (isNumber(ctrl.$modelValue) && isNaN(ctrl.$modelValue)) { - ctrl.$modelValue = ngModelGet($scope); + return test; + }, + logicalOR: function() { + var left = this.logicalAND(); + while (this.expect("||")) { + left = { + type: AST.LogicalExpression, + operator: "||", + left: left, + right: this.logicalAND() + }; } - var prevModelValue = ctrl.$modelValue; - var allowInvalid = ctrl.$options && ctrl.$options.allowInvalid; - ctrl.$$rawModelValue = modelValue; - if (allowInvalid) { - ctrl.$modelValue = modelValue; - writeToModelIfNeeded(); + return left; + }, + logicalAND: function() { + var left = this.equality(); + while (this.expect("&&")) { + left = { + type: AST.LogicalExpression, + operator: "&&", + left: left, + right: this.equality() + }; } - ctrl.$$runValidators(modelValue, ctrl.$$lastCommittedViewValue, function(allValid) { - if (!allowInvalid) { - ctrl.$modelValue = allValid ? modelValue : undefined; - writeToModelIfNeeded(); - } - }); - function writeToModelIfNeeded() { - if (ctrl.$modelValue !== prevModelValue) { - ctrl.$$writeModelToScope(); - } + return left; + }, + equality: function() { + var left = this.relational(); + var token; + while (token = this.expect("==", "!=", "===", "!==")) { + left = { + type: AST.BinaryExpression, + operator: token.text, + left: left, + right: this.relational() + }; } - }; - this.$$writeModelToScope = function() { - ngModelSet($scope, ctrl.$modelValue); - forEach(ctrl.$viewChangeListeners, function(listener) { - try { - listener(); - } catch (e) { - $exceptionHandler(e); - } - }); - }; - this.$setViewValue = function(value, trigger) { - ctrl.$viewValue = value; - if (!ctrl.$options || ctrl.$options.updateOnDefault) { - ctrl.$$debounceViewValueCommit(trigger); + return left; + }, + relational: function() { + var left = this.additive(); + var token; + while (token = this.expect("<", ">", "<=", ">=")) { + left = { + type: AST.BinaryExpression, + operator: token.text, + left: left, + right: this.additive() + }; } - }; - this.$$debounceViewValueCommit = function(trigger) { - var debounceDelay = 0, options = ctrl.$options, debounce; - if (options && isDefined(options.debounce)) { - debounce = options.debounce; - if (isNumber(debounce)) { - debounceDelay = debounce; - } else if (isNumber(debounce[trigger])) { - debounceDelay = debounce[trigger]; - } else if (isNumber(debounce["default"])) { - debounceDelay = debounce["default"]; - } + return left; + }, + additive: function() { + var left = this.multiplicative(); + var token; + while (token = this.expect("+", "-")) { + left = { + type: AST.BinaryExpression, + operator: token.text, + left: left, + right: this.multiplicative() + }; } - $timeout.cancel(pendingDebounce); - if (debounceDelay) { - pendingDebounce = $timeout(function() { - ctrl.$commitViewValue(); - }, debounceDelay); - } else if ($rootScope.$$phase) { - ctrl.$commitViewValue(); + return left; + }, + multiplicative: function() { + var left = this.unary(); + var token; + while (token = this.expect("*", "/", "%")) { + left = { + type: AST.BinaryExpression, + operator: token.text, + left: left, + right: this.unary() + }; + } + return left; + }, + unary: function() { + var token; + if (token = this.expect("+", "-", "!")) { + return { + type: AST.UnaryExpression, + operator: token.text, + prefix: true, + argument: this.unary() + }; } else { - $scope.$apply(function() { - ctrl.$commitViewValue(); - }); + return this.primary(); } - }; - $scope.$watch(function ngModelWatch() { - var modelValue = ngModelGet($scope); - if (modelValue !== ctrl.$modelValue && (ctrl.$modelValue === ctrl.$modelValue || modelValue === modelValue)) { - ctrl.$modelValue = ctrl.$$rawModelValue = modelValue; - parserValid = undefined; - var formatters = ctrl.$formatters, idx = formatters.length; - var viewValue = modelValue; - while (idx--) { - viewValue = formatters[idx](viewValue); - } - if (ctrl.$viewValue !== viewValue) { - ctrl.$viewValue = ctrl.$$lastCommittedViewValue = viewValue; - ctrl.$render(); - ctrl.$$runValidators(modelValue, viewValue, noop); - } - } - return modelValue; - }); - } ]; - var ngModelDirective = [ "$rootScope", function($rootScope) { - return { - restrict: "A", - require: [ "ngModel", "^?form", "^?ngModelOptions" ], - controller: NgModelController, - priority: 1, - compile: function ngModelCompile(element) { - element.addClass(PRISTINE_CLASS).addClass(UNTOUCHED_CLASS).addClass(VALID_CLASS); - return { - pre: function ngModelPreLink(scope, element, attr, ctrls) { - var modelCtrl = ctrls[0], formCtrl = ctrls[1] || modelCtrl.$$parentForm; - modelCtrl.$$setOptions(ctrls[2] && ctrls[2].$options); - formCtrl.$addControl(modelCtrl); - attr.$observe("name", function(newValue) { - if (modelCtrl.$name !== newValue) { - modelCtrl.$$parentForm.$$renameControl(modelCtrl, newValue); - } - }); - scope.$on("$destroy", function() { - modelCtrl.$$parentForm.$removeControl(modelCtrl); - }); - }, - post: function ngModelPostLink(scope, element, attr, ctrls) { - var modelCtrl = ctrls[0]; - if (modelCtrl.$options && modelCtrl.$options.updateOn) { - element.on(modelCtrl.$options.updateOn, function(ev) { - modelCtrl.$$debounceViewValueCommit(ev && ev.type); - }); - } - element.on("blur", function(ev) { - if (modelCtrl.$touched) return; - if ($rootScope.$$phase) { - scope.$evalAsync(modelCtrl.$setTouched); - } else { - scope.$apply(modelCtrl.$setTouched); - } - }); - } - }; - } - }; - } ]; - var DEFAULT_REGEXP = /(\s+|^)default(\s+|$)/; - var ngModelOptionsDirective = function() { - return { - restrict: "A", - controller: [ "$scope", "$attrs", function($scope, $attrs) { - var that = this; - this.$options = copy($scope.$eval($attrs.ngModelOptions)); - if (isDefined(this.$options.updateOn)) { - this.$options.updateOnDefault = false; - this.$options.updateOn = trim(this.$options.updateOn.replace(DEFAULT_REGEXP, function() { - that.$options.updateOnDefault = true; - return " "; - })); - } else { - this.$options.updateOnDefault = true; - } - } ] - }; - }; - function addSetValidityMethod(context) { - var ctrl = context.ctrl, $element = context.$element, classCache = {}, set = context.set, unset = context.unset, $animate = context.$animate; - classCache[INVALID_CLASS] = !(classCache[VALID_CLASS] = $element.hasClass(VALID_CLASS)); - ctrl.$setValidity = setValidity; - function setValidity(validationErrorKey, state, controller) { - if (isUndefined(state)) { - createAndSet("$pending", validationErrorKey, controller); + }, + primary: function() { + var primary; + if (this.expect("(")) { + primary = this.filterChain(); + this.consume(")"); + } else if (this.expect("[")) { + primary = this.arrayDeclaration(); + } else if (this.expect("{")) { + primary = this.object(); + } else if (this.constants.hasOwnProperty(this.peek().text)) { + primary = copy(this.constants[this.consume().text]); + } else if (this.peek().identifier) { + primary = this.identifier(); + } else if (this.peek().constant) { + primary = this.constant(); } else { - unsetAndCleanup("$pending", validationErrorKey, controller); + this.throwError("not a primary expression", this.peek()); } - if (!isBoolean(state)) { - unset(ctrl.$error, validationErrorKey, controller); - unset(ctrl.$$success, validationErrorKey, controller); - } else { - if (state) { - unset(ctrl.$error, validationErrorKey, controller); - set(ctrl.$$success, validationErrorKey, controller); + var next; + while (next = this.expect("(", "[", ".")) { + if (next.text === "(") { + primary = { + type: AST.CallExpression, + callee: primary, + arguments: this.parseArguments() + }; + this.consume(")"); + } else if (next.text === "[") { + primary = { + type: AST.MemberExpression, + object: primary, + property: this.expression(), + computed: true + }; + this.consume("]"); + } else if (next.text === ".") { + primary = { + type: AST.MemberExpression, + object: primary, + property: this.identifier(), + computed: false + }; } else { - set(ctrl.$error, validationErrorKey, controller); - unset(ctrl.$$success, validationErrorKey, controller); + this.throwError("IMPOSSIBLE"); } } - if (ctrl.$pending) { - cachedToggleClass(PENDING_CLASS, true); - ctrl.$valid = ctrl.$invalid = undefined; - toggleValidationCss("", null); - } else { - cachedToggleClass(PENDING_CLASS, false); - ctrl.$valid = isObjectEmpty(ctrl.$error); - ctrl.$invalid = !ctrl.$valid; - toggleValidationCss("", ctrl.$valid); - } - var combinedState; - if (ctrl.$pending && ctrl.$pending[validationErrorKey]) { - combinedState = undefined; - } else if (ctrl.$error[validationErrorKey]) { - combinedState = false; - } else if (ctrl.$$success[validationErrorKey]) { - combinedState = true; - } else { - combinedState = null; - } - toggleValidationCss(validationErrorKey, combinedState); - ctrl.$$parentForm.$setValidity(validationErrorKey, combinedState, ctrl); - } - function createAndSet(name, value, controller) { - if (!ctrl[name]) { - ctrl[name] = {}; - } - set(ctrl[name], value, controller); - } - function unsetAndCleanup(name, value, controller) { - if (ctrl[name]) { - unset(ctrl[name], value, controller); - } - if (isObjectEmpty(ctrl[name])) { - ctrl[name] = undefined; - } - } - function cachedToggleClass(className, switchValue) { - if (switchValue && !classCache[className]) { - $animate.addClass($element, className); - classCache[className] = true; - } else if (!switchValue && classCache[className]) { - $animate.removeClass($element, className); - classCache[className] = false; + return primary; + }, + filter: function(baseExpression) { + var args = [ baseExpression ]; + var result = { + type: AST.CallExpression, + callee: this.identifier(), + arguments: args, + filter: true + }; + while (this.expect(":")) { + args.push(this.expression()); } - } - function toggleValidationCss(validationErrorKey, isValid) { - validationErrorKey = validationErrorKey ? "-" + snake_case(validationErrorKey, "-") : ""; - cachedToggleClass(VALID_CLASS + validationErrorKey, isValid === true); - cachedToggleClass(INVALID_CLASS + validationErrorKey, isValid === false); - } - } - function isObjectEmpty(obj) { - if (obj) { - for (var prop in obj) { - if (obj.hasOwnProperty(prop)) { - return false; - } + return result; + }, + parseArguments: function() { + var args = []; + if (this.peekToken().text !== ")") { + do { + args.push(this.expression()); + } while (this.expect(",")); } - } - return true; - } - var ngNonBindableDirective = ngDirective({ - terminal: true, - priority: 1e3 - }); - var ngOptionsMinErr = minErr("ngOptions"); - var NG_OPTIONS_REGEXP = /^\s*([\s\S]+?)(?:\s+as\s+([\s\S]+?))?(?:\s+group\s+by\s+([\s\S]+?))?(?:\s+disable\s+when\s+([\s\S]+?))?\s+for\s+(?:([\$\w][\$\w]*)|(?:\(\s*([\$\w][\$\w]*)\s*,\s*([\$\w][\$\w]*)\s*\)))\s+in\s+([\s\S]+?)(?:\s+track\s+by\s+([\s\S]+?))?$/; - var ngOptionsDirective = [ "$compile", "$parse", function($compile, $parse) { - function parseOptionsExpression(optionsExp, selectElement, scope) { - var match = optionsExp.match(NG_OPTIONS_REGEXP); - if (!match) { - throw ngOptionsMinErr("iexp", "Expected expression in form of " + "'_select_ (as _label_)? for (_key_,)?_value_ in _collection_'" + " but got '{0}'. Element: {1}", optionsExp, startingTag(selectElement)); + return args; + }, + identifier: function() { + var token = this.consume(); + if (!token.identifier) { + this.throwError("is not a valid identifier", token); } - var valueName = match[5] || match[7]; - var keyName = match[6]; - var selectAs = / as /.test(match[0]) && match[1]; - var trackBy = match[9]; - var valueFn = $parse(match[2] ? match[1] : valueName); - var selectAsFn = selectAs && $parse(selectAs); - var viewValueFn = selectAsFn || valueFn; - var trackByFn = trackBy && $parse(trackBy); - var getTrackByValueFn = trackBy ? function(value, locals) { - return trackByFn(scope, locals); - } : function getHashOfValue(value) { - return hashKey(value); + return { + type: AST.Identifier, + name: token.text }; - var getTrackByValue = function(value, key) { - return getTrackByValueFn(value, getLocals(value, key)); + }, + constant: function() { + return { + type: AST.Literal, + value: this.consume().value }; - var displayFn = $parse(match[2] || match[1]); - var groupByFn = $parse(match[3] || ""); - var disableWhenFn = $parse(match[4] || ""); - var valuesFn = $parse(match[8]); - var locals = {}; - var getLocals = keyName ? function(value, key) { - locals[keyName] = key; - locals[valueName] = value; - return locals; - } : function(value) { - locals[valueName] = value; - return locals; - }; - function Option(selectValue, viewValue, label, group, disabled) { - this.selectValue = selectValue; - this.viewValue = viewValue; - this.label = label; - this.group = group; - this.disabled = disabled; - } - function getOptionValuesKeys(optionValues) { - var optionValuesKeys; - if (!keyName && isArrayLike(optionValues)) { - optionValuesKeys = optionValues; - } else { - optionValuesKeys = []; - for (var itemKey in optionValues) { - if (optionValues.hasOwnProperty(itemKey) && itemKey.charAt(0) !== "$") { - optionValuesKeys.push(itemKey); - } + }, + arrayDeclaration: function() { + var elements = []; + if (this.peekToken().text !== "]") { + do { + if (this.peek("]")) { + break; } - } - return optionValuesKeys; + elements.push(this.expression()); + } while (this.expect(",")); } + this.consume("]"); return { - trackBy: trackBy, - getTrackByValue: getTrackByValue, - getWatchables: $parse(valuesFn, function(optionValues) { - var watchedArray = []; - optionValues = optionValues || []; - var optionValuesKeys = getOptionValuesKeys(optionValues); - var optionValuesLength = optionValuesKeys.length; - for (var index = 0; index < optionValuesLength; index++) { - var key = optionValues === optionValuesKeys ? index : optionValuesKeys[index]; - var value = optionValues[key]; - var locals = getLocals(optionValues[key], key); - var selectValue = getTrackByValueFn(optionValues[key], locals); - watchedArray.push(selectValue); - if (match[2] || match[1]) { - var label = displayFn(scope, locals); - watchedArray.push(label); - } - if (match[4]) { - var disableWhen = disableWhenFn(scope, locals); - watchedArray.push(disableWhen); - } - } - return watchedArray; - }), - getOptions: function() { - var optionItems = []; - var selectValueMap = {}; - var optionValues = valuesFn(scope) || []; - var optionValuesKeys = getOptionValuesKeys(optionValues); - var optionValuesLength = optionValuesKeys.length; - for (var index = 0; index < optionValuesLength; index++) { - var key = optionValues === optionValuesKeys ? index : optionValuesKeys[index]; - var value = optionValues[key]; - var locals = getLocals(value, key); - var viewValue = viewValueFn(scope, locals); - var selectValue = getTrackByValueFn(viewValue, locals); - var label = displayFn(scope, locals); - var group = groupByFn(scope, locals); - var disabled = disableWhenFn(scope, locals); - var optionItem = new Option(selectValue, viewValue, label, group, disabled); - optionItems.push(optionItem); - selectValueMap[selectValue] = optionItem; - } - return { - items: optionItems, - selectValueMap: selectValueMap, - getOptionFromViewValue: function(value) { - return selectValueMap[getTrackByValue(value)]; - }, - getViewValueFromOption: function(option) { - return trackBy ? angular.copy(option.viewValue) : option.viewValue; - } - }; - } + type: AST.ArrayExpression, + elements: elements }; - } - var optionTemplate = document.createElement("option"), optGroupTemplate = document.createElement("optgroup"); - return { - restrict: "A", - terminal: true, - require: [ "select", "?ngModel" ], - link: function(scope, selectElement, attr, ctrls) { - var ngModelCtrl = ctrls[1]; - if (!ngModelCtrl) return; - var selectCtrl = ctrls[0]; - var multiple = attr.multiple; - var emptyOption; - for (var i = 0, children = selectElement.children(), ii = children.length; i < ii; i++) { - if (children[i].value === "") { - emptyOption = children.eq(i); + }, + object: function() { + var properties = [], property; + if (this.peekToken().text !== "}") { + do { + if (this.peek("}")) { break; } - } - var providedEmptyOption = !!emptyOption; - var unknownOption = jqLite(optionTemplate.cloneNode(false)); - unknownOption.val("?"); - var options; - var ngOptions = parseOptionsExpression(attr.ngOptions, selectElement, scope); - var renderEmptyOption = function() { - if (!providedEmptyOption) { - selectElement.prepend(emptyOption); - } - selectElement.val(""); - emptyOption.prop("selected", true); - emptyOption.attr("selected", true); - }; - var removeEmptyOption = function() { - if (!providedEmptyOption) { - emptyOption.remove(); - } - }; - var renderUnknownOption = function() { - selectElement.prepend(unknownOption); - selectElement.val("?"); - unknownOption.prop("selected", true); - unknownOption.attr("selected", true); - }; - var removeUnknownOption = function() { - unknownOption.remove(); - }; - if (!multiple) { - selectCtrl.writeValue = function writeNgOptionsValue(value) { - var option = options.getOptionFromViewValue(value); - if (option && !option.disabled) { - if (selectElement[0].value !== option.selectValue) { - removeUnknownOption(); - removeEmptyOption(); - selectElement[0].value = option.selectValue; - option.element.selected = true; - option.element.setAttribute("selected", "selected"); - } - } else { - if (value === null || providedEmptyOption) { - removeUnknownOption(); - renderEmptyOption(); - } else { - removeEmptyOption(); - renderUnknownOption(); - } - } - }; - selectCtrl.readValue = function readNgOptionsValue() { - var selectedOption = options.selectValueMap[selectElement.val()]; - if (selectedOption && !selectedOption.disabled) { - removeEmptyOption(); - removeUnknownOption(); - return options.getViewValueFromOption(selectedOption); - } - return null; - }; - if (ngOptions.trackBy) { - scope.$watch(function() { - return ngOptions.getTrackByValue(ngModelCtrl.$viewValue); - }, function() { - ngModelCtrl.$render(); - }); - } - } else { - ngModelCtrl.$isEmpty = function(value) { - return !value || value.length === 0; - }; - selectCtrl.writeValue = function writeNgOptionsMultiple(value) { - options.items.forEach(function(option) { - option.element.selected = false; - }); - if (value) { - value.forEach(function(item) { - var option = options.getOptionFromViewValue(item); - if (option && !option.disabled) option.element.selected = true; - }); - } - }; - selectCtrl.readValue = function readNgOptionsMultiple() { - var selectedValues = selectElement.val() || [], selections = []; - forEach(selectedValues, function(value) { - var option = options.selectValueMap[value]; - if (option && !option.disabled) selections.push(options.getViewValueFromOption(option)); - }); - return selections; + property = { + type: AST.Property, + kind: "init" }; - if (ngOptions.trackBy) { - scope.$watchCollection(function() { - if (isArray(ngModelCtrl.$viewValue)) { - return ngModelCtrl.$viewValue.map(function(value) { - return ngOptions.getTrackByValue(value); - }); - } - }, function() { - ngModelCtrl.$render(); - }); - } - } - if (providedEmptyOption) { - emptyOption.remove(); - $compile(emptyOption)(scope); - emptyOption.removeClass("ng-scope"); - } else { - emptyOption = jqLite(optionTemplate.cloneNode(false)); - } - updateOptions(); - scope.$watchCollection(ngOptions.getWatchables, updateOptions); - function updateOptionElement(option, element) { - option.element = element; - element.disabled = option.disabled; - if (option.value !== element.value) element.value = option.selectValue; - if (option.label !== element.label) { - element.label = option.label; - element.textContent = option.label; - } - } - function addOrReuseElement(parent, current, type, templateElement) { - var element; - if (current && lowercase(current.nodeName) === type) { - element = current; + if (this.peek().constant) { + property.key = this.constant(); + } else if (this.peek().identifier) { + property.key = this.identifier(); } else { - element = templateElement.cloneNode(false); - if (!current) { - parent.appendChild(element); - } else { - parent.insertBefore(element, current); - } + this.throwError("invalid key", this.peek()); } - return element; - } - function removeExcessElements(current) { - var next; - while (current) { - next = current.nextSibling; - jqLiteRemove(current); - current = next; - } - } - function skipEmptyAndUnknownOptions(current) { - var emptyOption_ = emptyOption && emptyOption[0]; - var unknownOption_ = unknownOption && unknownOption[0]; - if (emptyOption_ || unknownOption_) { - while (current && (current === emptyOption_ || current === unknownOption_)) { - current = current.nextSibling; - } - } - return current; - } - function updateOptions() { - var previousValue = options && selectCtrl.readValue(); - options = ngOptions.getOptions(); - var groupMap = {}; - var currentElement = selectElement[0].firstChild; - if (providedEmptyOption) { - selectElement.prepend(emptyOption); - } - currentElement = skipEmptyAndUnknownOptions(currentElement); - options.items.forEach(function updateOption(option) { - var group; - var groupElement; - var optionElement; - if (option.group) { - group = groupMap[option.group]; - if (!group) { - groupElement = addOrReuseElement(selectElement[0], currentElement, "optgroup", optGroupTemplate); - currentElement = groupElement.nextSibling; - groupElement.label = option.group; - group = groupMap[option.group] = { - groupElement: groupElement, - currentOptionElement: groupElement.firstChild - }; - } - optionElement = addOrReuseElement(group.groupElement, group.currentOptionElement, "option", optionTemplate); - updateOptionElement(option, optionElement); - group.currentOptionElement = optionElement.nextSibling; - } else { - optionElement = addOrReuseElement(selectElement[0], currentElement, "option", optionTemplate); - updateOptionElement(option, optionElement); - currentElement = optionElement.nextSibling; - } - }); - Object.keys(groupMap).forEach(function(key) { - removeExcessElements(groupMap[key].currentOptionElement); - }); - removeExcessElements(currentElement); - ngModelCtrl.$render(); - if (!ngModelCtrl.$isEmpty(previousValue)) { - var nextValue = selectCtrl.readValue(); - if (ngOptions.trackBy ? !equals(previousValue, nextValue) : previousValue !== nextValue) { - ngModelCtrl.$setViewValue(nextValue); - ngModelCtrl.$render(); - } - } - } + this.consume(":"); + property.value = this.expression(); + properties.push(property); + } while (this.expect(",")); } - }; - } ]; - var ngPluralizeDirective = [ "$locale", "$interpolate", "$log", function($locale, $interpolate, $log) { - var BRACE = /{}/g, IS_WHEN = /^when(Minus)?(.+)$/; - return { - link: function(scope, element, attr) { - var numberExp = attr.count, whenExp = attr.$attr.when && element.attr(attr.$attr.when), offset = attr.offset || 0, whens = scope.$eval(whenExp) || {}, whensExpFns = {}, startSymbol = $interpolate.startSymbol(), endSymbol = $interpolate.endSymbol(), braceReplacement = startSymbol + numberExp + "-" + offset + endSymbol, watchRemover = angular.noop, lastCount; - forEach(attr, function(expression, attributeName) { - var tmpMatch = IS_WHEN.exec(attributeName); - if (tmpMatch) { - var whenKey = (tmpMatch[1] ? "-" : "") + lowercase(tmpMatch[2]); - whens[whenKey] = element.attr(attr.$attr[attributeName]); - } - }); - forEach(whens, function(expression, key) { - whensExpFns[key] = $interpolate(expression.replace(BRACE, braceReplacement)); - }); - scope.$watch(numberExp, function ngPluralizeWatchAction(newVal) { - var count = parseFloat(newVal); - var countIsNaN = isNaN(count); - if (!countIsNaN && !(count in whens)) { - count = $locale.pluralCat(count - offset); - } - if (count !== lastCount && !(countIsNaN && isNumber(lastCount) && isNaN(lastCount))) { - watchRemover(); - var whenExpFn = whensExpFns[count]; - if (isUndefined(whenExpFn)) { - if (newVal != null) { - $log.debug("ngPluralize: no rule defined for '" + count + "' in " + whenExp); - } - watchRemover = noop; - updateElementText(); - } else { - watchRemover = scope.$watch(whenExpFn, updateElementText); - } - lastCount = count; - } - }); - function updateElementText(newText) { - element.text(newText || ""); - } + this.consume("}"); + return { + type: AST.ObjectExpression, + properties: properties + }; + }, + throwError: function(msg, token) { + throw $parseMinErr("syntax", "Syntax Error: Token '{0}' {1} at column {2} of the expression [{3}] starting at [{4}].", token.text, msg, token.index + 1, this.text, this.text.substring(token.index)); + }, + consume: function(e1) { + if (this.tokens.length === 0) { + throw $parseMinErr("ueoe", "Unexpected end of expression: {0}", this.text); } - }; - } ]; - var ngRepeatDirective = [ "$parse", "$animate", function($parse, $animate) { - var NG_REMOVED = "$$NG_REMOVED"; - var ngRepeatMinErr = minErr("ngRepeat"); - var updateScope = function(scope, index, valueIdentifier, value, keyIdentifier, key, arrayLength) { - scope[valueIdentifier] = value; - if (keyIdentifier) scope[keyIdentifier] = key; - scope.$index = index; - scope.$first = index === 0; - scope.$last = index === arrayLength - 1; - scope.$middle = !(scope.$first || scope.$last); - scope.$odd = !(scope.$even = (index & 1) === 0); - }; - var getBlockStart = function(block) { - return block.clone[0]; - }; - var getBlockEnd = function(block) { - return block.clone[block.clone.length - 1]; - }; - return { - restrict: "A", - multiElement: true, - transclude: "element", - priority: 1e3, - terminal: true, - $$tlb: true, - compile: function ngRepeatCompile($element, $attr) { - var expression = $attr.ngRepeat; - var ngRepeatEndComment = document.createComment(" end ngRepeat: " + expression + " "); - var match = expression.match(/^\s*([\s\S]+?)\s+in\s+([\s\S]+?)(?:\s+as\s+([\s\S]+?))?(?:\s+track\s+by\s+([\s\S]+?))?\s*$/); - if (!match) { - throw ngRepeatMinErr("iexp", "Expected expression in form of '_item_ in _collection_[ track by _id_]' but got '{0}'.", expression); - } - var lhs = match[1]; - var rhs = match[2]; - var aliasAs = match[3]; - var trackByExp = match[4]; - match = lhs.match(/^(?:(\s*[\$\w]+)|\(\s*([\$\w]+)\s*,\s*([\$\w]+)\s*\))$/); - if (!match) { - throw ngRepeatMinErr("iidexp", "'_item_' in '_item_ in _collection_' should be an identifier or '(_key_, _value_)' expression, but got '{0}'.", lhs); - } - var valueIdentifier = match[3] || match[1]; - var keyIdentifier = match[2]; - if (aliasAs && (!/^[$a-zA-Z_][$a-zA-Z0-9_]*$/.test(aliasAs) || /^(null|undefined|this|\$index|\$first|\$middle|\$last|\$even|\$odd|\$parent|\$root|\$id)$/.test(aliasAs))) { - throw ngRepeatMinErr("badident", "alias '{0}' is invalid --- must be a valid JS identifier which is not a reserved name.", aliasAs); - } - var trackByExpGetter, trackByIdExpFn, trackByIdArrayFn, trackByIdObjFn; - var hashFnLocals = { - $id: hashKey - }; - if (trackByExp) { - trackByExpGetter = $parse(trackByExp); - } else { - trackByIdArrayFn = function(key, value) { - return hashKey(value); - }; - trackByIdObjFn = function(key) { - return key; - }; + var token = this.expect(e1); + if (!token) { + this.throwError("is unexpected, expecting [" + e1 + "]", this.peek()); + } + return token; + }, + peekToken: function() { + if (this.tokens.length === 0) { + throw $parseMinErr("ueoe", "Unexpected end of expression: {0}", this.text); + } + return this.tokens[0]; + }, + peek: function(e1, e2, e3, e4) { + return this.peekAhead(0, e1, e2, e3, e4); + }, + peekAhead: function(i, e1, e2, e3, e4) { + if (this.tokens.length > i) { + var token = this.tokens[i]; + var t = token.text; + if (t === e1 || t === e2 || t === e3 || t === e4 || !e1 && !e2 && !e3 && !e4) { + return token; } - return function ngRepeatLink($scope, $element, $attr, ctrl, $transclude) { - if (trackByExpGetter) { - trackByIdExpFn = function(key, value, index) { - if (keyIdentifier) hashFnLocals[keyIdentifier] = key; - hashFnLocals[valueIdentifier] = value; - hashFnLocals.$index = index; - return trackByExpGetter($scope, hashFnLocals); - }; - } - var lastBlockMap = createMap(); - $scope.$watchCollection(rhs, function ngRepeatAction(collection) { - var index, length, previousNode = $element[0], nextNode, nextBlockMap = createMap(), collectionLength, key, value, trackById, trackByIdFn, collectionKeys, block, nextBlockOrder, elementsToRemove; - if (aliasAs) { - $scope[aliasAs] = collection; - } - if (isArrayLike(collection)) { - collectionKeys = collection; - trackByIdFn = trackByIdExpFn || trackByIdArrayFn; - } else { - trackByIdFn = trackByIdExpFn || trackByIdObjFn; - collectionKeys = []; - for (var itemKey in collection) { - if (hasOwnProperty.call(collection, itemKey) && itemKey.charAt(0) !== "$") { - collectionKeys.push(itemKey); - } - } - } - collectionLength = collectionKeys.length; - nextBlockOrder = new Array(collectionLength); - for (index = 0; index < collectionLength; index++) { - key = collection === collectionKeys ? index : collectionKeys[index]; - value = collection[key]; - trackById = trackByIdFn(key, value, index); - if (lastBlockMap[trackById]) { - block = lastBlockMap[trackById]; - delete lastBlockMap[trackById]; - nextBlockMap[trackById] = block; - nextBlockOrder[index] = block; - } else if (nextBlockMap[trackById]) { - forEach(nextBlockOrder, function(block) { - if (block && block.scope) lastBlockMap[block.id] = block; - }); - throw ngRepeatMinErr("dupes", "Duplicates in a repeater are not allowed. Use 'track by' expression to specify unique keys. Repeater: {0}, Duplicate key: {1}, Duplicate value: {2}", expression, trackById, value); - } else { - nextBlockOrder[index] = { - id: trackById, - scope: undefined, - clone: undefined - }; - nextBlockMap[trackById] = true; - } - } - for (var blockKey in lastBlockMap) { - block = lastBlockMap[blockKey]; - elementsToRemove = getBlockNodes(block.clone); - $animate.leave(elementsToRemove); - if (elementsToRemove[0].parentNode) { - for (index = 0, length = elementsToRemove.length; index < length; index++) { - elementsToRemove[index][NG_REMOVED] = true; - } - } - block.scope.$destroy(); - } - for (index = 0; index < collectionLength; index++) { - key = collection === collectionKeys ? index : collectionKeys[index]; - value = collection[key]; - block = nextBlockOrder[index]; - if (block.scope) { - nextNode = previousNode; - do { - nextNode = nextNode.nextSibling; - } while (nextNode && nextNode[NG_REMOVED]); - if (getBlockStart(block) != nextNode) { - $animate.move(getBlockNodes(block.clone), null, jqLite(previousNode)); - } - previousNode = getBlockEnd(block); - updateScope(block.scope, index, valueIdentifier, value, keyIdentifier, key, collectionLength); - } else { - $transclude(function ngRepeatTransclude(clone, scope) { - block.scope = scope; - var endNode = ngRepeatEndComment.cloneNode(false); - clone[clone.length++] = endNode; - $animate.enter(clone, null, jqLite(previousNode)); - previousNode = endNode; - block.clone = clone; - nextBlockMap[block.id] = block; - updateScope(block.scope, index, valueIdentifier, value, keyIdentifier, key, collectionLength); - }); - } - } - lastBlockMap = nextBlockMap; - }); - }; - } - }; - } ]; - var NG_HIDE_CLASS = "ng-hide"; - var NG_HIDE_IN_PROGRESS_CLASS = "ng-hide-animate"; - var ngShowDirective = [ "$animate", function($animate) { - return { - restrict: "A", - multiElement: true, - link: function(scope, element, attr) { - scope.$watch(attr.ngShow, function ngShowWatchAction(value) { - $animate[value ? "removeClass" : "addClass"](element, NG_HIDE_CLASS, { - tempClasses: NG_HIDE_IN_PROGRESS_CLASS - }); - }); - } - }; - } ]; - var ngHideDirective = [ "$animate", function($animate) { - return { - restrict: "A", - multiElement: true, - link: function(scope, element, attr) { - scope.$watch(attr.ngHide, function ngHideWatchAction(value) { - $animate[value ? "addClass" : "removeClass"](element, NG_HIDE_CLASS, { - tempClasses: NG_HIDE_IN_PROGRESS_CLASS - }); - }); } - }; - } ]; - var ngStyleDirective = ngDirective(function(scope, element, attr) { - scope.$watch(attr.ngStyle, function ngStyleWatchAction(newStyles, oldStyles) { - if (oldStyles && newStyles !== oldStyles) { - forEach(oldStyles, function(val, style) { - element.css(style, ""); - }); + return false; + }, + expect: function(e1, e2, e3, e4) { + var token = this.peek(e1, e2, e3, e4); + if (token) { + this.tokens.shift(); + return token; } - if (newStyles) element.css(newStyles); - }, true); - }); - var ngSwitchDirective = [ "$animate", function($animate) { - return { - require: "ngSwitch", - controller: [ "$scope", function ngSwitchController() { - this.cases = {}; - } ], - link: function(scope, element, attr, ngSwitchController) { - var watchExpr = attr.ngSwitch || attr.on, selectedTranscludes = [], selectedElements = [], previousLeaveAnimations = [], selectedScopes = []; - var spliceFactory = function(array, index) { - return function() { - array.splice(index, 1); - }; - }; - scope.$watch(watchExpr, function ngSwitchWatchAction(value) { - var i, ii; - for (i = 0, ii = previousLeaveAnimations.length; i < ii; ++i) { - $animate.cancel(previousLeaveAnimations[i]); - } - previousLeaveAnimations.length = 0; - for (i = 0, ii = selectedScopes.length; i < ii; ++i) { - var selected = getBlockNodes(selectedElements[i].clone); - selectedScopes[i].$destroy(); - var promise = previousLeaveAnimations[i] = $animate.leave(selected); - promise.then(spliceFactory(previousLeaveAnimations, i)); - } - selectedElements.length = 0; - selectedScopes.length = 0; - if (selectedTranscludes = ngSwitchController.cases["!" + value] || ngSwitchController.cases["?"]) { - forEach(selectedTranscludes, function(selectedTransclude) { - selectedTransclude.transclude(function(caseElement, selectedScope) { - selectedScopes.push(selectedScope); - var anchor = selectedTransclude.element; - caseElement[caseElement.length++] = document.createComment(" end ngSwitchWhen: "); - var block = { - clone: caseElement - }; - selectedElements.push(block); - $animate.enter(caseElement, anchor.parent(), anchor); - }); - }); - } - }); + return false; + }, + constants: { + "true": { + type: AST.Literal, + value: true + }, + "false": { + type: AST.Literal, + value: false + }, + "null": { + type: AST.Literal, + value: null + }, + undefined: { + type: AST.Literal, + value: undefined + }, + "this": { + type: AST.ThisExpression } - }; - } ]; - var ngSwitchWhenDirective = ngDirective({ - transclude: "element", - priority: 1200, - require: "^ngSwitch", - multiElement: true, - link: function(scope, element, attrs, ctrl, $transclude) { - ctrl.cases["!" + attrs.ngSwitchWhen] = ctrl.cases["!" + attrs.ngSwitchWhen] || []; - ctrl.cases["!" + attrs.ngSwitchWhen].push({ - transclude: $transclude, - element: element - }); } - }); - var ngSwitchDefaultDirective = ngDirective({ - transclude: "element", - priority: 1200, - require: "^ngSwitch", - multiElement: true, - link: function(scope, element, attr, ctrl, $transclude) { - ctrl.cases["?"] = ctrl.cases["?"] || []; - ctrl.cases["?"].push({ - transclude: $transclude, - element: element + }; + function ifDefined(v, d) { + return typeof v !== "undefined" ? v : d; + } + function plusFn(l, r) { + if (typeof l === "undefined") return r; + if (typeof r === "undefined") return l; + return l + r; + } + function isStateless($filter, filterName) { + var fn = $filter(filterName); + return !fn.$stateful; + } + function findConstantAndWatchExpressions(ast, $filter) { + var allConstants; + var argsToWatch; + switch (ast.type) { + case AST.Program: + allConstants = true; + forEach(ast.body, function(expr) { + findConstantAndWatchExpressions(expr.expression, $filter); + allConstants = allConstants && expr.expression.constant; }); - } - }); - var ngTranscludeDirective = ngDirective({ - restrict: "EAC", - link: function($scope, $element, $attrs, controller, $transclude) { - if (!$transclude) { - throw minErr("ngTransclude")("orphan", "Illegal use of ngTransclude directive in the template! " + "No parent directive that requires a transclusion found. " + "Element: {0}", startingTag($element)); + ast.constant = allConstants; + break; + + case AST.Literal: + ast.constant = true; + ast.toWatch = []; + break; + + case AST.UnaryExpression: + findConstantAndWatchExpressions(ast.argument, $filter); + ast.constant = ast.argument.constant; + ast.toWatch = ast.argument.toWatch; + break; + + case AST.BinaryExpression: + findConstantAndWatchExpressions(ast.left, $filter); + findConstantAndWatchExpressions(ast.right, $filter); + ast.constant = ast.left.constant && ast.right.constant; + ast.toWatch = ast.left.toWatch.concat(ast.right.toWatch); + break; + + case AST.LogicalExpression: + findConstantAndWatchExpressions(ast.left, $filter); + findConstantAndWatchExpressions(ast.right, $filter); + ast.constant = ast.left.constant && ast.right.constant; + ast.toWatch = ast.constant ? [] : [ ast ]; + break; + + case AST.ConditionalExpression: + findConstantAndWatchExpressions(ast.test, $filter); + findConstantAndWatchExpressions(ast.alternate, $filter); + findConstantAndWatchExpressions(ast.consequent, $filter); + ast.constant = ast.test.constant && ast.alternate.constant && ast.consequent.constant; + ast.toWatch = ast.constant ? [] : [ ast ]; + break; + + case AST.Identifier: + ast.constant = false; + ast.toWatch = [ ast ]; + break; + + case AST.MemberExpression: + findConstantAndWatchExpressions(ast.object, $filter); + if (ast.computed) { + findConstantAndWatchExpressions(ast.property, $filter); } - $transclude(function(clone) { - $element.empty(); - $element.append(clone); - }); - } - }); - var scriptDirective = [ "$templateCache", function($templateCache) { - return { - restrict: "E", - terminal: true, - compile: function(element, attr) { - if (attr.type == "text/ng-template") { - var templateUrl = attr.id, text = element[0].text; - $templateCache.put(templateUrl, text); + ast.constant = ast.object.constant && (!ast.computed || ast.property.constant); + ast.toWatch = [ ast ]; + break; + + case AST.CallExpression: + allConstants = ast.filter ? isStateless($filter, ast.callee.name) : false; + argsToWatch = []; + forEach(ast.arguments, function(expr) { + findConstantAndWatchExpressions(expr, $filter); + allConstants = allConstants && expr.constant; + if (!expr.constant) { + argsToWatch.push.apply(argsToWatch, expr.toWatch); } - } - }; - } ]; - var noopNgModelController = { - $setViewValue: noop, - $render: noop - }; - var SelectController = [ "$element", "$scope", "$attrs", function($element, $scope, $attrs) { - var self = this, optionsMap = new HashMap(); - self.ngModelCtrl = noopNgModelController; - self.unknownOption = jqLite(document.createElement("option")); - self.renderUnknownOption = function(val) { - var unknownVal = "? " + hashKey(val) + " ?"; - self.unknownOption.val(unknownVal); - $element.prepend(self.unknownOption); - $element.val(unknownVal); - }; - $scope.$on("$destroy", function() { - self.renderUnknownOption = noop; - }); - self.removeUnknownOption = function() { - if (self.unknownOption.parent()) self.unknownOption.remove(); - }; - self.readValue = function readSingleValue() { - self.removeUnknownOption(); - return $element.val(); - }; - self.writeValue = function writeSingleValue(value) { - if (self.hasOption(value)) { - self.removeUnknownOption(); - $element.val(value); - if (value === "") self.emptyOption.prop("selected", true); - } else { - if (value == null && self.emptyOption) { - self.removeUnknownOption(); - $element.val(""); - } else { - self.renderUnknownOption(value); + }); + ast.constant = allConstants; + ast.toWatch = ast.filter && isStateless($filter, ast.callee.name) ? argsToWatch : [ ast ]; + break; + + case AST.AssignmentExpression: + findConstantAndWatchExpressions(ast.left, $filter); + findConstantAndWatchExpressions(ast.right, $filter); + ast.constant = ast.left.constant && ast.right.constant; + ast.toWatch = [ ast ]; + break; + + case AST.ArrayExpression: + allConstants = true; + argsToWatch = []; + forEach(ast.elements, function(expr) { + findConstantAndWatchExpressions(expr, $filter); + allConstants = allConstants && expr.constant; + if (!expr.constant) { + argsToWatch.push.apply(argsToWatch, expr.toWatch); } - } - }; - self.addOption = function(value, element) { - assertNotHasOwnProperty(value, '"option value"'); - if (value === "") { - self.emptyOption = element; - } - var count = optionsMap.get(value) || 0; - optionsMap.put(value, count + 1); - }; - self.removeOption = function(value) { - var count = optionsMap.get(value); - if (count) { - if (count === 1) { - optionsMap.remove(value); - if (value === "") { - self.emptyOption = undefined; - } - } else { - optionsMap.put(value, count - 1); + }); + ast.constant = allConstants; + ast.toWatch = argsToWatch; + break; + + case AST.ObjectExpression: + allConstants = true; + argsToWatch = []; + forEach(ast.properties, function(property) { + findConstantAndWatchExpressions(property.value, $filter); + allConstants = allConstants && property.value.constant; + if (!property.value.constant) { + argsToWatch.push.apply(argsToWatch, property.value.toWatch); } + }); + ast.constant = allConstants; + ast.toWatch = argsToWatch; + break; + + case AST.ThisExpression: + ast.constant = false; + ast.toWatch = []; + break; + } + } + function getInputs(body) { + if (body.length != 1) return; + var lastExpression = body[0].expression; + var candidate = lastExpression.toWatch; + if (candidate.length !== 1) return candidate; + return candidate[0] !== lastExpression ? candidate : undefined; + } + function isAssignable(ast) { + return ast.type === AST.Identifier || ast.type === AST.MemberExpression; + } + function assignableAST(ast) { + if (ast.body.length === 1 && isAssignable(ast.body[0].expression)) { + return { + type: AST.AssignmentExpression, + left: ast.body[0].expression, + right: { + type: AST.NGValueParameter + }, + operator: "=" + }; + } + } + function isLiteral(ast) { + return ast.body.length === 0 || ast.body.length === 1 && (ast.body[0].expression.type === AST.Literal || ast.body[0].expression.type === AST.ArrayExpression || ast.body[0].expression.type === AST.ObjectExpression); + } + function isConstant(ast) { + return ast.constant; + } + function ASTCompiler(astBuilder, $filter) { + this.astBuilder = astBuilder; + this.$filter = $filter; + } + ASTCompiler.prototype = { + compile: function(expression, expensiveChecks) { + var self = this; + var ast = this.astBuilder.ast(expression); + this.state = { + nextId: 0, + filters: {}, + expensiveChecks: expensiveChecks, + fn: { + vars: [], + body: [], + own: {} + }, + assign: { + vars: [], + body: [], + own: {} + }, + inputs: [] + }; + findConstantAndWatchExpressions(ast, self.$filter); + var extra = ""; + var assignable; + this.stage = "assign"; + if (assignable = assignableAST(ast)) { + this.state.computing = "assign"; + var result = this.nextId(); + this.recurse(assignable, result); + this.return_(result); + extra = "fn.assign=" + this.generateFunction("assign", "s,v,l"); } - }; - self.hasOption = function(value) { - return !!optionsMap.get(value); - }; - } ]; - var selectDirective = function() { - return { - restrict: "E", - require: [ "select", "?ngModel" ], - controller: SelectController, - link: function(scope, element, attr, ctrls) { - var ngModelCtrl = ctrls[1]; - if (!ngModelCtrl) return; - var selectCtrl = ctrls[0]; - selectCtrl.ngModelCtrl = ngModelCtrl; - ngModelCtrl.$render = function() { - selectCtrl.writeValue(ngModelCtrl.$viewValue); - }; - element.on("change", function() { - scope.$apply(function() { - ngModelCtrl.$setViewValue(selectCtrl.readValue()); - }); - }); - if (attr.multiple) { - selectCtrl.readValue = function readMultipleValue() { - var array = []; - forEach(element.find("option"), function(option) { - if (option.selected) { - array.push(option.value); - } - }); - return array; - }; - selectCtrl.writeValue = function writeMultipleValue(value) { - var items = new HashMap(value); - forEach(element.find("option"), function(option) { - option.selected = isDefined(items.get(option.value)); - }); - }; - var lastView, lastViewRef = NaN; - scope.$watch(function selectMultipleWatch() { - if (lastViewRef === ngModelCtrl.$viewValue && !equals(lastView, ngModelCtrl.$viewValue)) { - lastView = shallowCopy(ngModelCtrl.$viewValue); - ngModelCtrl.$render(); - } - lastViewRef = ngModelCtrl.$viewValue; - }); - ngModelCtrl.$isEmpty = function(value) { - return !value || value.length === 0; - }; - } - } - }; - }; - var optionDirective = [ "$interpolate", function($interpolate) { - function chromeHack(optionElement) { - if (optionElement[0].hasAttribute("selected")) { - optionElement[0].selected = true; - } - } - return { - restrict: "E", - priority: 100, - compile: function(element, attr) { - if (isDefined(attr.value)) { - var valueInterpolated = $interpolate(attr.value, true); - } else { - var interpolateFn = $interpolate(element.text(), true); - if (!interpolateFn) { - attr.$set("value", element.text()); - } - } - return function(scope, element, attr) { - var selectCtrlName = "$selectController", parent = element.parent(), selectCtrl = parent.data(selectCtrlName) || parent.parent().data(selectCtrlName); - function addOption(optionValue) { - selectCtrl.addOption(optionValue, element); - selectCtrl.ngModelCtrl.$render(); - chromeHack(element); - } - if (selectCtrl && selectCtrl.ngModelCtrl) { - if (valueInterpolated) { - var oldVal; - attr.$observe("value", function valueAttributeObserveAction(newVal) { - if (isDefined(oldVal)) { - selectCtrl.removeOption(oldVal); - } - oldVal = newVal; - addOption(newVal); - }); - } else if (interpolateFn) { - scope.$watch(interpolateFn, function interpolateWatchAction(newVal, oldVal) { - attr.$set("value", newVal); - if (oldVal !== newVal) { - selectCtrl.removeOption(oldVal); - } - addOption(newVal); - }); - } else { - addOption(attr.value); - } - element.on("$destroy", function() { - selectCtrl.removeOption(attr.value); - selectCtrl.ngModelCtrl.$render(); - }); - } + var toWatch = getInputs(ast.body); + self.stage = "inputs"; + forEach(toWatch, function(watch, key) { + var fnKey = "fn" + key; + self.state[fnKey] = { + vars: [], + body: [], + own: {} }; + self.state.computing = fnKey; + var intoId = self.nextId(); + self.recurse(watch, intoId); + self.return_(intoId); + self.state.inputs.push(fnKey); + watch.watchId = key; + }); + this.state.computing = "fn"; + this.stage = "main"; + this.recurse(ast); + var fnString = '"' + this.USE + " " + this.STRICT + '";\n' + this.filterPrefix() + "var fn=" + this.generateFunction("fn", "s,l,a,i") + extra + this.watchFns() + "return fn;"; + var fn = new Function("$filter", "ensureSafeMemberName", "ensureSafeObject", "ensureSafeFunction", "getStringValue", "ensureSafeAssignContext", "ifDefined", "plus", "text", fnString)(this.$filter, ensureSafeMemberName, ensureSafeObject, ensureSafeFunction, getStringValue, ensureSafeAssignContext, ifDefined, plusFn, expression); + this.state = this.stage = undefined; + fn.literal = isLiteral(ast); + fn.constant = isConstant(ast); + return fn; + }, + USE: "use", + STRICT: "strict", + watchFns: function() { + var result = []; + var fns = this.state.inputs; + var self = this; + forEach(fns, function(name) { + result.push("var " + name + "=" + self.generateFunction(name, "s")); + }); + if (fns.length) { + result.push("fn.inputs=[" + fns.join(",") + "];"); } - }; - } ]; - var styleDirective = valueFn({ - restrict: "E", - terminal: false - }); - var requiredDirective = function() { - return { - restrict: "A", - require: "?ngModel", - link: function(scope, elm, attr, ctrl) { - if (!ctrl) return; - attr.required = true; - ctrl.$validators.required = function(modelValue, viewValue) { - return !attr.required || !ctrl.$isEmpty(viewValue); - }; - attr.$observe("required", function() { - ctrl.$validate(); - }); + return result.join(""); + }, + generateFunction: function(name, params) { + return "function(" + params + "){" + this.varsPrefix(name) + this.body(name) + "};"; + }, + filterPrefix: function() { + var parts = []; + var self = this; + forEach(this.state.filters, function(id, filter) { + parts.push(id + "=$filter(" + self.escape(filter) + ")"); + }); + if (parts.length) return "var " + parts.join(",") + ";"; + return ""; + }, + varsPrefix: function(section) { + return this.state[section].vars.length ? "var " + this.state[section].vars.join(",") + ";" : ""; + }, + body: function(section) { + return this.state[section].body.join(""); + }, + recurse: function(ast, intoId, nameId, recursionFn, create, skipWatchIdCheck) { + var left, right, self = this, args, expression; + recursionFn = recursionFn || noop; + if (!skipWatchIdCheck && isDefined(ast.watchId)) { + intoId = intoId || this.nextId(); + this.if_("i", this.lazyAssign(intoId, this.computedMember("i", ast.watchId)), this.lazyRecurse(ast, intoId, nameId, recursionFn, create, true)); + return; } - }; - }; - var patternDirective = function() { - return { - restrict: "A", - require: "?ngModel", - link: function(scope, elm, attr, ctrl) { - if (!ctrl) return; - var regexp, patternExp = attr.ngPattern || attr.pattern; - attr.$observe("pattern", function(regex) { - if (isString(regex) && regex.length > 0) { - regex = new RegExp("^" + regex + "$"); - } - if (regex && !regex.test) { - throw minErr("ngPattern")("noregexp", "Expected {0} to be a RegExp but was {1}. Element: {2}", patternExp, regex, startingTag(elm)); + switch (ast.type) { + case AST.Program: + forEach(ast.body, function(expression, pos) { + self.recurse(expression.expression, undefined, undefined, function(expr) { + right = expr; + }); + if (pos !== ast.body.length - 1) { + self.current().body.push(right, ";"); + } else { + self.return_(right); } - regexp = regex || undefined; - ctrl.$validate(); }); - ctrl.$validators.pattern = function(modelValue, viewValue) { - return ctrl.$isEmpty(viewValue) || isUndefined(regexp) || regexp.test(viewValue); - }; - } - }; - }; - var maxlengthDirective = function() { - return { - restrict: "A", - require: "?ngModel", - link: function(scope, elm, attr, ctrl) { - if (!ctrl) return; - var maxlength = -1; - attr.$observe("maxlength", function(value) { - var intVal = toInt(value); - maxlength = isNaN(intVal) ? -1 : intVal; - ctrl.$validate(); + break; + + case AST.Literal: + expression = this.escape(ast.value); + this.assign(intoId, expression); + recursionFn(expression); + break; + + case AST.UnaryExpression: + this.recurse(ast.argument, undefined, undefined, function(expr) { + right = expr; }); - ctrl.$validators.maxlength = function(modelValue, viewValue) { - return maxlength < 0 || ctrl.$isEmpty(viewValue) || viewValue.length <= maxlength; - }; - } - }; - }; - var minlengthDirective = function() { - return { - restrict: "A", - require: "?ngModel", - link: function(scope, elm, attr, ctrl) { - if (!ctrl) return; - var minlength = 0; - attr.$observe("minlength", function(value) { - minlength = toInt(value) || 0; - ctrl.$validate(); + expression = ast.operator + "(" + this.ifDefined(right, 0) + ")"; + this.assign(intoId, expression); + recursionFn(expression); + break; + + case AST.BinaryExpression: + this.recurse(ast.left, undefined, undefined, function(expr) { + left = expr; }); - ctrl.$validators.minlength = function(modelValue, viewValue) { - return ctrl.$isEmpty(viewValue) || viewValue.length >= minlength; - }; - } - }; - }; - if (window.angular.bootstrap) { - console.log("WARNING: Tried to load angular more than once."); - return; - } - bindJQuery(); - publishExternalAPI(angular); - angular.module("ngLocale", [], [ "$provide", function($provide) { - var PLURAL_CATEGORY = { - ZERO: "zero", - ONE: "one", - TWO: "two", - FEW: "few", - MANY: "many", - OTHER: "other" - }; - function getDecimals(n) { - n = n + ""; - var i = n.indexOf("."); - return i == -1 ? 0 : n.length - i - 1; - } - function getVF(n, opt_precision) { - var v = opt_precision; - if (undefined === v) { - v = Math.min(getDecimals(n), 3); - } - var base = Math.pow(10, v); - var f = (n * base | 0) % base; - return { - v: v, - f: f - }; - } - $provide.value("$locale", { - DATETIME_FORMATS: { - AMPMS: [ "AM", "PM" ], - DAY: [ "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" ], - ERANAMES: [ "Before Christ", "Anno Domini" ], - ERAS: [ "BC", "AD" ], - FIRSTDAYOFWEEK: 6, - MONTH: [ "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" ], - SHORTDAY: [ "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" ], - SHORTMONTH: [ "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" ], - WEEKENDRANGE: [ 5, 6 ], - fullDate: "EEEE, MMMM d, y", - longDate: "MMMM d, y", - medium: "MMM d, y h:mm:ss a", - mediumDate: "MMM d, y", - mediumTime: "h:mm:ss a", - "short": "M/d/yy h:mm a", - shortDate: "M/d/yy", - shortTime: "h:mm a" - }, - NUMBER_FORMATS: { - CURRENCY_SYM: "$", - DECIMAL_SEP: ".", - GROUP_SEP: ",", - PATTERNS: [ { - gSize: 3, - lgSize: 3, - maxFrac: 3, - minFrac: 0, - minInt: 1, - negPre: "-", - negSuf: "", - posPre: "", - posSuf: "" - }, { - gSize: 3, - lgSize: 3, - maxFrac: 2, - minFrac: 2, - minInt: 1, - negPre: "-¤", - negSuf: "", - posPre: "¤", - posSuf: "" - } ] - }, - id: "en-us", - pluralCat: function(n, opt_precision) { - var i = n | 0; - var vf = getVF(n, opt_precision); - if (i == 1 && vf.v == 0) { - return PLURAL_CATEGORY.ONE; + this.recurse(ast.right, undefined, undefined, function(expr) { + right = expr; + }); + if (ast.operator === "+") { + expression = this.plus(left, right); + } else if (ast.operator === "-") { + expression = this.ifDefined(left, 0) + ast.operator + this.ifDefined(right, 0); + } else { + expression = "(" + left + ")" + ast.operator + "(" + right + ")"; } - return PLURAL_CATEGORY.OTHER; - } - }); - } ]); - jqLite(document).ready(function() { - angularInit(document, bootstrap); - }); -})(window, document); + this.assign(intoId, expression); + recursionFn(expression); + break; -!window.angular.$$csp().noInlineStyle && window.angular.element(document.head).prepend(''); + case AST.LogicalExpression: + intoId = intoId || this.nextId(); + self.recurse(ast.left, intoId); + self.if_(ast.operator === "&&" ? intoId : self.not(intoId), self.lazyRecurse(ast.right, intoId)); + recursionFn(intoId); + break; -if (typeof jQuery === "undefined") { - throw new Error("Bootstrap's JavaScript requires jQuery"); -} + case AST.ConditionalExpression: + intoId = intoId || this.nextId(); + self.recurse(ast.test, intoId); + self.if_(intoId, self.lazyRecurse(ast.alternate, intoId), self.lazyRecurse(ast.consequent, intoId)); + recursionFn(intoId); + break; -+function($) { - "use strict"; - var version = $.fn.jquery.split(" ")[0].split("."); - if (version[0] < 2 && version[1] < 9 || version[0] == 1 && version[1] == 9 && version[2] < 1) { - throw new Error("Bootstrap's JavaScript requires jQuery version 1.9.1 or higher"); - } -}(jQuery); + case AST.Identifier: + intoId = intoId || this.nextId(); + if (nameId) { + nameId.context = self.stage === "inputs" ? "s" : this.assign(this.nextId(), this.getHasOwnProperty("l", ast.name) + "?l:s"); + nameId.computed = false; + nameId.name = ast.name; + } + ensureSafeMemberName(ast.name); + self.if_(self.stage === "inputs" || self.not(self.getHasOwnProperty("l", ast.name)), function() { + self.if_(self.stage === "inputs" || "s", function() { + if (create && create !== 1) { + self.if_(self.not(self.nonComputedMember("s", ast.name)), self.lazyAssign(self.nonComputedMember("s", ast.name), "{}")); + } + self.assign(intoId, self.nonComputedMember("s", ast.name)); + }); + }, intoId && self.lazyAssign(intoId, self.nonComputedMember("l", ast.name))); + if (self.state.expensiveChecks || isPossiblyDangerousMemberName(ast.name)) { + self.addEnsureSafeObject(intoId); + } + recursionFn(intoId); + break; -+function($) { - "use strict"; - function transitionEnd() { - var el = document.createElement("bootstrap"); - var transEndEventNames = { - WebkitTransition: "webkitTransitionEnd", - MozTransition: "transitionend", - OTransition: "oTransitionEnd otransitionend", - transition: "transitionend" - }; - for (var name in transEndEventNames) { - if (el.style[name] !== undefined) { - return { - end: transEndEventNames[name] - }; - } - } - return false; - } - $.fn.emulateTransitionEnd = function(duration) { - var called = false; - var $el = this; - $(this).one("bsTransitionEnd", function() { - called = true; - }); - var callback = function() { - if (!called) $($el).trigger($.support.transition.end); - }; - setTimeout(callback, duration); - return this; - }; - $(function() { - $.support.transition = transitionEnd(); - if (!$.support.transition) return; - $.event.special.bsTransitionEnd = { - bindType: $.support.transition.end, - delegateType: $.support.transition.end, - handle: function(e) { - if ($(e.target).is(this)) return e.handleObj.handler.apply(this, arguments); - } - }; - }); -}(jQuery); + case AST.MemberExpression: + left = nameId && (nameId.context = this.nextId()) || this.nextId(); + intoId = intoId || this.nextId(); + self.recurse(ast.object, left, undefined, function() { + self.if_(self.notNull(left), function() { + if (ast.computed) { + right = self.nextId(); + self.recurse(ast.property, right); + self.getStringValue(right); + self.addEnsureSafeMemberName(right); + if (create && create !== 1) { + self.if_(self.not(self.computedMember(left, right)), self.lazyAssign(self.computedMember(left, right), "{}")); + } + expression = self.ensureSafeObject(self.computedMember(left, right)); + self.assign(intoId, expression); + if (nameId) { + nameId.computed = true; + nameId.name = right; + } + } else { + ensureSafeMemberName(ast.property.name); + if (create && create !== 1) { + self.if_(self.not(self.nonComputedMember(left, ast.property.name)), self.lazyAssign(self.nonComputedMember(left, ast.property.name), "{}")); + } + expression = self.nonComputedMember(left, ast.property.name); + if (self.state.expensiveChecks || isPossiblyDangerousMemberName(ast.property.name)) { + expression = self.ensureSafeObject(expression); + } + self.assign(intoId, expression); + if (nameId) { + nameId.computed = false; + nameId.name = ast.property.name; + } + } + }, function() { + self.assign(intoId, "undefined"); + }); + recursionFn(intoId); + }, !!create); + break; -+function($) { - "use strict"; - var dismiss = '[data-dismiss="alert"]'; - var Alert = function(el) { - $(el).on("click", dismiss, this.close); - }; - Alert.VERSION = "3.3.5"; - Alert.TRANSITION_DURATION = 150; - Alert.prototype.close = function(e) { - var $this = $(this); - var selector = $this.attr("data-target"); - if (!selector) { - selector = $this.attr("href"); - selector = selector && selector.replace(/.*(?=#[^\s]*$)/, ""); - } - var $parent = $(selector); - if (e) e.preventDefault(); - if (!$parent.length) { - $parent = $this.closest(".alert"); - } - $parent.trigger(e = $.Event("close.bs.alert")); - if (e.isDefaultPrevented()) return; - $parent.removeClass("in"); - function removeElement() { - $parent.detach().trigger("closed.bs.alert").remove(); - } - $.support.transition && $parent.hasClass("fade") ? $parent.one("bsTransitionEnd", removeElement).emulateTransitionEnd(Alert.TRANSITION_DURATION) : removeElement(); - }; - function Plugin(option) { - return this.each(function() { - var $this = $(this); - var data = $this.data("bs.alert"); - if (!data) $this.data("bs.alert", data = new Alert(this)); - if (typeof option == "string") data[option].call($this); - }); - } - var old = $.fn.alert; - $.fn.alert = Plugin; - $.fn.alert.Constructor = Alert; - $.fn.alert.noConflict = function() { - $.fn.alert = old; - return this; - }; - $(document).on("click.bs.alert.data-api", dismiss, Alert.prototype.close); -}(jQuery); + case AST.CallExpression: + intoId = intoId || this.nextId(); + if (ast.filter) { + right = self.filter(ast.callee.name); + args = []; + forEach(ast.arguments, function(expr) { + var argument = self.nextId(); + self.recurse(expr, argument); + args.push(argument); + }); + expression = right + "(" + args.join(",") + ")"; + self.assign(intoId, expression); + recursionFn(intoId); + } else { + right = self.nextId(); + left = {}; + args = []; + self.recurse(ast.callee, right, left, function() { + self.if_(self.notNull(right), function() { + self.addEnsureSafeFunction(right); + forEach(ast.arguments, function(expr) { + self.recurse(expr, self.nextId(), undefined, function(argument) { + args.push(self.ensureSafeObject(argument)); + }); + }); + if (left.name) { + if (!self.state.expensiveChecks) { + self.addEnsureSafeObject(left.context); + } + expression = self.member(left.context, left.name, left.computed) + "(" + args.join(",") + ")"; + } else { + expression = right + "(" + args.join(",") + ")"; + } + expression = self.ensureSafeObject(expression); + self.assign(intoId, expression); + }, function() { + self.assign(intoId, "undefined"); + }); + recursionFn(intoId); + }); + } + break; -+function($) { - "use strict"; - var Button = function(element, options) { - this.$element = $(element); - this.options = $.extend({}, Button.DEFAULTS, options); - this.isLoading = false; - }; - Button.VERSION = "3.3.5"; - Button.DEFAULTS = { - loadingText: "loading..." - }; - Button.prototype.setState = function(state) { - var d = "disabled"; - var $el = this.$element; - var val = $el.is("input") ? "val" : "html"; - var data = $el.data(); - state += "Text"; - if (data.resetText == null) $el.data("resetText", $el[val]()); - setTimeout($.proxy(function() { - $el[val](data[state] == null ? this.options[state] : data[state]); - if (state == "loadingText") { - this.isLoading = true; - $el.addClass(d).attr(d, d); - } else if (this.isLoading) { - this.isLoading = false; - $el.removeClass(d).removeAttr(d); + case AST.AssignmentExpression: + right = this.nextId(); + left = {}; + if (!isAssignable(ast.left)) { + throw $parseMinErr("lval", "Trying to assing a value to a non l-value"); + } + this.recurse(ast.left, undefined, left, function() { + self.if_(self.notNull(left.context), function() { + self.recurse(ast.right, right); + self.addEnsureSafeObject(self.member(left.context, left.name, left.computed)); + self.addEnsureSafeAssignContext(left.context); + expression = self.member(left.context, left.name, left.computed) + ast.operator + right; + self.assign(intoId, expression); + recursionFn(intoId || expression); + }); + }, 1); + break; + + case AST.ArrayExpression: + args = []; + forEach(ast.elements, function(expr) { + self.recurse(expr, self.nextId(), undefined, function(argument) { + args.push(argument); + }); + }); + expression = "[" + args.join(",") + "]"; + this.assign(intoId, expression); + recursionFn(expression); + break; + + case AST.ObjectExpression: + args = []; + forEach(ast.properties, function(property) { + self.recurse(property.value, self.nextId(), undefined, function(expr) { + args.push(self.escape(property.key.type === AST.Identifier ? property.key.name : "" + property.key.value) + ":" + expr); + }); + }); + expression = "{" + args.join(",") + "}"; + this.assign(intoId, expression); + recursionFn(expression); + break; + + case AST.ThisExpression: + this.assign(intoId, "s"); + recursionFn("s"); + break; + + case AST.NGValueParameter: + this.assign(intoId, "v"); + recursionFn("v"); + break; } - }, this), 0); - }; - Button.prototype.toggle = function() { - var changed = true; - var $parent = this.$element.closest('[data-toggle="buttons"]'); - if ($parent.length) { - var $input = this.$element.find("input"); - if ($input.prop("type") == "radio") { - if ($input.prop("checked")) changed = false; - $parent.find(".active").removeClass("active"); - this.$element.addClass("active"); - } else if ($input.prop("type") == "checkbox") { - if ($input.prop("checked") !== this.$element.hasClass("active")) changed = false; - this.$element.toggleClass("active"); + }, + getHasOwnProperty: function(element, property) { + var key = element + "." + property; + var own = this.current().own; + if (!own.hasOwnProperty(key)) { + own[key] = this.nextId(false, element + "&&(" + this.escape(property) + " in " + element + ")"); } - $input.prop("checked", this.$element.hasClass("active")); - if (changed) $input.trigger("change"); - } else { - this.$element.attr("aria-pressed", !this.$element.hasClass("active")); - this.$element.toggleClass("active"); + return own[key]; + }, + assign: function(id, value) { + if (!id) return; + this.current().body.push(id, "=", value, ";"); + return id; + }, + filter: function(filterName) { + if (!this.state.filters.hasOwnProperty(filterName)) { + this.state.filters[filterName] = this.nextId(true); + } + return this.state.filters[filterName]; + }, + ifDefined: function(id, defaultValue) { + return "ifDefined(" + id + "," + this.escape(defaultValue) + ")"; + }, + plus: function(left, right) { + return "plus(" + left + "," + right + ")"; + }, + return_: function(id) { + this.current().body.push("return ", id, ";"); + }, + if_: function(test, alternate, consequent) { + if (test === true) { + alternate(); + } else { + var body = this.current().body; + body.push("if(", test, "){"); + alternate(); + body.push("}"); + if (consequent) { + body.push("else{"); + consequent(); + body.push("}"); + } + } + }, + not: function(expression) { + return "!(" + expression + ")"; + }, + notNull: function(expression) { + return expression + "!=null"; + }, + nonComputedMember: function(left, right) { + return left + "." + right; + }, + computedMember: function(left, right) { + return left + "[" + right + "]"; + }, + member: function(left, right, computed) { + if (computed) return this.computedMember(left, right); + return this.nonComputedMember(left, right); + }, + addEnsureSafeObject: function(item) { + this.current().body.push(this.ensureSafeObject(item), ";"); + }, + addEnsureSafeMemberName: function(item) { + this.current().body.push(this.ensureSafeMemberName(item), ";"); + }, + addEnsureSafeFunction: function(item) { + this.current().body.push(this.ensureSafeFunction(item), ";"); + }, + addEnsureSafeAssignContext: function(item) { + this.current().body.push(this.ensureSafeAssignContext(item), ";"); + }, + ensureSafeObject: function(item) { + return "ensureSafeObject(" + item + ",text)"; + }, + ensureSafeMemberName: function(item) { + return "ensureSafeMemberName(" + item + ",text)"; + }, + ensureSafeFunction: function(item) { + return "ensureSafeFunction(" + item + ",text)"; + }, + getStringValue: function(item) { + this.assign(item, "getStringValue(" + item + ",text)"); + }, + ensureSafeAssignContext: function(item) { + return "ensureSafeAssignContext(" + item + ",text)"; + }, + lazyRecurse: function(ast, intoId, nameId, recursionFn, create, skipWatchIdCheck) { + var self = this; + return function() { + self.recurse(ast, intoId, nameId, recursionFn, create, skipWatchIdCheck); + }; + }, + lazyAssign: function(id, value) { + var self = this; + return function() { + self.assign(id, value); + }; + }, + stringEscapeRegex: /[^ a-zA-Z0-9]/g, + stringEscapeFn: function(c) { + return "\\u" + ("0000" + c.charCodeAt(0).toString(16)).slice(-4); + }, + escape: function(value) { + if (isString(value)) return "'" + value.replace(this.stringEscapeRegex, this.stringEscapeFn) + "'"; + if (isNumber(value)) return value.toString(); + if (value === true) return "true"; + if (value === false) return "false"; + if (value === null) return "null"; + if (typeof value === "undefined") return "undefined"; + throw $parseMinErr("esc", "IMPOSSIBLE"); + }, + nextId: function(skip, init) { + var id = "v" + this.state.nextId++; + if (!skip) { + this.current().vars.push(id + (init ? "=" + init : "")); + } + return id; + }, + current: function() { + return this.state[this.state.computing]; } }; - function Plugin(option) { - return this.each(function() { - var $this = $(this); - var data = $this.data("bs.button"); - var options = typeof option == "object" && option; - if (!data) $this.data("bs.button", data = new Button(this, options)); - if (option == "toggle") data.toggle(); else if (option) data.setState(option); - }); + function ASTInterpreter(astBuilder, $filter) { + this.astBuilder = astBuilder; + this.$filter = $filter; } - var old = $.fn.button; - $.fn.button = Plugin; - $.fn.button.Constructor = Button; - $.fn.button.noConflict = function() { - $.fn.button = old; - return this; - }; - $(document).on("click.bs.button.data-api", '[data-toggle^="button"]', function(e) { - var $btn = $(e.target); - if (!$btn.hasClass("btn")) $btn = $btn.closest(".btn"); - Plugin.call($btn, "toggle"); - if (!($(e.target).is('input[type="radio"]') || $(e.target).is('input[type="checkbox"]'))) e.preventDefault(); - }).on("focus.bs.button.data-api blur.bs.button.data-api", '[data-toggle^="button"]', function(e) { - $(e.target).closest(".btn").toggleClass("focus", /^focus(in)?$/.test(e.type)); - }); -}(jQuery); - -+function($) { - "use strict"; - var Carousel = function(element, options) { - this.$element = $(element); - this.$indicators = this.$element.find(".carousel-indicators"); - this.options = options; - this.paused = null; - this.sliding = null; - this.interval = null; - this.$active = null; - this.$items = null; - this.options.keyboard && this.$element.on("keydown.bs.carousel", $.proxy(this.keydown, this)); - this.options.pause == "hover" && !("ontouchstart" in document.documentElement) && this.$element.on("mouseenter.bs.carousel", $.proxy(this.pause, this)).on("mouseleave.bs.carousel", $.proxy(this.cycle, this)); - }; - Carousel.VERSION = "3.3.5"; - Carousel.TRANSITION_DURATION = 600; - Carousel.DEFAULTS = { - interval: 5e3, - pause: "hover", - wrap: true, - keyboard: true - }; - Carousel.prototype.keydown = function(e) { - if (/input|textarea/i.test(e.target.tagName)) return; - switch (e.which) { - case 37: - this.prev(); - break; + ASTInterpreter.prototype = { + compile: function(expression, expensiveChecks) { + var self = this; + var ast = this.astBuilder.ast(expression); + this.expression = expression; + this.expensiveChecks = expensiveChecks; + findConstantAndWatchExpressions(ast, self.$filter); + var assignable; + var assign; + if (assignable = assignableAST(ast)) { + assign = this.recurse(assignable); + } + var toWatch = getInputs(ast.body); + var inputs; + if (toWatch) { + inputs = []; + forEach(toWatch, function(watch, key) { + var input = self.recurse(watch); + watch.input = input; + inputs.push(input); + watch.watchId = key; + }); + } + var expressions = []; + forEach(ast.body, function(expression) { + expressions.push(self.recurse(expression.expression)); + }); + var fn = ast.body.length === 0 ? function() {} : ast.body.length === 1 ? expressions[0] : function(scope, locals) { + var lastValue; + forEach(expressions, function(exp) { + lastValue = exp(scope, locals); + }); + return lastValue; + }; + if (assign) { + fn.assign = function(scope, value, locals) { + return assign(scope, locals, value); + }; + } + if (inputs) { + fn.inputs = inputs; + } + fn.literal = isLiteral(ast); + fn.constant = isConstant(ast); + return fn; + }, + recurse: function(ast, context, create) { + var left, right, self = this, args, expression; + if (ast.input) { + return this.inputs(ast.input, ast.watchId); + } + switch (ast.type) { + case AST.Literal: + return this.value(ast.value, context); - case 39: - this.next(); - break; + case AST.UnaryExpression: + right = this.recurse(ast.argument); + return this["unary" + ast.operator](right, context); - default: - return; - } - e.preventDefault(); - }; - Carousel.prototype.cycle = function(e) { - e || (this.paused = false); - this.interval && clearInterval(this.interval); - this.options.interval && !this.paused && (this.interval = setInterval($.proxy(this.next, this), this.options.interval)); - return this; - }; - Carousel.prototype.getItemIndex = function(item) { - this.$items = item.parent().children(".item"); - return this.$items.index(item || this.$active); - }; - Carousel.prototype.getItemForDirection = function(direction, active) { - var activeIndex = this.getItemIndex(active); - var willWrap = direction == "prev" && activeIndex === 0 || direction == "next" && activeIndex == this.$items.length - 1; - if (willWrap && !this.options.wrap) return active; - var delta = direction == "prev" ? -1 : 1; - var itemIndex = (activeIndex + delta) % this.$items.length; - return this.$items.eq(itemIndex); - }; - Carousel.prototype.to = function(pos) { - var that = this; - var activeIndex = this.getItemIndex(this.$active = this.$element.find(".item.active")); - if (pos > this.$items.length - 1 || pos < 0) return; - if (this.sliding) return this.$element.one("slid.bs.carousel", function() { - that.to(pos); - }); - if (activeIndex == pos) return this.pause().cycle(); - return this.slide(pos > activeIndex ? "next" : "prev", this.$items.eq(pos)); - }; - Carousel.prototype.pause = function(e) { - e || (this.paused = true); - if (this.$element.find(".next, .prev").length && $.support.transition) { - this.$element.trigger($.support.transition.end); - this.cycle(true); - } - this.interval = clearInterval(this.interval); - return this; - }; - Carousel.prototype.next = function() { - if (this.sliding) return; - return this.slide("next"); - }; - Carousel.prototype.prev = function() { - if (this.sliding) return; - return this.slide("prev"); - }; - Carousel.prototype.slide = function(type, next) { - var $active = this.$element.find(".item.active"); - var $next = next || this.getItemForDirection(type, $active); - var isCycling = this.interval; - var direction = type == "next" ? "left" : "right"; - var that = this; - if ($next.hasClass("active")) return this.sliding = false; - var relatedTarget = $next[0]; - var slideEvent = $.Event("slide.bs.carousel", { - relatedTarget: relatedTarget, - direction: direction - }); - this.$element.trigger(slideEvent); - if (slideEvent.isDefaultPrevented()) return; - this.sliding = true; - isCycling && this.pause(); - if (this.$indicators.length) { - this.$indicators.find(".active").removeClass("active"); - var $nextIndicator = $(this.$indicators.children()[this.getItemIndex($next)]); - $nextIndicator && $nextIndicator.addClass("active"); - } - var slidEvent = $.Event("slid.bs.carousel", { - relatedTarget: relatedTarget, - direction: direction - }); - if ($.support.transition && this.$element.hasClass("slide")) { - $next.addClass(type); - $next[0].offsetWidth; - $active.addClass(direction); - $next.addClass(direction); - $active.one("bsTransitionEnd", function() { - $next.removeClass([ type, direction ].join(" ")).addClass("active"); - $active.removeClass([ "active", direction ].join(" ")); - that.sliding = false; - setTimeout(function() { - that.$element.trigger(slidEvent); - }, 0); - }).emulateTransitionEnd(Carousel.TRANSITION_DURATION); - } else { - $active.removeClass("active"); - $next.addClass("active"); - this.sliding = false; - this.$element.trigger(slidEvent); - } - isCycling && this.cycle(); - return this; - }; - function Plugin(option) { - return this.each(function() { - var $this = $(this); - var data = $this.data("bs.carousel"); - var options = $.extend({}, Carousel.DEFAULTS, $this.data(), typeof option == "object" && option); - var action = typeof option == "string" ? option : options.slide; - if (!data) $this.data("bs.carousel", data = new Carousel(this, options)); - if (typeof option == "number") data.to(option); else if (action) data[action](); else if (options.interval) data.pause().cycle(); - }); - } - var old = $.fn.carousel; - $.fn.carousel = Plugin; - $.fn.carousel.Constructor = Carousel; - $.fn.carousel.noConflict = function() { - $.fn.carousel = old; - return this; - }; - var clickHandler = function(e) { - var href; - var $this = $(this); - var $target = $($this.attr("data-target") || (href = $this.attr("href")) && href.replace(/.*(?=#[^\s]+$)/, "")); - if (!$target.hasClass("carousel")) return; - var options = $.extend({}, $target.data(), $this.data()); - var slideIndex = $this.attr("data-slide-to"); - if (slideIndex) options.interval = false; - Plugin.call($target, options); - if (slideIndex) { - $target.data("bs.carousel").to(slideIndex); - } - e.preventDefault(); - }; - $(document).on("click.bs.carousel.data-api", "[data-slide]", clickHandler).on("click.bs.carousel.data-api", "[data-slide-to]", clickHandler); - $(window).on("load", function() { - $('[data-ride="carousel"]').each(function() { - var $carousel = $(this); - Plugin.call($carousel, $carousel.data()); - }); - }); -}(jQuery); + case AST.BinaryExpression: + left = this.recurse(ast.left); + right = this.recurse(ast.right); + return this["binary" + ast.operator](left, right, context); -+function($) { - "use strict"; - var Collapse = function(element, options) { - this.$element = $(element); - this.options = $.extend({}, Collapse.DEFAULTS, options); - this.$trigger = $('[data-toggle="collapse"][href="#' + element.id + '"],' + '[data-toggle="collapse"][data-target="#' + element.id + '"]'); - this.transitioning = null; - if (this.options.parent) { - this.$parent = this.getParent(); - } else { - this.addAriaAndCollapsedClass(this.$element, this.$trigger); - } - if (this.options.toggle) this.toggle(); - }; - Collapse.VERSION = "3.3.5"; - Collapse.TRANSITION_DURATION = 350; - Collapse.DEFAULTS = { - toggle: true - }; - Collapse.prototype.dimension = function() { - var hasWidth = this.$element.hasClass("width"); - return hasWidth ? "width" : "height"; - }; - Collapse.prototype.show = function() { - if (this.transitioning || this.$element.hasClass("in")) return; - var activesData; - var actives = this.$parent && this.$parent.children(".panel").children(".in, .collapsing"); - if (actives && actives.length) { - activesData = actives.data("bs.collapse"); - if (activesData && activesData.transitioning) return; - } - var startEvent = $.Event("show.bs.collapse"); - this.$element.trigger(startEvent); - if (startEvent.isDefaultPrevented()) return; - if (actives && actives.length) { - Plugin.call(actives, "hide"); - activesData || actives.data("bs.collapse", null); - } - var dimension = this.dimension(); - this.$element.removeClass("collapse").addClass("collapsing")[dimension](0).attr("aria-expanded", true); - this.$trigger.removeClass("collapsed").attr("aria-expanded", true); - this.transitioning = 1; - var complete = function() { - this.$element.removeClass("collapsing").addClass("collapse in")[dimension](""); - this.transitioning = 0; - this.$element.trigger("shown.bs.collapse"); - }; - if (!$.support.transition) return complete.call(this); - var scrollSize = $.camelCase([ "scroll", dimension ].join("-")); - this.$element.one("bsTransitionEnd", $.proxy(complete, this)).emulateTransitionEnd(Collapse.TRANSITION_DURATION)[dimension](this.$element[0][scrollSize]); - }; - Collapse.prototype.hide = function() { - if (this.transitioning || !this.$element.hasClass("in")) return; - var startEvent = $.Event("hide.bs.collapse"); - this.$element.trigger(startEvent); - if (startEvent.isDefaultPrevented()) return; - var dimension = this.dimension(); - this.$element[dimension](this.$element[dimension]())[0].offsetHeight; - this.$element.addClass("collapsing").removeClass("collapse in").attr("aria-expanded", false); - this.$trigger.addClass("collapsed").attr("aria-expanded", false); - this.transitioning = 1; - var complete = function() { - this.transitioning = 0; - this.$element.removeClass("collapsing").addClass("collapse").trigger("hidden.bs.collapse"); - }; - if (!$.support.transition) return complete.call(this); - this.$element[dimension](0).one("bsTransitionEnd", $.proxy(complete, this)).emulateTransitionEnd(Collapse.TRANSITION_DURATION); - }; - Collapse.prototype.toggle = function() { - this[this.$element.hasClass("in") ? "hide" : "show"](); - }; - Collapse.prototype.getParent = function() { - return $(this.options.parent).find('[data-toggle="collapse"][data-parent="' + this.options.parent + '"]').each($.proxy(function(i, element) { - var $element = $(element); - this.addAriaAndCollapsedClass(getTargetFromTrigger($element), $element); - }, this)).end(); - }; - Collapse.prototype.addAriaAndCollapsedClass = function($element, $trigger) { - var isOpen = $element.hasClass("in"); - $element.attr("aria-expanded", isOpen); - $trigger.toggleClass("collapsed", !isOpen).attr("aria-expanded", isOpen); - }; - function getTargetFromTrigger($trigger) { - var href; - var target = $trigger.attr("data-target") || (href = $trigger.attr("href")) && href.replace(/.*(?=#[^\s]+$)/, ""); - return $(target); - } - function Plugin(option) { - return this.each(function() { - var $this = $(this); - var data = $this.data("bs.collapse"); - var options = $.extend({}, Collapse.DEFAULTS, $this.data(), typeof option == "object" && option); - if (!data && options.toggle && /show|hide/.test(option)) options.toggle = false; - if (!data) $this.data("bs.collapse", data = new Collapse(this, options)); - if (typeof option == "string") data[option](); - }); - } - var old = $.fn.collapse; - $.fn.collapse = Plugin; - $.fn.collapse.Constructor = Collapse; - $.fn.collapse.noConflict = function() { - $.fn.collapse = old; - return this; - }; - $(document).on("click.bs.collapse.data-api", '[data-toggle="collapse"]', function(e) { - var $this = $(this); - if (!$this.attr("data-target")) e.preventDefault(); - var $target = getTargetFromTrigger($this); - var data = $target.data("bs.collapse"); - var option = data ? "toggle" : $this.data(); - Plugin.call($target, option); - }); -}(jQuery); + case AST.LogicalExpression: + left = this.recurse(ast.left); + right = this.recurse(ast.right); + return this["binary" + ast.operator](left, right, context); -+function($) { - "use strict"; - var backdrop = ".dropdown-backdrop"; - var toggle = '[data-toggle="dropdown"]'; - var Dropdown = function(element) { - $(element).on("click.bs.dropdown", this.toggle); - }; - Dropdown.VERSION = "3.3.5"; - function getParent($this) { - var selector = $this.attr("data-target"); - if (!selector) { - selector = $this.attr("href"); - selector = selector && /#[A-Za-z]/.test(selector) && selector.replace(/.*(?=#[^\s]*$)/, ""); - } - var $parent = selector && $(selector); - return $parent && $parent.length ? $parent : $this.parent(); - } - function clearMenus(e) { - if (e && e.which === 3) return; - $(backdrop).remove(); - $(toggle).each(function() { - var $this = $(this); - var $parent = getParent($this); - var relatedTarget = { - relatedTarget: this - }; - if (!$parent.hasClass("open")) return; - if (e && e.type == "click" && /input|textarea/i.test(e.target.tagName) && $.contains($parent[0], e.target)) return; - $parent.trigger(e = $.Event("hide.bs.dropdown", relatedTarget)); - if (e.isDefaultPrevented()) return; - $this.attr("aria-expanded", "false"); - $parent.removeClass("open").trigger("hidden.bs.dropdown", relatedTarget); - }); - } - Dropdown.prototype.toggle = function(e) { - var $this = $(this); - if ($this.is(".disabled, :disabled")) return; - var $parent = getParent($this); - var isActive = $parent.hasClass("open"); - clearMenus(); - if (!isActive) { - if ("ontouchstart" in document.documentElement && !$parent.closest(".navbar-nav").length) { - $(document.createElement("div")).addClass("dropdown-backdrop").insertAfter($(this)).on("click", clearMenus); + case AST.ConditionalExpression: + return this["ternary?:"](this.recurse(ast.test), this.recurse(ast.alternate), this.recurse(ast.consequent), context); + + case AST.Identifier: + ensureSafeMemberName(ast.name, self.expression); + return self.identifier(ast.name, self.expensiveChecks || isPossiblyDangerousMemberName(ast.name), context, create, self.expression); + + case AST.MemberExpression: + left = this.recurse(ast.object, false, !!create); + if (!ast.computed) { + ensureSafeMemberName(ast.property.name, self.expression); + right = ast.property.name; + } + if (ast.computed) right = this.recurse(ast.property); + return ast.computed ? this.computedMember(left, right, context, create, self.expression) : this.nonComputedMember(left, right, self.expensiveChecks, context, create, self.expression); + + case AST.CallExpression: + args = []; + forEach(ast.arguments, function(expr) { + args.push(self.recurse(expr)); + }); + if (ast.filter) right = this.$filter(ast.callee.name); + if (!ast.filter) right = this.recurse(ast.callee, true); + return ast.filter ? function(scope, locals, assign, inputs) { + var values = []; + for (var i = 0; i < args.length; ++i) { + values.push(args[i](scope, locals, assign, inputs)); + } + var value = right.apply(undefined, values, inputs); + return context ? { + context: undefined, + name: undefined, + value: value + } : value; + } : function(scope, locals, assign, inputs) { + var rhs = right(scope, locals, assign, inputs); + var value; + if (rhs.value != null) { + ensureSafeObject(rhs.context, self.expression); + ensureSafeFunction(rhs.value, self.expression); + var values = []; + for (var i = 0; i < args.length; ++i) { + values.push(ensureSafeObject(args[i](scope, locals, assign, inputs), self.expression)); + } + value = ensureSafeObject(rhs.value.apply(rhs.context, values), self.expression); + } + return context ? { + value: value + } : value; + }; + + case AST.AssignmentExpression: + left = this.recurse(ast.left, true, 1); + right = this.recurse(ast.right); + return function(scope, locals, assign, inputs) { + var lhs = left(scope, locals, assign, inputs); + var rhs = right(scope, locals, assign, inputs); + ensureSafeObject(lhs.value, self.expression); + ensureSafeAssignContext(lhs.context); + lhs.context[lhs.name] = rhs; + return context ? { + value: rhs + } : rhs; + }; + + case AST.ArrayExpression: + args = []; + forEach(ast.elements, function(expr) { + args.push(self.recurse(expr)); + }); + return function(scope, locals, assign, inputs) { + var value = []; + for (var i = 0; i < args.length; ++i) { + value.push(args[i](scope, locals, assign, inputs)); + } + return context ? { + value: value + } : value; + }; + + case AST.ObjectExpression: + args = []; + forEach(ast.properties, function(property) { + args.push({ + key: property.key.type === AST.Identifier ? property.key.name : "" + property.key.value, + value: self.recurse(property.value) + }); + }); + return function(scope, locals, assign, inputs) { + var value = {}; + for (var i = 0; i < args.length; ++i) { + value[args[i].key] = args[i].value(scope, locals, assign, inputs); + } + return context ? { + value: value + } : value; + }; + + case AST.ThisExpression: + return function(scope) { + return context ? { + value: scope + } : scope; + }; + + case AST.NGValueParameter: + return function(scope, locals, assign, inputs) { + return context ? { + value: assign + } : assign; + }; } - var relatedTarget = { - relatedTarget: this + }, + "unary+": function(argument, context) { + return function(scope, locals, assign, inputs) { + var arg = argument(scope, locals, assign, inputs); + if (isDefined(arg)) { + arg = +arg; + } else { + arg = 0; + } + return context ? { + value: arg + } : arg; }; - $parent.trigger(e = $.Event("show.bs.dropdown", relatedTarget)); - if (e.isDefaultPrevented()) return; - $this.trigger("focus").attr("aria-expanded", "true"); - $parent.toggleClass("open").trigger("shown.bs.dropdown", relatedTarget); - } - return false; - }; - Dropdown.prototype.keydown = function(e) { - if (!/(38|40|27|32)/.test(e.which) || /input|textarea/i.test(e.target.tagName)) return; - var $this = $(this); - e.preventDefault(); - e.stopPropagation(); - if ($this.is(".disabled, :disabled")) return; - var $parent = getParent($this); - var isActive = $parent.hasClass("open"); - if (!isActive && e.which != 27 || isActive && e.which == 27) { - if (e.which == 27) $parent.find(toggle).trigger("focus"); - return $this.trigger("click"); - } - var desc = " li:not(.disabled):visible a"; - var $items = $parent.find(".dropdown-menu" + desc); - if (!$items.length) return; - var index = $items.index(e.target); - if (e.which == 38 && index > 0) index--; - if (e.which == 40 && index < $items.length - 1) index++; - if (!~index) index = 0; - $items.eq(index).trigger("focus"); - }; - function Plugin(option) { - return this.each(function() { - var $this = $(this); - var data = $this.data("bs.dropdown"); - if (!data) $this.data("bs.dropdown", data = new Dropdown(this)); - if (typeof option == "string") data[option].call($this); - }); - } - var old = $.fn.dropdown; - $.fn.dropdown = Plugin; - $.fn.dropdown.Constructor = Dropdown; - $.fn.dropdown.noConflict = function() { - $.fn.dropdown = old; - return this; - }; - $(document).on("click.bs.dropdown.data-api", clearMenus).on("click.bs.dropdown.data-api", ".dropdown form", function(e) { - e.stopPropagation(); - }).on("click.bs.dropdown.data-api", toggle, Dropdown.prototype.toggle).on("keydown.bs.dropdown.data-api", toggle, Dropdown.prototype.keydown).on("keydown.bs.dropdown.data-api", ".dropdown-menu", Dropdown.prototype.keydown); -}(jQuery); - -+function($) { - "use strict"; - var Modal = function(element, options) { - this.options = options; - this.$body = $(document.body); - this.$element = $(element); - this.$dialog = this.$element.find(".modal-dialog"); - this.$backdrop = null; - this.isShown = null; - this.originalBodyPad = null; - this.scrollbarWidth = 0; - this.ignoreBackdropClick = false; - if (this.options.remote) { - this.$element.find(".modal-content").load(this.options.remote, $.proxy(function() { - this.$element.trigger("loaded.bs.modal"); - }, this)); - } - }; - Modal.VERSION = "3.3.5"; - Modal.TRANSITION_DURATION = 300; - Modal.BACKDROP_TRANSITION_DURATION = 150; - Modal.DEFAULTS = { - backdrop: true, - keyboard: true, - show: true - }; - Modal.prototype.toggle = function(_relatedTarget) { - return this.isShown ? this.hide() : this.show(_relatedTarget); - }; - Modal.prototype.show = function(_relatedTarget) { - var that = this; - var e = $.Event("show.bs.modal", { - relatedTarget: _relatedTarget - }); - this.$element.trigger(e); - if (this.isShown || e.isDefaultPrevented()) return; - this.isShown = true; - this.checkScrollbar(); - this.setScrollbar(); - this.$body.addClass("modal-open"); - this.escape(); - this.resize(); - this.$element.on("click.dismiss.bs.modal", '[data-dismiss="modal"]', $.proxy(this.hide, this)); - this.$dialog.on("mousedown.dismiss.bs.modal", function() { - that.$element.one("mouseup.dismiss.bs.modal", function(e) { - if ($(e.target).is(that.$element)) that.ignoreBackdropClick = true; - }); - }); - this.backdrop(function() { - var transition = $.support.transition && that.$element.hasClass("fade"); - if (!that.$element.parent().length) { - that.$element.appendTo(that.$body); - } - that.$element.show().scrollTop(0); - that.adjustDialog(); - if (transition) { - that.$element[0].offsetWidth; - } - that.$element.addClass("in"); - that.enforceFocus(); - var e = $.Event("shown.bs.modal", { - relatedTarget: _relatedTarget - }); - transition ? that.$dialog.one("bsTransitionEnd", function() { - that.$element.trigger("focus").trigger(e); - }).emulateTransitionEnd(Modal.TRANSITION_DURATION) : that.$element.trigger("focus").trigger(e); - }); - }; - Modal.prototype.hide = function(e) { - if (e) e.preventDefault(); - e = $.Event("hide.bs.modal"); - this.$element.trigger(e); - if (!this.isShown || e.isDefaultPrevented()) return; - this.isShown = false; - this.escape(); - this.resize(); - $(document).off("focusin.bs.modal"); - this.$element.removeClass("in").off("click.dismiss.bs.modal").off("mouseup.dismiss.bs.modal"); - this.$dialog.off("mousedown.dismiss.bs.modal"); - $.support.transition && this.$element.hasClass("fade") ? this.$element.one("bsTransitionEnd", $.proxy(this.hideModal, this)).emulateTransitionEnd(Modal.TRANSITION_DURATION) : this.hideModal(); - }; - Modal.prototype.enforceFocus = function() { - $(document).off("focusin.bs.modal").on("focusin.bs.modal", $.proxy(function(e) { - if (this.$element[0] !== e.target && !this.$element.has(e.target).length) { - this.$element.trigger("focus"); - } - }, this)); - }; - Modal.prototype.escape = function() { - if (this.isShown && this.options.keyboard) { - this.$element.on("keydown.dismiss.bs.modal", $.proxy(function(e) { - e.which == 27 && this.hide(); - }, this)); - } else if (!this.isShown) { - this.$element.off("keydown.dismiss.bs.modal"); - } - }; - Modal.prototype.resize = function() { - if (this.isShown) { - $(window).on("resize.bs.modal", $.proxy(this.handleUpdate, this)); - } else { - $(window).off("resize.bs.modal"); - } - }; - Modal.prototype.hideModal = function() { - var that = this; - this.$element.hide(); - this.backdrop(function() { - that.$body.removeClass("modal-open"); - that.resetAdjustments(); - that.resetScrollbar(); - that.$element.trigger("hidden.bs.modal"); - }); - }; - Modal.prototype.removeBackdrop = function() { - this.$backdrop && this.$backdrop.remove(); - this.$backdrop = null; - }; - Modal.prototype.backdrop = function(callback) { - var that = this; - var animate = this.$element.hasClass("fade") ? "fade" : ""; - if (this.isShown && this.options.backdrop) { - var doAnimate = $.support.transition && animate; - this.$backdrop = $(document.createElement("div")).addClass("modal-backdrop " + animate).appendTo(this.$body); - this.$element.on("click.dismiss.bs.modal", $.proxy(function(e) { - if (this.ignoreBackdropClick) { - this.ignoreBackdropClick = false; - return; + }, + "unary-": function(argument, context) { + return function(scope, locals, assign, inputs) { + var arg = argument(scope, locals, assign, inputs); + if (isDefined(arg)) { + arg = -arg; + } else { + arg = 0; } - if (e.target !== e.currentTarget) return; - this.options.backdrop == "static" ? this.$element[0].focus() : this.hide(); - }, this)); - if (doAnimate) this.$backdrop[0].offsetWidth; - this.$backdrop.addClass("in"); - if (!callback) return; - doAnimate ? this.$backdrop.one("bsTransitionEnd", callback).emulateTransitionEnd(Modal.BACKDROP_TRANSITION_DURATION) : callback(); - } else if (!this.isShown && this.$backdrop) { - this.$backdrop.removeClass("in"); - var callbackRemove = function() { - that.removeBackdrop(); - callback && callback(); + return context ? { + value: arg + } : arg; }; - $.support.transition && this.$element.hasClass("fade") ? this.$backdrop.one("bsTransitionEnd", callbackRemove).emulateTransitionEnd(Modal.BACKDROP_TRANSITION_DURATION) : callbackRemove(); - } else if (callback) { - callback(); - } - }; - Modal.prototype.handleUpdate = function() { - this.adjustDialog(); - }; - Modal.prototype.adjustDialog = function() { - var modalIsOverflowing = this.$element[0].scrollHeight > document.documentElement.clientHeight; - this.$element.css({ - paddingLeft: !this.bodyIsOverflowing && modalIsOverflowing ? this.scrollbarWidth : "", - paddingRight: this.bodyIsOverflowing && !modalIsOverflowing ? this.scrollbarWidth : "" - }); - }; - Modal.prototype.resetAdjustments = function() { - this.$element.css({ - paddingLeft: "", - paddingRight: "" - }); - }; - Modal.prototype.checkScrollbar = function() { - var fullWindowWidth = window.innerWidth; - if (!fullWindowWidth) { - var documentElementRect = document.documentElement.getBoundingClientRect(); - fullWindowWidth = documentElementRect.right - Math.abs(documentElementRect.left); - } - this.bodyIsOverflowing = document.body.clientWidth < fullWindowWidth; - this.scrollbarWidth = this.measureScrollbar(); - }; - Modal.prototype.setScrollbar = function() { - var bodyPad = parseInt(this.$body.css("padding-right") || 0, 10); - this.originalBodyPad = document.body.style.paddingRight || ""; - if (this.bodyIsOverflowing) this.$body.css("padding-right", bodyPad + this.scrollbarWidth); - }; - Modal.prototype.resetScrollbar = function() { - this.$body.css("padding-right", this.originalBodyPad); - }; - Modal.prototype.measureScrollbar = function() { - var scrollDiv = document.createElement("div"); - scrollDiv.className = "modal-scrollbar-measure"; - this.$body.append(scrollDiv); - var scrollbarWidth = scrollDiv.offsetWidth - scrollDiv.clientWidth; - this.$body[0].removeChild(scrollDiv); - return scrollbarWidth; - }; - function Plugin(option, _relatedTarget) { - return this.each(function() { - var $this = $(this); - var data = $this.data("bs.modal"); - var options = $.extend({}, Modal.DEFAULTS, $this.data(), typeof option == "object" && option); - if (!data) $this.data("bs.modal", data = new Modal(this, options)); - if (typeof option == "string") data[option](_relatedTarget); else if (options.show) data.show(_relatedTarget); - }); - } - var old = $.fn.modal; - $.fn.modal = Plugin; - $.fn.modal.Constructor = Modal; - $.fn.modal.noConflict = function() { - $.fn.modal = old; - return this; - }; - $(document).on("click.bs.modal.data-api", '[data-toggle="modal"]', function(e) { - var $this = $(this); - var href = $this.attr("href"); - var $target = $($this.attr("data-target") || href && href.replace(/.*(?=#[^\s]+$)/, "")); - var option = $target.data("bs.modal") ? "toggle" : $.extend({ - remote: !/#/.test(href) && href - }, $target.data(), $this.data()); - if ($this.is("a")) e.preventDefault(); - $target.one("show.bs.modal", function(showEvent) { - if (showEvent.isDefaultPrevented()) return; - $target.one("hidden.bs.modal", function() { - $this.is(":visible") && $this.trigger("focus"); - }); - }); - Plugin.call($target, option, this); - }); -}(jQuery); - -+function($) { - "use strict"; - var Tooltip = function(element, options) { - this.type = null; - this.options = null; - this.enabled = null; - this.timeout = null; - this.hoverState = null; - this.$element = null; - this.inState = null; - this.init("tooltip", element, options); - }; - Tooltip.VERSION = "3.3.5"; - Tooltip.TRANSITION_DURATION = 150; - Tooltip.DEFAULTS = { - animation: true, - placement: "top", - selector: false, - template: '', - trigger: "hover focus", - title: "", - delay: 0, - html: false, - container: false, - viewport: { - selector: "body", - padding: 0 - } - }; - Tooltip.prototype.init = function(type, element, options) { - this.enabled = true; - this.type = type; - this.$element = $(element); - this.options = this.getOptions(options); - this.$viewport = this.options.viewport && $($.isFunction(this.options.viewport) ? this.options.viewport.call(this, this.$element) : this.options.viewport.selector || this.options.viewport); - this.inState = { - click: false, - hover: false, - focus: false - }; - if (this.$element[0] instanceof document.constructor && !this.options.selector) { - throw new Error("`selector` option must be specified when initializing " + this.type + " on the window.document object!"); - } - var triggers = this.options.trigger.split(" "); - for (var i = triggers.length; i--; ) { - var trigger = triggers[i]; - if (trigger == "click") { - this.$element.on("click." + this.type, this.options.selector, $.proxy(this.toggle, this)); - } else if (trigger != "manual") { - var eventIn = trigger == "hover" ? "mouseenter" : "focusin"; - var eventOut = trigger == "hover" ? "mouseleave" : "focusout"; - this.$element.on(eventIn + "." + this.type, this.options.selector, $.proxy(this.enter, this)); - this.$element.on(eventOut + "." + this.type, this.options.selector, $.proxy(this.leave, this)); - } - } - this.options.selector ? this._options = $.extend({}, this.options, { - trigger: "manual", - selector: "" - }) : this.fixTitle(); - }; - Tooltip.prototype.getDefaults = function() { - return Tooltip.DEFAULTS; - }; - Tooltip.prototype.getOptions = function(options) { - options = $.extend({}, this.getDefaults(), this.$element.data(), options); - if (options.delay && typeof options.delay == "number") { - options.delay = { - show: options.delay, - hide: options.delay + }, + "unary!": function(argument, context) { + return function(scope, locals, assign, inputs) { + var arg = !argument(scope, locals, assign, inputs); + return context ? { + value: arg + } : arg; }; - } - return options; - }; - Tooltip.prototype.getDelegateOptions = function() { - var options = {}; - var defaults = this.getDefaults(); - this._options && $.each(this._options, function(key, value) { - if (defaults[key] != value) options[key] = value; - }); - return options; - }; - Tooltip.prototype.enter = function(obj) { - var self = obj instanceof this.constructor ? obj : $(obj.currentTarget).data("bs." + this.type); - if (!self) { - self = new this.constructor(obj.currentTarget, this.getDelegateOptions()); - $(obj.currentTarget).data("bs." + this.type, self); - } - if (obj instanceof $.Event) { - self.inState[obj.type == "focusin" ? "focus" : "hover"] = true; - } - if (self.tip().hasClass("in") || self.hoverState == "in") { - self.hoverState = "in"; - return; - } - clearTimeout(self.timeout); - self.hoverState = "in"; - if (!self.options.delay || !self.options.delay.show) return self.show(); - self.timeout = setTimeout(function() { - if (self.hoverState == "in") self.show(); - }, self.options.delay.show); - }; - Tooltip.prototype.isInStateTrue = function() { - for (var key in this.inState) { - if (this.inState[key]) return true; - } - return false; - }; - Tooltip.prototype.leave = function(obj) { - var self = obj instanceof this.constructor ? obj : $(obj.currentTarget).data("bs." + this.type); - if (!self) { - self = new this.constructor(obj.currentTarget, this.getDelegateOptions()); - $(obj.currentTarget).data("bs." + this.type, self); - } - if (obj instanceof $.Event) { - self.inState[obj.type == "focusout" ? "focus" : "hover"] = false; - } - if (self.isInStateTrue()) return; - clearTimeout(self.timeout); - self.hoverState = "out"; - if (!self.options.delay || !self.options.delay.hide) return self.hide(); - self.timeout = setTimeout(function() { - if (self.hoverState == "out") self.hide(); - }, self.options.delay.hide); - }; - Tooltip.prototype.show = function() { - var e = $.Event("show.bs." + this.type); - if (this.hasContent() && this.enabled) { - this.$element.trigger(e); - var inDom = $.contains(this.$element[0].ownerDocument.documentElement, this.$element[0]); - if (e.isDefaultPrevented() || !inDom) return; - var that = this; - var $tip = this.tip(); - var tipId = this.getUID(this.type); - this.setContent(); - $tip.attr("id", tipId); - this.$element.attr("aria-describedby", tipId); - if (this.options.animation) $tip.addClass("fade"); - var placement = typeof this.options.placement == "function" ? this.options.placement.call(this, $tip[0], this.$element[0]) : this.options.placement; - var autoToken = /\s?auto?\s?/i; - var autoPlace = autoToken.test(placement); - if (autoPlace) placement = placement.replace(autoToken, "") || "top"; - $tip.detach().css({ - top: 0, - left: 0, - display: "block" - }).addClass(placement).data("bs." + this.type, this); - this.options.container ? $tip.appendTo(this.options.container) : $tip.insertAfter(this.$element); - this.$element.trigger("inserted.bs." + this.type); - var pos = this.getPosition(); - var actualWidth = $tip[0].offsetWidth; - var actualHeight = $tip[0].offsetHeight; - if (autoPlace) { - var orgPlacement = placement; - var viewportDim = this.getPosition(this.$viewport); - placement = placement == "bottom" && pos.bottom + actualHeight > viewportDim.bottom ? "top" : placement == "top" && pos.top - actualHeight < viewportDim.top ? "bottom" : placement == "right" && pos.right + actualWidth > viewportDim.width ? "left" : placement == "left" && pos.left - actualWidth < viewportDim.left ? "right" : placement; - $tip.removeClass(orgPlacement).addClass(placement); - } - var calculatedOffset = this.getCalculatedOffset(placement, pos, actualWidth, actualHeight); - this.applyPlacement(calculatedOffset, placement); - var complete = function() { - var prevHoverState = that.hoverState; - that.$element.trigger("shown.bs." + that.type); - that.hoverState = null; - if (prevHoverState == "out") that.leave(that); + }, + "binary+": function(left, right, context) { + return function(scope, locals, assign, inputs) { + var lhs = left(scope, locals, assign, inputs); + var rhs = right(scope, locals, assign, inputs); + var arg = plusFn(lhs, rhs); + return context ? { + value: arg + } : arg; + }; + }, + "binary-": function(left, right, context) { + return function(scope, locals, assign, inputs) { + var lhs = left(scope, locals, assign, inputs); + var rhs = right(scope, locals, assign, inputs); + var arg = (isDefined(lhs) ? lhs : 0) - (isDefined(rhs) ? rhs : 0); + return context ? { + value: arg + } : arg; + }; + }, + "binary*": function(left, right, context) { + return function(scope, locals, assign, inputs) { + var arg = left(scope, locals, assign, inputs) * right(scope, locals, assign, inputs); + return context ? { + value: arg + } : arg; + }; + }, + "binary/": function(left, right, context) { + return function(scope, locals, assign, inputs) { + var arg = left(scope, locals, assign, inputs) / right(scope, locals, assign, inputs); + return context ? { + value: arg + } : arg; + }; + }, + "binary%": function(left, right, context) { + return function(scope, locals, assign, inputs) { + var arg = left(scope, locals, assign, inputs) % right(scope, locals, assign, inputs); + return context ? { + value: arg + } : arg; + }; + }, + "binary===": function(left, right, context) { + return function(scope, locals, assign, inputs) { + var arg = left(scope, locals, assign, inputs) === right(scope, locals, assign, inputs); + return context ? { + value: arg + } : arg; + }; + }, + "binary!==": function(left, right, context) { + return function(scope, locals, assign, inputs) { + var arg = left(scope, locals, assign, inputs) !== right(scope, locals, assign, inputs); + return context ? { + value: arg + } : arg; + }; + }, + "binary==": function(left, right, context) { + return function(scope, locals, assign, inputs) { + var arg = left(scope, locals, assign, inputs) == right(scope, locals, assign, inputs); + return context ? { + value: arg + } : arg; + }; + }, + "binary!=": function(left, right, context) { + return function(scope, locals, assign, inputs) { + var arg = left(scope, locals, assign, inputs) != right(scope, locals, assign, inputs); + return context ? { + value: arg + } : arg; + }; + }, + "binary<": function(left, right, context) { + return function(scope, locals, assign, inputs) { + var arg = left(scope, locals, assign, inputs) < right(scope, locals, assign, inputs); + return context ? { + value: arg + } : arg; + }; + }, + "binary>": function(left, right, context) { + return function(scope, locals, assign, inputs) { + var arg = left(scope, locals, assign, inputs) > right(scope, locals, assign, inputs); + return context ? { + value: arg + } : arg; + }; + }, + "binary<=": function(left, right, context) { + return function(scope, locals, assign, inputs) { + var arg = left(scope, locals, assign, inputs) <= right(scope, locals, assign, inputs); + return context ? { + value: arg + } : arg; + }; + }, + "binary>=": function(left, right, context) { + return function(scope, locals, assign, inputs) { + var arg = left(scope, locals, assign, inputs) >= right(scope, locals, assign, inputs); + return context ? { + value: arg + } : arg; + }; + }, + "binary&&": function(left, right, context) { + return function(scope, locals, assign, inputs) { + var arg = left(scope, locals, assign, inputs) && right(scope, locals, assign, inputs); + return context ? { + value: arg + } : arg; + }; + }, + "binary||": function(left, right, context) { + return function(scope, locals, assign, inputs) { + var arg = left(scope, locals, assign, inputs) || right(scope, locals, assign, inputs); + return context ? { + value: arg + } : arg; + }; + }, + "ternary?:": function(test, alternate, consequent, context) { + return function(scope, locals, assign, inputs) { + var arg = test(scope, locals, assign, inputs) ? alternate(scope, locals, assign, inputs) : consequent(scope, locals, assign, inputs); + return context ? { + value: arg + } : arg; + }; + }, + value: function(value, context) { + return function() { + return context ? { + context: undefined, + name: undefined, + value: value + } : value; + }; + }, + identifier: function(name, expensiveChecks, context, create, expression) { + return function(scope, locals, assign, inputs) { + var base = locals && name in locals ? locals : scope; + if (create && create !== 1 && base && !base[name]) { + base[name] = {}; + } + var value = base ? base[name] : undefined; + if (expensiveChecks) { + ensureSafeObject(value, expression); + } + if (context) { + return { + context: base, + name: name, + value: value + }; + } else { + return value; + } + }; + }, + computedMember: function(left, right, context, create, expression) { + return function(scope, locals, assign, inputs) { + var lhs = left(scope, locals, assign, inputs); + var rhs; + var value; + if (lhs != null) { + rhs = right(scope, locals, assign, inputs); + rhs = getStringValue(rhs); + ensureSafeMemberName(rhs, expression); + if (create && create !== 1 && lhs && !lhs[rhs]) { + lhs[rhs] = {}; + } + value = lhs[rhs]; + ensureSafeObject(value, expression); + } + if (context) { + return { + context: lhs, + name: rhs, + value: value + }; + } else { + return value; + } + }; + }, + nonComputedMember: function(left, right, expensiveChecks, context, create, expression) { + return function(scope, locals, assign, inputs) { + var lhs = left(scope, locals, assign, inputs); + if (create && create !== 1 && lhs && !lhs[right]) { + lhs[right] = {}; + } + var value = lhs != null ? lhs[right] : undefined; + if (expensiveChecks || isPossiblyDangerousMemberName(right)) { + ensureSafeObject(value, expression); + } + if (context) { + return { + context: lhs, + name: right, + value: value + }; + } else { + return value; + } + }; + }, + inputs: function(input, watchId) { + return function(scope, value, locals, inputs) { + if (inputs) return inputs[watchId]; + return input(scope, value, locals); }; - $.support.transition && this.$tip.hasClass("fade") ? $tip.one("bsTransitionEnd", complete).emulateTransitionEnd(Tooltip.TRANSITION_DURATION) : complete(); - } - }; - Tooltip.prototype.applyPlacement = function(offset, placement) { - var $tip = this.tip(); - var width = $tip[0].offsetWidth; - var height = $tip[0].offsetHeight; - var marginTop = parseInt($tip.css("margin-top"), 10); - var marginLeft = parseInt($tip.css("margin-left"), 10); - if (isNaN(marginTop)) marginTop = 0; - if (isNaN(marginLeft)) marginLeft = 0; - offset.top += marginTop; - offset.left += marginLeft; - $.offset.setOffset($tip[0], $.extend({ - using: function(props) { - $tip.css({ - top: Math.round(props.top), - left: Math.round(props.left) - }); - } - }, offset), 0); - $tip.addClass("in"); - var actualWidth = $tip[0].offsetWidth; - var actualHeight = $tip[0].offsetHeight; - if (placement == "top" && actualHeight != height) { - offset.top = offset.top + height - actualHeight; - } - var delta = this.getViewportAdjustedDelta(placement, offset, actualWidth, actualHeight); - if (delta.left) offset.left += delta.left; else offset.top += delta.top; - var isVertical = /top|bottom/.test(placement); - var arrowDelta = isVertical ? delta.left * 2 - width + actualWidth : delta.top * 2 - height + actualHeight; - var arrowOffsetPosition = isVertical ? "offsetWidth" : "offsetHeight"; - $tip.offset(offset); - this.replaceArrow(arrowDelta, $tip[0][arrowOffsetPosition], isVertical); - }; - Tooltip.prototype.replaceArrow = function(delta, dimension, isVertical) { - this.arrow().css(isVertical ? "left" : "top", 50 * (1 - delta / dimension) + "%").css(isVertical ? "top" : "left", ""); - }; - Tooltip.prototype.setContent = function() { - var $tip = this.tip(); - var title = this.getTitle(); - $tip.find(".tooltip-inner")[this.options.html ? "html" : "text"](title); - $tip.removeClass("fade in top bottom left right"); - }; - Tooltip.prototype.hide = function(callback) { - var that = this; - var $tip = $(this.$tip); - var e = $.Event("hide.bs." + this.type); - function complete() { - if (that.hoverState != "in") $tip.detach(); - that.$element.removeAttr("aria-describedby").trigger("hidden.bs." + that.type); - callback && callback(); - } - this.$element.trigger(e); - if (e.isDefaultPrevented()) return; - $tip.removeClass("in"); - $.support.transition && $tip.hasClass("fade") ? $tip.one("bsTransitionEnd", complete).emulateTransitionEnd(Tooltip.TRANSITION_DURATION) : complete(); - this.hoverState = null; - return this; - }; - Tooltip.prototype.fixTitle = function() { - var $e = this.$element; - if ($e.attr("title") || typeof $e.attr("data-original-title") != "string") { - $e.attr("data-original-title", $e.attr("title") || "").attr("title", ""); - } - }; - Tooltip.prototype.hasContent = function() { - return this.getTitle(); - }; - Tooltip.prototype.getPosition = function($element) { - $element = $element || this.$element; - var el = $element[0]; - var isBody = el.tagName == "BODY"; - var elRect = el.getBoundingClientRect(); - if (elRect.width == null) { - elRect = $.extend({}, elRect, { - width: elRect.right - elRect.left, - height: elRect.bottom - elRect.top - }); } - var elOffset = isBody ? { - top: 0, - left: 0 - } : $element.offset(); - var scroll = { - scroll: isBody ? document.documentElement.scrollTop || document.body.scrollTop : $element.scrollTop() - }; - var outerDims = isBody ? { - width: $(window).width(), - height: $(window).height() - } : null; - return $.extend({}, elRect, scroll, outerDims, elOffset); }; - Tooltip.prototype.getCalculatedOffset = function(placement, pos, actualWidth, actualHeight) { - return placement == "bottom" ? { - top: pos.top + pos.height, - left: pos.left + pos.width / 2 - actualWidth / 2 - } : placement == "top" ? { - top: pos.top - actualHeight, - left: pos.left + pos.width / 2 - actualWidth / 2 - } : placement == "left" ? { - top: pos.top + pos.height / 2 - actualHeight / 2, - left: pos.left - actualWidth - } : { - top: pos.top + pos.height / 2 - actualHeight / 2, - left: pos.left + pos.width - }; + var Parser = function(lexer, $filter, options) { + this.lexer = lexer; + this.$filter = $filter; + this.options = options; + this.ast = new AST(this.lexer); + this.astCompiler = options.csp ? new ASTInterpreter(this.ast, $filter) : new ASTCompiler(this.ast, $filter); }; - Tooltip.prototype.getViewportAdjustedDelta = function(placement, pos, actualWidth, actualHeight) { - var delta = { - top: 0, - left: 0 - }; - if (!this.$viewport) return delta; - var viewportPadding = this.options.viewport && this.options.viewport.padding || 0; - var viewportDimensions = this.getPosition(this.$viewport); - if (/right|left/.test(placement)) { - var topEdgeOffset = pos.top - viewportPadding - viewportDimensions.scroll; - var bottomEdgeOffset = pos.top + viewportPadding - viewportDimensions.scroll + actualHeight; - if (topEdgeOffset < viewportDimensions.top) { - delta.top = viewportDimensions.top - topEdgeOffset; - } else if (bottomEdgeOffset > viewportDimensions.top + viewportDimensions.height) { - delta.top = viewportDimensions.top + viewportDimensions.height - bottomEdgeOffset; - } - } else { - var leftEdgeOffset = pos.left - viewportPadding; - var rightEdgeOffset = pos.left + viewportPadding + actualWidth; - if (leftEdgeOffset < viewportDimensions.left) { - delta.left = viewportDimensions.left - leftEdgeOffset; - } else if (rightEdgeOffset > viewportDimensions.right) { - delta.left = viewportDimensions.left + viewportDimensions.width - rightEdgeOffset; - } + Parser.prototype = { + constructor: Parser, + parse: function(text) { + return this.astCompiler.compile(text, this.options.expensiveChecks); } - return delta; - }; - Tooltip.prototype.getTitle = function() { - var title; - var $e = this.$element; - var o = this.options; - title = $e.attr("data-original-title") || (typeof o.title == "function" ? o.title.call($e[0]) : o.title); - return title; - }; - Tooltip.prototype.getUID = function(prefix) { - do prefix += ~~(Math.random() * 1e6); while (document.getElementById(prefix)); - return prefix; }; - Tooltip.prototype.tip = function() { - if (!this.$tip) { - this.$tip = $(this.options.template); - if (this.$tip.length != 1) { - throw new Error(this.type + " `template` option must consist of exactly 1 top-level element!"); + var getterFnCacheDefault = createMap(); + var getterFnCacheExpensive = createMap(); + function isPossiblyDangerousMemberName(name) { + return name == "constructor"; + } + var objectValueOf = Object.prototype.valueOf; + function getValueOf(value) { + return isFunction(value.valueOf) ? value.valueOf() : objectValueOf.call(value); + } + function $ParseProvider() { + var cacheDefault = createMap(); + var cacheExpensive = createMap(); + this.$get = [ "$filter", function($filter) { + var noUnsafeEval = csp().noUnsafeEval; + var $parseOptions = { + csp: noUnsafeEval, + expensiveChecks: false + }, $parseOptionsExpensive = { + csp: noUnsafeEval, + expensiveChecks: true + }; + return function $parse(exp, interceptorFn, expensiveChecks) { + var parsedExpression, oneTime, cacheKey; + switch (typeof exp) { + case "string": + exp = exp.trim(); + cacheKey = exp; + var cache = expensiveChecks ? cacheExpensive : cacheDefault; + parsedExpression = cache[cacheKey]; + if (!parsedExpression) { + if (exp.charAt(0) === ":" && exp.charAt(1) === ":") { + oneTime = true; + exp = exp.substring(2); + } + var parseOptions = expensiveChecks ? $parseOptionsExpensive : $parseOptions; + var lexer = new Lexer(parseOptions); + var parser = new Parser(lexer, $filter, parseOptions); + parsedExpression = parser.parse(exp); + if (parsedExpression.constant) { + parsedExpression.$$watchDelegate = constantWatchDelegate; + } else if (oneTime) { + parsedExpression.$$watchDelegate = parsedExpression.literal ? oneTimeLiteralWatchDelegate : oneTimeWatchDelegate; + } else if (parsedExpression.inputs) { + parsedExpression.$$watchDelegate = inputsWatchDelegate; + } + cache[cacheKey] = parsedExpression; + } + return addInterceptor(parsedExpression, interceptorFn); + + case "function": + return addInterceptor(exp, interceptorFn); + + default: + return noop; + } + }; + function expressionInputDirtyCheck(newValue, oldValueOfValue) { + if (newValue == null || oldValueOfValue == null) { + return newValue === oldValueOfValue; + } + if (typeof newValue === "object") { + newValue = getValueOf(newValue); + if (typeof newValue === "object") { + return false; + } + } + return newValue === oldValueOfValue || newValue !== newValue && oldValueOfValue !== oldValueOfValue; } - } - return this.$tip; - }; - Tooltip.prototype.arrow = function() { - return this.$arrow = this.$arrow || this.tip().find(".tooltip-arrow"); - }; - Tooltip.prototype.enable = function() { - this.enabled = true; - }; - Tooltip.prototype.disable = function() { - this.enabled = false; - }; - Tooltip.prototype.toggleEnabled = function() { - this.enabled = !this.enabled; - }; - Tooltip.prototype.toggle = function(e) { - var self = this; - if (e) { - self = $(e.currentTarget).data("bs." + this.type); - if (!self) { - self = new this.constructor(e.currentTarget, this.getDelegateOptions()); - $(e.currentTarget).data("bs." + this.type, self); + function inputsWatchDelegate(scope, listener, objectEquality, parsedExpression, prettyPrintExpression) { + var inputExpressions = parsedExpression.inputs; + var lastResult; + if (inputExpressions.length === 1) { + var oldInputValueOf = expressionInputDirtyCheck; + inputExpressions = inputExpressions[0]; + return scope.$watch(function expressionInputWatch(scope) { + var newInputValue = inputExpressions(scope); + if (!expressionInputDirtyCheck(newInputValue, oldInputValueOf)) { + lastResult = parsedExpression(scope, undefined, undefined, [ newInputValue ]); + oldInputValueOf = newInputValue && getValueOf(newInputValue); + } + return lastResult; + }, listener, objectEquality, prettyPrintExpression); + } + var oldInputValueOfValues = []; + var oldInputValues = []; + for (var i = 0, ii = inputExpressions.length; i < ii; i++) { + oldInputValueOfValues[i] = expressionInputDirtyCheck; + oldInputValues[i] = null; + } + return scope.$watch(function expressionInputsWatch(scope) { + var changed = false; + for (var i = 0, ii = inputExpressions.length; i < ii; i++) { + var newInputValue = inputExpressions[i](scope); + if (changed || (changed = !expressionInputDirtyCheck(newInputValue, oldInputValueOfValues[i]))) { + oldInputValues[i] = newInputValue; + oldInputValueOfValues[i] = newInputValue && getValueOf(newInputValue); + } + } + if (changed) { + lastResult = parsedExpression(scope, undefined, undefined, oldInputValues); + } + return lastResult; + }, listener, objectEquality, prettyPrintExpression); } - } - if (e) { - self.inState.click = !self.inState.click; - if (self.isInStateTrue()) self.enter(self); else self.leave(self); - } else { - self.tip().hasClass("in") ? self.leave(self) : self.enter(self); - } - }; - Tooltip.prototype.destroy = function() { - var that = this; - clearTimeout(this.timeout); - this.hide(function() { - that.$element.off("." + that.type).removeData("bs." + that.type); - if (that.$tip) { - that.$tip.detach(); + function oneTimeWatchDelegate(scope, listener, objectEquality, parsedExpression) { + var unwatch, lastValue; + return unwatch = scope.$watch(function oneTimeWatch(scope) { + return parsedExpression(scope); + }, function oneTimeListener(value, old, scope) { + lastValue = value; + if (isFunction(listener)) { + listener.apply(this, arguments); + } + if (isDefined(value)) { + scope.$$postDigest(function() { + if (isDefined(lastValue)) { + unwatch(); + } + }); + } + }, objectEquality); } - that.$tip = null; - that.$arrow = null; - that.$viewport = null; - }); - }; - function Plugin(option) { - return this.each(function() { - var $this = $(this); - var data = $this.data("bs.tooltip"); - var options = typeof option == "object" && option; - if (!data && /destroy|hide/.test(option)) return; - if (!data) $this.data("bs.tooltip", data = new Tooltip(this, options)); - if (typeof option == "string") data[option](); - }); + function oneTimeLiteralWatchDelegate(scope, listener, objectEquality, parsedExpression) { + var unwatch, lastValue; + return unwatch = scope.$watch(function oneTimeWatch(scope) { + return parsedExpression(scope); + }, function oneTimeListener(value, old, scope) { + lastValue = value; + if (isFunction(listener)) { + listener.call(this, value, old, scope); + } + if (isAllDefined(value)) { + scope.$$postDigest(function() { + if (isAllDefined(lastValue)) unwatch(); + }); + } + }, objectEquality); + function isAllDefined(value) { + var allDefined = true; + forEach(value, function(val) { + if (!isDefined(val)) allDefined = false; + }); + return allDefined; + } + } + function constantWatchDelegate(scope, listener, objectEquality, parsedExpression) { + var unwatch; + return unwatch = scope.$watch(function constantWatch(scope) { + return parsedExpression(scope); + }, function constantListener(value, old, scope) { + if (isFunction(listener)) { + listener.apply(this, arguments); + } + unwatch(); + }, objectEquality); + } + function addInterceptor(parsedExpression, interceptorFn) { + if (!interceptorFn) return parsedExpression; + var watchDelegate = parsedExpression.$$watchDelegate; + var regularWatch = watchDelegate !== oneTimeLiteralWatchDelegate && watchDelegate !== oneTimeWatchDelegate; + var fn = regularWatch ? function regularInterceptedExpression(scope, locals, assign, inputs) { + var value = parsedExpression(scope, locals, assign, inputs); + return interceptorFn(value, scope, locals); + } : function oneTimeInterceptedExpression(scope, locals, assign, inputs) { + var value = parsedExpression(scope, locals, assign, inputs); + var result = interceptorFn(value, scope, locals); + return isDefined(value) ? result : value; + }; + if (parsedExpression.$$watchDelegate && parsedExpression.$$watchDelegate !== inputsWatchDelegate) { + fn.$$watchDelegate = parsedExpression.$$watchDelegate; + } else if (!interceptorFn.$stateful) { + fn.$$watchDelegate = inputsWatchDelegate; + fn.inputs = parsedExpression.inputs ? parsedExpression.inputs : [ parsedExpression ]; + } + return fn; + } + } ]; } - var old = $.fn.tooltip; - $.fn.tooltip = Plugin; - $.fn.tooltip.Constructor = Tooltip; - $.fn.tooltip.noConflict = function() { - $.fn.tooltip = old; - return this; - }; -}(jQuery); - -+function($) { - "use strict"; - var Popover = function(element, options) { - this.init("popover", element, options); - }; - if (!$.fn.tooltip) throw new Error("Popover requires tooltip.js"); - Popover.VERSION = "3.3.5"; - Popover.DEFAULTS = $.extend({}, $.fn.tooltip.Constructor.DEFAULTS, { - placement: "right", - trigger: "click", - content: "", - template: '' - }); - Popover.prototype = $.extend({}, $.fn.tooltip.Constructor.prototype); - Popover.prototype.constructor = Popover; - Popover.prototype.getDefaults = function() { - return Popover.DEFAULTS; - }; - Popover.prototype.setContent = function() { - var $tip = this.tip(); - var title = this.getTitle(); - var content = this.getContent(); - $tip.find(".popover-title")[this.options.html ? "html" : "text"](title); - $tip.find(".popover-content").children().detach().end()[this.options.html ? typeof content == "string" ? "html" : "append" : "text"](content); - $tip.removeClass("fade top bottom left right in"); - if (!$tip.find(".popover-title").html()) $tip.find(".popover-title").hide(); - }; - Popover.prototype.hasContent = function() { - return this.getTitle() || this.getContent(); - }; - Popover.prototype.getContent = function() { - var $e = this.$element; - var o = this.options; - return $e.attr("data-content") || (typeof o.content == "function" ? o.content.call($e[0]) : o.content); - }; - Popover.prototype.arrow = function() { - return this.$arrow = this.$arrow || this.tip().find(".arrow"); - }; - function Plugin(option) { - return this.each(function() { - var $this = $(this); - var data = $this.data("bs.popover"); - var options = typeof option == "object" && option; - if (!data && /destroy|hide/.test(option)) return; - if (!data) $this.data("bs.popover", data = new Popover(this, options)); - if (typeof option == "string") data[option](); - }); + function $QProvider() { + this.$get = [ "$rootScope", "$exceptionHandler", function($rootScope, $exceptionHandler) { + return qFactory(function(callback) { + $rootScope.$evalAsync(callback); + }, $exceptionHandler); + } ]; } - var old = $.fn.popover; - $.fn.popover = Plugin; - $.fn.popover.Constructor = Popover; - $.fn.popover.noConflict = function() { - $.fn.popover = old; - return this; - }; -}(jQuery); - -+function($) { - "use strict"; - function ScrollSpy(element, options) { - this.$body = $(document.body); - this.$scrollElement = $(element).is(document.body) ? $(window) : $(element); - this.options = $.extend({}, ScrollSpy.DEFAULTS, options); - this.selector = (this.options.target || "") + " .nav li > a"; - this.offsets = []; - this.targets = []; - this.activeTarget = null; - this.scrollHeight = 0; - this.$scrollElement.on("scroll.bs.scrollspy", $.proxy(this.process, this)); - this.refresh(); - this.process(); + function $$QProvider() { + this.$get = [ "$browser", "$exceptionHandler", function($browser, $exceptionHandler) { + return qFactory(function(callback) { + $browser.defer(callback); + }, $exceptionHandler); + } ]; } - ScrollSpy.VERSION = "3.3.5"; - ScrollSpy.DEFAULTS = { - offset: 10 - }; - ScrollSpy.prototype.getScrollHeight = function() { - return this.$scrollElement[0].scrollHeight || Math.max(this.$body[0].scrollHeight, document.documentElement.scrollHeight); - }; - ScrollSpy.prototype.refresh = function() { - var that = this; - var offsetMethod = "offset"; - var offsetBase = 0; - this.offsets = []; - this.targets = []; - this.scrollHeight = this.getScrollHeight(); - if (!$.isWindow(this.$scrollElement[0])) { - offsetMethod = "position"; - offsetBase = this.$scrollElement.scrollTop(); + function qFactory(nextTick, exceptionHandler) { + var $qMinErr = minErr("$q", TypeError); + function callOnce(self, resolveFn, rejectFn) { + var called = false; + function wrap(fn) { + return function(value) { + if (called) return; + called = true; + fn.call(self, value); + }; + } + return [ wrap(resolveFn), wrap(rejectFn) ]; } - this.$body.find(this.selector).map(function() { - var $el = $(this); - var href = $el.data("target") || $el.attr("href"); - var $href = /^#./.test(href) && $(href); - return $href && $href.length && $href.is(":visible") && [ [ $href[offsetMethod]().top + offsetBase, href ] ] || null; - }).sort(function(a, b) { - return a[0] - b[0]; - }).each(function() { - that.offsets.push(this[0]); - that.targets.push(this[1]); - }); - }; - ScrollSpy.prototype.process = function() { - var scrollTop = this.$scrollElement.scrollTop() + this.options.offset; - var scrollHeight = this.getScrollHeight(); - var maxScroll = this.options.offset + scrollHeight - this.$scrollElement.height(); - var offsets = this.offsets; - var targets = this.targets; - var activeTarget = this.activeTarget; - var i; - if (this.scrollHeight != scrollHeight) { - this.refresh(); + var defer = function() { + return new Deferred(); + }; + function Promise() { + this.$$state = { + status: 0 + }; } - if (scrollTop >= maxScroll) { - return activeTarget != (i = targets[targets.length - 1]) && this.activate(i); + extend(Promise.prototype, { + then: function(onFulfilled, onRejected, progressBack) { + if (isUndefined(onFulfilled) && isUndefined(onRejected) && isUndefined(progressBack)) { + return this; + } + var result = new Deferred(); + this.$$state.pending = this.$$state.pending || []; + this.$$state.pending.push([ result, onFulfilled, onRejected, progressBack ]); + if (this.$$state.status > 0) scheduleProcessQueue(this.$$state); + return result.promise; + }, + "catch": function(callback) { + return this.then(null, callback); + }, + "finally": function(callback, progressBack) { + return this.then(function(value) { + return handleCallback(value, true, callback); + }, function(error) { + return handleCallback(error, false, callback); + }, progressBack); + } + }); + function simpleBind(context, fn) { + return function(value) { + fn.call(context, value); + }; } - if (activeTarget && scrollTop < offsets[0]) { - this.activeTarget = null; - return this.clear(); + function processQueue(state) { + var fn, deferred, pending; + pending = state.pending; + state.processScheduled = false; + state.pending = undefined; + for (var i = 0, ii = pending.length; i < ii; ++i) { + deferred = pending[i][0]; + fn = pending[i][state.status]; + try { + if (isFunction(fn)) { + deferred.resolve(fn(state.value)); + } else if (state.status === 1) { + deferred.resolve(state.value); + } else { + deferred.reject(state.value); + } + } catch (e) { + deferred.reject(e); + exceptionHandler(e); + } + } } - for (i = offsets.length; i--; ) { - activeTarget != targets[i] && scrollTop >= offsets[i] && (offsets[i + 1] === undefined || scrollTop < offsets[i + 1]) && this.activate(targets[i]); + function scheduleProcessQueue(state) { + if (state.processScheduled || !state.pending) return; + state.processScheduled = true; + nextTick(function() { + processQueue(state); + }); } - }; - ScrollSpy.prototype.activate = function(target) { - this.activeTarget = target; - this.clear(); - var selector = this.selector + '[data-target="' + target + '"],' + this.selector + '[href="' + target + '"]'; - var active = $(selector).parents("li").addClass("active"); - if (active.parent(".dropdown-menu").length) { - active = active.closest("li.dropdown").addClass("active"); + function Deferred() { + this.promise = new Promise(); + this.resolve = simpleBind(this, this.resolve); + this.reject = simpleBind(this, this.reject); + this.notify = simpleBind(this, this.notify); } - active.trigger("activate.bs.scrollspy"); - }; - ScrollSpy.prototype.clear = function() { - $(this.selector).parentsUntil(this.options.target, ".active").removeClass("active"); - }; - function Plugin(option) { - return this.each(function() { - var $this = $(this); - var data = $this.data("bs.scrollspy"); - var options = typeof option == "object" && option; - if (!data) $this.data("bs.scrollspy", data = new ScrollSpy(this, options)); - if (typeof option == "string") data[option](); - }); - } - var old = $.fn.scrollspy; - $.fn.scrollspy = Plugin; - $.fn.scrollspy.Constructor = ScrollSpy; - $.fn.scrollspy.noConflict = function() { - $.fn.scrollspy = old; - return this; - }; - $(window).on("load.bs.scrollspy.data-api", function() { - $('[data-spy="scroll"]').each(function() { - var $spy = $(this); - Plugin.call($spy, $spy.data()); - }); - }); -}(jQuery); - -+function($) { - "use strict"; - var Tab = function(element) { - this.element = $(element); - }; - Tab.VERSION = "3.3.5"; - Tab.TRANSITION_DURATION = 150; - Tab.prototype.show = function() { - var $this = this.element; - var $ul = $this.closest("ul:not(.dropdown-menu)"); - var selector = $this.data("target"); - if (!selector) { - selector = $this.attr("href"); - selector = selector && selector.replace(/.*(?=#[^\s]*$)/, ""); - } - if ($this.parent("li").hasClass("active")) return; - var $previous = $ul.find(".active:last a"); - var hideEvent = $.Event("hide.bs.tab", { - relatedTarget: $this[0] - }); - var showEvent = $.Event("show.bs.tab", { - relatedTarget: $previous[0] - }); - $previous.trigger(hideEvent); - $this.trigger(showEvent); - if (showEvent.isDefaultPrevented() || hideEvent.isDefaultPrevented()) return; - var $target = $(selector); - this.activate($this.closest("li"), $ul); - this.activate($target, $target.parent(), function() { - $previous.trigger({ - type: "hidden.bs.tab", - relatedTarget: $this[0] - }); - $this.trigger({ - type: "shown.bs.tab", - relatedTarget: $previous[0] - }); + extend(Deferred.prototype, { + resolve: function(val) { + if (this.promise.$$state.status) return; + if (val === this.promise) { + this.$$reject($qMinErr("qcycle", "Expected promise to be resolved with value other than itself '{0}'", val)); + } else { + this.$$resolve(val); + } + }, + $$resolve: function(val) { + var then, fns; + fns = callOnce(this, this.$$resolve, this.$$reject); + try { + if (isObject(val) || isFunction(val)) then = val && val.then; + if (isFunction(then)) { + this.promise.$$state.status = -1; + then.call(val, fns[0], fns[1], this.notify); + } else { + this.promise.$$state.value = val; + this.promise.$$state.status = 1; + scheduleProcessQueue(this.promise.$$state); + } + } catch (e) { + fns[1](e); + exceptionHandler(e); + } + }, + reject: function(reason) { + if (this.promise.$$state.status) return; + this.$$reject(reason); + }, + $$reject: function(reason) { + this.promise.$$state.value = reason; + this.promise.$$state.status = 2; + scheduleProcessQueue(this.promise.$$state); + }, + notify: function(progress) { + var callbacks = this.promise.$$state.pending; + if (this.promise.$$state.status <= 0 && callbacks && callbacks.length) { + nextTick(function() { + var callback, result; + for (var i = 0, ii = callbacks.length; i < ii; i++) { + result = callbacks[i][0]; + callback = callbacks[i][3]; + try { + result.notify(isFunction(callback) ? callback(progress) : progress); + } catch (e) { + exceptionHandler(e); + } + } + }); + } + } }); - }; - Tab.prototype.activate = function(element, container, callback) { - var $active = container.find("> .active"); - var transition = callback && $.support.transition && ($active.length && $active.hasClass("fade") || !!container.find("> .fade").length); - function next() { - $active.removeClass("active").find("> .dropdown-menu > .active").removeClass("active").end().find('[data-toggle="tab"]').attr("aria-expanded", false); - element.addClass("active").find('[data-toggle="tab"]').attr("aria-expanded", true); - if (transition) { - element[0].offsetWidth; - element.addClass("in"); + var reject = function(reason) { + var result = new Deferred(); + result.reject(reason); + return result.promise; + }; + var makePromise = function makePromise(value, resolved) { + var result = new Deferred(); + if (resolved) { + result.resolve(value); } else { - element.removeClass("fade"); + result.reject(value); } - if (element.parent(".dropdown-menu").length) { - element.closest("li.dropdown").addClass("active").end().find('[data-toggle="tab"]').attr("aria-expanded", true); + return result.promise; + }; + var handleCallback = function handleCallback(value, isResolved, callback) { + var callbackOutput = null; + try { + if (isFunction(callback)) callbackOutput = callback(); + } catch (e) { + return makePromise(e, false); } - callback && callback(); - } - $active.length && transition ? $active.one("bsTransitionEnd", next).emulateTransitionEnd(Tab.TRANSITION_DURATION) : next(); - $active.removeClass("in"); - }; - function Plugin(option) { - return this.each(function() { - var $this = $(this); - var data = $this.data("bs.tab"); - if (!data) $this.data("bs.tab", data = new Tab(this)); - if (typeof option == "string") data[option](); - }); - } - var old = $.fn.tab; - $.fn.tab = Plugin; - $.fn.tab.Constructor = Tab; - $.fn.tab.noConflict = function() { - $.fn.tab = old; - return this; - }; - var clickHandler = function(e) { - e.preventDefault(); - Plugin.call($(this), "show"); - }; - $(document).on("click.bs.tab.data-api", '[data-toggle="tab"]', clickHandler).on("click.bs.tab.data-api", '[data-toggle="pill"]', clickHandler); -}(jQuery); - -+function($) { - "use strict"; - var Affix = function(element, options) { - this.options = $.extend({}, Affix.DEFAULTS, options); - this.$target = $(this.options.target).on("scroll.bs.affix.data-api", $.proxy(this.checkPosition, this)).on("click.bs.affix.data-api", $.proxy(this.checkPositionWithEventLoop, this)); - this.$element = $(element); - this.affixed = null; - this.unpin = null; - this.pinnedOffset = null; - this.checkPosition(); - }; - Affix.VERSION = "3.3.5"; - Affix.RESET = "affix affix-top affix-bottom"; - Affix.DEFAULTS = { - offset: 0, - target: window - }; - Affix.prototype.getState = function(scrollHeight, height, offsetTop, offsetBottom) { - var scrollTop = this.$target.scrollTop(); - var position = this.$element.offset(); - var targetHeight = this.$target.height(); - if (offsetTop != null && this.affixed == "top") return scrollTop < offsetTop ? "top" : false; - if (this.affixed == "bottom") { - if (offsetTop != null) return scrollTop + this.unpin <= position.top ? false : "bottom"; - return scrollTop + targetHeight <= scrollHeight - offsetBottom ? false : "bottom"; - } - var initializing = this.affixed == null; - var colliderTop = initializing ? scrollTop : position.top; - var colliderHeight = initializing ? targetHeight : height; - if (offsetTop != null && scrollTop <= offsetTop) return "top"; - if (offsetBottom != null && colliderTop + colliderHeight >= scrollHeight - offsetBottom) return "bottom"; - return false; - }; - Affix.prototype.getPinnedOffset = function() { - if (this.pinnedOffset) return this.pinnedOffset; - this.$element.removeClass(Affix.RESET).addClass("affix"); - var scrollTop = this.$target.scrollTop(); - var position = this.$element.offset(); - return this.pinnedOffset = position.top - scrollTop; - }; - Affix.prototype.checkPositionWithEventLoop = function() { - setTimeout($.proxy(this.checkPosition, this), 1); - }; - Affix.prototype.checkPosition = function() { - if (!this.$element.is(":visible")) return; - var height = this.$element.height(); - var offset = this.options.offset; - var offsetTop = offset.top; - var offsetBottom = offset.bottom; - var scrollHeight = Math.max($(document).height(), $(document.body).height()); - if (typeof offset != "object") offsetBottom = offsetTop = offset; - if (typeof offsetTop == "function") offsetTop = offset.top(this.$element); - if (typeof offsetBottom == "function") offsetBottom = offset.bottom(this.$element); - var affix = this.getState(scrollHeight, height, offsetTop, offsetBottom); - if (this.affixed != affix) { - if (this.unpin != null) this.$element.css("top", ""); - var affixType = "affix" + (affix ? "-" + affix : ""); - var e = $.Event(affixType + ".bs.affix"); - this.$element.trigger(e); - if (e.isDefaultPrevented()) return; - this.affixed = affix; - this.unpin = affix == "bottom" ? this.getPinnedOffset() : null; - this.$element.removeClass(Affix.RESET).addClass(affixType).trigger(affixType.replace("affix", "affixed") + ".bs.affix"); - } - if (affix == "bottom") { - this.$element.offset({ - top: scrollHeight - height - offsetBottom + if (isPromiseLike(callbackOutput)) { + return callbackOutput.then(function() { + return makePromise(value, isResolved); + }, function(error) { + return makePromise(error, false); + }); + } else { + return makePromise(value, isResolved); + } + }; + var when = function(value, callback, errback, progressBack) { + var result = new Deferred(); + result.resolve(value); + return result.promise.then(callback, errback, progressBack); + }; + var resolve = when; + function all(promises) { + var deferred = new Deferred(), counter = 0, results = isArray(promises) ? [] : {}; + forEach(promises, function(promise, key) { + counter++; + when(promise).then(function(value) { + if (results.hasOwnProperty(key)) return; + results[key] = value; + if (!--counter) deferred.resolve(results); + }, function(reason) { + if (results.hasOwnProperty(key)) return; + deferred.reject(reason); + }); }); + if (counter === 0) { + deferred.resolve(results); + } + return deferred.promise; } - }; - function Plugin(option) { - return this.each(function() { - var $this = $(this); - var data = $this.data("bs.affix"); - var options = typeof option == "object" && option; - if (!data) $this.data("bs.affix", data = new Affix(this, options)); - if (typeof option == "string") data[option](); - }); - } - var old = $.fn.affix; - $.fn.affix = Plugin; - $.fn.affix.Constructor = Affix; - $.fn.affix.noConflict = function() { - $.fn.affix = old; - return this; - }; - $(window).on("load", function() { - $('[data-spy="affix"]').each(function() { - var $spy = $(this); - var data = $spy.data(); - data.offset = data.offset || {}; - if (data.offsetBottom != null) data.offset.bottom = data.offsetBottom; - if (data.offsetTop != null) data.offset.top = data.offsetTop; - Plugin.call($spy, data); - }); - }); -}(jQuery); - -angular.module("ui.bootstrap", [ "ui.bootstrap.collapse", "ui.bootstrap.accordion", "ui.bootstrap.alert", "ui.bootstrap.bindHtml", "ui.bootstrap.buttons", "ui.bootstrap.carousel", "ui.bootstrap.dateparser", "ui.bootstrap.position", "ui.bootstrap.datepicker", "ui.bootstrap.dropdown", "ui.bootstrap.modal", "ui.bootstrap.pagination", "ui.bootstrap.tooltip", "ui.bootstrap.popover", "ui.bootstrap.progressbar", "ui.bootstrap.rating", "ui.bootstrap.tabs", "ui.bootstrap.timepicker", "ui.bootstrap.transition", "ui.bootstrap.typeahead" ]); - -angular.module("ui.bootstrap.collapse", []).directive("collapse", [ "$animate", function($animate) { - return { - link: function(scope, element, attrs) { - function expand() { - element.removeClass("collapse").addClass("collapsing").attr("aria-expanded", true).attr("aria-hidden", false); - $animate.addClass(element, "in", { - to: { - height: element[0].scrollHeight + "px" - } - }).then(expandDone); + var $Q = function Q(resolver) { + if (!isFunction(resolver)) { + throw $qMinErr("norslvr", "Expected resolverFn, got '{0}'", resolver); } - function expandDone() { - element.removeClass("collapsing"); - element.css({ - height: "auto" - }); + if (!(this instanceof Q)) { + return new Q(resolver); } - function collapse() { - if (!element.hasClass("collapse") && !element.hasClass("in")) { - return collapseDone(); - } - element.css({ - height: element[0].scrollHeight + "px" - }).removeClass("collapse").addClass("collapsing").attr("aria-expanded", false).attr("aria-hidden", true); - $animate.removeClass(element, "in", { - to: { - height: "0" - } - }).then(collapseDone); + var deferred = new Deferred(); + function resolveFn(value) { + deferred.resolve(value); } - function collapseDone() { - element.css({ - height: "0" - }); - element.removeClass("collapsing"); - element.addClass("collapse"); + function rejectFn(reason) { + deferred.reject(reason); } - scope.$watch(attrs.collapse, function(shouldCollapse) { - if (shouldCollapse) { - collapse(); - } else { - expand(); - } - }); - } - }; -} ]); - -angular.module("ui.bootstrap.accordion", [ "ui.bootstrap.collapse" ]).constant("accordionConfig", { - closeOthers: true -}).controller("AccordionController", [ "$scope", "$attrs", "accordionConfig", function($scope, $attrs, accordionConfig) { - this.groups = []; - this.closeOthers = function(openGroup) { - var closeOthers = angular.isDefined($attrs.closeOthers) ? $scope.$eval($attrs.closeOthers) : accordionConfig.closeOthers; - if (closeOthers) { - angular.forEach(this.groups, function(group) { - if (group !== openGroup) { - group.isOpen = false; - } - }); - } - }; - this.addGroup = function(groupScope) { - var that = this; - this.groups.push(groupScope); - groupScope.$on("$destroy", function(event) { - that.removeGroup(groupScope); - }); - }; - this.removeGroup = function(group) { - var index = this.groups.indexOf(group); - if (index !== -1) { - this.groups.splice(index, 1); - } - }; -} ]).directive("accordion", function() { - return { - restrict: "EA", - controller: "AccordionController", - controllerAs: "accordion", - transclude: true, - replace: false, - templateUrl: function(element, attrs) { - return attrs.templateUrl || "template/accordion/accordion.html"; - } - }; -}).directive("accordionGroup", function() { - return { - require: "^accordion", - restrict: "EA", - transclude: true, - replace: true, - templateUrl: function(element, attrs) { - return attrs.templateUrl || "template/accordion/accordion-group.html"; - }, - scope: { - heading: "@", - isOpen: "=?", - isDisabled: "=?" - }, - controller: function() { - this.setHeading = function(element) { - this.heading = element; - }; - }, - link: function(scope, element, attrs, accordionCtrl) { - accordionCtrl.addGroup(scope); - scope.openClass = attrs.openClass || "panel-open"; - scope.panelClass = attrs.panelClass; - scope.$watch("isOpen", function(value) { - element.toggleClass(scope.openClass, value); - if (value) { - accordionCtrl.closeOthers(scope); - } - }); - scope.toggleOpen = function($event) { - if (!scope.isDisabled) { - if (!$event || $event.which === 32) { - scope.isOpen = !scope.isOpen; - } - } + resolver(resolveFn, rejectFn); + return deferred.promise; + }; + $Q.defer = defer; + $Q.reject = reject; + $Q.when = when; + $Q.resolve = resolve; + $Q.all = all; + return $Q; + } + function $$RAFProvider() { + this.$get = [ "$window", "$timeout", function($window, $timeout) { + var requestAnimationFrame = $window.requestAnimationFrame || $window.webkitRequestAnimationFrame; + var cancelAnimationFrame = $window.cancelAnimationFrame || $window.webkitCancelAnimationFrame || $window.webkitCancelRequestAnimationFrame; + var rafSupported = !!requestAnimationFrame; + var raf = rafSupported ? function(fn) { + var id = requestAnimationFrame(fn); + return function() { + cancelAnimationFrame(id); + }; + } : function(fn) { + var timer = $timeout(fn, 16.66, false); + return function() { + $timeout.cancel(timer); + }; }; + raf.supported = rafSupported; + return raf; + } ]; + } + function $RootScopeProvider() { + var TTL = 10; + var $rootScopeMinErr = minErr("$rootScope"); + var lastDirtyWatch = null; + var applyAsyncId = null; + this.digestTtl = function(value) { + if (arguments.length) { + TTL = value; + } + return TTL; + }; + function createChildScopeClass(parent) { + function ChildScope() { + this.$$watchers = this.$$nextSibling = this.$$childHead = this.$$childTail = null; + this.$$listeners = {}; + this.$$listenerCount = {}; + this.$$watchersCount = 0; + this.$id = nextUid(); + this.$$ChildScope = null; + } + ChildScope.prototype = parent; + return ChildScope; } - }; -}).directive("accordionHeading", function() { - return { - restrict: "EA", - transclude: true, - template: "", - replace: true, - require: "^accordionGroup", - link: function(scope, element, attr, accordionGroupCtrl, transclude) { - accordionGroupCtrl.setHeading(transclude(scope, angular.noop)); - } - }; -}).directive("accordionTransclude", function() { - return { - require: "^accordionGroup", - link: function(scope, element, attr, controller) { - scope.$watch(function() { - return controller[attr.accordionTransclude]; - }, function(heading) { - if (heading) { - element.find("span").html(""); - element.find("span").append(heading); - } - }); - } - }; -}); - -angular.module("ui.bootstrap.alert", []).controller("AlertController", [ "$scope", "$attrs", function($scope, $attrs) { - $scope.closeable = !!$attrs.close; - this.close = $scope.close; -} ]).directive("alert", function() { - return { - controller: "AlertController", - controllerAs: "alert", - templateUrl: function(element, attrs) { - return attrs.templateUrl || "template/alert/alert.html"; - }, - transclude: true, - replace: true, - scope: { - type: "@", - close: "&" - } - }; -}).directive("dismissOnTimeout", [ "$timeout", function($timeout) { - return { - require: "alert", - link: function(scope, element, attrs, alertCtrl) { - $timeout(function() { - alertCtrl.close(); - }, parseInt(attrs.dismissOnTimeout, 10)); - } - }; -} ]); - -angular.module("ui.bootstrap.bindHtml", []).value("$bindHtmlUnsafeSuppressDeprecated", false).directive("bindHtmlUnsafe", [ "$log", "$bindHtmlUnsafeSuppressDeprecated", function($log, $bindHtmlUnsafeSuppressDeprecated) { - return function(scope, element, attr) { - if (!$bindHtmlUnsafeSuppressDeprecated) { - $log.warn("bindHtmlUnsafe is now deprecated. Use ngBindHtml instead"); - } - element.addClass("ng-binding").data("$binding", attr.bindHtmlUnsafe); - scope.$watch(attr.bindHtmlUnsafe, function bindHtmlUnsafeWatchAction(value) { - element.html(value || ""); - }); - }; -} ]); - -angular.module("ui.bootstrap.buttons", []).constant("buttonConfig", { - activeClass: "active", - toggleEvent: "click" -}).controller("ButtonsController", [ "buttonConfig", function(buttonConfig) { - this.activeClass = buttonConfig.activeClass || "active"; - this.toggleEvent = buttonConfig.toggleEvent || "click"; -} ]).directive("btnRadio", function() { - return { - require: [ "btnRadio", "ngModel" ], - controller: "ButtonsController", - controllerAs: "buttons", - link: function(scope, element, attrs, ctrls) { - var buttonsCtrl = ctrls[0], ngModelCtrl = ctrls[1]; - element.find("input").css({ - display: "none" - }); - ngModelCtrl.$render = function() { - element.toggleClass(buttonsCtrl.activeClass, angular.equals(ngModelCtrl.$modelValue, scope.$eval(attrs.btnRadio))); - }; - element.bind(buttonsCtrl.toggleEvent, function() { - if (attrs.disabled) { - return; - } - var isActive = element.hasClass(buttonsCtrl.activeClass); - if (!isActive || angular.isDefined(attrs.uncheckable)) { - scope.$apply(function() { - ngModelCtrl.$setViewValue(isActive ? null : scope.$eval(attrs.btnRadio)); - ngModelCtrl.$render(); - }); - } - }); - } - }; -}).directive("btnCheckbox", [ "$document", function($document) { - return { - require: [ "btnCheckbox", "ngModel" ], - controller: "ButtonsController", - controllerAs: "button", - link: function(scope, element, attrs, ctrls) { - var buttonsCtrl = ctrls[0], ngModelCtrl = ctrls[1]; - element.find("input").css({ - display: "none" - }); - function getTrueValue() { - return getCheckboxValue(attrs.btnCheckboxTrue, true); - } - function getFalseValue() { - return getCheckboxValue(attrs.btnCheckboxFalse, false); - } - function getCheckboxValue(attributeValue, defaultValue) { - var val = scope.$eval(attributeValue); - return angular.isDefined(val) ? val : defaultValue; + this.$get = [ "$injector", "$exceptionHandler", "$parse", "$browser", function($injector, $exceptionHandler, $parse, $browser) { + function destroyChildScope($event) { + $event.currentScope.$$destroyed = true; } - ngModelCtrl.$render = function() { - element.toggleClass(buttonsCtrl.activeClass, angular.equals(ngModelCtrl.$modelValue, getTrueValue())); - }; - element.bind(buttonsCtrl.toggleEvent, function() { - if (attrs.disabled) { - return; - } - scope.$apply(function() { - ngModelCtrl.$setViewValue(element.hasClass(buttonsCtrl.activeClass) ? getFalseValue() : getTrueValue()); - ngModelCtrl.$render(); - }); - }); - element.on("keypress", function(e) { - if (attrs.disabled || e.which !== 32 || $document[0].activeElement !== element[0]) { - return; - } - scope.$apply(function() { - ngModelCtrl.$setViewValue(element.hasClass(buttonsCtrl.activeClass) ? getFalseValue() : getTrueValue()); - ngModelCtrl.$render(); - }); - }); - } - }; -} ]); - -angular.module("ui.bootstrap.carousel", []).controller("CarouselController", [ "$scope", "$element", "$interval", "$animate", function($scope, $element, $interval, $animate) { - var self = this, slides = self.slides = $scope.slides = [], NEW_ANIMATE = angular.version.minor >= 4, NO_TRANSITION = "uib-noTransition", SLIDE_DIRECTION = "uib-slideDirection", currentIndex = -1, currentInterval, isPlaying; - self.currentSlide = null; - var destroyed = false; - self.select = $scope.select = function(nextSlide, direction) { - var nextIndex = $scope.indexOfSlide(nextSlide); - if (direction === undefined) { - direction = nextIndex > self.getCurrentIndex() ? "next" : "prev"; - } - if (nextSlide && nextSlide !== self.currentSlide && !$scope.$currentTransition) { - goNext(nextSlide, nextIndex, direction); - } - }; - function goNext(slide, index, direction) { - if (destroyed) { - return; - } - angular.extend(slide, { - direction: direction, - active: true - }); - angular.extend(self.currentSlide || {}, { - direction: direction, - active: false - }); - if ($animate.enabled() && !$scope.noTransition && !$scope.$currentTransition && slide.$element && self.slides.length > 1) { - slide.$element.data(SLIDE_DIRECTION, slide.direction); - if (self.currentSlide && self.currentSlide.$element) { - self.currentSlide.$element.data(SLIDE_DIRECTION, slide.direction); + function Scope() { + this.$id = nextUid(); + this.$$phase = this.$parent = this.$$watchers = this.$$nextSibling = this.$$prevSibling = this.$$childHead = this.$$childTail = null; + this.$root = this; + this.$$destroyed = false; + this.$$listeners = {}; + this.$$listenerCount = {}; + this.$$watchersCount = 0; + this.$$isolateBindings = null; } - $scope.$currentTransition = true; - if (NEW_ANIMATE) { - $animate.on("addClass", slide.$element, function(element, phase) { - if (phase === "close") { - $scope.$currentTransition = null; - $animate.off("addClass", element); + Scope.prototype = { + constructor: Scope, + $new: function(isolate, parent) { + var child; + parent = parent || this; + if (isolate) { + child = new Scope(); + child.$root = this.$root; + } else { + if (!this.$$ChildScope) { + this.$$ChildScope = createChildScopeClass(this); + } + child = new this.$$ChildScope(); } - }); - } else { - slide.$element.one("$animate:close", function closeFn() { - $scope.$currentTransition = null; - }); - } - } - self.currentSlide = slide; - currentIndex = index; - restartTimer(); - } - $scope.$on("$destroy", function() { - destroyed = true; - }); - function getSlideByIndex(index) { - if (angular.isUndefined(slides[index].index)) { - return slides[index]; - } - var i, len = slides.length; - for (i = 0; i < slides.length; ++i) { - if (slides[i].index == index) { - return slides[i]; - } - } - } - self.getCurrentIndex = function() { - if (self.currentSlide && angular.isDefined(self.currentSlide.index)) { - return +self.currentSlide.index; - } - return currentIndex; - }; - $scope.indexOfSlide = function(slide) { - return angular.isDefined(slide.index) ? +slide.index : slides.indexOf(slide); - }; - $scope.next = function() { - var newIndex = (self.getCurrentIndex() + 1) % slides.length; - if (newIndex === 0 && $scope.noWrap()) { - $scope.pause(); - return; - } - return self.select(getSlideByIndex(newIndex), "next"); - }; - $scope.prev = function() { - var newIndex = self.getCurrentIndex() - 1 < 0 ? slides.length - 1 : self.getCurrentIndex() - 1; - if ($scope.noWrap() && newIndex === slides.length - 1) { - $scope.pause(); - return; - } - return self.select(getSlideByIndex(newIndex), "prev"); - }; - $scope.isActive = function(slide) { - return self.currentSlide === slide; - }; - $scope.$watch("interval", restartTimer); - $scope.$on("$destroy", resetTimer); - function restartTimer() { - resetTimer(); - var interval = +$scope.interval; - if (!isNaN(interval) && interval > 0) { - currentInterval = $interval(timerFn, interval); - } - } - function resetTimer() { - if (currentInterval) { - $interval.cancel(currentInterval); - currentInterval = null; - } - } - function timerFn() { - var interval = +$scope.interval; - if (isPlaying && !isNaN(interval) && interval > 0 && slides.length) { - $scope.next(); - } else { - $scope.pause(); - } - } - $scope.play = function() { - if (!isPlaying) { - isPlaying = true; - restartTimer(); - } - }; - $scope.pause = function() { - if (!$scope.noPause) { - isPlaying = false; - resetTimer(); - } - }; - self.addSlide = function(slide, element) { - slide.$element = element; - slides.push(slide); - if (slides.length === 1 || slide.active) { - self.select(slides[slides.length - 1]); - if (slides.length == 1) { - $scope.play(); - } - } else { - slide.active = false; - } - }; - self.removeSlide = function(slide) { - if (angular.isDefined(slide.index)) { - slides.sort(function(a, b) { - return +a.index > +b.index; - }); - } - var index = slides.indexOf(slide); - slides.splice(index, 1); - if (slides.length > 0 && slide.active) { - if (index >= slides.length) { - self.select(slides[index - 1]); - } else { - self.select(slides[index]); - } - } else if (currentIndex > index) { - currentIndex--; - } - if (slides.length === 0) { - self.currentSlide = null; - } - }; - $scope.$watch("noTransition", function(noTransition) { - $element.data(NO_TRANSITION, noTransition); - }); -} ]).directive("carousel", [ function() { - return { - restrict: "EA", - transclude: true, - replace: true, - controller: "CarouselController", - controllerAs: "carousel", - require: "carousel", - templateUrl: function(element, attrs) { - return attrs.templateUrl || "template/carousel/carousel.html"; - }, - scope: { - interval: "=", - noTransition: "=", - noPause: "=", - noWrap: "&" - } - }; -} ]).directive("slide", function() { - return { - require: "^carousel", - restrict: "EA", - transclude: true, - replace: true, - templateUrl: function(element, attrs) { - return attrs.templateUrl || "template/carousel/slide.html"; - }, - scope: { - active: "=?", - actual: "=?", - index: "=?" - }, - link: function(scope, element, attrs, carouselCtrl) { - carouselCtrl.addSlide(scope, element); - scope.$on("$destroy", function() { - carouselCtrl.removeSlide(scope); - }); - scope.$watch("active", function(active) { - if (active) { - carouselCtrl.select(scope); - } - }); - } - }; -}).animation(".item", [ "$injector", "$animate", function($injector, $animate) { - var NO_TRANSITION = "uib-noTransition", SLIDE_DIRECTION = "uib-slideDirection", $animateCss = null; - if ($injector.has("$animateCss")) { - $animateCss = $injector.get("$animateCss"); - } - function removeClass(element, className, callback) { - element.removeClass(className); - if (callback) { - callback(); - } - } - return { - beforeAddClass: function(element, className, done) { - if (className == "active" && element.parent() && !element.parent().data(NO_TRANSITION)) { - var stopped = false; - var direction = element.data(SLIDE_DIRECTION); - var directionClass = direction == "next" ? "left" : "right"; - var removeClassFn = removeClass.bind(this, element, directionClass + " " + direction, done); - element.addClass(direction); - if ($animateCss) { - $animateCss(element, { - addClass: directionClass - }).start().done(removeClassFn); - } else { - $animate.addClass(element, directionClass).then(function() { - if (!stopped) { - removeClassFn(); + child.$parent = parent; + child.$$prevSibling = parent.$$childTail; + if (parent.$$childHead) { + parent.$$childTail.$$nextSibling = child; + parent.$$childTail = child; + } else { + parent.$$childHead = parent.$$childTail = child; + } + if (isolate || parent != this) child.$on("$destroy", destroyChildScope); + return child; + }, + $watch: function(watchExp, listener, objectEquality, prettyPrintExpression) { + var get = $parse(watchExp); + if (get.$$watchDelegate) { + return get.$$watchDelegate(this, listener, objectEquality, get, watchExp); + } + var scope = this, array = scope.$$watchers, watcher = { + fn: listener, + last: initWatchVal, + get: get, + exp: prettyPrintExpression || watchExp, + eq: !!objectEquality + }; + lastDirtyWatch = null; + if (!isFunction(listener)) { + watcher.fn = noop; + } + if (!array) { + array = scope.$$watchers = []; + } + array.unshift(watcher); + incrementWatchersCount(this, 1); + return function deregisterWatch() { + if (arrayRemove(array, watcher) >= 0) { + incrementWatchersCount(scope, -1); } - done(); + lastDirtyWatch = null; + }; + }, + $watchGroup: function(watchExpressions, listener) { + var oldValues = new Array(watchExpressions.length); + var newValues = new Array(watchExpressions.length); + var deregisterFns = []; + var self = this; + var changeReactionScheduled = false; + var firstRun = true; + if (!watchExpressions.length) { + var shouldCall = true; + self.$evalAsync(function() { + if (shouldCall) listener(newValues, newValues, self); + }); + return function deregisterWatchGroup() { + shouldCall = false; + }; + } + if (watchExpressions.length === 1) { + return this.$watch(watchExpressions[0], function watchGroupAction(value, oldValue, scope) { + newValues[0] = value; + oldValues[0] = oldValue; + listener(newValues, value === oldValue ? newValues : oldValues, scope); + }); + } + forEach(watchExpressions, function(expr, i) { + var unwatchFn = self.$watch(expr, function watchGroupSubAction(value, oldValue) { + newValues[i] = value; + oldValues[i] = oldValue; + if (!changeReactionScheduled) { + changeReactionScheduled = true; + self.$evalAsync(watchGroupAction); + } + }); + deregisterFns.push(unwatchFn); }); - } - return function() { - stopped = true; - }; - } - done(); - }, - beforeRemoveClass: function(element, className, done) { - if (className === "active" && element.parent() && !element.parent().data(NO_TRANSITION)) { - var stopped = false; - var direction = element.data(SLIDE_DIRECTION); - var directionClass = direction == "next" ? "left" : "right"; - var removeClassFn = removeClass.bind(this, element, directionClass, done); - if ($animateCss) { - $animateCss(element, { - addClass: directionClass - }).start().done(removeClassFn); - } else { - $animate.addClass(element, directionClass).then(function() { - if (!stopped) { - removeClassFn(); + function watchGroupAction() { + changeReactionScheduled = false; + if (firstRun) { + firstRun = false; + listener(newValues, newValues, self); + } else { + listener(newValues, oldValues, self); } - done(); - }); - } - return function() { - stopped = true; - }; - } - done(); - } - }; -} ]); - -angular.module("ui.bootstrap.dateparser", []).service("dateParser", [ "$log", "$locale", "orderByFilter", function($log, $locale, orderByFilter) { - var SPECIAL_CHARACTERS_REGEXP = /[\\\^\$\*\+\?\|\[\]\(\)\.\{\}]/g; - this.parsers = {}; - var formatCodeToRegex = { - yyyy: { - regex: "\\d{4}", - apply: function(value) { - this.year = +value; - } - }, - yy: { - regex: "\\d{2}", - apply: function(value) { - this.year = +value + 2e3; - } - }, - y: { - regex: "\\d{1,4}", - apply: function(value) { - this.year = +value; - } - }, - MMMM: { - regex: $locale.DATETIME_FORMATS.MONTH.join("|"), - apply: function(value) { - this.month = $locale.DATETIME_FORMATS.MONTH.indexOf(value); - } - }, - MMM: { - regex: $locale.DATETIME_FORMATS.SHORTMONTH.join("|"), - apply: function(value) { - this.month = $locale.DATETIME_FORMATS.SHORTMONTH.indexOf(value); - } - }, - MM: { - regex: "0[1-9]|1[0-2]", - apply: function(value) { - this.month = value - 1; - } - }, - M: { - regex: "[1-9]|1[0-2]", - apply: function(value) { - this.month = value - 1; - } - }, - dd: { - regex: "[0-2][0-9]{1}|3[0-1]{1}", - apply: function(value) { - this.date = +value; - } - }, - d: { - regex: "[1-2]?[0-9]{1}|3[0-1]{1}", - apply: function(value) { - this.date = +value; - } - }, - EEEE: { - regex: $locale.DATETIME_FORMATS.DAY.join("|") - }, - EEE: { - regex: $locale.DATETIME_FORMATS.SHORTDAY.join("|") - }, - HH: { - regex: "(?:0|1)[0-9]|2[0-3]", - apply: function(value) { - this.hours = +value; - } - }, - hh: { - regex: "0[0-9]|1[0-2]", - apply: function(value) { - this.hours = +value; - } - }, - H: { - regex: "1?[0-9]|2[0-3]", - apply: function(value) { - this.hours = +value; - } - }, - h: { - regex: "[0-9]|1[0-2]", - apply: function(value) { - this.hours = +value; - } - }, - mm: { - regex: "[0-5][0-9]", - apply: function(value) { - this.minutes = +value; - } - }, - m: { - regex: "[0-9]|[1-5][0-9]", - apply: function(value) { - this.minutes = +value; - } - }, - sss: { - regex: "[0-9][0-9][0-9]", - apply: function(value) { - this.milliseconds = +value; - } - }, - ss: { - regex: "[0-5][0-9]", - apply: function(value) { - this.seconds = +value; - } - }, - s: { - regex: "[0-9]|[1-5][0-9]", - apply: function(value) { - this.seconds = +value; - } - }, - a: { - regex: $locale.DATETIME_FORMATS.AMPMS.join("|"), - apply: function(value) { - if (this.hours === 12) { - this.hours = 0; - } - if (value === "PM") { - this.hours += 12; - } - } - } - }; - function createParser(format) { - var map = [], regex = format.split(""); - angular.forEach(formatCodeToRegex, function(data, code) { - var index = format.indexOf(code); - if (index > -1) { - format = format.split(""); - regex[index] = "(" + data.regex + ")"; - format[index] = "$"; - for (var i = index + 1, n = index + code.length; i < n; i++) { - regex[i] = ""; - format[i] = "$"; - } - format = format.join(""); - map.push({ - index: index, - apply: data.apply - }); - } - }); - return { - regex: new RegExp("^" + regex.join("") + "$"), - map: orderByFilter(map, "index") - }; - } - this.parse = function(input, format, baseDate) { - if (!angular.isString(input) || !format) { - return input; - } - format = $locale.DATETIME_FORMATS[format] || format; - format = format.replace(SPECIAL_CHARACTERS_REGEXP, "\\$&"); - if (!this.parsers[format]) { - this.parsers[format] = createParser(format); - } - var parser = this.parsers[format], regex = parser.regex, map = parser.map, results = input.match(regex); - if (results && results.length) { - var fields, dt; - if (angular.isDate(baseDate) && !isNaN(baseDate.getTime())) { - fields = { - year: baseDate.getFullYear(), - month: baseDate.getMonth(), - date: baseDate.getDate(), - hours: baseDate.getHours(), - minutes: baseDate.getMinutes(), - seconds: baseDate.getSeconds(), - milliseconds: baseDate.getMilliseconds() - }; - } else { - if (baseDate) { - $log.warn("dateparser:", "baseDate is not a valid date"); - } - fields = { - year: 1900, - month: 0, - date: 1, - hours: 0, - minutes: 0, - seconds: 0, - milliseconds: 0 - }; - } - for (var i = 1, n = results.length; i < n; i++) { - var mapper = map[i - 1]; - if (mapper.apply) { - mapper.apply.call(fields, results[i]); - } - } - if (isValid(fields.year, fields.month, fields.date)) { - dt = new Date(fields.year, fields.month, fields.date, fields.hours, fields.minutes, fields.seconds, fields.milliseconds || 0); - } - return dt; - } - }; - function isValid(year, month, date) { - if (date < 1) { - return false; - } - if (month === 1 && date > 28) { - return date === 29 && (year % 4 === 0 && year % 100 !== 0 || year % 400 === 0); - } - if (month === 3 || month === 5 || month === 8 || month === 10) { - return date < 31; - } - return true; - } -} ]); - -angular.module("ui.bootstrap.position", []).factory("$position", [ "$document", "$window", function($document, $window) { - function getStyle(el, cssprop) { - if (el.currentStyle) { - return el.currentStyle[cssprop]; - } else if ($window.getComputedStyle) { - return $window.getComputedStyle(el)[cssprop]; - } - return el.style[cssprop]; - } - function isStaticPositioned(element) { - return (getStyle(element, "position") || "static") === "static"; - } - var parentOffsetEl = function(element) { - var docDomEl = $document[0]; - var offsetParent = element.offsetParent || docDomEl; - while (offsetParent && offsetParent !== docDomEl && isStaticPositioned(offsetParent)) { - offsetParent = offsetParent.offsetParent; - } - return offsetParent || docDomEl; - }; - return { - position: function(element) { - var elBCR = this.offset(element); - var offsetParentBCR = { - top: 0, - left: 0 - }; - var offsetParentEl = parentOffsetEl(element[0]); - if (offsetParentEl != $document[0]) { - offsetParentBCR = this.offset(angular.element(offsetParentEl)); - offsetParentBCR.top += offsetParentEl.clientTop - offsetParentEl.scrollTop; - offsetParentBCR.left += offsetParentEl.clientLeft - offsetParentEl.scrollLeft; - } - var boundingClientRect = element[0].getBoundingClientRect(); - return { - width: boundingClientRect.width || element.prop("offsetWidth"), - height: boundingClientRect.height || element.prop("offsetHeight"), - top: elBCR.top - offsetParentBCR.top, - left: elBCR.left - offsetParentBCR.left - }; - }, - offset: function(element) { - var boundingClientRect = element[0].getBoundingClientRect(); - return { - width: boundingClientRect.width || element.prop("offsetWidth"), - height: boundingClientRect.height || element.prop("offsetHeight"), - top: boundingClientRect.top + ($window.pageYOffset || $document[0].documentElement.scrollTop), - left: boundingClientRect.left + ($window.pageXOffset || $document[0].documentElement.scrollLeft) - }; - }, - positionElements: function(hostEl, targetEl, positionStr, appendToBody) { - var positionStrParts = positionStr.split("-"); - var pos0 = positionStrParts[0], pos1 = positionStrParts[1] || "center"; - var hostElPos, targetElWidth, targetElHeight, targetElPos; - hostElPos = appendToBody ? this.offset(hostEl) : this.position(hostEl); - targetElWidth = targetEl.prop("offsetWidth"); - targetElHeight = targetEl.prop("offsetHeight"); - var shiftWidth = { - center: function() { - return hostElPos.left + hostElPos.width / 2 - targetElWidth / 2; - }, - left: function() { - return hostElPos.left; - }, - right: function() { - return hostElPos.left + hostElPos.width; - } - }; - var shiftHeight = { - center: function() { - return hostElPos.top + hostElPos.height / 2 - targetElHeight / 2; - }, - top: function() { - return hostElPos.top; + } + return function deregisterWatchGroup() { + while (deregisterFns.length) { + deregisterFns.shift()(); + } + }; }, - bottom: function() { - return hostElPos.top + hostElPos.height; - } - }; - switch (pos0) { - case "right": - targetElPos = { - top: shiftHeight[pos1](), - left: shiftWidth[pos0]() - }; - break; - - case "left": - targetElPos = { - top: shiftHeight[pos1](), - left: hostElPos.left - targetElWidth - }; - break; - - case "bottom": - targetElPos = { - top: shiftHeight[pos0](), - left: shiftWidth[pos1]() - }; - break; + $watchCollection: function(obj, listener) { + $watchCollectionInterceptor.$stateful = true; + var self = this; + var newValue; + var oldValue; + var veryOldValue; + var trackVeryOldValue = listener.length > 1; + var changeDetected = 0; + var changeDetector = $parse(obj, $watchCollectionInterceptor); + var internalArray = []; + var internalObject = {}; + var initRun = true; + var oldLength = 0; + function $watchCollectionInterceptor(_value) { + newValue = _value; + var newLength, key, bothNaN, newItem, oldItem; + if (isUndefined(newValue)) return; + if (!isObject(newValue)) { + if (oldValue !== newValue) { + oldValue = newValue; + changeDetected++; + } + } else if (isArrayLike(newValue)) { + if (oldValue !== internalArray) { + oldValue = internalArray; + oldLength = oldValue.length = 0; + changeDetected++; + } + newLength = newValue.length; + if (oldLength !== newLength) { + changeDetected++; + oldValue.length = oldLength = newLength; + } + for (var i = 0; i < newLength; i++) { + oldItem = oldValue[i]; + newItem = newValue[i]; + bothNaN = oldItem !== oldItem && newItem !== newItem; + if (!bothNaN && oldItem !== newItem) { + changeDetected++; + oldValue[i] = newItem; + } + } + } else { + if (oldValue !== internalObject) { + oldValue = internalObject = {}; + oldLength = 0; + changeDetected++; + } + newLength = 0; + for (key in newValue) { + if (hasOwnProperty.call(newValue, key)) { + newLength++; + newItem = newValue[key]; + oldItem = oldValue[key]; + if (key in oldValue) { + bothNaN = oldItem !== oldItem && newItem !== newItem; + if (!bothNaN && oldItem !== newItem) { + changeDetected++; + oldValue[key] = newItem; + } + } else { + oldLength++; + oldValue[key] = newItem; + changeDetected++; + } + } + } + if (oldLength > newLength) { + changeDetected++; + for (key in oldValue) { + if (!hasOwnProperty.call(newValue, key)) { + oldLength--; + delete oldValue[key]; + } + } + } + } + return changeDetected; + } + function $watchCollectionAction() { + if (initRun) { + initRun = false; + listener(newValue, newValue, self); + } else { + listener(newValue, veryOldValue, self); + } + if (trackVeryOldValue) { + if (!isObject(newValue)) { + veryOldValue = newValue; + } else if (isArrayLike(newValue)) { + veryOldValue = new Array(newValue.length); + for (var i = 0; i < newValue.length; i++) { + veryOldValue[i] = newValue[i]; + } + } else { + veryOldValue = {}; + for (var key in newValue) { + if (hasOwnProperty.call(newValue, key)) { + veryOldValue[key] = newValue[key]; + } + } + } + } + } + return this.$watch(changeDetector, $watchCollectionAction); + }, + $digest: function() { + var watch, value, last, watchers, length, dirty, ttl = TTL, next, current, target = this, watchLog = [], logIdx, logMsg, asyncTask; + beginPhase("$digest"); + $browser.$$checkUrlChange(); + if (this === $rootScope && applyAsyncId !== null) { + $browser.defer.cancel(applyAsyncId); + flushApplyAsync(); + } + lastDirtyWatch = null; + do { + dirty = false; + current = target; + while (asyncQueue.length) { + try { + asyncTask = asyncQueue.shift(); + asyncTask.scope.$eval(asyncTask.expression, asyncTask.locals); + } catch (e) { + $exceptionHandler(e); + } + lastDirtyWatch = null; + } + traverseScopesLoop: do { + if (watchers = current.$$watchers) { + length = watchers.length; + while (length--) { + try { + watch = watchers[length]; + if (watch) { + if ((value = watch.get(current)) !== (last = watch.last) && !(watch.eq ? equals(value, last) : typeof value === "number" && typeof last === "number" && isNaN(value) && isNaN(last))) { + dirty = true; + lastDirtyWatch = watch; + watch.last = watch.eq ? copy(value, null) : value; + watch.fn(value, last === initWatchVal ? value : last, current); + if (ttl < 5) { + logIdx = 4 - ttl; + if (!watchLog[logIdx]) watchLog[logIdx] = []; + watchLog[logIdx].push({ + msg: isFunction(watch.exp) ? "fn: " + (watch.exp.name || watch.exp.toString()) : watch.exp, + newVal: value, + oldVal: last + }); + } + } else if (watch === lastDirtyWatch) { + dirty = false; + break traverseScopesLoop; + } + } + } catch (e) { + $exceptionHandler(e); + } + } + } + if (!(next = current.$$watchersCount && current.$$childHead || current !== target && current.$$nextSibling)) { + while (current !== target && !(next = current.$$nextSibling)) { + current = current.$parent; + } + } + } while (current = next); + if ((dirty || asyncQueue.length) && !ttl--) { + clearPhase(); + throw $rootScopeMinErr("infdig", "{0} $digest() iterations reached. Aborting!\n" + "Watchers fired in the last 5 iterations: {1}", TTL, watchLog); + } + } while (dirty || asyncQueue.length); + clearPhase(); + while (postDigestQueue.length) { + try { + postDigestQueue.shift()(); + } catch (e) { + $exceptionHandler(e); + } + } + }, + $destroy: function() { + if (this.$$destroyed) return; + var parent = this.$parent; + this.$broadcast("$destroy"); + this.$$destroyed = true; + if (this === $rootScope) { + $browser.$$applicationDestroyed(); + } + incrementWatchersCount(this, -this.$$watchersCount); + for (var eventName in this.$$listenerCount) { + decrementListenerCount(this, this.$$listenerCount[eventName], eventName); + } + if (parent && parent.$$childHead == this) parent.$$childHead = this.$$nextSibling; + if (parent && parent.$$childTail == this) parent.$$childTail = this.$$prevSibling; + if (this.$$prevSibling) this.$$prevSibling.$$nextSibling = this.$$nextSibling; + if (this.$$nextSibling) this.$$nextSibling.$$prevSibling = this.$$prevSibling; + this.$destroy = this.$digest = this.$apply = this.$evalAsync = this.$applyAsync = noop; + this.$on = this.$watch = this.$watchGroup = function() { + return noop; + }; + this.$$listeners = {}; + this.$parent = this.$$nextSibling = this.$$prevSibling = this.$$childHead = this.$$childTail = this.$root = this.$$watchers = null; + }, + $eval: function(expr, locals) { + return $parse(expr)(this, locals); + }, + $evalAsync: function(expr, locals) { + if (!$rootScope.$$phase && !asyncQueue.length) { + $browser.defer(function() { + if (asyncQueue.length) { + $rootScope.$digest(); + } + }); + } + asyncQueue.push({ + scope: this, + expression: expr, + locals: locals + }); + }, + $$postDigest: function(fn) { + postDigestQueue.push(fn); + }, + $apply: function(expr) { + try { + beginPhase("$apply"); + try { + return this.$eval(expr); + } finally { + clearPhase(); + } + } catch (e) { + $exceptionHandler(e); + } finally { + try { + $rootScope.$digest(); + } catch (e) { + $exceptionHandler(e); + throw e; + } + } + }, + $applyAsync: function(expr) { + var scope = this; + expr && applyAsyncQueue.push($applyAsyncExpression); + scheduleApplyAsync(); + function $applyAsyncExpression() { + scope.$eval(expr); + } + }, + $on: function(name, listener) { + var namedListeners = this.$$listeners[name]; + if (!namedListeners) { + this.$$listeners[name] = namedListeners = []; + } + namedListeners.push(listener); + var current = this; + do { + if (!current.$$listenerCount[name]) { + current.$$listenerCount[name] = 0; + } + current.$$listenerCount[name]++; + } while (current = current.$parent); + var self = this; + return function() { + var indexOfListener = namedListeners.indexOf(listener); + if (indexOfListener !== -1) { + namedListeners[indexOfListener] = null; + decrementListenerCount(self, 1, name); + } + }; + }, + $emit: function(name, args) { + var empty = [], namedListeners, scope = this, stopPropagation = false, event = { + name: name, + targetScope: scope, + stopPropagation: function() { + stopPropagation = true; + }, + preventDefault: function() { + event.defaultPrevented = true; + }, + defaultPrevented: false + }, listenerArgs = concat([ event ], arguments, 1), i, length; + do { + namedListeners = scope.$$listeners[name] || empty; + event.currentScope = scope; + for (i = 0, length = namedListeners.length; i < length; i++) { + if (!namedListeners[i]) { + namedListeners.splice(i, 1); + i--; + length--; + continue; + } + try { + namedListeners[i].apply(null, listenerArgs); + } catch (e) { + $exceptionHandler(e); + } + } + if (stopPropagation) { + event.currentScope = null; + return event; + } + scope = scope.$parent; + } while (scope); + event.currentScope = null; + return event; + }, + $broadcast: function(name, args) { + var target = this, current = target, next = target, event = { + name: name, + targetScope: target, + preventDefault: function() { + event.defaultPrevented = true; + }, + defaultPrevented: false + }; + if (!target.$$listenerCount[name]) return event; + var listenerArgs = concat([ event ], arguments, 1), listeners, i, length; + while (current = next) { + event.currentScope = current; + listeners = current.$$listeners[name] || []; + for (i = 0, length = listeners.length; i < length; i++) { + if (!listeners[i]) { + listeners.splice(i, 1); + i--; + length--; + continue; + } + try { + listeners[i].apply(null, listenerArgs); + } catch (e) { + $exceptionHandler(e); + } + } + if (!(next = current.$$listenerCount[name] && current.$$childHead || current !== target && current.$$nextSibling)) { + while (current !== target && !(next = current.$$nextSibling)) { + current = current.$parent; + } + } + } + event.currentScope = null; + return event; + } + }; + var $rootScope = new Scope(); + var asyncQueue = $rootScope.$$asyncQueue = []; + var postDigestQueue = $rootScope.$$postDigestQueue = []; + var applyAsyncQueue = $rootScope.$$applyAsyncQueue = []; + return $rootScope; + function beginPhase(phase) { + if ($rootScope.$$phase) { + throw $rootScopeMinErr("inprog", "{0} already in progress", $rootScope.$$phase); + } + $rootScope.$$phase = phase; + } + function clearPhase() { + $rootScope.$$phase = null; + } + function incrementWatchersCount(current, count) { + do { + current.$$watchersCount += count; + } while (current = current.$parent); + } + function decrementListenerCount(current, count, name) { + do { + current.$$listenerCount[name] -= count; + if (current.$$listenerCount[name] === 0) { + delete current.$$listenerCount[name]; + } + } while (current = current.$parent); + } + function initWatchVal() {} + function flushApplyAsync() { + while (applyAsyncQueue.length) { + try { + applyAsyncQueue.shift()(); + } catch (e) { + $exceptionHandler(e); + } + } + applyAsyncId = null; + } + function scheduleApplyAsync() { + if (applyAsyncId === null) { + applyAsyncId = $browser.defer(function() { + $rootScope.$apply(flushApplyAsync); + }); + } + } + } ]; + } + function $$SanitizeUriProvider() { + var aHrefSanitizationWhitelist = /^\s*(https?|ftp|mailto|tel|file):/, imgSrcSanitizationWhitelist = /^\s*((https?|ftp|file|blob):|data:image\/)/; + this.aHrefSanitizationWhitelist = function(regexp) { + if (isDefined(regexp)) { + aHrefSanitizationWhitelist = regexp; + return this; + } + return aHrefSanitizationWhitelist; + }; + this.imgSrcSanitizationWhitelist = function(regexp) { + if (isDefined(regexp)) { + imgSrcSanitizationWhitelist = regexp; + return this; + } + return imgSrcSanitizationWhitelist; + }; + this.$get = function() { + return function sanitizeUri(uri, isImage) { + var regex = isImage ? imgSrcSanitizationWhitelist : aHrefSanitizationWhitelist; + var normalizedVal; + normalizedVal = urlResolve(uri).href; + if (normalizedVal !== "" && !normalizedVal.match(regex)) { + return "unsafe:" + normalizedVal; + } + return uri; + }; + }; + } + var $sceMinErr = minErr("$sce"); + var SCE_CONTEXTS = { + HTML: "html", + CSS: "css", + URL: "url", + RESOURCE_URL: "resourceUrl", + JS: "js" + }; + function adjustMatcher(matcher) { + if (matcher === "self") { + return matcher; + } else if (isString(matcher)) { + if (matcher.indexOf("***") > -1) { + throw $sceMinErr("iwcard", "Illegal sequence *** in string matcher. String: {0}", matcher); + } + matcher = escapeForRegexp(matcher).replace("\\*\\*", ".*").replace("\\*", "[^:/.?&;]*"); + return new RegExp("^" + matcher + "$"); + } else if (isRegExp(matcher)) { + return new RegExp("^" + matcher.source + "$"); + } else { + throw $sceMinErr("imatcher", 'Matchers may only be "self", string patterns or RegExp objects'); + } + } + function adjustMatchers(matchers) { + var adjustedMatchers = []; + if (isDefined(matchers)) { + forEach(matchers, function(matcher) { + adjustedMatchers.push(adjustMatcher(matcher)); + }); + } + return adjustedMatchers; + } + function $SceDelegateProvider() { + this.SCE_CONTEXTS = SCE_CONTEXTS; + var resourceUrlWhitelist = [ "self" ], resourceUrlBlacklist = []; + this.resourceUrlWhitelist = function(value) { + if (arguments.length) { + resourceUrlWhitelist = adjustMatchers(value); + } + return resourceUrlWhitelist; + }; + this.resourceUrlBlacklist = function(value) { + if (arguments.length) { + resourceUrlBlacklist = adjustMatchers(value); + } + return resourceUrlBlacklist; + }; + this.$get = [ "$injector", function($injector) { + var htmlSanitizer = function htmlSanitizer(html) { + throw $sceMinErr("unsafe", "Attempting to use an unsafe value in a safe context."); + }; + if ($injector.has("$sanitize")) { + htmlSanitizer = $injector.get("$sanitize"); + } + function matchUrl(matcher, parsedUrl) { + if (matcher === "self") { + return urlIsSameOrigin(parsedUrl); + } else { + return !!matcher.exec(parsedUrl.href); + } + } + function isResourceUrlAllowedByPolicy(url) { + var parsedUrl = urlResolve(url.toString()); + var i, n, allowed = false; + for (i = 0, n = resourceUrlWhitelist.length; i < n; i++) { + if (matchUrl(resourceUrlWhitelist[i], parsedUrl)) { + allowed = true; + break; + } + } + if (allowed) { + for (i = 0, n = resourceUrlBlacklist.length; i < n; i++) { + if (matchUrl(resourceUrlBlacklist[i], parsedUrl)) { + allowed = false; + break; + } + } + } + return allowed; + } + function generateHolderType(Base) { + var holderType = function TrustedValueHolderType(trustedValue) { + this.$$unwrapTrustedValue = function() { + return trustedValue; + }; + }; + if (Base) { + holderType.prototype = new Base(); + } + holderType.prototype.valueOf = function sceValueOf() { + return this.$$unwrapTrustedValue(); + }; + holderType.prototype.toString = function sceToString() { + return this.$$unwrapTrustedValue().toString(); + }; + return holderType; + } + var trustedValueHolderBase = generateHolderType(), byType = {}; + byType[SCE_CONTEXTS.HTML] = generateHolderType(trustedValueHolderBase); + byType[SCE_CONTEXTS.CSS] = generateHolderType(trustedValueHolderBase); + byType[SCE_CONTEXTS.URL] = generateHolderType(trustedValueHolderBase); + byType[SCE_CONTEXTS.JS] = generateHolderType(trustedValueHolderBase); + byType[SCE_CONTEXTS.RESOURCE_URL] = generateHolderType(byType[SCE_CONTEXTS.URL]); + function trustAs(type, trustedValue) { + var Constructor = byType.hasOwnProperty(type) ? byType[type] : null; + if (!Constructor) { + throw $sceMinErr("icontext", "Attempted to trust a value in invalid context. Context: {0}; Value: {1}", type, trustedValue); + } + if (trustedValue === null || isUndefined(trustedValue) || trustedValue === "") { + return trustedValue; + } + if (typeof trustedValue !== "string") { + throw $sceMinErr("itype", "Attempted to trust a non-string value in a content requiring a string: Context: {0}", type); + } + return new Constructor(trustedValue); + } + function valueOf(maybeTrusted) { + if (maybeTrusted instanceof trustedValueHolderBase) { + return maybeTrusted.$$unwrapTrustedValue(); + } else { + return maybeTrusted; + } + } + function getTrusted(type, maybeTrusted) { + if (maybeTrusted === null || isUndefined(maybeTrusted) || maybeTrusted === "") { + return maybeTrusted; + } + var constructor = byType.hasOwnProperty(type) ? byType[type] : null; + if (constructor && maybeTrusted instanceof constructor) { + return maybeTrusted.$$unwrapTrustedValue(); + } + if (type === SCE_CONTEXTS.RESOURCE_URL) { + if (isResourceUrlAllowedByPolicy(maybeTrusted)) { + return maybeTrusted; + } else { + throw $sceMinErr("insecurl", "Blocked loading resource from url not allowed by $sceDelegate policy. URL: {0}", maybeTrusted.toString()); + } + } else if (type === SCE_CONTEXTS.HTML) { + return htmlSanitizer(maybeTrusted); + } + throw $sceMinErr("unsafe", "Attempting to use an unsafe value in a safe context."); + } + return { + trustAs: trustAs, + getTrusted: getTrusted, + valueOf: valueOf + }; + } ]; + } + function $SceProvider() { + var enabled = true; + this.enabled = function(value) { + if (arguments.length) { + enabled = !!value; + } + return enabled; + }; + this.$get = [ "$parse", "$sceDelegate", function($parse, $sceDelegate) { + if (enabled && msie < 8) { + throw $sceMinErr("iequirks", "Strict Contextual Escaping does not support Internet Explorer version < 11 in quirks " + "mode. You can fix this by adding the text to the top of your HTML " + "document. See http://docs.angularjs.org/api/ng.$sce for more information."); + } + var sce = shallowCopy(SCE_CONTEXTS); + sce.isEnabled = function() { + return enabled; + }; + sce.trustAs = $sceDelegate.trustAs; + sce.getTrusted = $sceDelegate.getTrusted; + sce.valueOf = $sceDelegate.valueOf; + if (!enabled) { + sce.trustAs = sce.getTrusted = function(type, value) { + return value; + }; + sce.valueOf = identity; + } + sce.parseAs = function sceParseAs(type, expr) { + var parsed = $parse(expr); + if (parsed.literal && parsed.constant) { + return parsed; + } else { + return $parse(expr, function(value) { + return sce.getTrusted(type, value); + }); + } + }; + var parse = sce.parseAs, getTrusted = sce.getTrusted, trustAs = sce.trustAs; + forEach(SCE_CONTEXTS, function(enumValue, name) { + var lName = lowercase(name); + sce[camelCase("parse_as_" + lName)] = function(expr) { + return parse(enumValue, expr); + }; + sce[camelCase("get_trusted_" + lName)] = function(value) { + return getTrusted(enumValue, value); + }; + sce[camelCase("trust_as_" + lName)] = function(value) { + return trustAs(enumValue, value); + }; + }); + return sce; + } ]; + } + function $SnifferProvider() { + this.$get = [ "$window", "$document", function($window, $document) { + var eventSupport = {}, android = toInt((/android (\d+)/.exec(lowercase(($window.navigator || {}).userAgent)) || [])[1]), boxee = /Boxee/i.test(($window.navigator || {}).userAgent), document = $document[0] || {}, vendorPrefix, vendorRegex = /^(Moz|webkit|ms)(?=[A-Z])/, bodyStyle = document.body && document.body.style, transitions = false, animations = false, match; + if (bodyStyle) { + for (var prop in bodyStyle) { + if (match = vendorRegex.exec(prop)) { + vendorPrefix = match[0]; + vendorPrefix = vendorPrefix.substr(0, 1).toUpperCase() + vendorPrefix.substr(1); + break; + } + } + if (!vendorPrefix) { + vendorPrefix = "WebkitOpacity" in bodyStyle && "webkit"; + } + transitions = !!("transition" in bodyStyle || vendorPrefix + "Transition" in bodyStyle); + animations = !!("animation" in bodyStyle || vendorPrefix + "Animation" in bodyStyle); + if (android && (!transitions || !animations)) { + transitions = isString(bodyStyle.webkitTransition); + animations = isString(bodyStyle.webkitAnimation); + } + } + return { + history: !!($window.history && $window.history.pushState && !(android < 4) && !boxee), + hasEvent: function(event) { + if (event === "input" && msie <= 11) return false; + if (isUndefined(eventSupport[event])) { + var divElm = document.createElement("div"); + eventSupport[event] = "on" + event in divElm; + } + return eventSupport[event]; + }, + csp: csp(), + vendorPrefix: vendorPrefix, + transitions: transitions, + animations: animations, + android: android + }; + } ]; + } + var $compileMinErr = minErr("$compile"); + function $TemplateRequestProvider() { + this.$get = [ "$templateCache", "$http", "$q", "$sce", function($templateCache, $http, $q, $sce) { + function handleRequestFn(tpl, ignoreRequestError) { + handleRequestFn.totalPendingRequests++; + if (!isString(tpl) || !$templateCache.get(tpl)) { + tpl = $sce.getTrustedResourceUrl(tpl); + } + var transformResponse = $http.defaults && $http.defaults.transformResponse; + if (isArray(transformResponse)) { + transformResponse = transformResponse.filter(function(transformer) { + return transformer !== defaultHttpResponseTransform; + }); + } else if (transformResponse === defaultHttpResponseTransform) { + transformResponse = null; + } + var httpOptions = { + cache: $templateCache, + transformResponse: transformResponse + }; + return $http.get(tpl, httpOptions)["finally"](function() { + handleRequestFn.totalPendingRequests--; + }).then(function(response) { + $templateCache.put(tpl, response.data); + return response.data; + }, handleError); + function handleError(resp) { + if (!ignoreRequestError) { + throw $compileMinErr("tpload", "Failed to load template: {0} (HTTP status: {1} {2})", tpl, resp.status, resp.statusText); + } + return $q.reject(resp); + } + } + handleRequestFn.totalPendingRequests = 0; + return handleRequestFn; + } ]; + } + function $$TestabilityProvider() { + this.$get = [ "$rootScope", "$browser", "$location", function($rootScope, $browser, $location) { + var testability = {}; + testability.findBindings = function(element, expression, opt_exactMatch) { + var bindings = element.getElementsByClassName("ng-binding"); + var matches = []; + forEach(bindings, function(binding) { + var dataBinding = angular.element(binding).data("$binding"); + if (dataBinding) { + forEach(dataBinding, function(bindingName) { + if (opt_exactMatch) { + var matcher = new RegExp("(^|\\s)" + escapeForRegexp(expression) + "(\\s|\\||$)"); + if (matcher.test(bindingName)) { + matches.push(binding); + } + } else { + if (bindingName.indexOf(expression) != -1) { + matches.push(binding); + } + } + }); + } + }); + return matches; + }; + testability.findModels = function(element, expression, opt_exactMatch) { + var prefixes = [ "ng-", "data-ng-", "ng\\:" ]; + for (var p = 0; p < prefixes.length; ++p) { + var attributeEquals = opt_exactMatch ? "=" : "*="; + var selector = "[" + prefixes[p] + "model" + attributeEquals + '"' + expression + '"]'; + var elements = element.querySelectorAll(selector); + if (elements.length) { + return elements; + } + } + }; + testability.getLocation = function() { + return $location.url(); + }; + testability.setLocation = function(url) { + if (url !== $location.url()) { + $location.url(url); + $rootScope.$digest(); + } + }; + testability.whenStable = function(callback) { + $browser.notifyWhenNoOutstandingRequests(callback); + }; + return testability; + } ]; + } + function $TimeoutProvider() { + this.$get = [ "$rootScope", "$browser", "$q", "$$q", "$exceptionHandler", function($rootScope, $browser, $q, $$q, $exceptionHandler) { + var deferreds = {}; + function timeout(fn, delay, invokeApply) { + if (!isFunction(fn)) { + invokeApply = delay; + delay = fn; + fn = noop; + } + var args = sliceArgs(arguments, 3), skipApply = isDefined(invokeApply) && !invokeApply, deferred = (skipApply ? $$q : $q).defer(), promise = deferred.promise, timeoutId; + timeoutId = $browser.defer(function() { + try { + deferred.resolve(fn.apply(null, args)); + } catch (e) { + deferred.reject(e); + $exceptionHandler(e); + } finally { + delete deferreds[promise.$$timeoutId]; + } + if (!skipApply) $rootScope.$apply(); + }, delay); + promise.$$timeoutId = timeoutId; + deferreds[timeoutId] = deferred; + return promise; + } + timeout.cancel = function(promise) { + if (promise && promise.$$timeoutId in deferreds) { + deferreds[promise.$$timeoutId].reject("canceled"); + delete deferreds[promise.$$timeoutId]; + return $browser.defer.cancel(promise.$$timeoutId); + } + return false; + }; + return timeout; + } ]; + } + var urlParsingNode = document.createElement("a"); + var originUrl = urlResolve(window.location.href); + function urlResolve(url) { + var href = url; + if (msie) { + urlParsingNode.setAttribute("href", href); + href = urlParsingNode.href; + } + urlParsingNode.setAttribute("href", href); + return { + href: urlParsingNode.href, + protocol: urlParsingNode.protocol ? urlParsingNode.protocol.replace(/:$/, "") : "", + host: urlParsingNode.host, + search: urlParsingNode.search ? urlParsingNode.search.replace(/^\?/, "") : "", + hash: urlParsingNode.hash ? urlParsingNode.hash.replace(/^#/, "") : "", + hostname: urlParsingNode.hostname, + port: urlParsingNode.port, + pathname: urlParsingNode.pathname.charAt(0) === "/" ? urlParsingNode.pathname : "/" + urlParsingNode.pathname + }; + } + function urlIsSameOrigin(requestUrl) { + var parsed = isString(requestUrl) ? urlResolve(requestUrl) : requestUrl; + return parsed.protocol === originUrl.protocol && parsed.host === originUrl.host; + } + function $WindowProvider() { + this.$get = valueFn(window); + } + function $$CookieReader($document) { + var rawDocument = $document[0] || {}; + var lastCookies = {}; + var lastCookieString = ""; + function safeDecodeURIComponent(str) { + try { + return decodeURIComponent(str); + } catch (e) { + return str; + } + } + return function() { + var cookieArray, cookie, i, index, name; + var currentCookieString = rawDocument.cookie || ""; + if (currentCookieString !== lastCookieString) { + lastCookieString = currentCookieString; + cookieArray = lastCookieString.split("; "); + lastCookies = {}; + for (i = 0; i < cookieArray.length; i++) { + cookie = cookieArray[i]; + index = cookie.indexOf("="); + if (index > 0) { + name = safeDecodeURIComponent(cookie.substring(0, index)); + if (isUndefined(lastCookies[name])) { + lastCookies[name] = safeDecodeURIComponent(cookie.substring(index + 1)); + } + } + } + } + return lastCookies; + }; + } + $$CookieReader.$inject = [ "$document" ]; + function $$CookieReaderProvider() { + this.$get = $$CookieReader; + } + $FilterProvider.$inject = [ "$provide" ]; + function $FilterProvider($provide) { + var suffix = "Filter"; + function register(name, factory) { + if (isObject(name)) { + var filters = {}; + forEach(name, function(filter, key) { + filters[key] = register(key, filter); + }); + return filters; + } else { + return $provide.factory(name + suffix, factory); + } + } + this.register = register; + this.$get = [ "$injector", function($injector) { + return function(name) { + return $injector.get(name + suffix); + }; + } ]; + register("currency", currencyFilter); + register("date", dateFilter); + register("filter", filterFilter); + register("json", jsonFilter); + register("limitTo", limitToFilter); + register("lowercase", lowercaseFilter); + register("number", numberFilter); + register("orderBy", orderByFilter); + register("uppercase", uppercaseFilter); + } + function filterFilter() { + return function(array, expression, comparator) { + if (!isArrayLike(array)) { + if (array == null) { + return array; + } else { + throw minErr("filter")("notarray", "Expected array but received: {0}", array); + } + } + var expressionType = getTypeForFilter(expression); + var predicateFn; + var matchAgainstAnyProp; + switch (expressionType) { + case "function": + predicateFn = expression; + break; - default: - targetElPos = { - top: hostElPos.top - targetElHeight, - left: shiftWidth[pos1]() - }; + case "boolean": + case "null": + case "number": + case "string": + matchAgainstAnyProp = true; + + case "object": + predicateFn = createPredicateFn(expression, comparator, matchAgainstAnyProp); break; + + default: + return array; + } + return Array.prototype.filter.call(array, predicateFn); + }; + } + function createPredicateFn(expression, comparator, matchAgainstAnyProp) { + var shouldMatchPrimitives = isObject(expression) && "$" in expression; + var predicateFn; + if (comparator === true) { + comparator = equals; + } else if (!isFunction(comparator)) { + comparator = function(actual, expected) { + if (isUndefined(actual)) { + return false; + } + if (actual === null || expected === null) { + return actual === expected; + } + if (isObject(expected) || isObject(actual) && !hasCustomToString(actual)) { + return false; + } + actual = lowercase("" + actual); + expected = lowercase("" + expected); + return actual.indexOf(expected) !== -1; + }; + } + predicateFn = function(item) { + if (shouldMatchPrimitives && !isObject(item)) { + return deepCompare(item, expression.$, comparator, false); + } + return deepCompare(item, expression, comparator, matchAgainstAnyProp); + }; + return predicateFn; + } + function deepCompare(actual, expected, comparator, matchAgainstAnyProp, dontMatchWholeObject) { + var actualType = getTypeForFilter(actual); + var expectedType = getTypeForFilter(expected); + if (expectedType === "string" && expected.charAt(0) === "!") { + return !deepCompare(actual, expected.substring(1), comparator, matchAgainstAnyProp); + } else if (isArray(actual)) { + return actual.some(function(item) { + return deepCompare(item, expected, comparator, matchAgainstAnyProp); + }); + } + switch (actualType) { + case "object": + var key; + if (matchAgainstAnyProp) { + for (key in actual) { + if (key.charAt(0) !== "$" && deepCompare(actual[key], expected, comparator, true)) { + return true; + } + } + return dontMatchWholeObject ? false : deepCompare(actual, expected, comparator, false); + } else if (expectedType === "object") { + for (key in expected) { + var expectedVal = expected[key]; + if (isFunction(expectedVal) || isUndefined(expectedVal)) { + continue; + } + var matchAnyProperty = key === "$"; + var actualVal = matchAnyProperty ? actual : actual[key]; + if (!deepCompare(actualVal, expectedVal, comparator, matchAnyProperty, matchAnyProperty)) { + return false; + } + } + return true; + } else { + return comparator(actual, expected); + } + break; + + case "function": + return false; + + default: + return comparator(actual, expected); + } + } + function getTypeForFilter(val) { + return val === null ? "null" : typeof val; + } + currencyFilter.$inject = [ "$locale" ]; + function currencyFilter($locale) { + var formats = $locale.NUMBER_FORMATS; + return function(amount, currencySymbol, fractionSize) { + if (isUndefined(currencySymbol)) { + currencySymbol = formats.CURRENCY_SYM; + } + if (isUndefined(fractionSize)) { + fractionSize = formats.PATTERNS[1].maxFrac; + } + return amount == null ? amount : formatNumber(amount, formats.PATTERNS[1], formats.GROUP_SEP, formats.DECIMAL_SEP, fractionSize).replace(/\u00A4/g, currencySymbol); + }; + } + numberFilter.$inject = [ "$locale" ]; + function numberFilter($locale) { + var formats = $locale.NUMBER_FORMATS; + return function(number, fractionSize) { + return number == null ? number : formatNumber(number, formats.PATTERNS[0], formats.GROUP_SEP, formats.DECIMAL_SEP, fractionSize); + }; + } + var DECIMAL_SEP = "."; + function formatNumber(number, pattern, groupSep, decimalSep, fractionSize) { + if (isObject(number)) return ""; + var isNegative = number < 0; + number = Math.abs(number); + var isInfinity = number === Infinity; + if (!isInfinity && !isFinite(number)) return ""; + var numStr = number + "", formatedText = "", hasExponent = false, parts = []; + if (isInfinity) formatedText = "∞"; + if (!isInfinity && numStr.indexOf("e") !== -1) { + var match = numStr.match(/([\d\.]+)e(-?)(\d+)/); + if (match && match[2] == "-" && match[3] > fractionSize + 1) { + number = 0; + } else { + formatedText = numStr; + hasExponent = true; } - return targetElPos; } + if (!isInfinity && !hasExponent) { + var fractionLen = (numStr.split(DECIMAL_SEP)[1] || "").length; + if (isUndefined(fractionSize)) { + fractionSize = Math.min(Math.max(pattern.minFrac, fractionLen), pattern.maxFrac); + } + number = +(Math.round(+(number.toString() + "e" + fractionSize)).toString() + "e" + -fractionSize); + var fraction = ("" + number).split(DECIMAL_SEP); + var whole = fraction[0]; + fraction = fraction[1] || ""; + var i, pos = 0, lgroup = pattern.lgSize, group = pattern.gSize; + if (whole.length >= lgroup + group) { + pos = whole.length - lgroup; + for (i = 0; i < pos; i++) { + if ((pos - i) % group === 0 && i !== 0) { + formatedText += groupSep; + } + formatedText += whole.charAt(i); + } + } + for (i = pos; i < whole.length; i++) { + if ((whole.length - i) % lgroup === 0 && i !== 0) { + formatedText += groupSep; + } + formatedText += whole.charAt(i); + } + while (fraction.length < fractionSize) { + fraction += "0"; + } + if (fractionSize && fractionSize !== "0") formatedText += decimalSep + fraction.substr(0, fractionSize); + } else { + if (fractionSize > 0 && number < 1) { + formatedText = number.toFixed(fractionSize); + number = parseFloat(formatedText); + formatedText = formatedText.replace(DECIMAL_SEP, decimalSep); + } + } + if (number === 0) { + isNegative = false; + } + parts.push(isNegative ? pattern.negPre : pattern.posPre, formatedText, isNegative ? pattern.negSuf : pattern.posSuf); + return parts.join(""); + } + function padNumber(num, digits, trim) { + var neg = ""; + if (num < 0) { + neg = "-"; + num = -num; + } + num = "" + num; + while (num.length < digits) num = "0" + num; + if (trim) { + num = num.substr(num.length - digits); + } + return neg + num; + } + function dateGetter(name, size, offset, trim) { + offset = offset || 0; + return function(date) { + var value = date["get" + name](); + if (offset > 0 || value > -offset) { + value += offset; + } + if (value === 0 && offset == -12) value = 12; + return padNumber(value, size, trim); + }; + } + function dateStrGetter(name, shortForm) { + return function(date, formats) { + var value = date["get" + name](); + var get = uppercase(shortForm ? "SHORT" + name : name); + return formats[get][value]; + }; + } + function timeZoneGetter(date, formats, offset) { + var zone = -1 * offset; + var paddedZone = zone >= 0 ? "+" : ""; + paddedZone += padNumber(Math[zone > 0 ? "floor" : "ceil"](zone / 60), 2) + padNumber(Math.abs(zone % 60), 2); + return paddedZone; + } + function getFirstThursdayOfYear(year) { + var dayOfWeekOnFirst = new Date(year, 0, 1).getDay(); + return new Date(year, 0, (dayOfWeekOnFirst <= 4 ? 5 : 12) - dayOfWeekOnFirst); + } + function getThursdayThisWeek(datetime) { + return new Date(datetime.getFullYear(), datetime.getMonth(), datetime.getDate() + (4 - datetime.getDay())); + } + function weekGetter(size) { + return function(date) { + var firstThurs = getFirstThursdayOfYear(date.getFullYear()), thisThurs = getThursdayThisWeek(date); + var diff = +thisThurs - +firstThurs, result = 1 + Math.round(diff / 6048e5); + return padNumber(result, size); + }; + } + function ampmGetter(date, formats) { + return date.getHours() < 12 ? formats.AMPMS[0] : formats.AMPMS[1]; + } + function eraGetter(date, formats) { + return date.getFullYear() <= 0 ? formats.ERAS[0] : formats.ERAS[1]; + } + function longEraGetter(date, formats) { + return date.getFullYear() <= 0 ? formats.ERANAMES[0] : formats.ERANAMES[1]; + } + var DATE_FORMATS = { + yyyy: dateGetter("FullYear", 4), + yy: dateGetter("FullYear", 2, 0, true), + y: dateGetter("FullYear", 1), + MMMM: dateStrGetter("Month"), + MMM: dateStrGetter("Month", true), + MM: dateGetter("Month", 2, 1), + M: dateGetter("Month", 1, 1), + dd: dateGetter("Date", 2), + d: dateGetter("Date", 1), + HH: dateGetter("Hours", 2), + H: dateGetter("Hours", 1), + hh: dateGetter("Hours", 2, -12), + h: dateGetter("Hours", 1, -12), + mm: dateGetter("Minutes", 2), + m: dateGetter("Minutes", 1), + ss: dateGetter("Seconds", 2), + s: dateGetter("Seconds", 1), + sss: dateGetter("Milliseconds", 3), + EEEE: dateStrGetter("Day"), + EEE: dateStrGetter("Day", true), + a: ampmGetter, + Z: timeZoneGetter, + ww: weekGetter(2), + w: weekGetter(1), + G: eraGetter, + GG: eraGetter, + GGG: eraGetter, + GGGG: longEraGetter }; -} ]); - -angular.module("ui.bootstrap.datepicker", [ "ui.bootstrap.dateparser", "ui.bootstrap.position" ]).value("$datepickerSuppressError", false).constant("datepickerConfig", { - formatDay: "dd", - formatMonth: "MMMM", - formatYear: "yyyy", - formatDayHeader: "EEE", - formatDayTitle: "MMMM yyyy", - formatMonthTitle: "yyyy", - datepickerMode: "day", - minMode: "day", - maxMode: "year", - showWeeks: true, - startingDay: 0, - yearRange: 20, - minDate: null, - maxDate: null, - shortcutPropagation: false -}).controller("DatepickerController", [ "$scope", "$attrs", "$parse", "$interpolate", "$log", "dateFilter", "datepickerConfig", "$datepickerSuppressError", function($scope, $attrs, $parse, $interpolate, $log, dateFilter, datepickerConfig, $datepickerSuppressError) { - var self = this, ngModelCtrl = { - $setViewValue: angular.noop - }; - this.modes = [ "day", "month", "year" ]; - angular.forEach([ "formatDay", "formatMonth", "formatYear", "formatDayHeader", "formatDayTitle", "formatMonthTitle", "showWeeks", "startingDay", "yearRange", "shortcutPropagation" ], function(key, index) { - self[key] = angular.isDefined($attrs[key]) ? index < 6 ? $interpolate($attrs[key])($scope.$parent) : $scope.$parent.$eval($attrs[key]) : datepickerConfig[key]; - }); - angular.forEach([ "minDate", "maxDate" ], function(key) { - if ($attrs[key]) { - $scope.$parent.$watch($parse($attrs[key]), function(value) { - self[key] = value ? new Date(value) : null; - self.refreshView(); + var DATE_FORMATS_SPLIT = /((?:[^yMdHhmsaZEwG']+)|(?:'(?:[^']|'')*')|(?:E+|y+|M+|d+|H+|h+|m+|s+|a|Z|G+|w+))(.*)/, NUMBER_STRING = /^\-?\d+$/; + dateFilter.$inject = [ "$locale" ]; + function dateFilter($locale) { + var R_ISO8601_STR = /^(\d{4})-?(\d\d)-?(\d\d)(?:T(\d\d)(?::?(\d\d)(?::?(\d\d)(?:\.(\d+))?)?)?(Z|([+-])(\d\d):?(\d\d))?)?$/; + function jsonStringToDate(string) { + var match; + if (match = string.match(R_ISO8601_STR)) { + var date = new Date(0), tzHour = 0, tzMin = 0, dateSetter = match[8] ? date.setUTCFullYear : date.setFullYear, timeSetter = match[8] ? date.setUTCHours : date.setHours; + if (match[9]) { + tzHour = toInt(match[9] + match[10]); + tzMin = toInt(match[9] + match[11]); + } + dateSetter.call(date, toInt(match[1]), toInt(match[2]) - 1, toInt(match[3])); + var h = toInt(match[4] || 0) - tzHour; + var m = toInt(match[5] || 0) - tzMin; + var s = toInt(match[6] || 0); + var ms = Math.round(parseFloat("0." + (match[7] || 0)) * 1e3); + timeSetter.call(date, h, m, s, ms); + return date; + } + return string; + } + return function(date, format, timezone) { + var text = "", parts = [], fn, match; + format = format || "mediumDate"; + format = $locale.DATETIME_FORMATS[format] || format; + if (isString(date)) { + date = NUMBER_STRING.test(date) ? toInt(date) : jsonStringToDate(date); + } + if (isNumber(date)) { + date = new Date(date); + } + if (!isDate(date) || !isFinite(date.getTime())) { + return date; + } + while (format) { + match = DATE_FORMATS_SPLIT.exec(format); + if (match) { + parts = concat(parts, match, 1); + format = parts.pop(); + } else { + parts.push(format); + format = null; + } + } + var dateTimezoneOffset = date.getTimezoneOffset(); + if (timezone) { + dateTimezoneOffset = timezoneToOffset(timezone, date.getTimezoneOffset()); + date = convertTimezoneToLocal(date, timezone, true); + } + forEach(parts, function(value) { + fn = DATE_FORMATS[value]; + text += fn ? fn(date, $locale.DATETIME_FORMATS, dateTimezoneOffset) : value.replace(/(^'|'$)/g, "").replace(/''/g, "'"); + }); + return text; + }; + } + function jsonFilter() { + return function(object, spacing) { + if (isUndefined(spacing)) { + spacing = 2; + } + return toJson(object, spacing); + }; + } + var lowercaseFilter = valueFn(lowercase); + var uppercaseFilter = valueFn(uppercase); + function limitToFilter() { + return function(input, limit, begin) { + if (Math.abs(Number(limit)) === Infinity) { + limit = Number(limit); + } else { + limit = toInt(limit); + } + if (isNaN(limit)) return input; + if (isNumber(input)) input = input.toString(); + if (!isArray(input) && !isString(input)) return input; + begin = !begin || isNaN(begin) ? 0 : toInt(begin); + begin = begin < 0 && begin >= -input.length ? input.length + begin : begin; + if (limit >= 0) { + return input.slice(begin, begin + limit); + } else { + if (begin === 0) { + return input.slice(limit, input.length); + } else { + return input.slice(Math.max(0, begin + limit), begin); + } + } + }; + } + orderByFilter.$inject = [ "$parse" ]; + function orderByFilter($parse) { + return function(array, sortPredicate, reverseOrder) { + if (!isArrayLike(array)) return array; + if (!isArray(sortPredicate)) { + sortPredicate = [ sortPredicate ]; + } + if (sortPredicate.length === 0) { + sortPredicate = [ "+" ]; + } + var predicates = processPredicates(sortPredicate, reverseOrder); + predicates.push({ + get: function() { + return {}; + }, + descending: reverseOrder ? -1 : 1 }); - } else { - self[key] = datepickerConfig[key] ? new Date(datepickerConfig[key]) : null; - } - }); - angular.forEach([ "minMode", "maxMode" ], function(key) { - if ($attrs[key]) { - $scope.$parent.$watch($parse($attrs[key]), function(value) { - self[key] = angular.isDefined(value) ? value : $attrs[key]; - $scope[key] = self[key]; - if (key == "minMode" && self.modes.indexOf($scope.datepickerMode) < self.modes.indexOf(self[key]) || key == "maxMode" && self.modes.indexOf($scope.datepickerMode) > self.modes.indexOf(self[key])) { - $scope.datepickerMode = self[key]; + var compareValues = Array.prototype.map.call(array, getComparisonObject); + compareValues.sort(doComparison); + array = compareValues.map(function(item) { + return item.value; + }); + return array; + function getComparisonObject(value, index) { + return { + value: value, + predicateValues: predicates.map(function(predicate) { + return getPredicateValue(predicate.get(value), index); + }) + }; + } + function doComparison(v1, v2) { + var result = 0; + for (var index = 0, length = predicates.length; index < length; ++index) { + result = compare(v1.predicateValues[index], v2.predicateValues[index]) * predicates[index].descending; + if (result) break; + } + return result; + } + }; + function processPredicates(sortPredicate, reverseOrder) { + reverseOrder = reverseOrder ? -1 : 1; + return sortPredicate.map(function(predicate) { + var descending = 1, get = identity; + if (isFunction(predicate)) { + get = predicate; + } else if (isString(predicate)) { + if (predicate.charAt(0) == "+" || predicate.charAt(0) == "-") { + descending = predicate.charAt(0) == "-" ? -1 : 1; + predicate = predicate.substring(1); + } + if (predicate !== "") { + get = $parse(predicate); + if (get.constant) { + var key = get(); + get = function(value) { + return value[key]; + }; + } + } } + return { + get: get, + descending: descending * reverseOrder + }; }); - } else { - self[key] = datepickerConfig[key] || null; - $scope[key] = self[key]; } - }); - $scope.datepickerMode = $scope.datepickerMode || datepickerConfig.datepickerMode; - $scope.uniqueId = "datepicker-" + $scope.$id + "-" + Math.floor(Math.random() * 1e4); - if (angular.isDefined($attrs.initDate)) { - this.activeDate = $scope.$parent.$eval($attrs.initDate) || new Date(); - $scope.$parent.$watch($attrs.initDate, function(initDate) { - if (initDate && (ngModelCtrl.$isEmpty(ngModelCtrl.$modelValue) || ngModelCtrl.$invalid)) { - self.activeDate = initDate; - self.refreshView(); + function isPrimitive(value) { + switch (typeof value) { + case "number": + case "boolean": + case "string": + return true; + + default: + return false; } - }); - } else { - this.activeDate = new Date(); - } - $scope.isActive = function(dateObject) { - if (self.compare(dateObject.date, self.activeDate) === 0) { - $scope.activeDateId = dateObject.uid; - return true; } - return false; - }; - this.init = function(ngModelCtrl_) { - ngModelCtrl = ngModelCtrl_; - ngModelCtrl.$render = function() { - self.render(); - }; - }; - this.render = function() { - if (ngModelCtrl.$viewValue) { - var date = new Date(ngModelCtrl.$viewValue), isValid = !isNaN(date); - if (isValid) { - this.activeDate = date; - } else if (!$datepickerSuppressError) { - $log.error('Datepicker directive: "ng-model" value must be a Date object, a number of milliseconds since 01.01.1970 or a string representing an RFC2822 or ISO 8601 date.'); + function objectValue(value, index) { + if (typeof value.valueOf === "function") { + value = value.valueOf(); + if (isPrimitive(value)) return value; } + if (hasCustomToString(value)) { + value = value.toString(); + if (isPrimitive(value)) return value; + } + return index; } - this.refreshView(); - }; - this.refreshView = function() { - if (this.element) { - this._refreshView(); - var date = ngModelCtrl.$viewValue ? new Date(ngModelCtrl.$viewValue) : null; - ngModelCtrl.$setValidity("dateDisabled", !date || this.element && !this.isDisabled(date)); - } - }; - this.createDateObject = function(date, format) { - var model = ngModelCtrl.$viewValue ? new Date(ngModelCtrl.$viewValue) : null; - return { - date: date, - label: dateFilter(date, format), - selected: model && this.compare(date, model) === 0, - disabled: this.isDisabled(date), - current: this.compare(date, new Date()) === 0, - customClass: this.customClass(date) - }; - }; - this.isDisabled = function(date) { - return this.minDate && this.compare(date, this.minDate) < 0 || this.maxDate && this.compare(date, this.maxDate) > 0 || $attrs.dateDisabled && $scope.dateDisabled({ - date: date, - mode: $scope.datepickerMode - }); - }; - this.customClass = function(date) { - return $scope.customClass({ - date: date, - mode: $scope.datepickerMode - }); - }; - this.split = function(arr, size) { - var arrays = []; - while (arr.length > 0) { - arrays.push(arr.splice(0, size)); - } - return arrays; - }; - this.fixTimeZone = function(date) { - var hours = date.getHours(); - date.setHours(hours === 23 ? hours + 2 : 0); - }; - $scope.select = function(date) { - if ($scope.datepickerMode === self.minMode) { - var dt = ngModelCtrl.$viewValue ? new Date(ngModelCtrl.$viewValue) : new Date(0, 0, 0, 0, 0, 0, 0); - dt.setFullYear(date.getFullYear(), date.getMonth(), date.getDate()); - ngModelCtrl.$setViewValue(dt); - ngModelCtrl.$render(); - } else { - self.activeDate = date; - $scope.datepickerMode = self.modes[self.modes.indexOf($scope.datepickerMode) - 1]; - } - }; - $scope.move = function(direction) { - var year = self.activeDate.getFullYear() + direction * (self.step.years || 0), month = self.activeDate.getMonth() + direction * (self.step.months || 0); - self.activeDate.setFullYear(year, month, 1); - self.refreshView(); - }; - $scope.toggleMode = function(direction) { - direction = direction || 1; - if ($scope.datepickerMode === self.maxMode && direction === 1 || $scope.datepickerMode === self.minMode && direction === -1) { - return; + function getPredicateValue(value, index) { + var type = typeof value; + if (value === null) { + type = "string"; + value = "null"; + } else if (type === "string") { + value = value.toLowerCase(); + } else if (type === "object") { + value = objectValue(value, index); + } + return { + value: value, + type: type + }; } - $scope.datepickerMode = self.modes[self.modes.indexOf($scope.datepickerMode) + direction]; - }; - $scope.keys = { - 13: "enter", - 32: "space", - 33: "pageup", - 34: "pagedown", - 35: "end", - 36: "home", - 37: "left", - 38: "up", - 39: "right", - 40: "down" - }; - var focusElement = function() { - self.element[0].focus(); - }; - $scope.$on("datepicker.focus", focusElement); - $scope.keydown = function(evt) { - var key = $scope.keys[evt.which]; - if (!key || evt.shiftKey || evt.altKey) { - return; + function compare(v1, v2) { + var result = 0; + if (v1.type === v2.type) { + if (v1.value !== v2.value) { + result = v1.value < v2.value ? -1 : 1; + } + } else { + result = v1.type < v2.type ? -1 : 1; + } + return result; } - evt.preventDefault(); - if (!self.shortcutPropagation) { - evt.stopPropagation(); + } + function ngDirective(directive) { + if (isFunction(directive)) { + directive = { + link: directive + }; } - if (key === "enter" || key === "space") { - if (self.isDisabled(self.activeDate)) { - return; + directive.restrict = directive.restrict || "AC"; + return valueFn(directive); + } + var htmlAnchorDirective = valueFn({ + restrict: "E", + compile: function(element, attr) { + if (!attr.href && !attr.xlinkHref) { + return function(scope, element) { + if (element[0].nodeName.toLowerCase() !== "a") return; + var href = toString.call(element.prop("href")) === "[object SVGAnimatedString]" ? "xlink:href" : "href"; + element.on("click", function(event) { + if (!element.attr(href)) { + event.preventDefault(); + } + }); + }; } - $scope.select(self.activeDate); - focusElement(); - } else if (evt.ctrlKey && (key === "up" || key === "down")) { - $scope.toggleMode(key === "up" ? 1 : -1); - focusElement(); - } else { - self.handleKeyDown(key, evt); - self.refreshView(); } - }; -} ]).directive("datepicker", function() { - return { - restrict: "EA", - replace: true, - templateUrl: function(element, attrs) { - return attrs.templateUrl || "template/datepicker/datepicker.html"; - }, - scope: { - datepickerMode: "=?", - dateDisabled: "&", - customClass: "&", - shortcutPropagation: "&?" - }, - require: [ "datepicker", "^ngModel" ], - controller: "DatepickerController", - controllerAs: "datepicker", - link: function(scope, element, attrs, ctrls) { - var datepickerCtrl = ctrls[0], ngModelCtrl = ctrls[1]; - datepickerCtrl.init(ngModelCtrl); + }); + var ngAttributeAliasDirectives = {}; + forEach(BOOLEAN_ATTR, function(propName, attrName) { + if (propName == "multiple") return; + function defaultLinkFn(scope, element, attr) { + scope.$watch(attr[normalized], function ngBooleanAttrWatchAction(value) { + attr.$set(attrName, !!value); + }); } - }; -}).directive("daypicker", [ "dateFilter", function(dateFilter) { - return { - restrict: "EA", - replace: true, - templateUrl: "template/datepicker/day.html", - require: "^datepicker", - link: function(scope, element, attrs, ctrl) { - scope.showWeeks = ctrl.showWeeks; - ctrl.step = { - months: 1 + var normalized = directiveNormalize("ng-" + attrName); + var linkFn = defaultLinkFn; + if (propName === "checked") { + linkFn = function(scope, element, attr) { + if (attr.ngModel !== attr[normalized]) { + defaultLinkFn(scope, element, attr); + } }; - ctrl.element = element; - var DAYS_IN_MONTH = [ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 ]; - function getDaysInMonth(year, month) { - return month === 1 && year % 4 === 0 && (year % 100 !== 0 || year % 400 === 0) ? 29 : DAYS_IN_MONTH[month]; - } - function getDates(startDate, n) { - var dates = new Array(n), current = new Date(startDate), i = 0, date; - while (i < n) { - date = new Date(current); - ctrl.fixTimeZone(date); - dates[i++] = date; - current.setDate(current.getDate() + 1); + } + ngAttributeAliasDirectives[normalized] = function() { + return { + restrict: "A", + priority: 100, + link: linkFn + }; + }; + }); + forEach(ALIASED_ATTR, function(htmlAttr, ngAttr) { + ngAttributeAliasDirectives[ngAttr] = function() { + return { + priority: 100, + link: function(scope, element, attr) { + if (ngAttr === "ngPattern" && attr.ngPattern.charAt(0) == "/") { + var match = attr.ngPattern.match(REGEX_STRING_REGEXP); + if (match) { + attr.$set("ngPattern", new RegExp(match[1], match[2])); + return; + } + } + scope.$watch(attr[ngAttr], function ngAttrAliasWatchAction(value) { + attr.$set(ngAttr, value); + }); } - return dates; + }; + }; + }); + forEach([ "src", "srcset", "href" ], function(attrName) { + var normalized = directiveNormalize("ng-" + attrName); + ngAttributeAliasDirectives[normalized] = function() { + return { + priority: 99, + link: function(scope, element, attr) { + var propName = attrName, name = attrName; + if (attrName === "href" && toString.call(element.prop("href")) === "[object SVGAnimatedString]") { + name = "xlinkHref"; + attr.$attr[name] = "xlink:href"; + propName = null; + } + attr.$observe(normalized, function(value) { + if (!value) { + if (attrName === "href") { + attr.$set(name, null); + } + return; + } + attr.$set(name, value); + if (msie && propName) element.prop(propName, attr[name]); + }); + } + }; + }; + }); + var nullFormCtrl = { + $addControl: noop, + $$renameControl: nullFormRenameControl, + $removeControl: noop, + $setValidity: noop, + $setDirty: noop, + $setPristine: noop, + $setSubmitted: noop + }, SUBMITTED_CLASS = "ng-submitted"; + function nullFormRenameControl(control, name) { + control.$name = name; + } + FormController.$inject = [ "$element", "$attrs", "$scope", "$animate", "$interpolate" ]; + function FormController(element, attrs, $scope, $animate, $interpolate) { + var form = this, controls = []; + form.$error = {}; + form.$$success = {}; + form.$pending = undefined; + form.$name = $interpolate(attrs.name || attrs.ngForm || "")($scope); + form.$dirty = false; + form.$pristine = true; + form.$valid = true; + form.$invalid = false; + form.$submitted = false; + form.$$parentForm = nullFormCtrl; + form.$rollbackViewValue = function() { + forEach(controls, function(control) { + control.$rollbackViewValue(); + }); + }; + form.$commitViewValue = function() { + forEach(controls, function(control) { + control.$commitViewValue(); + }); + }; + form.$addControl = function(control) { + assertNotHasOwnProperty(control.$name, "input"); + controls.push(control); + if (control.$name) { + form[control.$name] = control; } - ctrl._refreshView = function() { - var year = ctrl.activeDate.getFullYear(), month = ctrl.activeDate.getMonth(), firstDayOfMonth = new Date(year, month, 1), difference = ctrl.startingDay - firstDayOfMonth.getDay(), numDisplayedFromPreviousMonth = difference > 0 ? 7 - difference : -difference, firstDate = new Date(firstDayOfMonth); - if (numDisplayedFromPreviousMonth > 0) { - firstDate.setDate(-numDisplayedFromPreviousMonth + 1); + control.$$parentForm = form; + }; + form.$$renameControl = function(control, newName) { + var oldName = control.$name; + if (form[oldName] === control) { + delete form[oldName]; + } + form[newName] = control; + control.$name = newName; + }; + form.$removeControl = function(control) { + if (control.$name && form[control.$name] === control) { + delete form[control.$name]; + } + forEach(form.$pending, function(value, name) { + form.$setValidity(name, null, control); + }); + forEach(form.$error, function(value, name) { + form.$setValidity(name, null, control); + }); + forEach(form.$$success, function(value, name) { + form.$setValidity(name, null, control); + }); + arrayRemove(controls, control); + control.$$parentForm = nullFormCtrl; + }; + addSetValidityMethod({ + ctrl: this, + $element: element, + set: function(object, property, controller) { + var list = object[property]; + if (!list) { + object[property] = [ controller ]; + } else { + var index = list.indexOf(controller); + if (index === -1) { + list.push(controller); + } } - var days = getDates(firstDate, 42); - for (var i = 0; i < 42; i++) { - days[i] = angular.extend(ctrl.createDateObject(days[i], ctrl.formatDay), { - secondary: days[i].getMonth() !== month, - uid: scope.uniqueId + "-" + i - }); + }, + unset: function(object, property, controller) { + var list = object[property]; + if (!list) { + return; } - scope.labels = new Array(7); - for (var j = 0; j < 7; j++) { - scope.labels[j] = { - abbr: dateFilter(days[j].date, ctrl.formatDayHeader), - full: dateFilter(days[j].date, "EEEE") + arrayRemove(list, controller); + if (list.length === 0) { + delete object[property]; + } + }, + $animate: $animate + }); + form.$setDirty = function() { + $animate.removeClass(element, PRISTINE_CLASS); + $animate.addClass(element, DIRTY_CLASS); + form.$dirty = true; + form.$pristine = false; + form.$$parentForm.$setDirty(); + }; + form.$setPristine = function() { + $animate.setClass(element, PRISTINE_CLASS, DIRTY_CLASS + " " + SUBMITTED_CLASS); + form.$dirty = false; + form.$pristine = true; + form.$submitted = false; + forEach(controls, function(control) { + control.$setPristine(); + }); + }; + form.$setUntouched = function() { + forEach(controls, function(control) { + control.$setUntouched(); + }); + }; + form.$setSubmitted = function() { + $animate.addClass(element, SUBMITTED_CLASS); + form.$submitted = true; + form.$$parentForm.$setSubmitted(); + }; + } + var formDirectiveFactory = function(isNgForm) { + return [ "$timeout", "$parse", function($timeout, $parse) { + var formDirective = { + name: "form", + restrict: isNgForm ? "EAC" : "E", + require: [ "form", "^^?form" ], + controller: FormController, + compile: function ngFormCompile(formElement, attr) { + formElement.addClass(PRISTINE_CLASS).addClass(VALID_CLASS); + var nameAttr = attr.name ? "name" : isNgForm && attr.ngForm ? "ngForm" : false; + return { + pre: function ngFormPreLink(scope, formElement, attr, ctrls) { + var controller = ctrls[0]; + if (!("action" in attr)) { + var handleFormSubmission = function(event) { + scope.$apply(function() { + controller.$commitViewValue(); + controller.$setSubmitted(); + }); + event.preventDefault(); + }; + addEventListenerFn(formElement[0], "submit", handleFormSubmission); + formElement.on("$destroy", function() { + $timeout(function() { + removeEventListenerFn(formElement[0], "submit", handleFormSubmission); + }, 0, false); + }); + } + var parentFormCtrl = ctrls[1] || controller.$$parentForm; + parentFormCtrl.$addControl(controller); + var setter = nameAttr ? getSetter(controller.$name) : noop; + if (nameAttr) { + setter(scope, controller); + attr.$observe(nameAttr, function(newValue) { + if (controller.$name === newValue) return; + setter(scope, undefined); + controller.$$parentForm.$$renameControl(controller, newValue); + setter = getSetter(controller.$name); + setter(scope, controller); + }); + } + formElement.on("$destroy", function() { + controller.$$parentForm.$removeControl(controller); + setter(scope, undefined); + extend(controller, nullFormCtrl); + }); + } }; } - scope.title = dateFilter(ctrl.activeDate, ctrl.formatDayTitle); - scope.rows = ctrl.split(days, 7); - if (scope.showWeeks) { - scope.weekNumbers = []; - var thursdayIndex = (4 + 7 - ctrl.startingDay) % 7, numWeeks = scope.rows.length; - for (var curWeek = 0; curWeek < numWeeks; curWeek++) { - scope.weekNumbers.push(getISO8601WeekNumber(scope.rows[curWeek][thursdayIndex].date)); - } - } - }; - ctrl.compare = function(date1, date2) { - return new Date(date1.getFullYear(), date1.getMonth(), date1.getDate()) - new Date(date2.getFullYear(), date2.getMonth(), date2.getDate()); }; - function getISO8601WeekNumber(date) { - var checkDate = new Date(date); - checkDate.setDate(checkDate.getDate() + 4 - (checkDate.getDay() || 7)); - var time = checkDate.getTime(); - checkDate.setMonth(0); - checkDate.setDate(1); - return Math.floor(Math.round((time - checkDate) / 864e5) / 7) + 1; - } - ctrl.handleKeyDown = function(key, evt) { - var date = ctrl.activeDate.getDate(); - if (key === "left") { - date = date - 1; - } else if (key === "up") { - date = date - 7; - } else if (key === "right") { - date = date + 1; - } else if (key === "down") { - date = date + 7; - } else if (key === "pageup" || key === "pagedown") { - var month = ctrl.activeDate.getMonth() + (key === "pageup" ? -1 : 1); - ctrl.activeDate.setMonth(month, 1); - date = Math.min(getDaysInMonth(ctrl.activeDate.getFullYear(), ctrl.activeDate.getMonth()), date); - } else if (key === "home") { - date = 1; - } else if (key === "end") { - date = getDaysInMonth(ctrl.activeDate.getFullYear(), ctrl.activeDate.getMonth()); + return formDirective; + function getSetter(expression) { + if (expression === "") { + return $parse('this[""]').assign; } - ctrl.activeDate.setDate(date); - }; - ctrl.refreshView(); - } + return $parse(expression).assign || noop; + } + } ]; }; -} ]).directive("monthpicker", [ "dateFilter", function(dateFilter) { - return { - restrict: "EA", - replace: true, - templateUrl: "template/datepicker/month.html", - require: "^datepicker", - link: function(scope, element, attrs, ctrl) { - ctrl.step = { - years: 1 - }; - ctrl.element = element; - ctrl._refreshView = function() { - var months = new Array(12), year = ctrl.activeDate.getFullYear(), date; - for (var i = 0; i < 12; i++) { - date = new Date(year, i, 1); - ctrl.fixTimeZone(date); - months[i] = angular.extend(ctrl.createDateObject(date, ctrl.formatMonth), { - uid: scope.uniqueId + "-" + i - }); - } - scope.title = dateFilter(ctrl.activeDate, ctrl.formatMonthTitle); - scope.rows = ctrl.split(months, 3); - }; - ctrl.compare = function(date1, date2) { - return new Date(date1.getFullYear(), date1.getMonth()) - new Date(date2.getFullYear(), date2.getMonth()); - }; - ctrl.handleKeyDown = function(key, evt) { - var date = ctrl.activeDate.getMonth(); - if (key === "left") { - date = date - 1; - } else if (key === "up") { - date = date - 3; - } else if (key === "right") { - date = date + 1; - } else if (key === "down") { - date = date + 3; - } else if (key === "pageup" || key === "pagedown") { - var year = ctrl.activeDate.getFullYear() + (key === "pageup" ? -1 : 1); - ctrl.activeDate.setFullYear(year); - } else if (key === "home") { - date = 0; - } else if (key === "end") { - date = 11; - } - ctrl.activeDate.setMonth(date); - }; - ctrl.refreshView(); - } + var formDirective = formDirectiveFactory(); + var ngFormDirective = formDirectiveFactory(true); + var ISO_DATE_REGEXP = /\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d:[0-5]\d\.\d+([+-][0-2]\d:[0-5]\d|Z)/; + var URL_REGEXP = /^(ftp|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?$/; + var EMAIL_REGEXP = /^[a-z0-9!#$%&'*+\/=?^_`{|}~.-]+@[a-z0-9]([a-z0-9-]*[a-z0-9])?(\.[a-z0-9]([a-z0-9-]*[a-z0-9])?)*$/i; + var NUMBER_REGEXP = /^\s*(\-|\+)?(\d+|(\d*(\.\d*)))([eE][+-]?\d+)?\s*$/; + var DATE_REGEXP = /^(\d{4})-(\d{2})-(\d{2})$/; + var DATETIMELOCAL_REGEXP = /^(\d{4})-(\d\d)-(\d\d)T(\d\d):(\d\d)(?::(\d\d)(\.\d{1,3})?)?$/; + var WEEK_REGEXP = /^(\d{4})-W(\d\d)$/; + var MONTH_REGEXP = /^(\d{4})-(\d\d)$/; + var TIME_REGEXP = /^(\d\d):(\d\d)(?::(\d\d)(\.\d{1,3})?)?$/; + var inputType = { + text: textInputType, + date: createDateInputType("date", DATE_REGEXP, createDateParser(DATE_REGEXP, [ "yyyy", "MM", "dd" ]), "yyyy-MM-dd"), + "datetime-local": createDateInputType("datetimelocal", DATETIMELOCAL_REGEXP, createDateParser(DATETIMELOCAL_REGEXP, [ "yyyy", "MM", "dd", "HH", "mm", "ss", "sss" ]), "yyyy-MM-ddTHH:mm:ss.sss"), + time: createDateInputType("time", TIME_REGEXP, createDateParser(TIME_REGEXP, [ "HH", "mm", "ss", "sss" ]), "HH:mm:ss.sss"), + week: createDateInputType("week", WEEK_REGEXP, weekParser, "yyyy-Www"), + month: createDateInputType("month", MONTH_REGEXP, createDateParser(MONTH_REGEXP, [ "yyyy", "MM" ]), "yyyy-MM"), + number: numberInputType, + url: urlInputType, + email: emailInputType, + radio: radioInputType, + checkbox: checkboxInputType, + hidden: noop, + button: noop, + submit: noop, + reset: noop, + file: noop }; -} ]).directive("yearpicker", [ "dateFilter", function(dateFilter) { - return { - restrict: "EA", - replace: true, - templateUrl: "template/datepicker/year.html", - require: "^datepicker", - link: function(scope, element, attrs, ctrl) { - var range = ctrl.yearRange; - ctrl.step = { - years: range - }; - ctrl.element = element; - function getStartingYear(year) { - return parseInt((year - 1) / range, 10) * range + 1; + function stringBasedInputType(ctrl) { + ctrl.$formatters.push(function(value) { + return ctrl.$isEmpty(value) ? value : value.toString(); + }); + } + function textInputType(scope, element, attr, ctrl, $sniffer, $browser) { + baseInputType(scope, element, attr, ctrl, $sniffer, $browser); + stringBasedInputType(ctrl); + } + function baseInputType(scope, element, attr, ctrl, $sniffer, $browser) { + var type = lowercase(element[0].type); + if (!$sniffer.android) { + var composing = false; + element.on("compositionstart", function(data) { + composing = true; + }); + element.on("compositionend", function() { + composing = false; + listener(); + }); + } + var listener = function(ev) { + if (timeout) { + $browser.defer.cancel(timeout); + timeout = null; } - ctrl._refreshView = function() { - var years = new Array(range), date; - for (var i = 0, start = getStartingYear(ctrl.activeDate.getFullYear()); i < range; i++) { - date = new Date(start + i, 0, 1); - ctrl.fixTimeZone(date); - years[i] = angular.extend(ctrl.createDateObject(date, ctrl.formatYear), { - uid: scope.uniqueId + "-" + i - }); - } - scope.title = [ years[0].label, years[range - 1].label ].join(" - "); - scope.rows = ctrl.split(years, 5); - }; - ctrl.compare = function(date1, date2) { - return date1.getFullYear() - date2.getFullYear(); - }; - ctrl.handleKeyDown = function(key, evt) { - var date = ctrl.activeDate.getFullYear(); - if (key === "left") { - date = date - 1; - } else if (key === "up") { - date = date - 5; - } else if (key === "right") { - date = date + 1; - } else if (key === "down") { - date = date + 5; - } else if (key === "pageup" || key === "pagedown") { - date += (key === "pageup" ? -1 : 1) * ctrl.step.years; - } else if (key === "home") { - date = getStartingYear(ctrl.activeDate.getFullYear()); - } else if (key === "end") { - date = getStartingYear(ctrl.activeDate.getFullYear()) + range - 1; + if (composing) return; + var value = element.val(), event = ev && ev.type; + if (type !== "password" && (!attr.ngTrim || attr.ngTrim !== "false")) { + value = trim(value); + } + if (ctrl.$viewValue !== value || value === "" && ctrl.$$hasNativeValidators) { + ctrl.$setViewValue(value, event); + } + }; + if ($sniffer.hasEvent("input")) { + element.on("input", listener); + } else { + var timeout; + var deferListener = function(ev, input, origValue) { + if (!timeout) { + timeout = $browser.defer(function() { + timeout = null; + if (!input || input.value !== origValue) { + listener(ev); + } + }); } - ctrl.activeDate.setFullYear(date); }; - ctrl.refreshView(); + element.on("keydown", function(event) { + var key = event.keyCode; + if (key === 91 || 15 < key && key < 19 || 37 <= key && key <= 40) return; + deferListener(event, this, this.value); + }); + if ($sniffer.hasEvent("paste")) { + element.on("paste cut", deferListener); + } } - }; -} ]).constant("datepickerPopupConfig", { - datepickerPopup: "yyyy-MM-dd", - datepickerPopupTemplateUrl: "template/datepicker/popup.html", - datepickerTemplateUrl: "template/datepicker/datepicker.html", - html5Types: { - date: "yyyy-MM-dd", - "datetime-local": "yyyy-MM-ddTHH:mm:ss.sss", - month: "yyyy-MM" - }, - currentText: "Today", - clearText: "Clear", - closeText: "Done", - closeOnDateSelection: true, - appendToBody: false, - showButtonBar: true, - onOpenFocus: true -}).directive("datepickerPopup", [ "$compile", "$parse", "$document", "$rootScope", "$position", "dateFilter", "dateParser", "datepickerPopupConfig", "$timeout", function($compile, $parse, $document, $rootScope, $position, dateFilter, dateParser, datepickerPopupConfig, $timeout) { - return { - restrict: "EA", - require: "ngModel", - scope: { - isOpen: "=?", - currentText: "@", - clearText: "@", - closeText: "@", - dateDisabled: "&", - customClass: "&" - }, - link: function(scope, element, attrs, ngModel) { - var dateFormat, closeOnDateSelection = angular.isDefined(attrs.closeOnDateSelection) ? scope.$parent.$eval(attrs.closeOnDateSelection) : datepickerPopupConfig.closeOnDateSelection, appendToBody = angular.isDefined(attrs.datepickerAppendToBody) ? scope.$parent.$eval(attrs.datepickerAppendToBody) : datepickerPopupConfig.appendToBody, onOpenFocus = angular.isDefined(attrs.onOpenFocus) ? scope.$parent.$eval(attrs.onOpenFocus) : datepickerPopupConfig.onOpenFocus, datepickerPopupTemplateUrl = angular.isDefined(attrs.datepickerPopupTemplateUrl) ? attrs.datepickerPopupTemplateUrl : datepickerPopupConfig.datepickerPopupTemplateUrl, datepickerTemplateUrl = angular.isDefined(attrs.datepickerTemplateUrl) ? attrs.datepickerTemplateUrl : datepickerPopupConfig.datepickerTemplateUrl, cache = {}; - scope.showButtonBar = angular.isDefined(attrs.showButtonBar) ? scope.$parent.$eval(attrs.showButtonBar) : datepickerPopupConfig.showButtonBar; - scope.getText = function(key) { - return scope[key + "Text"] || datepickerPopupConfig[key + "Text"]; - }; - scope.isDisabled = function(date) { - if (date === "today") { - date = new Date(); + element.on("change", listener); + ctrl.$render = function() { + var value = ctrl.$isEmpty(ctrl.$viewValue) ? "" : ctrl.$viewValue; + if (element.val() !== value) { + element.val(value); + } + }; + } + function weekParser(isoWeek, existingDate) { + if (isDate(isoWeek)) { + return isoWeek; + } + if (isString(isoWeek)) { + WEEK_REGEXP.lastIndex = 0; + var parts = WEEK_REGEXP.exec(isoWeek); + if (parts) { + var year = +parts[1], week = +parts[2], hours = 0, minutes = 0, seconds = 0, milliseconds = 0, firstThurs = getFirstThursdayOfYear(year), addDays = (week - 1) * 7; + if (existingDate) { + hours = existingDate.getHours(); + minutes = existingDate.getMinutes(); + seconds = existingDate.getSeconds(); + milliseconds = existingDate.getMilliseconds(); } - return scope.watchData.minDate && scope.compare(date, cache.minDate) < 0 || scope.watchData.maxDate && scope.compare(date, cache.maxDate) > 0; - }; - scope.compare = function(date1, date2) { - return new Date(date1.getFullYear(), date1.getMonth(), date1.getDate()) - new Date(date2.getFullYear(), date2.getMonth(), date2.getDate()); - }; - var isHtml5DateInput = false; - if (datepickerPopupConfig.html5Types[attrs.type]) { - dateFormat = datepickerPopupConfig.html5Types[attrs.type]; - isHtml5DateInput = true; - } else { - dateFormat = attrs.datepickerPopup || datepickerPopupConfig.datepickerPopup; - attrs.$observe("datepickerPopup", function(value, oldValue) { - var newDateFormat = value || datepickerPopupConfig.datepickerPopup; - if (newDateFormat !== dateFormat) { - dateFormat = newDateFormat; - ngModel.$modelValue = null; - if (!dateFormat) { - throw new Error("datepickerPopup must have a date format specified."); + return new Date(year, 0, firstThurs.getDate() + addDays, hours, minutes, seconds, milliseconds); + } + } + return NaN; + } + function createDateParser(regexp, mapping) { + return function(iso, date) { + var parts, map; + if (isDate(iso)) { + return iso; + } + if (isString(iso)) { + if (iso.charAt(0) == '"' && iso.charAt(iso.length - 1) == '"') { + iso = iso.substring(1, iso.length - 1); + } + if (ISO_DATE_REGEXP.test(iso)) { + return new Date(iso); + } + regexp.lastIndex = 0; + parts = regexp.exec(iso); + if (parts) { + parts.shift(); + if (date) { + map = { + yyyy: date.getFullYear(), + MM: date.getMonth() + 1, + dd: date.getDate(), + HH: date.getHours(), + mm: date.getMinutes(), + ss: date.getSeconds(), + sss: date.getMilliseconds() / 1e3 + }; + } else { + map = { + yyyy: 1970, + MM: 1, + dd: 1, + HH: 0, + mm: 0, + ss: 0, + sss: 0 + }; + } + forEach(parts, function(part, index) { + if (index < mapping.length) { + map[mapping[index]] = +part; } + }); + return new Date(map.yyyy, map.MM - 1, map.dd, map.HH, map.mm, map.ss || 0, map.sss * 1e3 || 0); + } + } + return NaN; + }; + } + function createDateInputType(type, regexp, parseDate, format) { + return function dynamicDateInputType(scope, element, attr, ctrl, $sniffer, $browser, $filter) { + badInputChecker(scope, element, attr, ctrl); + baseInputType(scope, element, attr, ctrl, $sniffer, $browser); + var timezone = ctrl && ctrl.$options && ctrl.$options.timezone; + var previousDate; + ctrl.$$parserName = type; + ctrl.$parsers.push(function(value) { + if (ctrl.$isEmpty(value)) return null; + if (regexp.test(value)) { + var parsedDate = parseDate(value, previousDate); + if (timezone) { + parsedDate = convertTimezoneToLocal(parsedDate, timezone); + } + return parsedDate; + } + return undefined; + }); + ctrl.$formatters.push(function(value) { + if (value && !isDate(value)) { + throw ngModelMinErr("datefmt", "Expected `{0}` to be a date", value); + } + if (isValidDate(value)) { + previousDate = value; + if (previousDate && timezone) { + previousDate = convertTimezoneToLocal(previousDate, timezone, true); } + return $filter("date")(value, format, timezone); + } else { + previousDate = null; + return ""; + } + }); + if (isDefined(attr.min) || attr.ngMin) { + var minVal; + ctrl.$validators.min = function(value) { + return !isValidDate(value) || isUndefined(minVal) || parseDate(value) >= minVal; + }; + attr.$observe("min", function(val) { + minVal = parseObservedDateValue(val); + ctrl.$validate(); }); } - if (!dateFormat) { - throw new Error("datepickerPopup must have a date format specified."); + if (isDefined(attr.max) || attr.ngMax) { + var maxVal; + ctrl.$validators.max = function(value) { + return !isValidDate(value) || isUndefined(maxVal) || parseDate(value) <= maxVal; + }; + attr.$observe("max", function(val) { + maxVal = parseObservedDateValue(val); + ctrl.$validate(); + }); } - if (isHtml5DateInput && attrs.datepickerPopup) { - throw new Error("HTML5 date input types do not support custom formats."); + function isValidDate(value) { + return value && !(value.getTime && value.getTime() !== value.getTime()); } - var popupEl = angular.element("
        "); - popupEl.attr({ - "ng-model": "date", - "ng-change": "dateSelection(date)", - "template-url": datepickerPopupTemplateUrl + function parseObservedDateValue(val) { + return isDefined(val) && !isDate(val) ? parseDate(val) || undefined : val; + } + }; + } + function badInputChecker(scope, element, attr, ctrl) { + var node = element[0]; + var nativeValidation = ctrl.$$hasNativeValidators = isObject(node.validity); + if (nativeValidation) { + ctrl.$parsers.push(function(value) { + var validity = element.prop(VALIDITY_STATE_PROPERTY) || {}; + return validity.badInput && !validity.typeMismatch ? undefined : value; + }); + } + } + function numberInputType(scope, element, attr, ctrl, $sniffer, $browser) { + badInputChecker(scope, element, attr, ctrl); + baseInputType(scope, element, attr, ctrl, $sniffer, $browser); + ctrl.$$parserName = "number"; + ctrl.$parsers.push(function(value) { + if (ctrl.$isEmpty(value)) return null; + if (NUMBER_REGEXP.test(value)) return parseFloat(value); + return undefined; + }); + ctrl.$formatters.push(function(value) { + if (!ctrl.$isEmpty(value)) { + if (!isNumber(value)) { + throw ngModelMinErr("numfmt", "Expected `{0}` to be a number", value); + } + value = value.toString(); + } + return value; + }); + if (isDefined(attr.min) || attr.ngMin) { + var minVal; + ctrl.$validators.min = function(value) { + return ctrl.$isEmpty(value) || isUndefined(minVal) || value >= minVal; + }; + attr.$observe("min", function(val) { + if (isDefined(val) && !isNumber(val)) { + val = parseFloat(val, 10); + } + minVal = isNumber(val) && !isNaN(val) ? val : undefined; + ctrl.$validate(); + }); + } + if (isDefined(attr.max) || attr.ngMax) { + var maxVal; + ctrl.$validators.max = function(value) { + return ctrl.$isEmpty(value) || isUndefined(maxVal) || value <= maxVal; + }; + attr.$observe("max", function(val) { + if (isDefined(val) && !isNumber(val)) { + val = parseFloat(val, 10); + } + maxVal = isNumber(val) && !isNaN(val) ? val : undefined; + ctrl.$validate(); }); - function cameltoDash(string) { - return string.replace(/([A-Z])/g, function($1) { - return "-" + $1.toLowerCase(); - }); + } + } + function urlInputType(scope, element, attr, ctrl, $sniffer, $browser) { + baseInputType(scope, element, attr, ctrl, $sniffer, $browser); + stringBasedInputType(ctrl); + ctrl.$$parserName = "url"; + ctrl.$validators.url = function(modelValue, viewValue) { + var value = modelValue || viewValue; + return ctrl.$isEmpty(value) || URL_REGEXP.test(value); + }; + } + function emailInputType(scope, element, attr, ctrl, $sniffer, $browser) { + baseInputType(scope, element, attr, ctrl, $sniffer, $browser); + stringBasedInputType(ctrl); + ctrl.$$parserName = "email"; + ctrl.$validators.email = function(modelValue, viewValue) { + var value = modelValue || viewValue; + return ctrl.$isEmpty(value) || EMAIL_REGEXP.test(value); + }; + } + function radioInputType(scope, element, attr, ctrl) { + if (isUndefined(attr.name)) { + element.attr("name", nextUid()); + } + var listener = function(ev) { + if (element[0].checked) { + ctrl.$setViewValue(attr.value, ev && ev.type); } - var datepickerEl = angular.element(popupEl.children()[0]); - datepickerEl.attr("template-url", datepickerTemplateUrl); - if (isHtml5DateInput) { - if (attrs.type === "month") { - datepickerEl.attr("datepicker-mode", '"month"'); - datepickerEl.attr("min-mode", "month"); + }; + element.on("click", listener); + ctrl.$render = function() { + var value = attr.value; + element[0].checked = value == ctrl.$viewValue; + }; + attr.$observe("value", ctrl.$render); + } + function parseConstantExpr($parse, context, name, expression, fallback) { + var parseFn; + if (isDefined(expression)) { + parseFn = $parse(expression); + if (!parseFn.constant) { + throw ngModelMinErr("constexpr", "Expected constant expression for `{0}`, but saw " + "`{1}`.", name, expression); + } + return parseFn(context); + } + return fallback; + } + function checkboxInputType(scope, element, attr, ctrl, $sniffer, $browser, $filter, $parse) { + var trueValue = parseConstantExpr($parse, scope, "ngTrueValue", attr.ngTrueValue, true); + var falseValue = parseConstantExpr($parse, scope, "ngFalseValue", attr.ngFalseValue, false); + var listener = function(ev) { + ctrl.$setViewValue(element[0].checked, ev && ev.type); + }; + element.on("click", listener); + ctrl.$render = function() { + element[0].checked = ctrl.$viewValue; + }; + ctrl.$isEmpty = function(value) { + return value === false; + }; + ctrl.$formatters.push(function(value) { + return equals(value, trueValue); + }); + ctrl.$parsers.push(function(value) { + return value ? trueValue : falseValue; + }); + } + var inputDirective = [ "$browser", "$sniffer", "$filter", "$parse", function($browser, $sniffer, $filter, $parse) { + return { + restrict: "E", + require: [ "?ngModel" ], + link: { + pre: function(scope, element, attr, ctrls) { + if (ctrls[0]) { + (inputType[lowercase(attr.type)] || inputType.text)(scope, element, attr, ctrls[0], $sniffer, $browser, $filter, $parse); + } } } - if (attrs.datepickerOptions) { - var options = scope.$parent.$eval(attrs.datepickerOptions); - if (options && options.initDate) { - scope.initDate = options.initDate; - datepickerEl.attr("init-date", "initDate"); - delete options.initDate; + }; + } ]; + var CONSTANT_VALUE_REGEXP = /^(true|false|\d+)$/; + var ngValueDirective = function() { + return { + restrict: "A", + priority: 100, + compile: function(tpl, tplAttr) { + if (CONSTANT_VALUE_REGEXP.test(tplAttr.ngValue)) { + return function ngValueConstantLink(scope, elm, attr) { + attr.$set("value", scope.$eval(attr.ngValue)); + }; + } else { + return function ngValueLink(scope, elm, attr) { + scope.$watch(attr.ngValue, function valueWatchAction(value) { + attr.$set("value", value); + }); + }; } - angular.forEach(options, function(value, option) { - datepickerEl.attr(cameltoDash(option), value); + } + }; + }; + var ngBindDirective = [ "$compile", function($compile) { + return { + restrict: "AC", + compile: function ngBindCompile(templateElement) { + $compile.$$addBindingClass(templateElement); + return function ngBindLink(scope, element, attr) { + $compile.$$addBindingInfo(element, attr.ngBind); + element = element[0]; + scope.$watch(attr.ngBind, function ngBindWatchAction(value) { + element.textContent = isUndefined(value) ? "" : value; + }); + }; + } + }; + } ]; + var ngBindTemplateDirective = [ "$interpolate", "$compile", function($interpolate, $compile) { + return { + compile: function ngBindTemplateCompile(templateElement) { + $compile.$$addBindingClass(templateElement); + return function ngBindTemplateLink(scope, element, attr) { + var interpolateFn = $interpolate(element.attr(attr.$attr.ngBindTemplate)); + $compile.$$addBindingInfo(element, interpolateFn.expressions); + element = element[0]; + attr.$observe("ngBindTemplate", function(value) { + element.textContent = isUndefined(value) ? "" : value; + }); + }; + } + }; + } ]; + var ngBindHtmlDirective = [ "$sce", "$parse", "$compile", function($sce, $parse, $compile) { + return { + restrict: "A", + compile: function ngBindHtmlCompile(tElement, tAttrs) { + var ngBindHtmlGetter = $parse(tAttrs.ngBindHtml); + var ngBindHtmlWatch = $parse(tAttrs.ngBindHtml, function getStringValue(value) { + return (value || "").toString(); }); + $compile.$$addBindingClass(tElement); + return function ngBindHtmlLink(scope, element, attr) { + $compile.$$addBindingInfo(element, attr.ngBindHtml); + scope.$watch(ngBindHtmlWatch, function ngBindHtmlWatchAction() { + element.html($sce.getTrustedHtml(ngBindHtmlGetter(scope)) || ""); + }); + }; } - scope.watchData = {}; - angular.forEach([ "minMode", "maxMode", "minDate", "maxDate", "datepickerMode", "initDate", "shortcutPropagation" ], function(key) { - if (attrs[key]) { - var getAttribute = $parse(attrs[key]); - scope.$parent.$watch(getAttribute, function(value) { - scope.watchData[key] = value; - if (key === "minDate" || key === "maxDate") { - cache[key] = new Date(value); - } + }; + } ]; + var ngChangeDirective = valueFn({ + restrict: "A", + require: "ngModel", + link: function(scope, element, attr, ctrl) { + ctrl.$viewChangeListeners.push(function() { + scope.$eval(attr.ngChange); + }); + } + }); + function classDirective(name, selector) { + name = "ngClass" + name; + return [ "$animate", function($animate) { + return { + restrict: "AC", + link: function(scope, element, attr) { + var oldVal; + scope.$watch(attr[name], ngClassWatchAction, true); + attr.$observe("class", function(value) { + ngClassWatchAction(scope.$eval(attr[name])); }); - datepickerEl.attr(cameltoDash(key), "watchData." + key); - if (key === "datepickerMode") { - var setAttribute = getAttribute.assign; - scope.$watch("watchData." + key, function(value, oldvalue) { - if (angular.isFunction(setAttribute) && value !== oldvalue) { - setAttribute(scope.$parent, value); + if (name !== "ngClass") { + scope.$watch("$index", function($index, old$index) { + var mod = $index & 1; + if (mod !== (old$index & 1)) { + var classes = arrayClasses(scope.$eval(attr[name])); + mod === selector ? addClasses(classes) : removeClasses(classes); + } + }); + } + function addClasses(classes) { + var newClasses = digestClassCounts(classes, 1); + attr.$addClass(newClasses); + } + function removeClasses(classes) { + var newClasses = digestClassCounts(classes, -1); + attr.$removeClass(newClasses); + } + function digestClassCounts(classes, count) { + var classCounts = element.data("$classCounts") || createMap(); + var classesToUpdate = []; + forEach(classes, function(className) { + if (count > 0 || classCounts[className]) { + classCounts[className] = (classCounts[className] || 0) + count; + if (classCounts[className] === +(count > 0)) { + classesToUpdate.push(className); + } } }); + element.data("$classCounts", classCounts); + return classesToUpdate.join(" "); + } + function updateClasses(oldClasses, newClasses) { + var toAdd = arrayDifference(newClasses, oldClasses); + var toRemove = arrayDifference(oldClasses, newClasses); + toAdd = digestClassCounts(toAdd, 1); + toRemove = digestClassCounts(toRemove, -1); + if (toAdd && toAdd.length) { + $animate.addClass(element, toAdd); + } + if (toRemove && toRemove.length) { + $animate.removeClass(element, toRemove); + } + } + function ngClassWatchAction(newVal) { + if (selector === true || scope.$index % 2 === selector) { + var newClasses = arrayClasses(newVal || []); + if (!oldVal) { + addClasses(newClasses); + } else if (!equals(newVal, oldVal)) { + var oldClasses = arrayClasses(oldVal); + updateClasses(oldClasses, newClasses); + } + } + oldVal = shallowCopy(newVal); } } - }); - if (attrs.dateDisabled) { - datepickerEl.attr("date-disabled", "dateDisabled({ date: date, mode: mode })"); - } - if (attrs.showWeeks) { - datepickerEl.attr("show-weeks", attrs.showWeeks); - } - if (attrs.customClass) { - datepickerEl.attr("custom-class", "customClass({ date: date, mode: mode })"); - } - function parseDate(viewValue) { - if (angular.isNumber(viewValue)) { - viewValue = new Date(viewValue); - } - if (!viewValue) { - return null; - } else if (angular.isDate(viewValue) && !isNaN(viewValue)) { - return viewValue; - } else if (angular.isString(viewValue)) { - var date = dateParser.parse(viewValue, dateFormat, scope.date); - if (isNaN(date)) { - return undefined; - } else { - return date; + }; + function arrayDifference(tokens1, tokens2) { + var values = []; + outer: for (var i = 0; i < tokens1.length; i++) { + var token = tokens1[i]; + for (var j = 0; j < tokens2.length; j++) { + if (token == tokens2[j]) continue outer; } - } else { - return undefined; + values.push(token); } + return values; } - function validator(modelValue, viewValue) { - var value = modelValue || viewValue; - if (!attrs.ngRequired && !value) { - return true; - } - if (angular.isNumber(value)) { - value = new Date(value); - } - if (!value) { - return true; - } else if (angular.isDate(value) && !isNaN(value)) { - return true; - } else if (angular.isString(value)) { - var date = dateParser.parse(value, dateFormat); - return !isNaN(date); - } else { - return false; + function arrayClasses(classVal) { + var classes = []; + if (isArray(classVal)) { + forEach(classVal, function(v) { + classes = classes.concat(arrayClasses(v)); + }); + return classes; + } else if (isString(classVal)) { + return classVal.split(" "); + } else if (isObject(classVal)) { + forEach(classVal, function(v, k) { + if (v) { + classes = classes.concat(k.split(" ")); + } + }); + return classes; } + return classVal; } - if (!isHtml5DateInput) { - ngModel.$$parserName = "date"; - ngModel.$validators.date = validator; - ngModel.$parsers.unshift(parseDate); - ngModel.$formatters.push(function(value) { - scope.date = value; - return ngModel.$isEmpty(value) ? value : dateFilter(value, dateFormat); - }); - } else { - ngModel.$formatters.push(function(value) { - scope.date = value; - return value; - }); - } - scope.dateSelection = function(dt) { - if (angular.isDefined(dt)) { - scope.date = dt; - } - var date = scope.date ? dateFilter(scope.date, dateFormat) : null; - element.val(date); - ngModel.$setViewValue(date); - if (closeOnDateSelection) { - scope.isOpen = false; - element[0].focus(); - } - }; - ngModel.$viewChangeListeners.push(function() { - scope.date = dateParser.parse(ngModel.$viewValue, dateFormat, scope.date); - }); - var documentClickBind = function(event) { - if (scope.isOpen && !(element[0].contains(event.target) || popupEl[0].contains(event.target))) { - scope.$apply(function() { - scope.isOpen = false; - }); + } ]; + } + var ngClassDirective = classDirective("", true); + var ngClassOddDirective = classDirective("Odd", 0); + var ngClassEvenDirective = classDirective("Even", 1); + var ngCloakDirective = ngDirective({ + compile: function(element, attr) { + attr.$set("ngCloak", undefined); + element.removeClass("ng-cloak"); + } + }); + var ngControllerDirective = [ function() { + return { + restrict: "A", + scope: true, + controller: "@", + priority: 500 + }; + } ]; + var ngEventDirectives = {}; + var forceAsyncEvents = { + blur: true, + focus: true + }; + forEach("click dblclick mousedown mouseup mouseover mouseout mousemove mouseenter mouseleave keydown keyup keypress submit focus blur copy cut paste".split(" "), function(eventName) { + var directiveName = directiveNormalize("ng-" + eventName); + ngEventDirectives[directiveName] = [ "$parse", "$rootScope", function($parse, $rootScope) { + return { + restrict: "A", + compile: function($element, attr) { + var fn = $parse(attr[directiveName], null, true); + return function ngEventHandler(scope, element) { + element.on(eventName, function(event) { + var callback = function() { + fn(scope, { + $event: event + }); + }; + if (forceAsyncEvents[eventName] && $rootScope.$$phase) { + scope.$evalAsync(callback); + } else { + scope.$apply(callback); + } + }); + }; } }; - var inputKeydownBind = function(evt) { - if (evt.which === 27 && scope.isOpen) { - evt.preventDefault(); - evt.stopPropagation(); - scope.$apply(function() { - scope.isOpen = false; + } ]; + }); + var ngIfDirective = [ "$animate", function($animate) { + return { + multiElement: true, + transclude: "element", + priority: 600, + terminal: true, + restrict: "A", + $$tlb: true, + link: function($scope, $element, $attr, ctrl, $transclude) { + var block, childScope, previousElements; + $scope.$watch($attr.ngIf, function ngIfWatchAction(value) { + if (value) { + if (!childScope) { + $transclude(function(clone, newScope) { + childScope = newScope; + clone[clone.length++] = document.createComment(" end ngIf: " + $attr.ngIf + " "); + block = { + clone: clone + }; + $animate.enter(clone, $element.parent(), $element); + }); + } + } else { + if (previousElements) { + previousElements.remove(); + previousElements = null; + } + if (childScope) { + childScope.$destroy(); + childScope = null; + } + if (block) { + previousElements = getBlockNodes(block.clone); + $animate.leave(previousElements).then(function() { + previousElements = null; + }); + block = null; + } + } + }); + } + }; + } ]; + var ngIncludeDirective = [ "$templateRequest", "$anchorScroll", "$animate", function($templateRequest, $anchorScroll, $animate) { + return { + restrict: "ECA", + priority: 400, + terminal: true, + transclude: "element", + controller: angular.noop, + compile: function(element, attr) { + var srcExp = attr.ngInclude || attr.src, onloadExp = attr.onload || "", autoScrollExp = attr.autoscroll; + return function(scope, $element, $attr, ctrl, $transclude) { + var changeCounter = 0, currentScope, previousElement, currentElement; + var cleanupLastIncludeContent = function() { + if (previousElement) { + previousElement.remove(); + previousElement = null; + } + if (currentScope) { + currentScope.$destroy(); + currentScope = null; + } + if (currentElement) { + $animate.leave(currentElement).then(function() { + previousElement = null; + }); + previousElement = currentElement; + currentElement = null; + } + }; + scope.$watch(srcExp, function ngIncludeWatchAction(src) { + var afterAnimation = function() { + if (isDefined(autoScrollExp) && (!autoScrollExp || scope.$eval(autoScrollExp))) { + $anchorScroll(); + } + }; + var thisChangeId = ++changeCounter; + if (src) { + $templateRequest(src, true).then(function(response) { + if (thisChangeId !== changeCounter) return; + var newScope = scope.$new(); + ctrl.template = response; + var clone = $transclude(newScope, function(clone) { + cleanupLastIncludeContent(); + $animate.enter(clone, null, $element).then(afterAnimation); + }); + currentScope = newScope; + currentElement = clone; + currentScope.$emit("$includeContentLoaded", src); + scope.$eval(onloadExp); + }, function() { + if (thisChangeId === changeCounter) { + cleanupLastIncludeContent(); + scope.$emit("$includeContentError", src); + } + }); + scope.$emit("$includeContentRequested", src); + } else { + cleanupLastIncludeContent(); + ctrl.template = null; + } }); - element[0].focus(); - } else if (evt.which === 40 && !scope.isOpen) { - evt.preventDefault(); - evt.stopPropagation(); - scope.$apply(function() { - scope.isOpen = true; + }; + } + }; + } ]; + var ngIncludeFillContentDirective = [ "$compile", function($compile) { + return { + restrict: "ECA", + priority: -400, + require: "ngInclude", + link: function(scope, $element, $attr, ctrl) { + if (/SVG/.test($element[0].toString())) { + $element.empty(); + $compile(jqLiteBuildFragment(ctrl.template, document).childNodes)(scope, function namespaceAdaptedClone(clone) { + $element.append(clone); + }, { + futureParentElement: $element }); + return; } - }; - element.bind("keydown", inputKeydownBind); - scope.keydown = function(evt) { - if (evt.which === 27) { - scope.isOpen = false; - element[0].focus(); - } - }; - scope.$watch("isOpen", function(value) { - if (value) { - scope.position = appendToBody ? $position.offset(element) : $position.position(element); - scope.position.top = scope.position.top + element.prop("offsetHeight"); - $timeout(function() { - if (onOpenFocus) { - scope.$broadcast("datepicker.focus"); - } - $document.bind("click", documentClickBind); - }, 0, false); - } else { - $document.unbind("click", documentClickBind); - } - }); - scope.select = function(date) { - if (date === "today") { - var today = new Date(); - if (angular.isDate(scope.date)) { - date = new Date(scope.date); - date.setFullYear(today.getFullYear(), today.getMonth(), today.getDate()); - } else { - date = new Date(today.setHours(0, 0, 0, 0)); - } + $element.html(ctrl.template); + $compile($element.contents())(scope); + } + }; + } ]; + var ngInitDirective = ngDirective({ + priority: 450, + compile: function() { + return { + pre: function(scope, element, attrs) { + scope.$eval(attrs.ngInit); } - scope.dateSelection(date); - }; - scope.close = function() { - scope.isOpen = false; - element[0].focus(); }; - var $popup = $compile(popupEl)(scope); - popupEl.remove(); - if (appendToBody) { - $document.find("body").append($popup); - } else { - element.after($popup); - } - scope.$on("$destroy", function() { - if (scope.isOpen === true) { - if (!$rootScope.$$phase) { - scope.$apply(function() { - scope.isOpen = false; + } + }); + var ngListDirective = function() { + return { + restrict: "A", + priority: 100, + require: "ngModel", + link: function(scope, element, attr, ctrl) { + var ngList = element.attr(attr.$attr.ngList) || ", "; + var trimValues = attr.ngTrim !== "false"; + var separator = trimValues ? trim(ngList) : ngList; + var parse = function(viewValue) { + if (isUndefined(viewValue)) return; + var list = []; + if (viewValue) { + forEach(viewValue.split(separator), function(value) { + if (value) list.push(trimValues ? trim(value) : value); }); } - } - $popup.remove(); - element.unbind("keydown", inputKeydownBind); - $document.unbind("click", documentClickBind); - }); - } - }; -} ]).directive("datepickerPopupWrap", function() { - return { - restrict: "EA", - replace: true, - transclude: true, - templateUrl: function(element, attrs) { - return attrs.templateUrl || "template/datepicker/popup.html"; - } - }; -}); - -angular.module("ui.bootstrap.dropdown", [ "ui.bootstrap.position" ]).constant("dropdownConfig", { - openClass: "open" -}).service("dropdownService", [ "$document", "$rootScope", function($document, $rootScope) { - var openScope = null; - this.open = function(dropdownScope) { - if (!openScope) { - $document.bind("click", closeDropdown); - $document.bind("keydown", keybindFilter); - } - if (openScope && openScope !== dropdownScope) { - openScope.isOpen = false; - } - openScope = dropdownScope; - }; - this.close = function(dropdownScope) { - if (openScope === dropdownScope) { - openScope = null; - $document.unbind("click", closeDropdown); - $document.unbind("keydown", keybindFilter); - } - }; - var closeDropdown = function(evt) { - if (!openScope) { - return; - } - if (evt && openScope.getAutoClose() === "disabled") { - return; - } - var toggleElement = openScope.getToggleElement(); - if (evt && toggleElement && toggleElement[0].contains(evt.target)) { - return; - } - var dropdownElement = openScope.getDropdownElement(); - if (evt && openScope.getAutoClose() === "outsideClick" && dropdownElement && dropdownElement[0].contains(evt.target)) { - return; - } - openScope.isOpen = false; - if (!$rootScope.$$phase) { - openScope.$apply(); - } - }; - var keybindFilter = function(evt) { - if (evt.which === 27) { - openScope.focusToggleElement(); - closeDropdown(); - } else if (openScope.isKeynavEnabled() && /(38|40)/.test(evt.which) && openScope.isOpen) { - evt.preventDefault(); - evt.stopPropagation(); - openScope.focusDropdownEntry(evt.which); - } - }; -} ]).controller("DropdownController", [ "$scope", "$attrs", "$parse", "dropdownConfig", "dropdownService", "$animate", "$position", "$document", "$compile", "$templateRequest", function($scope, $attrs, $parse, dropdownConfig, dropdownService, $animate, $position, $document, $compile, $templateRequest) { - var self = this, scope = $scope.$new(), templateScope, openClass = dropdownConfig.openClass, getIsOpen, setIsOpen = angular.noop, toggleInvoker = $attrs.onToggle ? $parse($attrs.onToggle) : angular.noop, appendToBody = false, keynavEnabled = false, selectedOption = null, body = $document.find("body"); - this.init = function(element) { - self.$element = element; - if ($attrs.isOpen) { - getIsOpen = $parse($attrs.isOpen); - setIsOpen = getIsOpen.assign; - $scope.$watch(getIsOpen, function(value) { - scope.isOpen = !!value; - }); - } - appendToBody = angular.isDefined($attrs.dropdownAppendToBody); - keynavEnabled = angular.isDefined($attrs.keyboardNav); - if (appendToBody && self.dropdownMenu) { - body.append(self.dropdownMenu); - body.addClass("dropdown"); - element.on("$destroy", function handleDestroyEvent() { - self.dropdownMenu.remove(); - }); - } - }; - this.toggle = function(open) { - return scope.isOpen = arguments.length ? !!open : !scope.isOpen; - }; - this.isOpen = function() { - return scope.isOpen; - }; - scope.getToggleElement = function() { - return self.toggleElement; - }; - scope.getAutoClose = function() { - return $attrs.autoClose || "always"; - }; - scope.getElement = function() { - return self.$element; - }; - scope.isKeynavEnabled = function() { - return keynavEnabled; + return list; + }; + ctrl.$parsers.push(parse); + ctrl.$formatters.push(function(value) { + if (isArray(value)) { + return value.join(ngList); + } + return undefined; + }); + ctrl.$isEmpty = function(value) { + return !value || !value.length; + }; + } + }; }; - scope.focusDropdownEntry = function(keyCode) { - var elems = self.dropdownMenu ? angular.element(self.dropdownMenu).find("a") : angular.element(self.$element).find("ul").eq(0).find("a"); - switch (keyCode) { - case 40: - { - if (!angular.isNumber(self.selectedOption)) { - self.selectedOption = 0; - } else { - self.selectedOption = self.selectedOption === elems.length - 1 ? self.selectedOption : self.selectedOption + 1; + var VALID_CLASS = "ng-valid", INVALID_CLASS = "ng-invalid", PRISTINE_CLASS = "ng-pristine", DIRTY_CLASS = "ng-dirty", UNTOUCHED_CLASS = "ng-untouched", TOUCHED_CLASS = "ng-touched", PENDING_CLASS = "ng-pending"; + var ngModelMinErr = minErr("ngModel"); + var NgModelController = [ "$scope", "$exceptionHandler", "$attrs", "$element", "$parse", "$animate", "$timeout", "$rootScope", "$q", "$interpolate", function($scope, $exceptionHandler, $attr, $element, $parse, $animate, $timeout, $rootScope, $q, $interpolate) { + this.$viewValue = Number.NaN; + this.$modelValue = Number.NaN; + this.$$rawModelValue = undefined; + this.$validators = {}; + this.$asyncValidators = {}; + this.$parsers = []; + this.$formatters = []; + this.$viewChangeListeners = []; + this.$untouched = true; + this.$touched = false; + this.$pristine = true; + this.$dirty = false; + this.$valid = true; + this.$invalid = false; + this.$error = {}; + this.$$success = {}; + this.$pending = undefined; + this.$name = $interpolate($attr.name || "", false)($scope); + this.$$parentForm = nullFormCtrl; + var parsedNgModel = $parse($attr.ngModel), parsedNgModelAssign = parsedNgModel.assign, ngModelGet = parsedNgModel, ngModelSet = parsedNgModelAssign, pendingDebounce = null, parserValid, ctrl = this; + this.$$setOptions = function(options) { + ctrl.$options = options; + if (options && options.getterSetter) { + var invokeModelGetter = $parse($attr.ngModel + "()"), invokeModelSetter = $parse($attr.ngModel + "($$$p)"); + ngModelGet = function($scope) { + var modelValue = parsedNgModel($scope); + if (isFunction(modelValue)) { + modelValue = invokeModelGetter($scope); + } + return modelValue; + }; + ngModelSet = function($scope, newValue) { + if (isFunction(parsedNgModel($scope))) { + invokeModelSetter($scope, { + $$$p: ctrl.$modelValue + }); + } else { + parsedNgModelAssign($scope, ctrl.$modelValue); + } + }; + } else if (!parsedNgModel.assign) { + throw ngModelMinErr("nonassign", "Expression '{0}' is non-assignable. Element: {1}", $attr.ngModel, startingTag($element)); + } + }; + this.$render = noop; + this.$isEmpty = function(value) { + return isUndefined(value) || value === "" || value === null || value !== value; + }; + var currentValidationRunId = 0; + addSetValidityMethod({ + ctrl: this, + $element: $element, + set: function(object, property) { + object[property] = true; + }, + unset: function(object, property) { + delete object[property]; + }, + $animate: $animate + }); + this.$setPristine = function() { + ctrl.$dirty = false; + ctrl.$pristine = true; + $animate.removeClass($element, DIRTY_CLASS); + $animate.addClass($element, PRISTINE_CLASS); + }; + this.$setDirty = function() { + ctrl.$dirty = true; + ctrl.$pristine = false; + $animate.removeClass($element, PRISTINE_CLASS); + $animate.addClass($element, DIRTY_CLASS); + ctrl.$$parentForm.$setDirty(); + }; + this.$setUntouched = function() { + ctrl.$touched = false; + ctrl.$untouched = true; + $animate.setClass($element, UNTOUCHED_CLASS, TOUCHED_CLASS); + }; + this.$setTouched = function() { + ctrl.$touched = true; + ctrl.$untouched = false; + $animate.setClass($element, TOUCHED_CLASS, UNTOUCHED_CLASS); + }; + this.$rollbackViewValue = function() { + $timeout.cancel(pendingDebounce); + ctrl.$viewValue = ctrl.$$lastCommittedViewValue; + ctrl.$render(); + }; + this.$validate = function() { + if (isNumber(ctrl.$modelValue) && isNaN(ctrl.$modelValue)) { + return; + } + var viewValue = ctrl.$$lastCommittedViewValue; + var modelValue = ctrl.$$rawModelValue; + var prevValid = ctrl.$valid; + var prevModelValue = ctrl.$modelValue; + var allowInvalid = ctrl.$options && ctrl.$options.allowInvalid; + ctrl.$$runValidators(modelValue, viewValue, function(allValid) { + if (!allowInvalid && prevValid !== allValid) { + ctrl.$modelValue = allValid ? modelValue : undefined; + if (ctrl.$modelValue !== prevModelValue) { + ctrl.$$writeModelToScope(); + } } - break; + }); + }; + this.$$runValidators = function(modelValue, viewValue, doneCallback) { + currentValidationRunId++; + var localValidationRunId = currentValidationRunId; + if (!processParseErrors()) { + validationDone(false); + return; } - - case 38: - { - if (!angular.isNumber(self.selectedOption)) { - self.selectedOption = elems.length - 1; + if (!processSyncValidators()) { + validationDone(false); + return; + } + processAsyncValidators(); + function processParseErrors() { + var errorKey = ctrl.$$parserName || "parse"; + if (isUndefined(parserValid)) { + setValidity(errorKey, null); } else { - self.selectedOption = self.selectedOption === 0 ? 0 : self.selectedOption - 1; + if (!parserValid) { + forEach(ctrl.$validators, function(v, name) { + setValidity(name, null); + }); + forEach(ctrl.$asyncValidators, function(v, name) { + setValidity(name, null); + }); + } + setValidity(errorKey, parserValid); + return parserValid; } - break; - } - } - elems[self.selectedOption].focus(); - }; - scope.getDropdownElement = function() { - return self.dropdownMenu; - }; - scope.focusToggleElement = function() { - if (self.toggleElement) { - self.toggleElement[0].focus(); - } - }; - scope.$watch("isOpen", function(isOpen, wasOpen) { - if (appendToBody && self.dropdownMenu) { - var pos = $position.positionElements(self.$element, self.dropdownMenu, "bottom-left", true); - var css = { - top: pos.top + "px", - display: isOpen ? "block" : "none" - }; - var rightalign = self.dropdownMenu.hasClass("dropdown-menu-right"); - if (!rightalign) { - css.left = pos.left + "px"; - css.right = "auto"; - } else { - css.left = "auto"; - css.right = window.innerWidth - (pos.left + self.$element.prop("offsetWidth")) + "px"; + return true; } - self.dropdownMenu.css(css); - } - var openContainer = appendToBody ? body : self.$element; - $animate[isOpen ? "addClass" : "removeClass"](openContainer, openClass).then(function() { - if (angular.isDefined(isOpen) && isOpen !== wasOpen) { - toggleInvoker($scope, { - open: !!isOpen + function processSyncValidators() { + var syncValidatorsValid = true; + forEach(ctrl.$validators, function(validator, name) { + var result = validator(modelValue, viewValue); + syncValidatorsValid = syncValidatorsValid && result; + setValidity(name, result); }); - } - }); - if (isOpen) { - if (self.dropdownMenuTemplateUrl) { - $templateRequest(self.dropdownMenuTemplateUrl).then(function(tplContent) { - templateScope = scope.$new(); - $compile(tplContent.trim())(templateScope, function(dropdownElement) { - var newEl = dropdownElement; - self.dropdownMenu.replaceWith(newEl); - self.dropdownMenu = newEl; + if (!syncValidatorsValid) { + forEach(ctrl.$asyncValidators, function(v, name) { + setValidity(name, null); }); + return false; + } + return true; + } + function processAsyncValidators() { + var validatorPromises = []; + var allValid = true; + forEach(ctrl.$asyncValidators, function(validator, name) { + var promise = validator(modelValue, viewValue); + if (!isPromiseLike(promise)) { + throw ngModelMinErr("$asyncValidators", "Expected asynchronous validator to return a promise but got '{0}' instead.", promise); + } + setValidity(name, undefined); + validatorPromises.push(promise.then(function() { + setValidity(name, true); + }, function(error) { + allValid = false; + setValidity(name, false); + })); }); + if (!validatorPromises.length) { + validationDone(true); + } else { + $q.all(validatorPromises).then(function() { + validationDone(allValid); + }, noop); + } } - scope.focusToggleElement(); - dropdownService.open(scope); - } else { - if (self.dropdownMenuTemplateUrl) { - if (templateScope) { - templateScope.$destroy(); + function setValidity(name, isValid) { + if (localValidationRunId === currentValidationRunId) { + ctrl.$setValidity(name, isValid); } - var newEl = angular.element(''); - self.dropdownMenu.replaceWith(newEl); - self.dropdownMenu = newEl; } - dropdownService.close(scope); - self.selectedOption = null; - } - if (angular.isFunction(setIsOpen)) { - setIsOpen($scope, isOpen); - } - }); - $scope.$on("$locationChangeSuccess", function() { - if (scope.getAutoClose() !== "disabled") { - scope.isOpen = false; - } - }); - var offDestroy = $scope.$on("$destroy", function() { - scope.$destroy(); - }); - scope.$on("$destroy", offDestroy); -} ]).directive("dropdown", function() { - return { - controller: "DropdownController", - link: function(scope, element, attrs, dropdownCtrl) { - dropdownCtrl.init(element); - element.addClass("dropdown"); - } - }; -}).directive("dropdownMenu", function() { - return { - restrict: "AC", - require: "?^dropdown", - link: function(scope, element, attrs, dropdownCtrl) { - if (!dropdownCtrl) { + function validationDone(allValid) { + if (localValidationRunId === currentValidationRunId) { + doneCallback(allValid); + } + } + }; + this.$commitViewValue = function() { + var viewValue = ctrl.$viewValue; + $timeout.cancel(pendingDebounce); + if (ctrl.$$lastCommittedViewValue === viewValue && (viewValue !== "" || !ctrl.$$hasNativeValidators)) { return; } - var tplUrl = attrs.templateUrl; - if (tplUrl) { - dropdownCtrl.dropdownMenuTemplateUrl = tplUrl; + ctrl.$$lastCommittedViewValue = viewValue; + if (ctrl.$pristine) { + this.$setDirty(); + } + this.$$parseAndValidate(); + }; + this.$$parseAndValidate = function() { + var viewValue = ctrl.$$lastCommittedViewValue; + var modelValue = viewValue; + parserValid = isUndefined(modelValue) ? undefined : true; + if (parserValid) { + for (var i = 0; i < ctrl.$parsers.length; i++) { + modelValue = ctrl.$parsers[i](modelValue); + if (isUndefined(modelValue)) { + parserValid = false; + break; + } + } + } + if (isNumber(ctrl.$modelValue) && isNaN(ctrl.$modelValue)) { + ctrl.$modelValue = ngModelGet($scope); } - if (!dropdownCtrl.dropdownMenu) { - dropdownCtrl.dropdownMenu = element; + var prevModelValue = ctrl.$modelValue; + var allowInvalid = ctrl.$options && ctrl.$options.allowInvalid; + ctrl.$$rawModelValue = modelValue; + if (allowInvalid) { + ctrl.$modelValue = modelValue; + writeToModelIfNeeded(); } - } - }; -}).directive("keyboardNav", function() { - return { - restrict: "A", - require: "?^dropdown", - link: function(scope, element, attrs, dropdownCtrl) { - element.bind("keydown", function(e) { - if ([ 38, 40 ].indexOf(e.which) !== -1) { - e.preventDefault(); - e.stopPropagation(); - var elems = dropdownCtrl.dropdownMenu.find("a"); - switch (e.which) { - case 40: - { - if (!angular.isNumber(dropdownCtrl.selectedOption)) { - dropdownCtrl.selectedOption = 0; - } else { - dropdownCtrl.selectedOption = dropdownCtrl.selectedOption === elems.length - 1 ? dropdownCtrl.selectedOption : dropdownCtrl.selectedOption + 1; - } - break; - } - - case 38: - { - if (!angular.isNumber(dropdownCtrl.selectedOption)) { - dropdownCtrl.selectedOption = elems.length - 1; - } else { - dropdownCtrl.selectedOption = dropdownCtrl.selectedOption === 0 ? 0 : dropdownCtrl.selectedOption - 1; - } - break; - } - } - elems[dropdownCtrl.selectedOption].focus(); + ctrl.$$runValidators(modelValue, ctrl.$$lastCommittedViewValue, function(allValid) { + if (!allowInvalid) { + ctrl.$modelValue = allValid ? modelValue : undefined; + writeToModelIfNeeded(); } }); - } - }; -}).directive("dropdownToggle", function() { - return { - require: "?^dropdown", - link: function(scope, element, attrs, dropdownCtrl) { - if (!dropdownCtrl) { - return; + function writeToModelIfNeeded() { + if (ctrl.$modelValue !== prevModelValue) { + ctrl.$$writeModelToScope(); + } } - element.addClass("dropdown-toggle"); - dropdownCtrl.toggleElement = element; - var toggleDropdown = function(event) { - event.preventDefault(); - if (!element.hasClass("disabled") && !attrs.disabled) { - scope.$apply(function() { - dropdownCtrl.toggle(); - }); + }; + this.$$writeModelToScope = function() { + ngModelSet($scope, ctrl.$modelValue); + forEach(ctrl.$viewChangeListeners, function(listener) { + try { + listener(); + } catch (e) { + $exceptionHandler(e); } - }; - element.bind("click", toggleDropdown); - element.attr({ - "aria-haspopup": true, - "aria-expanded": false - }); - scope.$watch(dropdownCtrl.isOpen, function(isOpen) { - element.attr("aria-expanded", !!isOpen); - }); - scope.$on("$destroy", function() { - element.unbind("click", toggleDropdown); }); - } - }; -}); - -angular.module("ui.bootstrap.modal", []).factory("$$stackedMap", function() { - return { - createNew: function() { - var stack = []; - return { - add: function(key, value) { - stack.push({ - key: key, - value: value - }); - }, - get: function(key) { - for (var i = 0; i < stack.length; i++) { - if (key == stack[i].key) { - return stack[i]; - } - } - }, - keys: function() { - var keys = []; - for (var i = 0; i < stack.length; i++) { - keys.push(stack[i].key); - } - return keys; - }, - top: function() { - return stack[stack.length - 1]; - }, - remove: function(key) { - var idx = -1; - for (var i = 0; i < stack.length; i++) { - if (key == stack[i].key) { - idx = i; - break; - } - } - return stack.splice(idx, 1)[0]; - }, - removeTop: function() { - return stack.splice(stack.length - 1, 1)[0]; - }, - length: function() { - return stack.length; + }; + this.$setViewValue = function(value, trigger) { + ctrl.$viewValue = value; + if (!ctrl.$options || ctrl.$options.updateOnDefault) { + ctrl.$$debounceViewValueCommit(trigger); + } + }; + this.$$debounceViewValueCommit = function(trigger) { + var debounceDelay = 0, options = ctrl.$options, debounce; + if (options && isDefined(options.debounce)) { + debounce = options.debounce; + if (isNumber(debounce)) { + debounceDelay = debounce; + } else if (isNumber(debounce[trigger])) { + debounceDelay = debounce[trigger]; + } else if (isNumber(debounce["default"])) { + debounceDelay = debounce["default"]; } - }; - } - }; -}).factory("$$multiMap", function() { - return { - createNew: function() { - var map = {}; - return { - entries: function() { - return Object.keys(map).map(function(key) { - return { - key: key, - value: map[key] - }; - }); - }, - get: function(key) { - return map[key]; - }, - hasKey: function(key) { - return !!map[key]; - }, - keys: function() { - return Object.keys(map); - }, - put: function(key, value) { - if (!map[key]) { - map[key] = []; - } - map[key].push(value); - }, - remove: function(key, value) { - var values = map[key]; - if (!values) { - return; - } - var idx = values.indexOf(value); - if (idx !== -1) { - values.splice(idx, 1); - } - if (!values.length) { - delete map[key]; + } + $timeout.cancel(pendingDebounce); + if (debounceDelay) { + pendingDebounce = $timeout(function() { + ctrl.$commitViewValue(); + }, debounceDelay); + } else if ($rootScope.$$phase) { + ctrl.$commitViewValue(); + } else { + $scope.$apply(function() { + ctrl.$commitViewValue(); + }); + } + }; + $scope.$watch(function ngModelWatch() { + var modelValue = ngModelGet($scope); + if (modelValue !== ctrl.$modelValue && (ctrl.$modelValue === ctrl.$modelValue || modelValue === modelValue)) { + ctrl.$modelValue = ctrl.$$rawModelValue = modelValue; + parserValid = undefined; + var formatters = ctrl.$formatters, idx = formatters.length; + var viewValue = modelValue; + while (idx--) { + viewValue = formatters[idx](viewValue); + } + if (ctrl.$viewValue !== viewValue) { + ctrl.$viewValue = ctrl.$$lastCommittedViewValue = viewValue; + ctrl.$render(); + ctrl.$$runValidators(modelValue, viewValue, noop); + } + } + return modelValue; + }); + } ]; + var ngModelDirective = [ "$rootScope", function($rootScope) { + return { + restrict: "A", + require: [ "ngModel", "^?form", "^?ngModelOptions" ], + controller: NgModelController, + priority: 1, + compile: function ngModelCompile(element) { + element.addClass(PRISTINE_CLASS).addClass(UNTOUCHED_CLASS).addClass(VALID_CLASS); + return { + pre: function ngModelPreLink(scope, element, attr, ctrls) { + var modelCtrl = ctrls[0], formCtrl = ctrls[1] || modelCtrl.$$parentForm; + modelCtrl.$$setOptions(ctrls[2] && ctrls[2].$options); + formCtrl.$addControl(modelCtrl); + attr.$observe("name", function(newValue) { + if (modelCtrl.$name !== newValue) { + modelCtrl.$$parentForm.$$renameControl(modelCtrl, newValue); + } + }); + scope.$on("$destroy", function() { + modelCtrl.$$parentForm.$removeControl(modelCtrl); + }); + }, + post: function ngModelPostLink(scope, element, attr, ctrls) { + var modelCtrl = ctrls[0]; + if (modelCtrl.$options && modelCtrl.$options.updateOn) { + element.on(modelCtrl.$options.updateOn, function(ev) { + modelCtrl.$$debounceViewValueCommit(ev && ev.type); + }); + } + element.on("blur", function(ev) { + if (modelCtrl.$touched) return; + if ($rootScope.$$phase) { + scope.$evalAsync(modelCtrl.$setTouched); + } else { + scope.$apply(modelCtrl.$setTouched); + } + }); } + }; + } + }; + } ]; + var DEFAULT_REGEXP = /(\s+|^)default(\s+|$)/; + var ngModelOptionsDirective = function() { + return { + restrict: "A", + controller: [ "$scope", "$attrs", function($scope, $attrs) { + var that = this; + this.$options = copy($scope.$eval($attrs.ngModelOptions)); + if (isDefined(this.$options.updateOn)) { + this.$options.updateOnDefault = false; + this.$options.updateOn = trim(this.$options.updateOn.replace(DEFAULT_REGEXP, function() { + that.$options.updateOnDefault = true; + return " "; + })); + } else { + this.$options.updateOnDefault = true; } - }; - } - }; -}).directive("modalBackdrop", [ "$animate", "$injector", "$modalStack", function($animate, $injector, $modalStack) { - var $animateCss = null; - if ($injector.has("$animateCss")) { - $animateCss = $injector.get("$animateCss"); - } - return { - restrict: "EA", - replace: true, - templateUrl: "template/modal/backdrop.html", - compile: function(tElement, tAttrs) { - tElement.addClass(tAttrs.backdropClass); - return linkFn; - } + } ] + }; }; - function linkFn(scope, element, attrs) { - if (attrs.modalInClass) { - if ($animateCss) { - $animateCss(element, { - addClass: attrs.modalInClass - }).start(); + function addSetValidityMethod(context) { + var ctrl = context.ctrl, $element = context.$element, classCache = {}, set = context.set, unset = context.unset, $animate = context.$animate; + classCache[INVALID_CLASS] = !(classCache[VALID_CLASS] = $element.hasClass(VALID_CLASS)); + ctrl.$setValidity = setValidity; + function setValidity(validationErrorKey, state, controller) { + if (isUndefined(state)) { + createAndSet("$pending", validationErrorKey, controller); } else { - $animate.addClass(element, attrs.modalInClass); + unsetAndCleanup("$pending", validationErrorKey, controller); } - scope.$on($modalStack.NOW_CLOSING_EVENT, function(e, setIsAsync) { - var done = setIsAsync(); - if ($animateCss) { - $animateCss(element, { - removeClass: attrs.modalInClass - }).start().then(done); + if (!isBoolean(state)) { + unset(ctrl.$error, validationErrorKey, controller); + unset(ctrl.$$success, validationErrorKey, controller); + } else { + if (state) { + unset(ctrl.$error, validationErrorKey, controller); + set(ctrl.$$success, validationErrorKey, controller); } else { - $animate.removeClass(element, attrs.modalInClass).then(done); - } - }); - } - } -} ]).directive("modalWindow", [ "$modalStack", "$q", "$animate", "$injector", function($modalStack, $q, $animate, $injector) { - var $animateCss = null; - if ($injector.has("$animateCss")) { - $animateCss = $injector.get("$animateCss"); - } - return { - restrict: "EA", - scope: { - index: "@" - }, - replace: true, - transclude: true, - templateUrl: function(tElement, tAttrs) { - return tAttrs.templateUrl || "template/modal/window.html"; - }, - link: function(scope, element, attrs) { - element.addClass(attrs.windowClass || ""); - scope.size = attrs.size; - scope.close = function(evt) { - var modal = $modalStack.getTop(); - if (modal && modal.value.backdrop && modal.value.backdrop !== "static" && evt.target === evt.currentTarget) { - evt.preventDefault(); - evt.stopPropagation(); - $modalStack.dismiss(modal.key, "backdrop click"); - } - }; - scope.$isRendered = true; - var modalRenderDeferObj = $q.defer(); - attrs.$observe("modalRender", function(value) { - if (value == "true") { - modalRenderDeferObj.resolve(); - } - }); - modalRenderDeferObj.promise.then(function() { - var animationPromise = null; - if (attrs.modalInClass) { - if ($animateCss) { - animationPromise = $animateCss(element, { - addClass: attrs.modalInClass - }).start(); - } else { - animationPromise = $animate.addClass(element, attrs.modalInClass); - } - scope.$on($modalStack.NOW_CLOSING_EVENT, function(e, setIsAsync) { - var done = setIsAsync(); - if ($animateCss) { - $animateCss(element, { - removeClass: attrs.modalInClass - }).start().then(done); - } else { - $animate.removeClass(element, attrs.modalInClass).then(done); - } - }); - } - $q.when(animationPromise).then(function() { - var inputsWithAutofocus = element[0].querySelectorAll("[autofocus]"); - if (inputsWithAutofocus.length) { - inputsWithAutofocus[0].focus(); - } else { - element[0].focus(); - } - }); - var modal = $modalStack.getTop(); - if (modal) { - $modalStack.modalRendered(modal.key); + set(ctrl.$error, validationErrorKey, controller); + unset(ctrl.$$success, validationErrorKey, controller); } - }); - } - }; -} ]).directive("modalAnimationClass", [ function() { - return { - compile: function(tElement, tAttrs) { - if (tAttrs.modalAnimation) { - tElement.addClass(tAttrs.modalAnimationClass); } + if (ctrl.$pending) { + cachedToggleClass(PENDING_CLASS, true); + ctrl.$valid = ctrl.$invalid = undefined; + toggleValidationCss("", null); + } else { + cachedToggleClass(PENDING_CLASS, false); + ctrl.$valid = isObjectEmpty(ctrl.$error); + ctrl.$invalid = !ctrl.$valid; + toggleValidationCss("", ctrl.$valid); + } + var combinedState; + if (ctrl.$pending && ctrl.$pending[validationErrorKey]) { + combinedState = undefined; + } else if (ctrl.$error[validationErrorKey]) { + combinedState = false; + } else if (ctrl.$$success[validationErrorKey]) { + combinedState = true; + } else { + combinedState = null; + } + toggleValidationCss(validationErrorKey, combinedState); + ctrl.$$parentForm.$setValidity(validationErrorKey, combinedState, ctrl); } - }; -} ]).directive("modalTransclude", function() { - return { - link: function($scope, $element, $attrs, controller, $transclude) { - $transclude($scope.$parent, function(clone) { - $element.empty(); - $element.append(clone); - }); - } - }; -}).factory("$modalStack", [ "$animate", "$timeout", "$document", "$compile", "$rootScope", "$q", "$injector", "$$multiMap", "$$stackedMap", function($animate, $timeout, $document, $compile, $rootScope, $q, $injector, $$multiMap, $$stackedMap) { - var $animateCss = null; - if ($injector.has("$animateCss")) { - $animateCss = $injector.get("$animateCss"); - } - var OPENED_MODAL_CLASS = "modal-open"; - var backdropDomEl, backdropScope; - var openedWindows = $$stackedMap.createNew(); - var openedClasses = $$multiMap.createNew(); - var $modalStack = { - NOW_CLOSING_EVENT: "modal.stack.now-closing" - }; - var focusableElementList; - var focusIndex = 0; - var tababbleSelector = "a[href], area[href], input:not([disabled]), " + "button:not([disabled]),select:not([disabled]), textarea:not([disabled]), " + "iframe, object, embed, *[tabindex], *[contenteditable=true]"; - function backdropIndex() { - var topBackdropIndex = -1; - var opened = openedWindows.keys(); - for (var i = 0; i < opened.length; i++) { - if (openedWindows.get(opened[i]).value.backdrop) { - topBackdropIndex = i; + function createAndSet(name, value, controller) { + if (!ctrl[name]) { + ctrl[name] = {}; } + set(ctrl[name], value, controller); } - return topBackdropIndex; - } - $rootScope.$watch(backdropIndex, function(newBackdropIndex) { - if (backdropScope) { - backdropScope.index = newBackdropIndex; + function unsetAndCleanup(name, value, controller) { + if (ctrl[name]) { + unset(ctrl[name], value, controller); + } + if (isObjectEmpty(ctrl[name])) { + ctrl[name] = undefined; + } } - }); - function removeModalWindow(modalInstance, elementToReceiveFocus) { - var body = $document.find("body").eq(0); - var modalWindow = openedWindows.get(modalInstance).value; - openedWindows.remove(modalInstance); - removeAfterAnimate(modalWindow.modalDomEl, modalWindow.modalScope, function() { - var modalBodyClass = modalWindow.openedClass || OPENED_MODAL_CLASS; - openedClasses.remove(modalBodyClass, modalInstance); - body.toggleClass(modalBodyClass, openedClasses.hasKey(modalBodyClass)); - }); - checkRemoveBackdrop(); - if (elementToReceiveFocus && elementToReceiveFocus.focus) { - elementToReceiveFocus.focus(); - } else { - body.focus(); + function cachedToggleClass(className, switchValue) { + if (switchValue && !classCache[className]) { + $animate.addClass($element, className); + classCache[className] = true; + } else if (!switchValue && classCache[className]) { + $animate.removeClass($element, className); + classCache[className] = false; + } + } + function toggleValidationCss(validationErrorKey, isValid) { + validationErrorKey = validationErrorKey ? "-" + snake_case(validationErrorKey, "-") : ""; + cachedToggleClass(VALID_CLASS + validationErrorKey, isValid === true); + cachedToggleClass(INVALID_CLASS + validationErrorKey, isValid === false); } } - function checkRemoveBackdrop() { - if (backdropDomEl && backdropIndex() == -1) { - var backdropScopeRef = backdropScope; - removeAfterAnimate(backdropDomEl, backdropScope, function() { - backdropScopeRef = null; - }); - backdropDomEl = undefined; - backdropScope = undefined; + function isObjectEmpty(obj) { + if (obj) { + for (var prop in obj) { + if (obj.hasOwnProperty(prop)) { + return false; + } + } } + return true; } - function removeAfterAnimate(domEl, scope, done) { - var asyncDeferred; - var asyncPromise = null; - var setIsAsync = function() { - if (!asyncDeferred) { - asyncDeferred = $q.defer(); - asyncPromise = asyncDeferred.promise; + var ngNonBindableDirective = ngDirective({ + terminal: true, + priority: 1e3 + }); + var ngOptionsMinErr = minErr("ngOptions"); + var NG_OPTIONS_REGEXP = /^\s*([\s\S]+?)(?:\s+as\s+([\s\S]+?))?(?:\s+group\s+by\s+([\s\S]+?))?(?:\s+disable\s+when\s+([\s\S]+?))?\s+for\s+(?:([\$\w][\$\w]*)|(?:\(\s*([\$\w][\$\w]*)\s*,\s*([\$\w][\$\w]*)\s*\)))\s+in\s+([\s\S]+?)(?:\s+track\s+by\s+([\s\S]+?))?$/; + var ngOptionsDirective = [ "$compile", "$parse", function($compile, $parse) { + function parseOptionsExpression(optionsExp, selectElement, scope) { + var match = optionsExp.match(NG_OPTIONS_REGEXP); + if (!match) { + throw ngOptionsMinErr("iexp", "Expected expression in form of " + "'_select_ (as _label_)? for (_key_,)?_value_ in _collection_'" + " but got '{0}'. Element: {1}", optionsExp, startingTag(selectElement)); } - return function asyncDone() { - asyncDeferred.resolve(); + var valueName = match[5] || match[7]; + var keyName = match[6]; + var selectAs = / as /.test(match[0]) && match[1]; + var trackBy = match[9]; + var valueFn = $parse(match[2] ? match[1] : valueName); + var selectAsFn = selectAs && $parse(selectAs); + var viewValueFn = selectAsFn || valueFn; + var trackByFn = trackBy && $parse(trackBy); + var getTrackByValueFn = trackBy ? function(value, locals) { + return trackByFn(scope, locals); + } : function getHashOfValue(value) { + return hashKey(value); }; - }; - scope.$broadcast($modalStack.NOW_CLOSING_EVENT, setIsAsync); - return $q.when(asyncPromise).then(afterAnimating); - function afterAnimating() { - if (afterAnimating.done) { - return; - } - afterAnimating.done = true; - if ($animateCss) { - $animateCss(domEl, { - event: "leave" - }).start().then(function() { - domEl.remove(); - }); - } else { - $animate.leave(domEl); + var getTrackByValue = function(value, key) { + return getTrackByValueFn(value, getLocals(value, key)); + }; + var displayFn = $parse(match[2] || match[1]); + var groupByFn = $parse(match[3] || ""); + var disableWhenFn = $parse(match[4] || ""); + var valuesFn = $parse(match[8]); + var locals = {}; + var getLocals = keyName ? function(value, key) { + locals[keyName] = key; + locals[valueName] = value; + return locals; + } : function(value) { + locals[valueName] = value; + return locals; + }; + function Option(selectValue, viewValue, label, group, disabled) { + this.selectValue = selectValue; + this.viewValue = viewValue; + this.label = label; + this.group = group; + this.disabled = disabled; } - scope.$destroy(); - if (done) { - done(); + function getOptionValuesKeys(optionValues) { + var optionValuesKeys; + if (!keyName && isArrayLike(optionValues)) { + optionValuesKeys = optionValues; + } else { + optionValuesKeys = []; + for (var itemKey in optionValues) { + if (optionValues.hasOwnProperty(itemKey) && itemKey.charAt(0) !== "$") { + optionValuesKeys.push(itemKey); + } + } + } + return optionValuesKeys; } + return { + trackBy: trackBy, + getTrackByValue: getTrackByValue, + getWatchables: $parse(valuesFn, function(optionValues) { + var watchedArray = []; + optionValues = optionValues || []; + var optionValuesKeys = getOptionValuesKeys(optionValues); + var optionValuesLength = optionValuesKeys.length; + for (var index = 0; index < optionValuesLength; index++) { + var key = optionValues === optionValuesKeys ? index : optionValuesKeys[index]; + var value = optionValues[key]; + var locals = getLocals(optionValues[key], key); + var selectValue = getTrackByValueFn(optionValues[key], locals); + watchedArray.push(selectValue); + if (match[2] || match[1]) { + var label = displayFn(scope, locals); + watchedArray.push(label); + } + if (match[4]) { + var disableWhen = disableWhenFn(scope, locals); + watchedArray.push(disableWhen); + } + } + return watchedArray; + }), + getOptions: function() { + var optionItems = []; + var selectValueMap = {}; + var optionValues = valuesFn(scope) || []; + var optionValuesKeys = getOptionValuesKeys(optionValues); + var optionValuesLength = optionValuesKeys.length; + for (var index = 0; index < optionValuesLength; index++) { + var key = optionValues === optionValuesKeys ? index : optionValuesKeys[index]; + var value = optionValues[key]; + var locals = getLocals(value, key); + var viewValue = viewValueFn(scope, locals); + var selectValue = getTrackByValueFn(viewValue, locals); + var label = displayFn(scope, locals); + var group = groupByFn(scope, locals); + var disabled = disableWhenFn(scope, locals); + var optionItem = new Option(selectValue, viewValue, label, group, disabled); + optionItems.push(optionItem); + selectValueMap[selectValue] = optionItem; + } + return { + items: optionItems, + selectValueMap: selectValueMap, + getOptionFromViewValue: function(value) { + return selectValueMap[getTrackByValue(value)]; + }, + getViewValueFromOption: function(option) { + return trackBy ? angular.copy(option.viewValue) : option.viewValue; + } + }; + } + }; } - } - $document.bind("keydown", function(evt) { - if (evt.isDefaultPrevented()) { - return evt; - } - var modal = openedWindows.top(); - if (modal && modal.value.keyboard) { - switch (evt.which) { - case 27: - { - evt.preventDefault(); - $rootScope.$apply(function() { - $modalStack.dismiss(modal.key, "escape key press"); - }); - break; + var optionTemplate = document.createElement("option"), optGroupTemplate = document.createElement("optgroup"); + return { + restrict: "A", + terminal: true, + require: [ "select", "?ngModel" ], + link: function(scope, selectElement, attr, ctrls) { + var ngModelCtrl = ctrls[1]; + if (!ngModelCtrl) return; + var selectCtrl = ctrls[0]; + var multiple = attr.multiple; + var emptyOption; + for (var i = 0, children = selectElement.children(), ii = children.length; i < ii; i++) { + if (children[i].value === "") { + emptyOption = children.eq(i); + break; + } } - - case 9: - { - $modalStack.loadFocusElementList(modal); - var focusChanged = false; - if (evt.shiftKey) { - if ($modalStack.isFocusInFirstItem(evt)) { - focusChanged = $modalStack.focusLastFocusableElement(); + var providedEmptyOption = !!emptyOption; + var unknownOption = jqLite(optionTemplate.cloneNode(false)); + unknownOption.val("?"); + var options; + var ngOptions = parseOptionsExpression(attr.ngOptions, selectElement, scope); + var renderEmptyOption = function() { + if (!providedEmptyOption) { + selectElement.prepend(emptyOption); + } + selectElement.val(""); + emptyOption.prop("selected", true); + emptyOption.attr("selected", true); + }; + var removeEmptyOption = function() { + if (!providedEmptyOption) { + emptyOption.remove(); + } + }; + var renderUnknownOption = function() { + selectElement.prepend(unknownOption); + selectElement.val("?"); + unknownOption.prop("selected", true); + unknownOption.attr("selected", true); + }; + var removeUnknownOption = function() { + unknownOption.remove(); + }; + if (!multiple) { + selectCtrl.writeValue = function writeNgOptionsValue(value) { + var option = options.getOptionFromViewValue(value); + if (option && !option.disabled) { + if (selectElement[0].value !== option.selectValue) { + removeUnknownOption(); + removeEmptyOption(); + selectElement[0].value = option.selectValue; + option.element.selected = true; + option.element.setAttribute("selected", "selected"); + } + } else { + if (value === null || providedEmptyOption) { + removeUnknownOption(); + renderEmptyOption(); + } else { + removeEmptyOption(); + renderUnknownOption(); + } } - } else { - if ($modalStack.isFocusInLastItem(evt)) { - focusChanged = $modalStack.focusFirstFocusableElement(); + }; + selectCtrl.readValue = function readNgOptionsValue() { + var selectedOption = options.selectValueMap[selectElement.val()]; + if (selectedOption && !selectedOption.disabled) { + removeEmptyOption(); + removeUnknownOption(); + return options.getViewValueFromOption(selectedOption); } + return null; + }; + if (ngOptions.trackBy) { + scope.$watch(function() { + return ngOptions.getTrackByValue(ngModelCtrl.$viewValue); + }, function() { + ngModelCtrl.$render(); + }); } - if (focusChanged) { - evt.preventDefault(); - evt.stopPropagation(); + } else { + ngModelCtrl.$isEmpty = function(value) { + return !value || value.length === 0; + }; + selectCtrl.writeValue = function writeNgOptionsMultiple(value) { + options.items.forEach(function(option) { + option.element.selected = false; + }); + if (value) { + value.forEach(function(item) { + var option = options.getOptionFromViewValue(item); + if (option && !option.disabled) option.element.selected = true; + }); + } + }; + selectCtrl.readValue = function readNgOptionsMultiple() { + var selectedValues = selectElement.val() || [], selections = []; + forEach(selectedValues, function(value) { + var option = options.selectValueMap[value]; + if (option && !option.disabled) selections.push(options.getViewValueFromOption(option)); + }); + return selections; + }; + if (ngOptions.trackBy) { + scope.$watchCollection(function() { + if (isArray(ngModelCtrl.$viewValue)) { + return ngModelCtrl.$viewValue.map(function(value) { + return ngOptions.getTrackByValue(value); + }); + } + }, function() { + ngModelCtrl.$render(); + }); } - break; } - } - } - }); - $modalStack.open = function(modalInstance, modal) { - var modalOpener = $document[0].activeElement, modalBodyClass = modal.openedClass || OPENED_MODAL_CLASS; - openedWindows.add(modalInstance, { - deferred: modal.deferred, - renderDeferred: modal.renderDeferred, - modalScope: modal.scope, - backdrop: modal.backdrop, - keyboard: modal.keyboard, - openedClass: modal.openedClass - }); - openedClasses.put(modalBodyClass, modalInstance); - var body = $document.find("body").eq(0), currBackdropIndex = backdropIndex(); - if (currBackdropIndex >= 0 && !backdropDomEl) { - backdropScope = $rootScope.$new(true); - backdropScope.index = currBackdropIndex; - var angularBackgroundDomEl = angular.element('
        '); - angularBackgroundDomEl.attr("backdrop-class", modal.backdropClass); - if (modal.animation) { - angularBackgroundDomEl.attr("modal-animation", "true"); - } - backdropDomEl = $compile(angularBackgroundDomEl)(backdropScope); - body.append(backdropDomEl); - } - var angularDomEl = angular.element('
        '); - angularDomEl.attr({ - "template-url": modal.windowTemplateUrl, - "window-class": modal.windowClass, - size: modal.size, - index: openedWindows.length() - 1, - animate: "animate" - }).html(modal.content); - if (modal.animation) { - angularDomEl.attr("modal-animation", "true"); - } - var modalDomEl = $compile(angularDomEl)(modal.scope); - openedWindows.top().value.modalDomEl = modalDomEl; - openedWindows.top().value.modalOpener = modalOpener; - body.append(modalDomEl); - body.addClass(modalBodyClass); - $modalStack.clearFocusListCache(); - }; - function broadcastClosing(modalWindow, resultOrReason, closing) { - return !modalWindow.value.modalScope.$broadcast("modal.closing", resultOrReason, closing).defaultPrevented; - } - $modalStack.close = function(modalInstance, result) { - var modalWindow = openedWindows.get(modalInstance); - if (modalWindow && broadcastClosing(modalWindow, result, true)) { - modalWindow.value.modalScope.$$uibDestructionScheduled = true; - modalWindow.value.deferred.resolve(result); - removeModalWindow(modalInstance, modalWindow.value.modalOpener); - return true; - } - return !modalWindow; - }; - $modalStack.dismiss = function(modalInstance, reason) { - var modalWindow = openedWindows.get(modalInstance); - if (modalWindow && broadcastClosing(modalWindow, reason, false)) { - modalWindow.value.modalScope.$$uibDestructionScheduled = true; - modalWindow.value.deferred.reject(reason); - removeModalWindow(modalInstance, modalWindow.value.modalOpener); - return true; - } - return !modalWindow; - }; - $modalStack.dismissAll = function(reason) { - var topModal = this.getTop(); - while (topModal && this.dismiss(topModal.key, reason)) { - topModal = this.getTop(); - } - }; - $modalStack.getTop = function() { - return openedWindows.top(); - }; - $modalStack.modalRendered = function(modalInstance) { - var modalWindow = openedWindows.get(modalInstance); - if (modalWindow) { - modalWindow.value.renderDeferred.resolve(); - } - }; - $modalStack.focusFirstFocusableElement = function() { - if (focusableElementList.length > 0) { - focusableElementList[0].focus(); - return true; - } - return false; - }; - $modalStack.focusLastFocusableElement = function() { - if (focusableElementList.length > 0) { - focusableElementList[focusableElementList.length - 1].focus(); - return true; - } - return false; - }; - $modalStack.isFocusInFirstItem = function(evt) { - if (focusableElementList.length > 0) { - return (evt.target || evt.srcElement) == focusableElementList[0]; - } - return false; - }; - $modalStack.isFocusInLastItem = function(evt) { - if (focusableElementList.length > 0) { - return (evt.target || evt.srcElement) == focusableElementList[focusableElementList.length - 1]; - } - return false; - }; - $modalStack.clearFocusListCache = function() { - focusableElementList = []; - focusIndex = 0; - }; - $modalStack.loadFocusElementList = function(modalWindow) { - if (focusableElementList === undefined || !focusableElementList.length0) { - if (modalWindow) { - var modalDomE1 = modalWindow.value.modalDomEl; - if (modalDomE1 && modalDomE1.length) { - focusableElementList = modalDomE1[0].querySelectorAll(tababbleSelector); + if (providedEmptyOption) { + emptyOption.remove(); + $compile(emptyOption)(scope); + emptyOption.removeClass("ng-scope"); + } else { + emptyOption = jqLite(optionTemplate.cloneNode(false)); } - } - } - }; - return $modalStack; -} ]).provider("$modal", function() { - var $modalProvider = { - options: { - animation: true, - backdrop: true, - keyboard: true - }, - $get: [ "$injector", "$rootScope", "$q", "$templateRequest", "$controller", "$modalStack", function($injector, $rootScope, $q, $templateRequest, $controller, $modalStack) { - var $modal = {}; - function getTemplatePromise(options) { - return options.template ? $q.when(options.template) : $templateRequest(angular.isFunction(options.templateUrl) ? options.templateUrl() : options.templateUrl); - } - function getResolvePromises(resolves) { - var promisesArr = []; - angular.forEach(resolves, function(value) { - if (angular.isFunction(value) || angular.isArray(value)) { - promisesArr.push($q.when($injector.invoke(value))); - } else if (angular.isString(value)) { - promisesArr.push($q.when($injector.get(value))); + updateOptions(); + scope.$watchCollection(ngOptions.getWatchables, updateOptions); + function updateOptionElement(option, element) { + option.element = element; + element.disabled = option.disabled; + if (option.label !== element.label) { + element.label = option.label; + element.textContent = option.label; + } + if (option.value !== element.value) element.value = option.selectValue; + } + function addOrReuseElement(parent, current, type, templateElement) { + var element; + if (current && lowercase(current.nodeName) === type) { + element = current; } else { - promisesArr.push($q.when(value)); + element = templateElement.cloneNode(false); + if (!current) { + parent.appendChild(element); + } else { + parent.insertBefore(element, current); + } } - }); - return promisesArr; - } - var promiseChain = null; - $modal.getPromiseChain = function() { - return promiseChain; - }; - $modal.open = function(modalOptions) { - var modalResultDeferred = $q.defer(); - var modalOpenedDeferred = $q.defer(); - var modalRenderDeferred = $q.defer(); - var modalInstance = { - result: modalResultDeferred.promise, - opened: modalOpenedDeferred.promise, - rendered: modalRenderDeferred.promise, - close: function(result) { - return $modalStack.close(modalInstance, result); - }, - dismiss: function(reason) { - return $modalStack.dismiss(modalInstance, reason); + return element; + } + function removeExcessElements(current) { + var next; + while (current) { + next = current.nextSibling; + jqLiteRemove(current); + current = next; } - }; - modalOptions = angular.extend({}, $modalProvider.options, modalOptions); - modalOptions.resolve = modalOptions.resolve || {}; - if (!modalOptions.template && !modalOptions.templateUrl) { - throw new Error("One of template or templateUrl options is required."); } - var templateAndResolvePromise = $q.all([ getTemplatePromise(modalOptions) ].concat(getResolvePromises(modalOptions.resolve))); - var samePromise; - samePromise = promiseChain = $q.all([ promiseChain ]).then(function() { - return templateAndResolvePromise; - }, function() { - return templateAndResolvePromise; - }).then(function resolveSuccess(tplAndVars) { - var modalScope = (modalOptions.scope || $rootScope).$new(); - modalScope.$close = modalInstance.close; - modalScope.$dismiss = modalInstance.dismiss; - modalScope.$on("$destroy", function() { - if (!modalScope.$$uibDestructionScheduled) { - modalScope.$dismiss("$uibUnscheduledDestruction"); + function skipEmptyAndUnknownOptions(current) { + var emptyOption_ = emptyOption && emptyOption[0]; + var unknownOption_ = unknownOption && unknownOption[0]; + if (emptyOption_ || unknownOption_) { + while (current && (current === emptyOption_ || current === unknownOption_ || emptyOption_ && emptyOption_.nodeType === NODE_TYPE_COMMENT)) { + current = current.nextSibling; + } + } + return current; + } + function updateOptions() { + var previousValue = options && selectCtrl.readValue(); + options = ngOptions.getOptions(); + var groupMap = {}; + var currentElement = selectElement[0].firstChild; + if (providedEmptyOption) { + selectElement.prepend(emptyOption); + } + currentElement = skipEmptyAndUnknownOptions(currentElement); + options.items.forEach(function updateOption(option) { + var group; + var groupElement; + var optionElement; + if (option.group) { + group = groupMap[option.group]; + if (!group) { + groupElement = addOrReuseElement(selectElement[0], currentElement, "optgroup", optGroupTemplate); + currentElement = groupElement.nextSibling; + groupElement.label = option.group; + group = groupMap[option.group] = { + groupElement: groupElement, + currentOptionElement: groupElement.firstChild + }; + } + optionElement = addOrReuseElement(group.groupElement, group.currentOptionElement, "option", optionTemplate); + updateOptionElement(option, optionElement); + group.currentOptionElement = optionElement.nextSibling; + } else { + optionElement = addOrReuseElement(selectElement[0], currentElement, "option", optionTemplate); + updateOptionElement(option, optionElement); + currentElement = optionElement.nextSibling; } }); - var ctrlInstance, ctrlLocals = {}; - var resolveIter = 1; - if (modalOptions.controller) { - ctrlLocals.$scope = modalScope; - ctrlLocals.$modalInstance = modalInstance; - angular.forEach(modalOptions.resolve, function(value, key) { - ctrlLocals[key] = tplAndVars[resolveIter++]; - }); - ctrlInstance = $controller(modalOptions.controller, ctrlLocals); - if (modalOptions.controllerAs) { - if (modalOptions.bindToController) { - angular.extend(ctrlInstance, modalScope); - } - modalScope[modalOptions.controllerAs] = ctrlInstance; + Object.keys(groupMap).forEach(function(key) { + removeExcessElements(groupMap[key].currentOptionElement); + }); + removeExcessElements(currentElement); + ngModelCtrl.$render(); + if (!ngModelCtrl.$isEmpty(previousValue)) { + var nextValue = selectCtrl.readValue(); + if (ngOptions.trackBy ? !equals(previousValue, nextValue) : previousValue !== nextValue) { + ngModelCtrl.$setViewValue(nextValue); + ngModelCtrl.$render(); } } - $modalStack.open(modalInstance, { - scope: modalScope, - deferred: modalResultDeferred, - renderDeferred: modalRenderDeferred, - content: tplAndVars[0], - animation: modalOptions.animation, - backdrop: modalOptions.backdrop, - keyboard: modalOptions.keyboard, - backdropClass: modalOptions.backdropClass, - windowClass: modalOptions.windowClass, - windowTemplateUrl: modalOptions.windowTemplateUrl, - size: modalOptions.size, - openedClass: modalOptions.openedClass - }); - modalOpenedDeferred.resolve(true); - }, function resolveError(reason) { - modalOpenedDeferred.reject(reason); - modalResultDeferred.reject(reason); - }).finally(function() { - if (promiseChain === samePromise) { - promiseChain = null; + } + } + }; + } ]; + var ngPluralizeDirective = [ "$locale", "$interpolate", "$log", function($locale, $interpolate, $log) { + var BRACE = /{}/g, IS_WHEN = /^when(Minus)?(.+)$/; + return { + link: function(scope, element, attr) { + var numberExp = attr.count, whenExp = attr.$attr.when && element.attr(attr.$attr.when), offset = attr.offset || 0, whens = scope.$eval(whenExp) || {}, whensExpFns = {}, startSymbol = $interpolate.startSymbol(), endSymbol = $interpolate.endSymbol(), braceReplacement = startSymbol + numberExp + "-" + offset + endSymbol, watchRemover = angular.noop, lastCount; + forEach(attr, function(expression, attributeName) { + var tmpMatch = IS_WHEN.exec(attributeName); + if (tmpMatch) { + var whenKey = (tmpMatch[1] ? "-" : "") + lowercase(tmpMatch[2]); + whens[whenKey] = element.attr(attr.$attr[attributeName]); } }); - return modalInstance; - }; - return $modal; - } ] - }; - return $modalProvider; -}); - -angular.module("ui.bootstrap.pagination", []).controller("PaginationController", [ "$scope", "$attrs", "$parse", function($scope, $attrs, $parse) { - var self = this, ngModelCtrl = { - $setViewValue: angular.noop - }, setNumPages = $attrs.numPages ? $parse($attrs.numPages).assign : angular.noop; - this.init = function(ngModelCtrl_, config) { - ngModelCtrl = ngModelCtrl_; - this.config = config; - ngModelCtrl.$render = function() { - self.render(); - }; - if ($attrs.itemsPerPage) { - $scope.$parent.$watch($parse($attrs.itemsPerPage), function(value) { - self.itemsPerPage = parseInt(value, 10); - $scope.totalPages = self.calculateTotalPages(); - }); - } else { - this.itemsPerPage = config.itemsPerPage; - } - $scope.$watch("totalItems", function() { - $scope.totalPages = self.calculateTotalPages(); - }); - $scope.$watch("totalPages", function(value) { - setNumPages($scope.$parent, value); - if ($scope.page > value) { - $scope.selectPage(value); - } else { - ngModelCtrl.$render(); - } - }); - }; - this.calculateTotalPages = function() { - var totalPages = this.itemsPerPage < 1 ? 1 : Math.ceil($scope.totalItems / this.itemsPerPage); - return Math.max(totalPages || 0, 1); - }; - this.render = function() { - $scope.page = parseInt(ngModelCtrl.$viewValue, 10) || 1; - }; - $scope.selectPage = function(page, evt) { - if (evt) { - evt.preventDefault(); - } - var clickAllowed = !$scope.ngDisabled || !evt; - if (clickAllowed && $scope.page !== page && page > 0 && page <= $scope.totalPages) { - if (evt && evt.target) { - evt.target.blur(); - } - ngModelCtrl.$setViewValue(page); - ngModelCtrl.$render(); - } - }; - $scope.getText = function(key) { - return $scope[key + "Text"] || self.config[key + "Text"]; - }; - $scope.noPrevious = function() { - return $scope.page === 1; - }; - $scope.noNext = function() { - return $scope.page === $scope.totalPages; - }; -} ]).constant("paginationConfig", { - itemsPerPage: 10, - boundaryLinks: false, - directionLinks: true, - firstText: "First", - previousText: "Previous", - nextText: "Next", - lastText: "Last", - rotate: true -}).directive("pagination", [ "$parse", "paginationConfig", function($parse, paginationConfig) { - return { - restrict: "EA", - scope: { - totalItems: "=", - firstText: "@", - previousText: "@", - nextText: "@", - lastText: "@", - ngDisabled: "=" - }, - require: [ "pagination", "?ngModel" ], - controller: "PaginationController", - controllerAs: "pagination", - templateUrl: function(element, attrs) { - return attrs.templateUrl || "template/pagination/pagination.html"; - }, - replace: true, - link: function(scope, element, attrs, ctrls) { - var paginationCtrl = ctrls[0], ngModelCtrl = ctrls[1]; - if (!ngModelCtrl) { - return; - } - var maxSize = angular.isDefined(attrs.maxSize) ? scope.$parent.$eval(attrs.maxSize) : paginationConfig.maxSize, rotate = angular.isDefined(attrs.rotate) ? scope.$parent.$eval(attrs.rotate) : paginationConfig.rotate; - scope.boundaryLinks = angular.isDefined(attrs.boundaryLinks) ? scope.$parent.$eval(attrs.boundaryLinks) : paginationConfig.boundaryLinks; - scope.directionLinks = angular.isDefined(attrs.directionLinks) ? scope.$parent.$eval(attrs.directionLinks) : paginationConfig.directionLinks; - paginationCtrl.init(ngModelCtrl, paginationConfig); - if (attrs.maxSize) { - scope.$parent.$watch($parse(attrs.maxSize), function(value) { - maxSize = parseInt(value, 10); - paginationCtrl.render(); + forEach(whens, function(expression, key) { + whensExpFns[key] = $interpolate(expression.replace(BRACE, braceReplacement)); }); - } - function makePage(number, text, isActive) { - return { - number: number, - text: text, - active: isActive - }; - } - function getPages(currentPage, totalPages) { - var pages = []; - var startPage = 1, endPage = totalPages; - var isMaxSized = angular.isDefined(maxSize) && maxSize < totalPages; - if (isMaxSized) { - if (rotate) { - startPage = Math.max(currentPage - Math.floor(maxSize / 2), 1); - endPage = startPage + maxSize - 1; - if (endPage > totalPages) { - endPage = totalPages; - startPage = endPage - maxSize + 1; - } - } else { - startPage = (Math.ceil(currentPage / maxSize) - 1) * maxSize + 1; - endPage = Math.min(startPage + maxSize - 1, totalPages); + scope.$watch(numberExp, function ngPluralizeWatchAction(newVal) { + var count = parseFloat(newVal); + var countIsNaN = isNaN(count); + if (!countIsNaN && !(count in whens)) { + count = $locale.pluralCat(count - offset); + } + if (count !== lastCount && !(countIsNaN && isNumber(lastCount) && isNaN(lastCount))) { + watchRemover(); + var whenExpFn = whensExpFns[count]; + if (isUndefined(whenExpFn)) { + if (newVal != null) { + $log.debug("ngPluralize: no rule defined for '" + count + "' in " + whenExp); + } + watchRemover = noop; + updateElementText(); + } else { + watchRemover = scope.$watch(whenExpFn, updateElementText); + } + lastCount = count; } + }); + function updateElementText(newText) { + element.text(newText || ""); } - for (var number = startPage; number <= endPage; number++) { - var page = makePage(number, number, number === currentPage); - pages.push(page); + } + }; + } ]; + var ngRepeatDirective = [ "$parse", "$animate", function($parse, $animate) { + var NG_REMOVED = "$$NG_REMOVED"; + var ngRepeatMinErr = minErr("ngRepeat"); + var updateScope = function(scope, index, valueIdentifier, value, keyIdentifier, key, arrayLength) { + scope[valueIdentifier] = value; + if (keyIdentifier) scope[keyIdentifier] = key; + scope.$index = index; + scope.$first = index === 0; + scope.$last = index === arrayLength - 1; + scope.$middle = !(scope.$first || scope.$last); + scope.$odd = !(scope.$even = (index & 1) === 0); + }; + var getBlockStart = function(block) { + return block.clone[0]; + }; + var getBlockEnd = function(block) { + return block.clone[block.clone.length - 1]; + }; + return { + restrict: "A", + multiElement: true, + transclude: "element", + priority: 1e3, + terminal: true, + $$tlb: true, + compile: function ngRepeatCompile($element, $attr) { + var expression = $attr.ngRepeat; + var ngRepeatEndComment = document.createComment(" end ngRepeat: " + expression + " "); + var match = expression.match(/^\s*([\s\S]+?)\s+in\s+([\s\S]+?)(?:\s+as\s+([\s\S]+?))?(?:\s+track\s+by\s+([\s\S]+?))?\s*$/); + if (!match) { + throw ngRepeatMinErr("iexp", "Expected expression in form of '_item_ in _collection_[ track by _id_]' but got '{0}'.", expression); } - if (isMaxSized && !rotate) { - if (startPage > 1) { - var previousPageSet = makePage(startPage - 1, "...", false); - pages.unshift(previousPageSet); - } - if (endPage < totalPages) { - var nextPageSet = makePage(endPage + 1, "...", false); - pages.push(nextPageSet); - } + var lhs = match[1]; + var rhs = match[2]; + var aliasAs = match[3]; + var trackByExp = match[4]; + match = lhs.match(/^(?:(\s*[\$\w]+)|\(\s*([\$\w]+)\s*,\s*([\$\w]+)\s*\))$/); + if (!match) { + throw ngRepeatMinErr("iidexp", "'_item_' in '_item_ in _collection_' should be an identifier or '(_key_, _value_)' expression, but got '{0}'.", lhs); } - return pages; - } - var originalRender = paginationCtrl.render; - paginationCtrl.render = function() { - originalRender(); - if (scope.page > 0 && scope.page <= scope.totalPages) { - scope.pages = getPages(scope.page, scope.totalPages); + var valueIdentifier = match[3] || match[1]; + var keyIdentifier = match[2]; + if (aliasAs && (!/^[$a-zA-Z_][$a-zA-Z0-9_]*$/.test(aliasAs) || /^(null|undefined|this|\$index|\$first|\$middle|\$last|\$even|\$odd|\$parent|\$root|\$id)$/.test(aliasAs))) { + throw ngRepeatMinErr("badident", "alias '{0}' is invalid --- must be a valid JS identifier which is not a reserved name.", aliasAs); } - }; - } - }; -} ]).constant("pagerConfig", { - itemsPerPage: 10, - previousText: "« Previous", - nextText: "Next »", - align: true -}).directive("pager", [ "pagerConfig", function(pagerConfig) { - return { - restrict: "EA", - scope: { - totalItems: "=", - previousText: "@", - nextText: "@", - ngDisabled: "=" - }, - require: [ "pager", "?ngModel" ], - controller: "PaginationController", - controllerAs: "pagination", - templateUrl: function(element, attrs) { - return attrs.templateUrl || "template/pagination/pager.html"; - }, - replace: true, - link: function(scope, element, attrs, ctrls) { - var paginationCtrl = ctrls[0], ngModelCtrl = ctrls[1]; - if (!ngModelCtrl) { - return; - } - scope.align = angular.isDefined(attrs.align) ? scope.$parent.$eval(attrs.align) : pagerConfig.align; - paginationCtrl.init(ngModelCtrl, pagerConfig); - } - }; -} ]); - -angular.module("ui.bootstrap.tooltip", [ "ui.bootstrap.position", "ui.bootstrap.bindHtml" ]).provider("$tooltip", function() { - var defaultOptions = { - placement: "top", - animation: true, - popupDelay: 0, - useContentExp: false - }; - var triggerMap = { - mouseenter: "mouseleave", - click: "click", - focus: "blur", - none: "" - }; - var globalOptions = {}; - this.options = function(value) { - angular.extend(globalOptions, value); - }; - this.setTriggers = function setTriggers(triggers) { - angular.extend(triggerMap, triggers); - }; - function snake_case(name) { - var regexp = /[A-Z]/g; - var separator = "-"; - return name.replace(regexp, function(letter, pos) { - return (pos ? separator : "") + letter.toLowerCase(); - }); - } - this.$get = [ "$window", "$compile", "$timeout", "$document", "$position", "$interpolate", "$rootScope", "$parse", function($window, $compile, $timeout, $document, $position, $interpolate, $rootScope, $parse) { - return function $tooltip(type, prefix, defaultTriggerShow, options) { - options = angular.extend({}, defaultOptions, globalOptions, options); - function getTriggers(trigger) { - var show = (trigger || options.trigger || defaultTriggerShow).split(" "); - var hide = show.map(function(trigger) { - return triggerMap[trigger] || trigger; - }); - return { - show: show, - hide: hide + var trackByExpGetter, trackByIdExpFn, trackByIdArrayFn, trackByIdObjFn; + var hashFnLocals = { + $id: hashKey }; - } - var directiveName = snake_case(type); - var startSym = $interpolate.startSymbol(); - var endSym = $interpolate.endSymbol(); - var template = "
        " + "
        "; - return { - restrict: "EA", - compile: function(tElem, tAttrs) { - var tooltipLinker = $compile(template); - return function link(scope, element, attrs, tooltipCtrl) { - var tooltip; - var tooltipLinkedScope; - var transitionTimeout; - var popupTimeout; - var positionTimeout; - var appendToBody = angular.isDefined(options.appendToBody) ? options.appendToBody : false; - var triggers = getTriggers(undefined); - var hasEnableExp = angular.isDefined(attrs[prefix + "Enable"]); - var ttScope = scope.$new(true); - var repositionScheduled = false; - var isOpenExp = angular.isDefined(attrs[prefix + "IsOpen"]) ? $parse(attrs[prefix + "IsOpen"]) : false; - var positionTooltip = function() { - if (!tooltip) { - return; - } - if (!positionTimeout) { - positionTimeout = $timeout(function() { - tooltip.css({ - top: 0, - left: 0, - width: "auto", - height: "auto" - }); - var ttBox = $position.position(tooltip); - var ttCss = $position.positionElements(element, tooltip, ttScope.placement, appendToBody); - ttCss.top += "px"; - ttCss.left += "px"; - ttCss.width = ttBox.width + "px"; - ttCss.height = ttBox.height + "px"; - tooltip.css(ttCss); - positionTimeout = null; - }, 0, false); - } + if (trackByExp) { + trackByExpGetter = $parse(trackByExp); + } else { + trackByIdArrayFn = function(key, value) { + return hashKey(value); + }; + trackByIdObjFn = function(key) { + return key; + }; + } + return function ngRepeatLink($scope, $element, $attr, ctrl, $transclude) { + if (trackByExpGetter) { + trackByIdExpFn = function(key, value, index) { + if (keyIdentifier) hashFnLocals[keyIdentifier] = key; + hashFnLocals[valueIdentifier] = value; + hashFnLocals.$index = index; + return trackByExpGetter($scope, hashFnLocals); }; - ttScope.origScope = scope; - ttScope.isOpen = false; - function toggleTooltipBind() { - if (!ttScope.isOpen) { - showTooltipBind(); - } else { - hideTooltipBind(); - } - } - function showTooltipBind() { - if (hasEnableExp && !scope.$eval(attrs[prefix + "Enable"])) { - return; - } - prepareTooltip(); - if (ttScope.popupDelay) { - if (!popupTimeout) { - popupTimeout = $timeout(show, ttScope.popupDelay, false); - } - } else { - show(); - } - } - function hideTooltipBind() { - hide(); - if (!$rootScope.$$phase) { - $rootScope.$digest(); - } - } - function show() { - popupTimeout = null; - if (transitionTimeout) { - $timeout.cancel(transitionTimeout); - transitionTimeout = null; - } - if (!(options.useContentExp ? ttScope.contentExp() : ttScope.content)) { - return angular.noop; - } - createTooltip(); - ttScope.isOpen = true; - if (isOpenExp) { - isOpenExp.assign(ttScope.origScope, ttScope.isOpen); - } - if (!$rootScope.$$phase) { - ttScope.$apply(); - } - tooltip.css({ - display: "block" - }); - positionTooltip(); + } + var lastBlockMap = createMap(); + $scope.$watchCollection(rhs, function ngRepeatAction(collection) { + var index, length, previousNode = $element[0], nextNode, nextBlockMap = createMap(), collectionLength, key, value, trackById, trackByIdFn, collectionKeys, block, nextBlockOrder, elementsToRemove; + if (aliasAs) { + $scope[aliasAs] = collection; } - function hide() { - ttScope.isOpen = false; - if (isOpenExp) { - isOpenExp.assign(ttScope.origScope, ttScope.isOpen); - } - $timeout.cancel(popupTimeout); - popupTimeout = null; - $timeout.cancel(positionTimeout); - positionTimeout = null; - if (ttScope.animation) { - if (!transitionTimeout) { - transitionTimeout = $timeout(removeTooltip, 500); + if (isArrayLike(collection)) { + collectionKeys = collection; + trackByIdFn = trackByIdExpFn || trackByIdArrayFn; + } else { + trackByIdFn = trackByIdExpFn || trackByIdObjFn; + collectionKeys = []; + for (var itemKey in collection) { + if (hasOwnProperty.call(collection, itemKey) && itemKey.charAt(0) !== "$") { + collectionKeys.push(itemKey); } - } else { - removeTooltip(); } } - function createTooltip() { - if (tooltip) { - removeTooltip(); - } - tooltipLinkedScope = ttScope.$new(); - tooltip = tooltipLinker(tooltipLinkedScope, function(tooltip) { - if (appendToBody) { - $document.find("body").append(tooltip); - } else { - element.after(tooltip); - } - }); - if (options.useContentExp) { - tooltipLinkedScope.$watch("contentExp()", function(val) { - if (!val && ttScope.isOpen) { - hide(); - } - }); - tooltipLinkedScope.$watch(function() { - if (!repositionScheduled) { - repositionScheduled = true; - tooltipLinkedScope.$$postDigest(function() { - repositionScheduled = false; - if (ttScope.isOpen) { - positionTooltip(); - } - }); - } + collectionLength = collectionKeys.length; + nextBlockOrder = new Array(collectionLength); + for (index = 0; index < collectionLength; index++) { + key = collection === collectionKeys ? index : collectionKeys[index]; + value = collection[key]; + trackById = trackByIdFn(key, value, index); + if (lastBlockMap[trackById]) { + block = lastBlockMap[trackById]; + delete lastBlockMap[trackById]; + nextBlockMap[trackById] = block; + nextBlockOrder[index] = block; + } else if (nextBlockMap[trackById]) { + forEach(nextBlockOrder, function(block) { + if (block && block.scope) lastBlockMap[block.id] = block; }); + throw ngRepeatMinErr("dupes", "Duplicates in a repeater are not allowed. Use 'track by' expression to specify unique keys. Repeater: {0}, Duplicate key: {1}, Duplicate value: {2}", expression, trackById, value); + } else { + nextBlockOrder[index] = { + id: trackById, + scope: undefined, + clone: undefined + }; + nextBlockMap[trackById] = true; } } - function removeTooltip() { - transitionTimeout = null; - if (tooltip) { - tooltip.remove(); - tooltip = null; - } - if (tooltipLinkedScope) { - tooltipLinkedScope.$destroy(); - tooltipLinkedScope = null; + for (var blockKey in lastBlockMap) { + block = lastBlockMap[blockKey]; + elementsToRemove = getBlockNodes(block.clone); + $animate.leave(elementsToRemove); + if (elementsToRemove[0].parentNode) { + for (index = 0, length = elementsToRemove.length; index < length; index++) { + elementsToRemove[index][NG_REMOVED] = true; + } } + block.scope.$destroy(); } - function prepareTooltip() { - prepPopupClass(); - prepPlacement(); - prepPopupDelay(); - } - ttScope.contentExp = function() { - return scope.$eval(attrs[type]); - }; - if (!options.useContentExp) { - attrs.$observe(type, function(val) { - ttScope.content = val; - if (!val && ttScope.isOpen) { - hide(); - } else { - positionTooltip(); + for (index = 0; index < collectionLength; index++) { + key = collection === collectionKeys ? index : collectionKeys[index]; + value = collection[key]; + block = nextBlockOrder[index]; + if (block.scope) { + nextNode = previousNode; + do { + nextNode = nextNode.nextSibling; + } while (nextNode && nextNode[NG_REMOVED]); + if (getBlockStart(block) != nextNode) { + $animate.move(getBlockNodes(block.clone), null, jqLite(previousNode)); } - }); - } - attrs.$observe("disabled", function(val) { - if (popupTimeout && val) { - $timeout.cancel(popupTimeout); - popupTimeout = null; + previousNode = getBlockEnd(block); + updateScope(block.scope, index, valueIdentifier, value, keyIdentifier, key, collectionLength); + } else { + $transclude(function ngRepeatTransclude(clone, scope) { + block.scope = scope; + var endNode = ngRepeatEndComment.cloneNode(false); + clone[clone.length++] = endNode; + $animate.enter(clone, null, jqLite(previousNode)); + previousNode = endNode; + block.clone = clone; + nextBlockMap[block.id] = block; + updateScope(block.scope, index, valueIdentifier, value, keyIdentifier, key, collectionLength); + }); } - if (val && ttScope.isOpen) { - hide(); + } + lastBlockMap = nextBlockMap; + }); + }; + } + }; + } ]; + var NG_HIDE_CLASS = "ng-hide"; + var NG_HIDE_IN_PROGRESS_CLASS = "ng-hide-animate"; + var ngShowDirective = [ "$animate", function($animate) { + return { + restrict: "A", + multiElement: true, + link: function(scope, element, attr) { + scope.$watch(attr.ngShow, function ngShowWatchAction(value) { + $animate[value ? "removeClass" : "addClass"](element, NG_HIDE_CLASS, { + tempClasses: NG_HIDE_IN_PROGRESS_CLASS + }); + }); + } + }; + } ]; + var ngHideDirective = [ "$animate", function($animate) { + return { + restrict: "A", + multiElement: true, + link: function(scope, element, attr) { + scope.$watch(attr.ngHide, function ngHideWatchAction(value) { + $animate[value ? "addClass" : "removeClass"](element, NG_HIDE_CLASS, { + tempClasses: NG_HIDE_IN_PROGRESS_CLASS + }); + }); + } + }; + } ]; + var ngStyleDirective = ngDirective(function(scope, element, attr) { + scope.$watch(attr.ngStyle, function ngStyleWatchAction(newStyles, oldStyles) { + if (oldStyles && newStyles !== oldStyles) { + forEach(oldStyles, function(val, style) { + element.css(style, ""); + }); + } + if (newStyles) element.css(newStyles); + }, true); + }); + var ngSwitchDirective = [ "$animate", function($animate) { + return { + require: "ngSwitch", + controller: [ "$scope", function ngSwitchController() { + this.cases = {}; + } ], + link: function(scope, element, attr, ngSwitchController) { + var watchExpr = attr.ngSwitch || attr.on, selectedTranscludes = [], selectedElements = [], previousLeaveAnimations = [], selectedScopes = []; + var spliceFactory = function(array, index) { + return function() { + array.splice(index, 1); + }; + }; + scope.$watch(watchExpr, function ngSwitchWatchAction(value) { + var i, ii; + for (i = 0, ii = previousLeaveAnimations.length; i < ii; ++i) { + $animate.cancel(previousLeaveAnimations[i]); + } + previousLeaveAnimations.length = 0; + for (i = 0, ii = selectedScopes.length; i < ii; ++i) { + var selected = getBlockNodes(selectedElements[i].clone); + selectedScopes[i].$destroy(); + var promise = previousLeaveAnimations[i] = $animate.leave(selected); + promise.then(spliceFactory(previousLeaveAnimations, i)); + } + selectedElements.length = 0; + selectedScopes.length = 0; + if (selectedTranscludes = ngSwitchController.cases["!" + value] || ngSwitchController.cases["?"]) { + forEach(selectedTranscludes, function(selectedTransclude) { + selectedTransclude.transclude(function(caseElement, selectedScope) { + selectedScopes.push(selectedScope); + var anchor = selectedTransclude.element; + caseElement[caseElement.length++] = document.createComment(" end ngSwitchWhen: "); + var block = { + clone: caseElement + }; + selectedElements.push(block); + $animate.enter(caseElement, anchor.parent(), anchor); + }); + }); + } + }); + } + }; + } ]; + var ngSwitchWhenDirective = ngDirective({ + transclude: "element", + priority: 1200, + require: "^ngSwitch", + multiElement: true, + link: function(scope, element, attrs, ctrl, $transclude) { + ctrl.cases["!" + attrs.ngSwitchWhen] = ctrl.cases["!" + attrs.ngSwitchWhen] || []; + ctrl.cases["!" + attrs.ngSwitchWhen].push({ + transclude: $transclude, + element: element + }); + } + }); + var ngSwitchDefaultDirective = ngDirective({ + transclude: "element", + priority: 1200, + require: "^ngSwitch", + multiElement: true, + link: function(scope, element, attr, ctrl, $transclude) { + ctrl.cases["?"] = ctrl.cases["?"] || []; + ctrl.cases["?"].push({ + transclude: $transclude, + element: element + }); + } + }); + var ngTranscludeDirective = ngDirective({ + restrict: "EAC", + link: function($scope, $element, $attrs, controller, $transclude) { + if (!$transclude) { + throw minErr("ngTransclude")("orphan", "Illegal use of ngTransclude directive in the template! " + "No parent directive that requires a transclusion found. " + "Element: {0}", startingTag($element)); + } + $transclude(function(clone) { + $element.empty(); + $element.append(clone); + }); + } + }); + var scriptDirective = [ "$templateCache", function($templateCache) { + return { + restrict: "E", + terminal: true, + compile: function(element, attr) { + if (attr.type == "text/ng-template") { + var templateUrl = attr.id, text = element[0].text; + $templateCache.put(templateUrl, text); + } + } + }; + } ]; + var noopNgModelController = { + $setViewValue: noop, + $render: noop + }; + var SelectController = [ "$element", "$scope", "$attrs", function($element, $scope, $attrs) { + var self = this, optionsMap = new HashMap(); + self.ngModelCtrl = noopNgModelController; + self.unknownOption = jqLite(document.createElement("option")); + self.renderUnknownOption = function(val) { + var unknownVal = "? " + hashKey(val) + " ?"; + self.unknownOption.val(unknownVal); + $element.prepend(self.unknownOption); + $element.val(unknownVal); + }; + $scope.$on("$destroy", function() { + self.renderUnknownOption = noop; + }); + self.removeUnknownOption = function() { + if (self.unknownOption.parent()) self.unknownOption.remove(); + }; + self.readValue = function readSingleValue() { + self.removeUnknownOption(); + return $element.val(); + }; + self.writeValue = function writeSingleValue(value) { + if (self.hasOption(value)) { + self.removeUnknownOption(); + $element.val(value); + if (value === "") self.emptyOption.prop("selected", true); + } else { + if (value == null && self.emptyOption) { + self.removeUnknownOption(); + $element.val(""); + } else { + self.renderUnknownOption(value); + } + } + }; + self.addOption = function(value, element) { + assertNotHasOwnProperty(value, '"option value"'); + if (value === "") { + self.emptyOption = element; + } + var count = optionsMap.get(value) || 0; + optionsMap.put(value, count + 1); + }; + self.removeOption = function(value) { + var count = optionsMap.get(value); + if (count) { + if (count === 1) { + optionsMap.remove(value); + if (value === "") { + self.emptyOption = undefined; + } + } else { + optionsMap.put(value, count - 1); + } + } + }; + self.hasOption = function(value) { + return !!optionsMap.get(value); + }; + } ]; + var selectDirective = function() { + return { + restrict: "E", + require: [ "select", "?ngModel" ], + controller: SelectController, + link: function(scope, element, attr, ctrls) { + var ngModelCtrl = ctrls[1]; + if (!ngModelCtrl) return; + var selectCtrl = ctrls[0]; + selectCtrl.ngModelCtrl = ngModelCtrl; + ngModelCtrl.$render = function() { + selectCtrl.writeValue(ngModelCtrl.$viewValue); + }; + element.on("change", function() { + scope.$apply(function() { + ngModelCtrl.$setViewValue(selectCtrl.readValue()); + }); + }); + if (attr.multiple) { + selectCtrl.readValue = function readMultipleValue() { + var array = []; + forEach(element.find("option"), function(option) { + if (option.selected) { + array.push(option.value); } }); - attrs.$observe(prefix + "Title", function(val) { - ttScope.title = val; - positionTooltip(); - }); - attrs.$observe(prefix + "Placement", function() { - if (ttScope.isOpen) { - prepPlacement(); - positionTooltip(); - } + return array; + }; + selectCtrl.writeValue = function writeMultipleValue(value) { + var items = new HashMap(value); + forEach(element.find("option"), function(option) { + option.selected = isDefined(items.get(option.value)); }); - if (isOpenExp) { - scope.$watch(isOpenExp, function(val) { - if (val !== ttScope.isOpen) { - toggleTooltipBind(); - } - }); - } - function prepPopupClass() { - ttScope.popupClass = attrs[prefix + "Class"]; - } - function prepPlacement() { - var val = attrs[prefix + "Placement"]; - ttScope.placement = angular.isDefined(val) ? val : options.placement; - } - function prepPopupDelay() { - var val = attrs[prefix + "PopupDelay"]; - var delay = parseInt(val, 10); - ttScope.popupDelay = !isNaN(delay) ? delay : options.popupDelay; + }; + var lastView, lastViewRef = NaN; + scope.$watch(function selectMultipleWatch() { + if (lastViewRef === ngModelCtrl.$viewValue && !equals(lastView, ngModelCtrl.$viewValue)) { + lastView = shallowCopy(ngModelCtrl.$viewValue); + ngModelCtrl.$render(); } - var unregisterTriggers = function() { - triggers.show.forEach(function(trigger) { - element.unbind(trigger, showTooltipBind); - }); - triggers.hide.forEach(function(trigger) { - element.unbind(trigger, hideTooltipBind); + lastViewRef = ngModelCtrl.$viewValue; + }); + ngModelCtrl.$isEmpty = function(value) { + return !value || value.length === 0; + }; + } + } + }; + }; + var optionDirective = [ "$interpolate", function($interpolate) { + function chromeHack(optionElement) { + if (optionElement[0].hasAttribute("selected")) { + optionElement[0].selected = true; + } + } + return { + restrict: "E", + priority: 100, + compile: function(element, attr) { + if (isDefined(attr.value)) { + var valueInterpolated = $interpolate(attr.value, true); + } else { + var interpolateFn = $interpolate(element.text(), true); + if (!interpolateFn) { + attr.$set("value", element.text()); + } + } + return function(scope, element, attr) { + var selectCtrlName = "$selectController", parent = element.parent(), selectCtrl = parent.data(selectCtrlName) || parent.parent().data(selectCtrlName); + function addOption(optionValue) { + selectCtrl.addOption(optionValue, element); + selectCtrl.ngModelCtrl.$render(); + chromeHack(element); + } + if (selectCtrl && selectCtrl.ngModelCtrl) { + if (valueInterpolated) { + var oldVal; + attr.$observe("value", function valueAttributeObserveAction(newVal) { + if (isDefined(oldVal)) { + selectCtrl.removeOption(oldVal); + } + oldVal = newVal; + addOption(newVal); }); - }; - function prepTriggers() { - var val = attrs[prefix + "Trigger"]; - unregisterTriggers(); - triggers = getTriggers(val); - if (triggers.show !== "none") { - triggers.show.forEach(function(trigger, idx) { - if (trigger === triggers.hide[idx]) { - element[0].addEventListener(trigger, toggleTooltipBind); - } else if (trigger) { - element[0].addEventListener(trigger, showTooltipBind); - element[0].addEventListener(triggers.hide[idx], hideTooltipBind); - } - }); - } - } - prepTriggers(); - var animation = scope.$eval(attrs[prefix + "Animation"]); - ttScope.animation = angular.isDefined(animation) ? !!animation : options.animation; - var appendToBodyVal = scope.$eval(attrs[prefix + "AppendToBody"]); - appendToBody = angular.isDefined(appendToBodyVal) ? appendToBodyVal : appendToBody; - if (appendToBody) { - scope.$on("$locationChangeSuccess", function closeTooltipOnLocationChangeSuccess() { - if (ttScope.isOpen) { - hide(); + } else if (interpolateFn) { + scope.$watch(interpolateFn, function interpolateWatchAction(newVal, oldVal) { + attr.$set("value", newVal); + if (oldVal !== newVal) { + selectCtrl.removeOption(oldVal); } + addOption(newVal); }); + } else { + addOption(attr.value); } - scope.$on("$destroy", function onDestroyTooltip() { - $timeout.cancel(transitionTimeout); - $timeout.cancel(popupTimeout); - $timeout.cancel(positionTimeout); - unregisterTriggers(); - removeTooltip(); - ttScope = null; + element.on("$destroy", function() { + selectCtrl.removeOption(attr.value); + selectCtrl.ngModelCtrl.$render(); }); - }; + } + }; + } + }; + } ]; + var styleDirective = valueFn({ + restrict: "E", + terminal: false + }); + var requiredDirective = function() { + return { + restrict: "A", + require: "?ngModel", + link: function(scope, elm, attr, ctrl) { + if (!ctrl) return; + attr.required = true; + ctrl.$validators.required = function(modelValue, viewValue) { + return !attr.required || !ctrl.$isEmpty(viewValue); + }; + attr.$observe("required", function() { + ctrl.$validate(); + }); + } + }; + }; + var patternDirective = function() { + return { + restrict: "A", + require: "?ngModel", + link: function(scope, elm, attr, ctrl) { + if (!ctrl) return; + var regexp, patternExp = attr.ngPattern || attr.pattern; + attr.$observe("pattern", function(regex) { + if (isString(regex) && regex.length > 0) { + regex = new RegExp("^" + regex + "$"); + } + if (regex && !regex.test) { + throw minErr("ngPattern")("noregexp", "Expected {0} to be a RegExp but was {1}. Element: {2}", patternExp, regex, startingTag(elm)); + } + regexp = regex || undefined; + ctrl.$validate(); + }); + ctrl.$validators.pattern = function(modelValue, viewValue) { + return ctrl.$isEmpty(viewValue) || isUndefined(regexp) || regexp.test(viewValue); + }; + } + }; + }; + var maxlengthDirective = function() { + return { + restrict: "A", + require: "?ngModel", + link: function(scope, elm, attr, ctrl) { + if (!ctrl) return; + var maxlength = -1; + attr.$observe("maxlength", function(value) { + var intVal = toInt(value); + maxlength = isNaN(intVal) ? -1 : intVal; + ctrl.$validate(); + }); + ctrl.$validators.maxlength = function(modelValue, viewValue) { + return maxlength < 0 || ctrl.$isEmpty(viewValue) || viewValue.length <= maxlength; + }; + } + }; + }; + var minlengthDirective = function() { + return { + restrict: "A", + require: "?ngModel", + link: function(scope, elm, attr, ctrl) { + if (!ctrl) return; + var minlength = 0; + attr.$observe("minlength", function(value) { + minlength = toInt(value) || 0; + ctrl.$validate(); + }); + ctrl.$validators.minlength = function(modelValue, viewValue) { + return ctrl.$isEmpty(viewValue) || viewValue.length >= minlength; + }; + } + }; + }; + if (window.angular.bootstrap) { + console.log("WARNING: Tried to load angular more than once."); + return; + } + bindJQuery(); + publishExternalAPI(angular); + angular.module("ngLocale", [], [ "$provide", function($provide) { + var PLURAL_CATEGORY = { + ZERO: "zero", + ONE: "one", + TWO: "two", + FEW: "few", + MANY: "many", + OTHER: "other" + }; + function getDecimals(n) { + n = n + ""; + var i = n.indexOf("."); + return i == -1 ? 0 : n.length - i - 1; + } + function getVF(n, opt_precision) { + var v = opt_precision; + if (undefined === v) { + v = Math.min(getDecimals(n), 3); + } + var base = Math.pow(10, v); + var f = (n * base | 0) % base; + return { + v: v, + f: f + }; + } + $provide.value("$locale", { + DATETIME_FORMATS: { + AMPMS: [ "AM", "PM" ], + DAY: [ "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" ], + ERANAMES: [ "Before Christ", "Anno Domini" ], + ERAS: [ "BC", "AD" ], + FIRSTDAYOFWEEK: 6, + MONTH: [ "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" ], + SHORTDAY: [ "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" ], + SHORTMONTH: [ "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" ], + WEEKENDRANGE: [ 5, 6 ], + fullDate: "EEEE, MMMM d, y", + longDate: "MMMM d, y", + medium: "MMM d, y h:mm:ss a", + mediumDate: "MMM d, y", + mediumTime: "h:mm:ss a", + "short": "M/d/yy h:mm a", + shortDate: "M/d/yy", + shortTime: "h:mm a" + }, + NUMBER_FORMATS: { + CURRENCY_SYM: "$", + DECIMAL_SEP: ".", + GROUP_SEP: ",", + PATTERNS: [ { + gSize: 3, + lgSize: 3, + maxFrac: 3, + minFrac: 0, + minInt: 1, + negPre: "-", + negSuf: "", + posPre: "", + posSuf: "" + }, { + gSize: 3, + lgSize: 3, + maxFrac: 2, + minFrac: 2, + minInt: 1, + negPre: "-¤", + negSuf: "", + posPre: "¤", + posSuf: "" + } ] + }, + id: "en-us", + pluralCat: function(n, opt_precision) { + var i = n | 0; + var vf = getVF(n, opt_precision); + if (i == 1 && vf.v == 0) { + return PLURAL_CATEGORY.ONE; + } + return PLURAL_CATEGORY.OTHER; + } + }); + } ]); + jqLite(document).ready(function() { + angularInit(document, bootstrap); + }); +})(window, document); + +!window.angular.$$csp().noInlineStyle && window.angular.element(document.head).prepend(''); + +if (typeof jQuery === "undefined") { + throw new Error("Bootstrap's JavaScript requires jQuery"); +} + ++function($) { + "use strict"; + var version = $.fn.jquery.split(" ")[0].split("."); + if (version[0] < 2 && version[1] < 9 || version[0] == 1 && version[1] == 9 && version[2] < 1) { + throw new Error("Bootstrap's JavaScript requires jQuery version 1.9.1 or higher"); + } +}(jQuery); + ++function($) { + "use strict"; + function transitionEnd() { + var el = document.createElement("bootstrap"); + var transEndEventNames = { + WebkitTransition: "webkitTransitionEnd", + MozTransition: "transitionend", + OTransition: "oTransitionEnd otransitionend", + transition: "transitionend" + }; + for (var name in transEndEventNames) { + if (el.style[name] !== undefined) { + return { + end: transEndEventNames[name] + }; + } + } + return false; + } + $.fn.emulateTransitionEnd = function(duration) { + var called = false; + var $el = this; + $(this).one("bsTransitionEnd", function() { + called = true; + }); + var callback = function() { + if (!called) $($el).trigger($.support.transition.end); + }; + setTimeout(callback, duration); + return this; + }; + $(function() { + $.support.transition = transitionEnd(); + if (!$.support.transition) return; + $.event.special.bsTransitionEnd = { + bindType: $.support.transition.end, + delegateType: $.support.transition.end, + handle: function(e) { + if ($(e.target).is(this)) return e.handleObj.handler.apply(this, arguments); + } + }; + }); +}(jQuery); + ++function($) { + "use strict"; + var dismiss = '[data-dismiss="alert"]'; + var Alert = function(el) { + $(el).on("click", dismiss, this.close); + }; + Alert.VERSION = "3.3.5"; + Alert.TRANSITION_DURATION = 150; + Alert.prototype.close = function(e) { + var $this = $(this); + var selector = $this.attr("data-target"); + if (!selector) { + selector = $this.attr("href"); + selector = selector && selector.replace(/.*(?=#[^\s]*$)/, ""); + } + var $parent = $(selector); + if (e) e.preventDefault(); + if (!$parent.length) { + $parent = $this.closest(".alert"); + } + $parent.trigger(e = $.Event("close.bs.alert")); + if (e.isDefaultPrevented()) return; + $parent.removeClass("in"); + function removeElement() { + $parent.detach().trigger("closed.bs.alert").remove(); + } + $.support.transition && $parent.hasClass("fade") ? $parent.one("bsTransitionEnd", removeElement).emulateTransitionEnd(Alert.TRANSITION_DURATION) : removeElement(); + }; + function Plugin(option) { + return this.each(function() { + var $this = $(this); + var data = $this.data("bs.alert"); + if (!data) $this.data("bs.alert", data = new Alert(this)); + if (typeof option == "string") data[option].call($this); + }); + } + var old = $.fn.alert; + $.fn.alert = Plugin; + $.fn.alert.Constructor = Alert; + $.fn.alert.noConflict = function() { + $.fn.alert = old; + return this; + }; + $(document).on("click.bs.alert.data-api", dismiss, Alert.prototype.close); +}(jQuery); + ++function($) { + "use strict"; + var Button = function(element, options) { + this.$element = $(element); + this.options = $.extend({}, Button.DEFAULTS, options); + this.isLoading = false; + }; + Button.VERSION = "3.3.5"; + Button.DEFAULTS = { + loadingText: "loading..." + }; + Button.prototype.setState = function(state) { + var d = "disabled"; + var $el = this.$element; + var val = $el.is("input") ? "val" : "html"; + var data = $el.data(); + state += "Text"; + if (data.resetText == null) $el.data("resetText", $el[val]()); + setTimeout($.proxy(function() { + $el[val](data[state] == null ? this.options[state] : data[state]); + if (state == "loadingText") { + this.isLoading = true; + $el.addClass(d).attr(d, d); + } else if (this.isLoading) { + this.isLoading = false; + $el.removeClass(d).removeAttr(d); + } + }, this), 0); + }; + Button.prototype.toggle = function() { + var changed = true; + var $parent = this.$element.closest('[data-toggle="buttons"]'); + if ($parent.length) { + var $input = this.$element.find("input"); + if ($input.prop("type") == "radio") { + if ($input.prop("checked")) changed = false; + $parent.find(".active").removeClass("active"); + this.$element.addClass("active"); + } else if ($input.prop("type") == "checkbox") { + if ($input.prop("checked") !== this.$element.hasClass("active")) changed = false; + this.$element.toggleClass("active"); + } + $input.prop("checked", this.$element.hasClass("active")); + if (changed) $input.trigger("change"); + } else { + this.$element.attr("aria-pressed", !this.$element.hasClass("active")); + this.$element.toggleClass("active"); + } + }; + function Plugin(option) { + return this.each(function() { + var $this = $(this); + var data = $this.data("bs.button"); + var options = typeof option == "object" && option; + if (!data) $this.data("bs.button", data = new Button(this, options)); + if (option == "toggle") data.toggle(); else if (option) data.setState(option); + }); + } + var old = $.fn.button; + $.fn.button = Plugin; + $.fn.button.Constructor = Button; + $.fn.button.noConflict = function() { + $.fn.button = old; + return this; + }; + $(document).on("click.bs.button.data-api", '[data-toggle^="button"]', function(e) { + var $btn = $(e.target); + if (!$btn.hasClass("btn")) $btn = $btn.closest(".btn"); + Plugin.call($btn, "toggle"); + if (!($(e.target).is('input[type="radio"]') || $(e.target).is('input[type="checkbox"]'))) e.preventDefault(); + }).on("focus.bs.button.data-api blur.bs.button.data-api", '[data-toggle^="button"]', function(e) { + $(e.target).closest(".btn").toggleClass("focus", /^focus(in)?$/.test(e.type)); + }); +}(jQuery); + ++function($) { + "use strict"; + var Carousel = function(element, options) { + this.$element = $(element); + this.$indicators = this.$element.find(".carousel-indicators"); + this.options = options; + this.paused = null; + this.sliding = null; + this.interval = null; + this.$active = null; + this.$items = null; + this.options.keyboard && this.$element.on("keydown.bs.carousel", $.proxy(this.keydown, this)); + this.options.pause == "hover" && !("ontouchstart" in document.documentElement) && this.$element.on("mouseenter.bs.carousel", $.proxy(this.pause, this)).on("mouseleave.bs.carousel", $.proxy(this.cycle, this)); + }; + Carousel.VERSION = "3.3.5"; + Carousel.TRANSITION_DURATION = 600; + Carousel.DEFAULTS = { + interval: 5e3, + pause: "hover", + wrap: true, + keyboard: true + }; + Carousel.prototype.keydown = function(e) { + if (/input|textarea/i.test(e.target.tagName)) return; + switch (e.which) { + case 37: + this.prev(); + break; + + case 39: + this.next(); + break; + + default: + return; + } + e.preventDefault(); + }; + Carousel.prototype.cycle = function(e) { + e || (this.paused = false); + this.interval && clearInterval(this.interval); + this.options.interval && !this.paused && (this.interval = setInterval($.proxy(this.next, this), this.options.interval)); + return this; + }; + Carousel.prototype.getItemIndex = function(item) { + this.$items = item.parent().children(".item"); + return this.$items.index(item || this.$active); + }; + Carousel.prototype.getItemForDirection = function(direction, active) { + var activeIndex = this.getItemIndex(active); + var willWrap = direction == "prev" && activeIndex === 0 || direction == "next" && activeIndex == this.$items.length - 1; + if (willWrap && !this.options.wrap) return active; + var delta = direction == "prev" ? -1 : 1; + var itemIndex = (activeIndex + delta) % this.$items.length; + return this.$items.eq(itemIndex); + }; + Carousel.prototype.to = function(pos) { + var that = this; + var activeIndex = this.getItemIndex(this.$active = this.$element.find(".item.active")); + if (pos > this.$items.length - 1 || pos < 0) return; + if (this.sliding) return this.$element.one("slid.bs.carousel", function() { + that.to(pos); + }); + if (activeIndex == pos) return this.pause().cycle(); + return this.slide(pos > activeIndex ? "next" : "prev", this.$items.eq(pos)); + }; + Carousel.prototype.pause = function(e) { + e || (this.paused = true); + if (this.$element.find(".next, .prev").length && $.support.transition) { + this.$element.trigger($.support.transition.end); + this.cycle(true); + } + this.interval = clearInterval(this.interval); + return this; + }; + Carousel.prototype.next = function() { + if (this.sliding) return; + return this.slide("next"); + }; + Carousel.prototype.prev = function() { + if (this.sliding) return; + return this.slide("prev"); + }; + Carousel.prototype.slide = function(type, next) { + var $active = this.$element.find(".item.active"); + var $next = next || this.getItemForDirection(type, $active); + var isCycling = this.interval; + var direction = type == "next" ? "left" : "right"; + var that = this; + if ($next.hasClass("active")) return this.sliding = false; + var relatedTarget = $next[0]; + var slideEvent = $.Event("slide.bs.carousel", { + relatedTarget: relatedTarget, + direction: direction + }); + this.$element.trigger(slideEvent); + if (slideEvent.isDefaultPrevented()) return; + this.sliding = true; + isCycling && this.pause(); + if (this.$indicators.length) { + this.$indicators.find(".active").removeClass("active"); + var $nextIndicator = $(this.$indicators.children()[this.getItemIndex($next)]); + $nextIndicator && $nextIndicator.addClass("active"); + } + var slidEvent = $.Event("slid.bs.carousel", { + relatedTarget: relatedTarget, + direction: direction + }); + if ($.support.transition && this.$element.hasClass("slide")) { + $next.addClass(type); + $next[0].offsetWidth; + $active.addClass(direction); + $next.addClass(direction); + $active.one("bsTransitionEnd", function() { + $next.removeClass([ type, direction ].join(" ")).addClass("active"); + $active.removeClass([ "active", direction ].join(" ")); + that.sliding = false; + setTimeout(function() { + that.$element.trigger(slidEvent); + }, 0); + }).emulateTransitionEnd(Carousel.TRANSITION_DURATION); + } else { + $active.removeClass("active"); + $next.addClass("active"); + this.sliding = false; + this.$element.trigger(slidEvent); + } + isCycling && this.cycle(); + return this; + }; + function Plugin(option) { + return this.each(function() { + var $this = $(this); + var data = $this.data("bs.carousel"); + var options = $.extend({}, Carousel.DEFAULTS, $this.data(), typeof option == "object" && option); + var action = typeof option == "string" ? option : options.slide; + if (!data) $this.data("bs.carousel", data = new Carousel(this, options)); + if (typeof option == "number") data.to(option); else if (action) data[action](); else if (options.interval) data.pause().cycle(); + }); + } + var old = $.fn.carousel; + $.fn.carousel = Plugin; + $.fn.carousel.Constructor = Carousel; + $.fn.carousel.noConflict = function() { + $.fn.carousel = old; + return this; + }; + var clickHandler = function(e) { + var href; + var $this = $(this); + var $target = $($this.attr("data-target") || (href = $this.attr("href")) && href.replace(/.*(?=#[^\s]+$)/, "")); + if (!$target.hasClass("carousel")) return; + var options = $.extend({}, $target.data(), $this.data()); + var slideIndex = $this.attr("data-slide-to"); + if (slideIndex) options.interval = false; + Plugin.call($target, options); + if (slideIndex) { + $target.data("bs.carousel").to(slideIndex); + } + e.preventDefault(); + }; + $(document).on("click.bs.carousel.data-api", "[data-slide]", clickHandler).on("click.bs.carousel.data-api", "[data-slide-to]", clickHandler); + $(window).on("load", function() { + $('[data-ride="carousel"]').each(function() { + var $carousel = $(this); + Plugin.call($carousel, $carousel.data()); + }); + }); +}(jQuery); + ++function($) { + "use strict"; + var Collapse = function(element, options) { + this.$element = $(element); + this.options = $.extend({}, Collapse.DEFAULTS, options); + this.$trigger = $('[data-toggle="collapse"][href="#' + element.id + '"],' + '[data-toggle="collapse"][data-target="#' + element.id + '"]'); + this.transitioning = null; + if (this.options.parent) { + this.$parent = this.getParent(); + } else { + this.addAriaAndCollapsedClass(this.$element, this.$trigger); + } + if (this.options.toggle) this.toggle(); + }; + Collapse.VERSION = "3.3.5"; + Collapse.TRANSITION_DURATION = 350; + Collapse.DEFAULTS = { + toggle: true + }; + Collapse.prototype.dimension = function() { + var hasWidth = this.$element.hasClass("width"); + return hasWidth ? "width" : "height"; + }; + Collapse.prototype.show = function() { + if (this.transitioning || this.$element.hasClass("in")) return; + var activesData; + var actives = this.$parent && this.$parent.children(".panel").children(".in, .collapsing"); + if (actives && actives.length) { + activesData = actives.data("bs.collapse"); + if (activesData && activesData.transitioning) return; + } + var startEvent = $.Event("show.bs.collapse"); + this.$element.trigger(startEvent); + if (startEvent.isDefaultPrevented()) return; + if (actives && actives.length) { + Plugin.call(actives, "hide"); + activesData || actives.data("bs.collapse", null); + } + var dimension = this.dimension(); + this.$element.removeClass("collapse").addClass("collapsing")[dimension](0).attr("aria-expanded", true); + this.$trigger.removeClass("collapsed").attr("aria-expanded", true); + this.transitioning = 1; + var complete = function() { + this.$element.removeClass("collapsing").addClass("collapse in")[dimension](""); + this.transitioning = 0; + this.$element.trigger("shown.bs.collapse"); + }; + if (!$.support.transition) return complete.call(this); + var scrollSize = $.camelCase([ "scroll", dimension ].join("-")); + this.$element.one("bsTransitionEnd", $.proxy(complete, this)).emulateTransitionEnd(Collapse.TRANSITION_DURATION)[dimension](this.$element[0][scrollSize]); + }; + Collapse.prototype.hide = function() { + if (this.transitioning || !this.$element.hasClass("in")) return; + var startEvent = $.Event("hide.bs.collapse"); + this.$element.trigger(startEvent); + if (startEvent.isDefaultPrevented()) return; + var dimension = this.dimension(); + this.$element[dimension](this.$element[dimension]())[0].offsetHeight; + this.$element.addClass("collapsing").removeClass("collapse in").attr("aria-expanded", false); + this.$trigger.addClass("collapsed").attr("aria-expanded", false); + this.transitioning = 1; + var complete = function() { + this.transitioning = 0; + this.$element.removeClass("collapsing").addClass("collapse").trigger("hidden.bs.collapse"); + }; + if (!$.support.transition) return complete.call(this); + this.$element[dimension](0).one("bsTransitionEnd", $.proxy(complete, this)).emulateTransitionEnd(Collapse.TRANSITION_DURATION); + }; + Collapse.prototype.toggle = function() { + this[this.$element.hasClass("in") ? "hide" : "show"](); + }; + Collapse.prototype.getParent = function() { + return $(this.options.parent).find('[data-toggle="collapse"][data-parent="' + this.options.parent + '"]').each($.proxy(function(i, element) { + var $element = $(element); + this.addAriaAndCollapsedClass(getTargetFromTrigger($element), $element); + }, this)).end(); + }; + Collapse.prototype.addAriaAndCollapsedClass = function($element, $trigger) { + var isOpen = $element.hasClass("in"); + $element.attr("aria-expanded", isOpen); + $trigger.toggleClass("collapsed", !isOpen).attr("aria-expanded", isOpen); + }; + function getTargetFromTrigger($trigger) { + var href; + var target = $trigger.attr("data-target") || (href = $trigger.attr("href")) && href.replace(/.*(?=#[^\s]+$)/, ""); + return $(target); + } + function Plugin(option) { + return this.each(function() { + var $this = $(this); + var data = $this.data("bs.collapse"); + var options = $.extend({}, Collapse.DEFAULTS, $this.data(), typeof option == "object" && option); + if (!data && options.toggle && /show|hide/.test(option)) options.toggle = false; + if (!data) $this.data("bs.collapse", data = new Collapse(this, options)); + if (typeof option == "string") data[option](); + }); + } + var old = $.fn.collapse; + $.fn.collapse = Plugin; + $.fn.collapse.Constructor = Collapse; + $.fn.collapse.noConflict = function() { + $.fn.collapse = old; + return this; + }; + $(document).on("click.bs.collapse.data-api", '[data-toggle="collapse"]', function(e) { + var $this = $(this); + if (!$this.attr("data-target")) e.preventDefault(); + var $target = getTargetFromTrigger($this); + var data = $target.data("bs.collapse"); + var option = data ? "toggle" : $this.data(); + Plugin.call($target, option); + }); +}(jQuery); + ++function($) { + "use strict"; + var backdrop = ".dropdown-backdrop"; + var toggle = '[data-toggle="dropdown"]'; + var Dropdown = function(element) { + $(element).on("click.bs.dropdown", this.toggle); + }; + Dropdown.VERSION = "3.3.5"; + function getParent($this) { + var selector = $this.attr("data-target"); + if (!selector) { + selector = $this.attr("href"); + selector = selector && /#[A-Za-z]/.test(selector) && selector.replace(/.*(?=#[^\s]*$)/, ""); + } + var $parent = selector && $(selector); + return $parent && $parent.length ? $parent : $this.parent(); + } + function clearMenus(e) { + if (e && e.which === 3) return; + $(backdrop).remove(); + $(toggle).each(function() { + var $this = $(this); + var $parent = getParent($this); + var relatedTarget = { + relatedTarget: this + }; + if (!$parent.hasClass("open")) return; + if (e && e.type == "click" && /input|textarea/i.test(e.target.tagName) && $.contains($parent[0], e.target)) return; + $parent.trigger(e = $.Event("hide.bs.dropdown", relatedTarget)); + if (e.isDefaultPrevented()) return; + $this.attr("aria-expanded", "false"); + $parent.removeClass("open").trigger("hidden.bs.dropdown", relatedTarget); + }); + } + Dropdown.prototype.toggle = function(e) { + var $this = $(this); + if ($this.is(".disabled, :disabled")) return; + var $parent = getParent($this); + var isActive = $parent.hasClass("open"); + clearMenus(); + if (!isActive) { + if ("ontouchstart" in document.documentElement && !$parent.closest(".navbar-nav").length) { + $(document.createElement("div")).addClass("dropdown-backdrop").insertAfter($(this)).on("click", clearMenus); + } + var relatedTarget = { + relatedTarget: this + }; + $parent.trigger(e = $.Event("show.bs.dropdown", relatedTarget)); + if (e.isDefaultPrevented()) return; + $this.trigger("focus").attr("aria-expanded", "true"); + $parent.toggleClass("open").trigger("shown.bs.dropdown", relatedTarget); + } + return false; + }; + Dropdown.prototype.keydown = function(e) { + if (!/(38|40|27|32)/.test(e.which) || /input|textarea/i.test(e.target.tagName)) return; + var $this = $(this); + e.preventDefault(); + e.stopPropagation(); + if ($this.is(".disabled, :disabled")) return; + var $parent = getParent($this); + var isActive = $parent.hasClass("open"); + if (!isActive && e.which != 27 || isActive && e.which == 27) { + if (e.which == 27) $parent.find(toggle).trigger("focus"); + return $this.trigger("click"); + } + var desc = " li:not(.disabled):visible a"; + var $items = $parent.find(".dropdown-menu" + desc); + if (!$items.length) return; + var index = $items.index(e.target); + if (e.which == 38 && index > 0) index--; + if (e.which == 40 && index < $items.length - 1) index++; + if (!~index) index = 0; + $items.eq(index).trigger("focus"); + }; + function Plugin(option) { + return this.each(function() { + var $this = $(this); + var data = $this.data("bs.dropdown"); + if (!data) $this.data("bs.dropdown", data = new Dropdown(this)); + if (typeof option == "string") data[option].call($this); + }); + } + var old = $.fn.dropdown; + $.fn.dropdown = Plugin; + $.fn.dropdown.Constructor = Dropdown; + $.fn.dropdown.noConflict = function() { + $.fn.dropdown = old; + return this; + }; + $(document).on("click.bs.dropdown.data-api", clearMenus).on("click.bs.dropdown.data-api", ".dropdown form", function(e) { + e.stopPropagation(); + }).on("click.bs.dropdown.data-api", toggle, Dropdown.prototype.toggle).on("keydown.bs.dropdown.data-api", toggle, Dropdown.prototype.keydown).on("keydown.bs.dropdown.data-api", ".dropdown-menu", Dropdown.prototype.keydown); +}(jQuery); + ++function($) { + "use strict"; + var Modal = function(element, options) { + this.options = options; + this.$body = $(document.body); + this.$element = $(element); + this.$dialog = this.$element.find(".modal-dialog"); + this.$backdrop = null; + this.isShown = null; + this.originalBodyPad = null; + this.scrollbarWidth = 0; + this.ignoreBackdropClick = false; + if (this.options.remote) { + this.$element.find(".modal-content").load(this.options.remote, $.proxy(function() { + this.$element.trigger("loaded.bs.modal"); + }, this)); + } + }; + Modal.VERSION = "3.3.5"; + Modal.TRANSITION_DURATION = 300; + Modal.BACKDROP_TRANSITION_DURATION = 150; + Modal.DEFAULTS = { + backdrop: true, + keyboard: true, + show: true + }; + Modal.prototype.toggle = function(_relatedTarget) { + return this.isShown ? this.hide() : this.show(_relatedTarget); + }; + Modal.prototype.show = function(_relatedTarget) { + var that = this; + var e = $.Event("show.bs.modal", { + relatedTarget: _relatedTarget + }); + this.$element.trigger(e); + if (this.isShown || e.isDefaultPrevented()) return; + this.isShown = true; + this.checkScrollbar(); + this.setScrollbar(); + this.$body.addClass("modal-open"); + this.escape(); + this.resize(); + this.$element.on("click.dismiss.bs.modal", '[data-dismiss="modal"]', $.proxy(this.hide, this)); + this.$dialog.on("mousedown.dismiss.bs.modal", function() { + that.$element.one("mouseup.dismiss.bs.modal", function(e) { + if ($(e.target).is(that.$element)) that.ignoreBackdropClick = true; + }); + }); + this.backdrop(function() { + var transition = $.support.transition && that.$element.hasClass("fade"); + if (!that.$element.parent().length) { + that.$element.appendTo(that.$body); + } + that.$element.show().scrollTop(0); + that.adjustDialog(); + if (transition) { + that.$element[0].offsetWidth; + } + that.$element.addClass("in"); + that.enforceFocus(); + var e = $.Event("shown.bs.modal", { + relatedTarget: _relatedTarget + }); + transition ? that.$dialog.one("bsTransitionEnd", function() { + that.$element.trigger("focus").trigger(e); + }).emulateTransitionEnd(Modal.TRANSITION_DURATION) : that.$element.trigger("focus").trigger(e); + }); + }; + Modal.prototype.hide = function(e) { + if (e) e.preventDefault(); + e = $.Event("hide.bs.modal"); + this.$element.trigger(e); + if (!this.isShown || e.isDefaultPrevented()) return; + this.isShown = false; + this.escape(); + this.resize(); + $(document).off("focusin.bs.modal"); + this.$element.removeClass("in").off("click.dismiss.bs.modal").off("mouseup.dismiss.bs.modal"); + this.$dialog.off("mousedown.dismiss.bs.modal"); + $.support.transition && this.$element.hasClass("fade") ? this.$element.one("bsTransitionEnd", $.proxy(this.hideModal, this)).emulateTransitionEnd(Modal.TRANSITION_DURATION) : this.hideModal(); + }; + Modal.prototype.enforceFocus = function() { + $(document).off("focusin.bs.modal").on("focusin.bs.modal", $.proxy(function(e) { + if (this.$element[0] !== e.target && !this.$element.has(e.target).length) { + this.$element.trigger("focus"); + } + }, this)); + }; + Modal.prototype.escape = function() { + if (this.isShown && this.options.keyboard) { + this.$element.on("keydown.dismiss.bs.modal", $.proxy(function(e) { + e.which == 27 && this.hide(); + }, this)); + } else if (!this.isShown) { + this.$element.off("keydown.dismiss.bs.modal"); + } + }; + Modal.prototype.resize = function() { + if (this.isShown) { + $(window).on("resize.bs.modal", $.proxy(this.handleUpdate, this)); + } else { + $(window).off("resize.bs.modal"); + } + }; + Modal.prototype.hideModal = function() { + var that = this; + this.$element.hide(); + this.backdrop(function() { + that.$body.removeClass("modal-open"); + that.resetAdjustments(); + that.resetScrollbar(); + that.$element.trigger("hidden.bs.modal"); + }); + }; + Modal.prototype.removeBackdrop = function() { + this.$backdrop && this.$backdrop.remove(); + this.$backdrop = null; + }; + Modal.prototype.backdrop = function(callback) { + var that = this; + var animate = this.$element.hasClass("fade") ? "fade" : ""; + if (this.isShown && this.options.backdrop) { + var doAnimate = $.support.transition && animate; + this.$backdrop = $(document.createElement("div")).addClass("modal-backdrop " + animate).appendTo(this.$body); + this.$element.on("click.dismiss.bs.modal", $.proxy(function(e) { + if (this.ignoreBackdropClick) { + this.ignoreBackdropClick = false; + return; } + if (e.target !== e.currentTarget) return; + this.options.backdrop == "static" ? this.$element[0].focus() : this.hide(); + }, this)); + if (doAnimate) this.$backdrop[0].offsetWidth; + this.$backdrop.addClass("in"); + if (!callback) return; + doAnimate ? this.$backdrop.one("bsTransitionEnd", callback).emulateTransitionEnd(Modal.BACKDROP_TRANSITION_DURATION) : callback(); + } else if (!this.isShown && this.$backdrop) { + this.$backdrop.removeClass("in"); + var callbackRemove = function() { + that.removeBackdrop(); + callback && callback(); }; + $.support.transition && this.$element.hasClass("fade") ? this.$backdrop.one("bsTransitionEnd", callbackRemove).emulateTransitionEnd(Modal.BACKDROP_TRANSITION_DURATION) : callbackRemove(); + } else if (callback) { + callback(); + } + }; + Modal.prototype.handleUpdate = function() { + this.adjustDialog(); + }; + Modal.prototype.adjustDialog = function() { + var modalIsOverflowing = this.$element[0].scrollHeight > document.documentElement.clientHeight; + this.$element.css({ + paddingLeft: !this.bodyIsOverflowing && modalIsOverflowing ? this.scrollbarWidth : "", + paddingRight: this.bodyIsOverflowing && !modalIsOverflowing ? this.scrollbarWidth : "" + }); + }; + Modal.prototype.resetAdjustments = function() { + this.$element.css({ + paddingLeft: "", + paddingRight: "" + }); + }; + Modal.prototype.checkScrollbar = function() { + var fullWindowWidth = window.innerWidth; + if (!fullWindowWidth) { + var documentElementRect = document.documentElement.getBoundingClientRect(); + fullWindowWidth = documentElementRect.right - Math.abs(documentElementRect.left); + } + this.bodyIsOverflowing = document.body.clientWidth < fullWindowWidth; + this.scrollbarWidth = this.measureScrollbar(); + }; + Modal.prototype.setScrollbar = function() { + var bodyPad = parseInt(this.$body.css("padding-right") || 0, 10); + this.originalBodyPad = document.body.style.paddingRight || ""; + if (this.bodyIsOverflowing) this.$body.css("padding-right", bodyPad + this.scrollbarWidth); + }; + Modal.prototype.resetScrollbar = function() { + this.$body.css("padding-right", this.originalBodyPad); + }; + Modal.prototype.measureScrollbar = function() { + var scrollDiv = document.createElement("div"); + scrollDiv.className = "modal-scrollbar-measure"; + this.$body.append(scrollDiv); + var scrollbarWidth = scrollDiv.offsetWidth - scrollDiv.clientWidth; + this.$body[0].removeChild(scrollDiv); + return scrollbarWidth; + }; + function Plugin(option, _relatedTarget) { + return this.each(function() { + var $this = $(this); + var data = $this.data("bs.modal"); + var options = $.extend({}, Modal.DEFAULTS, $this.data(), typeof option == "object" && option); + if (!data) $this.data("bs.modal", data = new Modal(this, options)); + if (typeof option == "string") data[option](_relatedTarget); else if (options.show) data.show(_relatedTarget); + }); + } + var old = $.fn.modal; + $.fn.modal = Plugin; + $.fn.modal.Constructor = Modal; + $.fn.modal.noConflict = function() { + $.fn.modal = old; + return this; + }; + $(document).on("click.bs.modal.data-api", '[data-toggle="modal"]', function(e) { + var $this = $(this); + var href = $this.attr("href"); + var $target = $($this.attr("data-target") || href && href.replace(/.*(?=#[^\s]+$)/, "")); + var option = $target.data("bs.modal") ? "toggle" : $.extend({ + remote: !/#/.test(href) && href + }, $target.data(), $this.data()); + if ($this.is("a")) e.preventDefault(); + $target.one("show.bs.modal", function(showEvent) { + if (showEvent.isDefaultPrevented()) return; + $target.one("hidden.bs.modal", function() { + $this.is(":visible") && $this.trigger("focus"); + }); + }); + Plugin.call($target, option, this); + }); +}(jQuery); + ++function($) { + "use strict"; + var Tooltip = function(element, options) { + this.type = null; + this.options = null; + this.enabled = null; + this.timeout = null; + this.hoverState = null; + this.$element = null; + this.inState = null; + this.init("tooltip", element, options); + }; + Tooltip.VERSION = "3.3.5"; + Tooltip.TRANSITION_DURATION = 150; + Tooltip.DEFAULTS = { + animation: true, + placement: "top", + selector: false, + template: '', + trigger: "hover focus", + title: "", + delay: 0, + html: false, + container: false, + viewport: { + selector: "body", + padding: 0 + } + }; + Tooltip.prototype.init = function(type, element, options) { + this.enabled = true; + this.type = type; + this.$element = $(element); + this.options = this.getOptions(options); + this.$viewport = this.options.viewport && $($.isFunction(this.options.viewport) ? this.options.viewport.call(this, this.$element) : this.options.viewport.selector || this.options.viewport); + this.inState = { + click: false, + hover: false, + focus: false }; - } ]; -}).directive("tooltipTemplateTransclude", [ "$animate", "$sce", "$compile", "$templateRequest", function($animate, $sce, $compile, $templateRequest) { - return { - link: function(scope, elem, attrs) { - var origScope = scope.$eval(attrs.tooltipTemplateTranscludeScope); - var changeCounter = 0, currentScope, previousElement, currentElement; - var cleanupLastIncludeContent = function() { - if (previousElement) { - previousElement.remove(); - previousElement = null; - } - if (currentScope) { - currentScope.$destroy(); - currentScope = null; - } - if (currentElement) { - $animate.leave(currentElement).then(function() { - previousElement = null; - }); - previousElement = currentElement; - currentElement = null; - } + if (this.$element[0] instanceof document.constructor && !this.options.selector) { + throw new Error("`selector` option must be specified when initializing " + this.type + " on the window.document object!"); + } + var triggers = this.options.trigger.split(" "); + for (var i = triggers.length; i--; ) { + var trigger = triggers[i]; + if (trigger == "click") { + this.$element.on("click." + this.type, this.options.selector, $.proxy(this.toggle, this)); + } else if (trigger != "manual") { + var eventIn = trigger == "hover" ? "mouseenter" : "focusin"; + var eventOut = trigger == "hover" ? "mouseleave" : "focusout"; + this.$element.on(eventIn + "." + this.type, this.options.selector, $.proxy(this.enter, this)); + this.$element.on(eventOut + "." + this.type, this.options.selector, $.proxy(this.leave, this)); + } + } + this.options.selector ? this._options = $.extend({}, this.options, { + trigger: "manual", + selector: "" + }) : this.fixTitle(); + }; + Tooltip.prototype.getDefaults = function() { + return Tooltip.DEFAULTS; + }; + Tooltip.prototype.getOptions = function(options) { + options = $.extend({}, this.getDefaults(), this.$element.data(), options); + if (options.delay && typeof options.delay == "number") { + options.delay = { + show: options.delay, + hide: options.delay }; - scope.$watch($sce.parseAsResourceUrl(attrs.tooltipTemplateTransclude), function(src) { - var thisChangeId = ++changeCounter; - if (src) { - $templateRequest(src, true).then(function(response) { - if (thisChangeId !== changeCounter) { - return; - } - var newScope = origScope.$new(); - var template = response; - var clone = $compile(template)(newScope, function(clone) { - cleanupLastIncludeContent(); - $animate.enter(clone, elem); - }); - currentScope = newScope; - currentElement = clone; - currentScope.$emit("$includeContentLoaded", src); - }, function() { - if (thisChangeId === changeCounter) { - cleanupLastIncludeContent(); - scope.$emit("$includeContentError", src); - } - }); - scope.$emit("$includeContentRequested", src); - } else { - cleanupLastIncludeContent(); - } + } + return options; + }; + Tooltip.prototype.getDelegateOptions = function() { + var options = {}; + var defaults = this.getDefaults(); + this._options && $.each(this._options, function(key, value) { + if (defaults[key] != value) options[key] = value; + }); + return options; + }; + Tooltip.prototype.enter = function(obj) { + var self = obj instanceof this.constructor ? obj : $(obj.currentTarget).data("bs." + this.type); + if (!self) { + self = new this.constructor(obj.currentTarget, this.getDelegateOptions()); + $(obj.currentTarget).data("bs." + this.type, self); + } + if (obj instanceof $.Event) { + self.inState[obj.type == "focusin" ? "focus" : "hover"] = true; + } + if (self.tip().hasClass("in") || self.hoverState == "in") { + self.hoverState = "in"; + return; + } + clearTimeout(self.timeout); + self.hoverState = "in"; + if (!self.options.delay || !self.options.delay.show) return self.show(); + self.timeout = setTimeout(function() { + if (self.hoverState == "in") self.show(); + }, self.options.delay.show); + }; + Tooltip.prototype.isInStateTrue = function() { + for (var key in this.inState) { + if (this.inState[key]) return true; + } + return false; + }; + Tooltip.prototype.leave = function(obj) { + var self = obj instanceof this.constructor ? obj : $(obj.currentTarget).data("bs." + this.type); + if (!self) { + self = new this.constructor(obj.currentTarget, this.getDelegateOptions()); + $(obj.currentTarget).data("bs." + this.type, self); + } + if (obj instanceof $.Event) { + self.inState[obj.type == "focusout" ? "focus" : "hover"] = false; + } + if (self.isInStateTrue()) return; + clearTimeout(self.timeout); + self.hoverState = "out"; + if (!self.options.delay || !self.options.delay.hide) return self.hide(); + self.timeout = setTimeout(function() { + if (self.hoverState == "out") self.hide(); + }, self.options.delay.hide); + }; + Tooltip.prototype.show = function() { + var e = $.Event("show.bs." + this.type); + if (this.hasContent() && this.enabled) { + this.$element.trigger(e); + var inDom = $.contains(this.$element[0].ownerDocument.documentElement, this.$element[0]); + if (e.isDefaultPrevented() || !inDom) return; + var that = this; + var $tip = this.tip(); + var tipId = this.getUID(this.type); + this.setContent(); + $tip.attr("id", tipId); + this.$element.attr("aria-describedby", tipId); + if (this.options.animation) $tip.addClass("fade"); + var placement = typeof this.options.placement == "function" ? this.options.placement.call(this, $tip[0], this.$element[0]) : this.options.placement; + var autoToken = /\s?auto?\s?/i; + var autoPlace = autoToken.test(placement); + if (autoPlace) placement = placement.replace(autoToken, "") || "top"; + $tip.detach().css({ + top: 0, + left: 0, + display: "block" + }).addClass(placement).data("bs." + this.type, this); + this.options.container ? $tip.appendTo(this.options.container) : $tip.insertAfter(this.$element); + this.$element.trigger("inserted.bs." + this.type); + var pos = this.getPosition(); + var actualWidth = $tip[0].offsetWidth; + var actualHeight = $tip[0].offsetHeight; + if (autoPlace) { + var orgPlacement = placement; + var viewportDim = this.getPosition(this.$viewport); + placement = placement == "bottom" && pos.bottom + actualHeight > viewportDim.bottom ? "top" : placement == "top" && pos.top - actualHeight < viewportDim.top ? "bottom" : placement == "right" && pos.right + actualWidth > viewportDim.width ? "left" : placement == "left" && pos.left - actualWidth < viewportDim.left ? "right" : placement; + $tip.removeClass(orgPlacement).addClass(placement); + } + var calculatedOffset = this.getCalculatedOffset(placement, pos, actualWidth, actualHeight); + this.applyPlacement(calculatedOffset, placement); + var complete = function() { + var prevHoverState = that.hoverState; + that.$element.trigger("shown.bs." + that.type); + that.hoverState = null; + if (prevHoverState == "out") that.leave(that); + }; + $.support.transition && this.$tip.hasClass("fade") ? $tip.one("bsTransitionEnd", complete).emulateTransitionEnd(Tooltip.TRANSITION_DURATION) : complete(); + } + }; + Tooltip.prototype.applyPlacement = function(offset, placement) { + var $tip = this.tip(); + var width = $tip[0].offsetWidth; + var height = $tip[0].offsetHeight; + var marginTop = parseInt($tip.css("margin-top"), 10); + var marginLeft = parseInt($tip.css("margin-left"), 10); + if (isNaN(marginTop)) marginTop = 0; + if (isNaN(marginLeft)) marginLeft = 0; + offset.top += marginTop; + offset.left += marginLeft; + $.offset.setOffset($tip[0], $.extend({ + using: function(props) { + $tip.css({ + top: Math.round(props.top), + left: Math.round(props.left) + }); + } + }, offset), 0); + $tip.addClass("in"); + var actualWidth = $tip[0].offsetWidth; + var actualHeight = $tip[0].offsetHeight; + if (placement == "top" && actualHeight != height) { + offset.top = offset.top + height - actualHeight; + } + var delta = this.getViewportAdjustedDelta(placement, offset, actualWidth, actualHeight); + if (delta.left) offset.left += delta.left; else offset.top += delta.top; + var isVertical = /top|bottom/.test(placement); + var arrowDelta = isVertical ? delta.left * 2 - width + actualWidth : delta.top * 2 - height + actualHeight; + var arrowOffsetPosition = isVertical ? "offsetWidth" : "offsetHeight"; + $tip.offset(offset); + this.replaceArrow(arrowDelta, $tip[0][arrowOffsetPosition], isVertical); + }; + Tooltip.prototype.replaceArrow = function(delta, dimension, isVertical) { + this.arrow().css(isVertical ? "left" : "top", 50 * (1 - delta / dimension) + "%").css(isVertical ? "top" : "left", ""); + }; + Tooltip.prototype.setContent = function() { + var $tip = this.tip(); + var title = this.getTitle(); + $tip.find(".tooltip-inner")[this.options.html ? "html" : "text"](title); + $tip.removeClass("fade in top bottom left right"); + }; + Tooltip.prototype.hide = function(callback) { + var that = this; + var $tip = $(this.$tip); + var e = $.Event("hide.bs." + this.type); + function complete() { + if (that.hoverState != "in") $tip.detach(); + that.$element.removeAttr("aria-describedby").trigger("hidden.bs." + that.type); + callback && callback(); + } + this.$element.trigger(e); + if (e.isDefaultPrevented()) return; + $tip.removeClass("in"); + $.support.transition && $tip.hasClass("fade") ? $tip.one("bsTransitionEnd", complete).emulateTransitionEnd(Tooltip.TRANSITION_DURATION) : complete(); + this.hoverState = null; + return this; + }; + Tooltip.prototype.fixTitle = function() { + var $e = this.$element; + if ($e.attr("title") || typeof $e.attr("data-original-title") != "string") { + $e.attr("data-original-title", $e.attr("title") || "").attr("title", ""); + } + }; + Tooltip.prototype.hasContent = function() { + return this.getTitle(); + }; + Tooltip.prototype.getPosition = function($element) { + $element = $element || this.$element; + var el = $element[0]; + var isBody = el.tagName == "BODY"; + var elRect = el.getBoundingClientRect(); + if (elRect.width == null) { + elRect = $.extend({}, elRect, { + width: elRect.right - elRect.left, + height: elRect.bottom - elRect.top }); - scope.$on("$destroy", cleanupLastIncludeContent); } + var elOffset = isBody ? { + top: 0, + left: 0 + } : $element.offset(); + var scroll = { + scroll: isBody ? document.documentElement.scrollTop || document.body.scrollTop : $element.scrollTop() + }; + var outerDims = isBody ? { + width: $(window).width(), + height: $(window).height() + } : null; + return $.extend({}, elRect, scroll, outerDims, elOffset); }; -} ]).directive("tooltipClasses", function() { - return { - restrict: "A", - link: function(scope, element, attrs) { - if (scope.placement) { - element.addClass(scope.placement); + Tooltip.prototype.getCalculatedOffset = function(placement, pos, actualWidth, actualHeight) { + return placement == "bottom" ? { + top: pos.top + pos.height, + left: pos.left + pos.width / 2 - actualWidth / 2 + } : placement == "top" ? { + top: pos.top - actualHeight, + left: pos.left + pos.width / 2 - actualWidth / 2 + } : placement == "left" ? { + top: pos.top + pos.height / 2 - actualHeight / 2, + left: pos.left - actualWidth + } : { + top: pos.top + pos.height / 2 - actualHeight / 2, + left: pos.left + pos.width + }; + }; + Tooltip.prototype.getViewportAdjustedDelta = function(placement, pos, actualWidth, actualHeight) { + var delta = { + top: 0, + left: 0 + }; + if (!this.$viewport) return delta; + var viewportPadding = this.options.viewport && this.options.viewport.padding || 0; + var viewportDimensions = this.getPosition(this.$viewport); + if (/right|left/.test(placement)) { + var topEdgeOffset = pos.top - viewportPadding - viewportDimensions.scroll; + var bottomEdgeOffset = pos.top + viewportPadding - viewportDimensions.scroll + actualHeight; + if (topEdgeOffset < viewportDimensions.top) { + delta.top = viewportDimensions.top - topEdgeOffset; + } else if (bottomEdgeOffset > viewportDimensions.top + viewportDimensions.height) { + delta.top = viewportDimensions.top + viewportDimensions.height - bottomEdgeOffset; } - if (scope.popupClass) { - element.addClass(scope.popupClass); + } else { + var leftEdgeOffset = pos.left - viewportPadding; + var rightEdgeOffset = pos.left + viewportPadding + actualWidth; + if (leftEdgeOffset < viewportDimensions.left) { + delta.left = viewportDimensions.left - leftEdgeOffset; + } else if (rightEdgeOffset > viewportDimensions.right) { + delta.left = viewportDimensions.left + viewportDimensions.width - rightEdgeOffset; } - if (scope.animation()) { - element.addClass(attrs.tooltipAnimationClass); + } + return delta; + }; + Tooltip.prototype.getTitle = function() { + var title; + var $e = this.$element; + var o = this.options; + title = $e.attr("data-original-title") || (typeof o.title == "function" ? o.title.call($e[0]) : o.title); + return title; + }; + Tooltip.prototype.getUID = function(prefix) { + do prefix += ~~(Math.random() * 1e6); while (document.getElementById(prefix)); + return prefix; + }; + Tooltip.prototype.tip = function() { + if (!this.$tip) { + this.$tip = $(this.options.template); + if (this.$tip.length != 1) { + throw new Error(this.type + " `template` option must consist of exactly 1 top-level element!"); } } + return this.$tip; }; -}).directive("tooltipPopup", function() { - return { - restrict: "EA", - replace: true, - scope: { - content: "@", - placement: "@", - popupClass: "@", - animation: "&", - isOpen: "&" - }, - templateUrl: "template/tooltip/tooltip-popup.html" + Tooltip.prototype.arrow = function() { + return this.$arrow = this.$arrow || this.tip().find(".tooltip-arrow"); }; -}).directive("tooltip", [ "$tooltip", function($tooltip) { - return $tooltip("tooltip", "tooltip", "mouseenter"); -} ]).directive("tooltipTemplatePopup", function() { - return { - restrict: "EA", - replace: true, - scope: { - contentExp: "&", - placement: "@", - popupClass: "@", - animation: "&", - isOpen: "&", - originScope: "&" - }, - templateUrl: "template/tooltip/tooltip-template-popup.html" + Tooltip.prototype.enable = function() { + this.enabled = true; }; -}).directive("tooltipTemplate", [ "$tooltip", function($tooltip) { - return $tooltip("tooltipTemplate", "tooltip", "mouseenter", { - useContentExp: true - }); -} ]).directive("tooltipHtmlPopup", function() { - return { - restrict: "EA", - replace: true, - scope: { - contentExp: "&", - placement: "@", - popupClass: "@", - animation: "&", - isOpen: "&" - }, - templateUrl: "template/tooltip/tooltip-html-popup.html" + Tooltip.prototype.disable = function() { + this.enabled = false; }; -}).directive("tooltipHtml", [ "$tooltip", function($tooltip) { - return $tooltip("tooltipHtml", "tooltip", "mouseenter", { - useContentExp: true - }); -} ]).directive("tooltipHtmlUnsafePopup", function() { - return { - restrict: "EA", - replace: true, - scope: { - content: "@", - placement: "@", - popupClass: "@", - animation: "&", - isOpen: "&" - }, - templateUrl: "template/tooltip/tooltip-html-unsafe-popup.html" + Tooltip.prototype.toggleEnabled = function() { + this.enabled = !this.enabled; }; -}).value("tooltipHtmlUnsafeSuppressDeprecated", false).directive("tooltipHtmlUnsafe", [ "$tooltip", "tooltipHtmlUnsafeSuppressDeprecated", "$log", function($tooltip, tooltipHtmlUnsafeSuppressDeprecated, $log) { - if (!tooltipHtmlUnsafeSuppressDeprecated) { - $log.warn("tooltip-html-unsafe is now deprecated. Use tooltip-html or tooltip-template instead."); + Tooltip.prototype.toggle = function(e) { + var self = this; + if (e) { + self = $(e.currentTarget).data("bs." + this.type); + if (!self) { + self = new this.constructor(e.currentTarget, this.getDelegateOptions()); + $(e.currentTarget).data("bs." + this.type, self); + } + } + if (e) { + self.inState.click = !self.inState.click; + if (self.isInStateTrue()) self.enter(self); else self.leave(self); + } else { + self.tip().hasClass("in") ? self.leave(self) : self.enter(self); + } + }; + Tooltip.prototype.destroy = function() { + var that = this; + clearTimeout(this.timeout); + this.hide(function() { + that.$element.off("." + that.type).removeData("bs." + that.type); + if (that.$tip) { + that.$tip.detach(); + } + that.$tip = null; + that.$arrow = null; + that.$viewport = null; + }); + }; + function Plugin(option) { + return this.each(function() { + var $this = $(this); + var data = $this.data("bs.tooltip"); + var options = typeof option == "object" && option; + if (!data && /destroy|hide/.test(option)) return; + if (!data) $this.data("bs.tooltip", data = new Tooltip(this, options)); + if (typeof option == "string") data[option](); + }); } - return $tooltip("tooltipHtmlUnsafe", "tooltip", "mouseenter"); -} ]); + var old = $.fn.tooltip; + $.fn.tooltip = Plugin; + $.fn.tooltip.Constructor = Tooltip; + $.fn.tooltip.noConflict = function() { + $.fn.tooltip = old; + return this; + }; +}(jQuery); -angular.module("ui.bootstrap.popover", [ "ui.bootstrap.tooltip" ]).directive("popoverTemplatePopup", function() { - return { - restrict: "EA", - replace: true, - scope: { - title: "@", - contentExp: "&", - placement: "@", - popupClass: "@", - animation: "&", - isOpen: "&", - originScope: "&" - }, - templateUrl: "template/popover/popover-template.html" ++function($) { + "use strict"; + var Popover = function(element, options) { + this.init("popover", element, options); }; -}).directive("popoverTemplate", [ "$tooltip", function($tooltip) { - return $tooltip("popoverTemplate", "popover", "click", { - useContentExp: true + if (!$.fn.tooltip) throw new Error("Popover requires tooltip.js"); + Popover.VERSION = "3.3.5"; + Popover.DEFAULTS = $.extend({}, $.fn.tooltip.Constructor.DEFAULTS, { + placement: "right", + trigger: "click", + content: "", + template: '' }); -} ]).directive("popoverHtmlPopup", function() { - return { - restrict: "EA", - replace: true, - scope: { - contentExp: "&", - title: "@", - placement: "@", - popupClass: "@", - animation: "&", - isOpen: "&" - }, - templateUrl: "template/popover/popover-html.html" + Popover.prototype = $.extend({}, $.fn.tooltip.Constructor.prototype); + Popover.prototype.constructor = Popover; + Popover.prototype.getDefaults = function() { + return Popover.DEFAULTS; }; -}).directive("popoverHtml", [ "$tooltip", function($tooltip) { - return $tooltip("popoverHtml", "popover", "click", { - useContentExp: true - }); -} ]).directive("popoverPopup", function() { - return { - restrict: "EA", - replace: true, - scope: { - title: "@", - content: "@", - placement: "@", - popupClass: "@", - animation: "&", - isOpen: "&" - }, - templateUrl: "template/popover/popover.html" + Popover.prototype.setContent = function() { + var $tip = this.tip(); + var title = this.getTitle(); + var content = this.getContent(); + $tip.find(".popover-title")[this.options.html ? "html" : "text"](title); + $tip.find(".popover-content").children().detach().end()[this.options.html ? typeof content == "string" ? "html" : "append" : "text"](content); + $tip.removeClass("fade top bottom left right in"); + if (!$tip.find(".popover-title").html()) $tip.find(".popover-title").hide(); }; -}).directive("popover", [ "$tooltip", function($tooltip) { - return $tooltip("popover", "popover", "click"); -} ]); - -angular.module("ui.bootstrap.progressbar", []).constant("progressConfig", { - animate: true, - max: 100 -}).value("$progressSuppressWarning", false).controller("ProgressController", [ "$scope", "$attrs", "progressConfig", function($scope, $attrs, progressConfig) { - var self = this, animate = angular.isDefined($attrs.animate) ? $scope.$parent.$eval($attrs.animate) : progressConfig.animate; - this.bars = []; - $scope.max = angular.isDefined($scope.max) ? $scope.max : progressConfig.max; - this.addBar = function(bar, element) { - if (!animate) { - element.css({ - transition: "none" - }); - } - this.bars.push(bar); - bar.max = $scope.max; - bar.$watch("value", function(value) { - bar.recalculatePercentage(); - }); - bar.recalculatePercentage = function() { - bar.percent = +(100 * bar.value / bar.max).toFixed(2); - var totalPercentage = self.bars.reduce(function(total, bar) { - return total + bar.percent; - }, 0); - if (totalPercentage > 100) { - bar.percent -= totalPercentage - 100; - } - }; - bar.$on("$destroy", function() { - element = null; - self.removeBar(bar); - }); + Popover.prototype.hasContent = function() { + return this.getTitle() || this.getContent(); }; - this.removeBar = function(bar) { - this.bars.splice(this.bars.indexOf(bar), 1); + Popover.prototype.getContent = function() { + var $e = this.$element; + var o = this.options; + return $e.attr("data-content") || (typeof o.content == "function" ? o.content.call($e[0]) : o.content); }; - $scope.$watch("max", function(max) { - self.bars.forEach(function(bar) { - bar.max = $scope.max; - bar.recalculatePercentage(); + Popover.prototype.arrow = function() { + return this.$arrow = this.$arrow || this.tip().find(".arrow"); + }; + function Plugin(option) { + return this.each(function() { + var $this = $(this); + var data = $this.data("bs.popover"); + var options = typeof option == "object" && option; + if (!data && /destroy|hide/.test(option)) return; + if (!data) $this.data("bs.popover", data = new Popover(this, options)); + if (typeof option == "string") data[option](); }); - }); -} ]).directive("uibProgress", function() { - return { - restrict: "EA", - replace: true, - transclude: true, - controller: "ProgressController", - require: "uibProgress", - scope: { - max: "=?" - }, - templateUrl: "template/progressbar/progress.html" + } + var old = $.fn.popover; + $.fn.popover = Plugin; + $.fn.popover.Constructor = Popover; + $.fn.popover.noConflict = function() { + $.fn.popover = old; + return this; }; -}).directive("progress", [ "$log", "$progressSuppressWarning", function($log, $progressSuppressWarning) { - return { - restrict: "EA", - replace: true, - transclude: true, - controller: "ProgressController", - require: "progress", - scope: { - max: "=?" - }, - templateUrl: "template/progressbar/progress.html", - link: function() { - if ($progressSuppressWarning) { - $log.warn("progress is now deprecated. Use uib-progress instead"); - } - } +}(jQuery); + ++function($) { + "use strict"; + function ScrollSpy(element, options) { + this.$body = $(document.body); + this.$scrollElement = $(element).is(document.body) ? $(window) : $(element); + this.options = $.extend({}, ScrollSpy.DEFAULTS, options); + this.selector = (this.options.target || "") + " .nav li > a"; + this.offsets = []; + this.targets = []; + this.activeTarget = null; + this.scrollHeight = 0; + this.$scrollElement.on("scroll.bs.scrollspy", $.proxy(this.process, this)); + this.refresh(); + this.process(); + } + ScrollSpy.VERSION = "3.3.5"; + ScrollSpy.DEFAULTS = { + offset: 10 }; -} ]).directive("uibBar", function() { - return { - restrict: "EA", - replace: true, - transclude: true, - require: "^uibProgress", - scope: { - value: "=", - type: "@" - }, - templateUrl: "template/progressbar/bar.html", - link: function(scope, element, attrs, progressCtrl) { - progressCtrl.addBar(scope, element); + ScrollSpy.prototype.getScrollHeight = function() { + return this.$scrollElement[0].scrollHeight || Math.max(this.$body[0].scrollHeight, document.documentElement.scrollHeight); + }; + ScrollSpy.prototype.refresh = function() { + var that = this; + var offsetMethod = "offset"; + var offsetBase = 0; + this.offsets = []; + this.targets = []; + this.scrollHeight = this.getScrollHeight(); + if (!$.isWindow(this.$scrollElement[0])) { + offsetMethod = "position"; + offsetBase = this.$scrollElement.scrollTop(); } + this.$body.find(this.selector).map(function() { + var $el = $(this); + var href = $el.data("target") || $el.attr("href"); + var $href = /^#./.test(href) && $(href); + return $href && $href.length && $href.is(":visible") && [ [ $href[offsetMethod]().top + offsetBase, href ] ] || null; + }).sort(function(a, b) { + return a[0] - b[0]; + }).each(function() { + that.offsets.push(this[0]); + that.targets.push(this[1]); + }); }; -}).directive("bar", [ "$log", "$progressSuppressWarning", function($log, $progressSuppressWarning) { - return { - restrict: "EA", - replace: true, - transclude: true, - require: "^progress", - scope: { - value: "=", - type: "@" - }, - templateUrl: "template/progressbar/bar.html", - link: function(scope, element, attrs, progressCtrl) { - if ($progressSuppressWarning) { - $log.warn("bar is now deprecated. Use uib-bar instead"); - } - progressCtrl.addBar(scope, element); + ScrollSpy.prototype.process = function() { + var scrollTop = this.$scrollElement.scrollTop() + this.options.offset; + var scrollHeight = this.getScrollHeight(); + var maxScroll = this.options.offset + scrollHeight - this.$scrollElement.height(); + var offsets = this.offsets; + var targets = this.targets; + var activeTarget = this.activeTarget; + var i; + if (this.scrollHeight != scrollHeight) { + this.refresh(); + } + if (scrollTop >= maxScroll) { + return activeTarget != (i = targets[targets.length - 1]) && this.activate(i); + } + if (activeTarget && scrollTop < offsets[0]) { + this.activeTarget = null; + return this.clear(); + } + for (i = offsets.length; i--; ) { + activeTarget != targets[i] && scrollTop >= offsets[i] && (offsets[i + 1] === undefined || scrollTop < offsets[i + 1]) && this.activate(targets[i]); } }; -} ]).directive("progressbar", function() { - return { - restrict: "EA", - replace: true, - transclude: true, - controller: "ProgressController", - scope: { - value: "=", - max: "=?", - type: "@" - }, - templateUrl: "template/progressbar/progressbar.html", - link: function(scope, element, attrs, progressCtrl) { - progressCtrl.addBar(scope, angular.element(element.children()[0])); + ScrollSpy.prototype.activate = function(target) { + this.activeTarget = target; + this.clear(); + var selector = this.selector + '[data-target="' + target + '"],' + this.selector + '[href="' + target + '"]'; + var active = $(selector).parents("li").addClass("active"); + if (active.parent(".dropdown-menu").length) { + active = active.closest("li.dropdown").addClass("active"); } + active.trigger("activate.bs.scrollspy"); }; -}); + ScrollSpy.prototype.clear = function() { + $(this.selector).parentsUntil(this.options.target, ".active").removeClass("active"); + }; + function Plugin(option) { + return this.each(function() { + var $this = $(this); + var data = $this.data("bs.scrollspy"); + var options = typeof option == "object" && option; + if (!data) $this.data("bs.scrollspy", data = new ScrollSpy(this, options)); + if (typeof option == "string") data[option](); + }); + } + var old = $.fn.scrollspy; + $.fn.scrollspy = Plugin; + $.fn.scrollspy.Constructor = ScrollSpy; + $.fn.scrollspy.noConflict = function() { + $.fn.scrollspy = old; + return this; + }; + $(window).on("load.bs.scrollspy.data-api", function() { + $('[data-spy="scroll"]').each(function() { + var $spy = $(this); + Plugin.call($spy, $spy.data()); + }); + }); +}(jQuery); -angular.module("ui.bootstrap.rating", []).constant("ratingConfig", { - max: 5, - stateOn: null, - stateOff: null, - titles: [ "one", "two", "three", "four", "five" ] -}).controller("RatingController", [ "$scope", "$attrs", "ratingConfig", function($scope, $attrs, ratingConfig) { - var ngModelCtrl = { - $setViewValue: angular.noop ++function($) { + "use strict"; + var Tab = function(element) { + this.element = $(element); }; - this.init = function(ngModelCtrl_) { - ngModelCtrl = ngModelCtrl_; - ngModelCtrl.$render = this.render; - ngModelCtrl.$formatters.push(function(value) { - if (angular.isNumber(value) && value << 0 !== value) { - value = Math.round(value); + Tab.VERSION = "3.3.5"; + Tab.TRANSITION_DURATION = 150; + Tab.prototype.show = function() { + var $this = this.element; + var $ul = $this.closest("ul:not(.dropdown-menu)"); + var selector = $this.data("target"); + if (!selector) { + selector = $this.attr("href"); + selector = selector && selector.replace(/.*(?=#[^\s]*$)/, ""); + } + if ($this.parent("li").hasClass("active")) return; + var $previous = $ul.find(".active:last a"); + var hideEvent = $.Event("hide.bs.tab", { + relatedTarget: $this[0] + }); + var showEvent = $.Event("show.bs.tab", { + relatedTarget: $previous[0] + }); + $previous.trigger(hideEvent); + $this.trigger(showEvent); + if (showEvent.isDefaultPrevented() || hideEvent.isDefaultPrevented()) return; + var $target = $(selector); + this.activate($this.closest("li"), $ul); + this.activate($target, $target.parent(), function() { + $previous.trigger({ + type: "hidden.bs.tab", + relatedTarget: $this[0] + }); + $this.trigger({ + type: "shown.bs.tab", + relatedTarget: $previous[0] + }); + }); + }; + Tab.prototype.activate = function(element, container, callback) { + var $active = container.find("> .active"); + var transition = callback && $.support.transition && ($active.length && $active.hasClass("fade") || !!container.find("> .fade").length); + function next() { + $active.removeClass("active").find("> .dropdown-menu > .active").removeClass("active").end().find('[data-toggle="tab"]').attr("aria-expanded", false); + element.addClass("active").find('[data-toggle="tab"]').attr("aria-expanded", true); + if (transition) { + element[0].offsetWidth; + element.addClass("in"); + } else { + element.removeClass("fade"); } - return value; + if (element.parent(".dropdown-menu").length) { + element.closest("li.dropdown").addClass("active").end().find('[data-toggle="tab"]').attr("aria-expanded", true); + } + callback && callback(); + } + $active.length && transition ? $active.one("bsTransitionEnd", next).emulateTransitionEnd(Tab.TRANSITION_DURATION) : next(); + $active.removeClass("in"); + }; + function Plugin(option) { + return this.each(function() { + var $this = $(this); + var data = $this.data("bs.tab"); + if (!data) $this.data("bs.tab", data = new Tab(this)); + if (typeof option == "string") data[option](); }); - this.stateOn = angular.isDefined($attrs.stateOn) ? $scope.$parent.$eval($attrs.stateOn) : ratingConfig.stateOn; - this.stateOff = angular.isDefined($attrs.stateOff) ? $scope.$parent.$eval($attrs.stateOff) : ratingConfig.stateOff; - var tmpTitles = angular.isDefined($attrs.titles) ? $scope.$parent.$eval($attrs.titles) : ratingConfig.titles; - this.titles = angular.isArray(tmpTitles) && tmpTitles.length > 0 ? tmpTitles : ratingConfig.titles; - var ratingStates = angular.isDefined($attrs.ratingStates) ? $scope.$parent.$eval($attrs.ratingStates) : new Array(angular.isDefined($attrs.max) ? $scope.$parent.$eval($attrs.max) : ratingConfig.max); - $scope.range = this.buildTemplateObjects(ratingStates); + } + var old = $.fn.tab; + $.fn.tab = Plugin; + $.fn.tab.Constructor = Tab; + $.fn.tab.noConflict = function() { + $.fn.tab = old; + return this; }; - this.buildTemplateObjects = function(states) { - for (var i = 0, n = states.length; i < n; i++) { - states[i] = angular.extend({ - index: i - }, { - stateOn: this.stateOn, - stateOff: this.stateOff, - title: this.getTitle(i) - }, states[i]); - } - return states; + var clickHandler = function(e) { + e.preventDefault(); + Plugin.call($(this), "show"); }; - this.getTitle = function(index) { - if (index >= this.titles.length) { - return index + 1; - } else { - return this.titles[index]; - } + $(document).on("click.bs.tab.data-api", '[data-toggle="tab"]', clickHandler).on("click.bs.tab.data-api", '[data-toggle="pill"]', clickHandler); +}(jQuery); + ++function($) { + "use strict"; + var Affix = function(element, options) { + this.options = $.extend({}, Affix.DEFAULTS, options); + this.$target = $(this.options.target).on("scroll.bs.affix.data-api", $.proxy(this.checkPosition, this)).on("click.bs.affix.data-api", $.proxy(this.checkPositionWithEventLoop, this)); + this.$element = $(element); + this.affixed = null; + this.unpin = null; + this.pinnedOffset = null; + this.checkPosition(); }; - $scope.rate = function(value) { - if (!$scope.readonly && value >= 0 && value <= $scope.range.length) { - ngModelCtrl.$setViewValue(ngModelCtrl.$viewValue === value ? 0 : value); - ngModelCtrl.$render(); - } + Affix.VERSION = "3.3.5"; + Affix.RESET = "affix affix-top affix-bottom"; + Affix.DEFAULTS = { + offset: 0, + target: window }; - $scope.enter = function(value) { - if (!$scope.readonly) { - $scope.value = value; + Affix.prototype.getState = function(scrollHeight, height, offsetTop, offsetBottom) { + var scrollTop = this.$target.scrollTop(); + var position = this.$element.offset(); + var targetHeight = this.$target.height(); + if (offsetTop != null && this.affixed == "top") return scrollTop < offsetTop ? "top" : false; + if (this.affixed == "bottom") { + if (offsetTop != null) return scrollTop + this.unpin <= position.top ? false : "bottom"; + return scrollTop + targetHeight <= scrollHeight - offsetBottom ? false : "bottom"; } - $scope.onHover({ - value: value - }); + var initializing = this.affixed == null; + var colliderTop = initializing ? scrollTop : position.top; + var colliderHeight = initializing ? targetHeight : height; + if (offsetTop != null && scrollTop <= offsetTop) return "top"; + if (offsetBottom != null && colliderTop + colliderHeight >= scrollHeight - offsetBottom) return "bottom"; + return false; }; - $scope.reset = function() { - $scope.value = ngModelCtrl.$viewValue; - $scope.onLeave(); + Affix.prototype.getPinnedOffset = function() { + if (this.pinnedOffset) return this.pinnedOffset; + this.$element.removeClass(Affix.RESET).addClass("affix"); + var scrollTop = this.$target.scrollTop(); + var position = this.$element.offset(); + return this.pinnedOffset = position.top - scrollTop; }; - $scope.onKeydown = function(evt) { - if (/(37|38|39|40)/.test(evt.which)) { - evt.preventDefault(); - evt.stopPropagation(); - $scope.rate($scope.value + (evt.which === 38 || evt.which === 39 ? 1 : -1)); + Affix.prototype.checkPositionWithEventLoop = function() { + setTimeout($.proxy(this.checkPosition, this), 1); + }; + Affix.prototype.checkPosition = function() { + if (!this.$element.is(":visible")) return; + var height = this.$element.height(); + var offset = this.options.offset; + var offsetTop = offset.top; + var offsetBottom = offset.bottom; + var scrollHeight = Math.max($(document).height(), $(document.body).height()); + if (typeof offset != "object") offsetBottom = offsetTop = offset; + if (typeof offsetTop == "function") offsetTop = offset.top(this.$element); + if (typeof offsetBottom == "function") offsetBottom = offset.bottom(this.$element); + var affix = this.getState(scrollHeight, height, offsetTop, offsetBottom); + if (this.affixed != affix) { + if (this.unpin != null) this.$element.css("top", ""); + var affixType = "affix" + (affix ? "-" + affix : ""); + var e = $.Event(affixType + ".bs.affix"); + this.$element.trigger(e); + if (e.isDefaultPrevented()) return; + this.affixed = affix; + this.unpin = affix == "bottom" ? this.getPinnedOffset() : null; + this.$element.removeClass(Affix.RESET).addClass(affixType).trigger(affixType.replace("affix", "affixed") + ".bs.affix"); + } + if (affix == "bottom") { + this.$element.offset({ + top: scrollHeight - height - offsetBottom + }); } }; - this.render = function() { - $scope.value = ngModelCtrl.$viewValue; + function Plugin(option) { + return this.each(function() { + var $this = $(this); + var data = $this.data("bs.affix"); + var options = typeof option == "object" && option; + if (!data) $this.data("bs.affix", data = new Affix(this, options)); + if (typeof option == "string") data[option](); + }); + } + var old = $.fn.affix; + $.fn.affix = Plugin; + $.fn.affix.Constructor = Affix; + $.fn.affix.noConflict = function() { + $.fn.affix = old; + return this; }; -} ]).directive("rating", function() { + $(window).on("load", function() { + $('[data-spy="affix"]').each(function() { + var $spy = $(this); + var data = $spy.data(); + data.offset = data.offset || {}; + if (data.offsetBottom != null) data.offset.bottom = data.offsetBottom; + if (data.offsetTop != null) data.offset.top = data.offsetTop; + Plugin.call($spy, data); + }); + }); +}(jQuery); + +angular.module("ui.bootstrap", [ "ui.bootstrap.collapse", "ui.bootstrap.accordion", "ui.bootstrap.alert", "ui.bootstrap.bindHtml", "ui.bootstrap.buttons", "ui.bootstrap.carousel", "ui.bootstrap.dateparser", "ui.bootstrap.position", "ui.bootstrap.datepicker", "ui.bootstrap.dropdown", "ui.bootstrap.modal", "ui.bootstrap.pagination", "ui.bootstrap.tooltip", "ui.bootstrap.popover", "ui.bootstrap.progressbar", "ui.bootstrap.rating", "ui.bootstrap.tabs", "ui.bootstrap.timepicker", "ui.bootstrap.transition", "ui.bootstrap.typeahead" ]); + +angular.module("ui.bootstrap.collapse", []).directive("collapse", [ "$animate", function($animate) { return { - restrict: "EA", - require: [ "rating", "ngModel" ], - scope: { - readonly: "=?", - onHover: "&", - onLeave: "&" - }, - controller: "RatingController", - templateUrl: "template/rating/rating.html", - replace: true, - link: function(scope, element, attrs, ctrls) { - var ratingCtrl = ctrls[0], ngModelCtrl = ctrls[1]; - ratingCtrl.init(ngModelCtrl); + link: function(scope, element, attrs) { + function expand() { + element.removeClass("collapse").addClass("collapsing").attr("aria-expanded", true).attr("aria-hidden", false); + $animate.addClass(element, "in", { + to: { + height: element[0].scrollHeight + "px" + } + }).then(expandDone); + } + function expandDone() { + element.removeClass("collapsing"); + element.css({ + height: "auto" + }); + } + function collapse() { + if (!element.hasClass("collapse") && !element.hasClass("in")) { + return collapseDone(); + } + element.css({ + height: element[0].scrollHeight + "px" + }).removeClass("collapse").addClass("collapsing").attr("aria-expanded", false).attr("aria-hidden", true); + $animate.removeClass(element, "in", { + to: { + height: "0" + } + }).then(collapseDone); + } + function collapseDone() { + element.css({ + height: "0" + }); + element.removeClass("collapsing"); + element.addClass("collapse"); + } + scope.$watch(attrs.collapse, function(shouldCollapse) { + if (shouldCollapse) { + collapse(); + } else { + expand(); + } + }); } }; -}); +} ]); -angular.module("ui.bootstrap.tabs", []).controller("TabsetController", [ "$scope", function TabsetCtrl($scope) { - var ctrl = this, tabs = ctrl.tabs = $scope.tabs = []; - ctrl.select = function(selectedTab) { - angular.forEach(tabs, function(tab) { - if (tab.active && tab !== selectedTab) { - tab.active = false; - tab.onDeselect(); - selectedTab.selectCalled = false; - } - }); - selectedTab.active = true; - if (!selectedTab.selectCalled) { - selectedTab.onSelect(); - selectedTab.selectCalled = true; +angular.module("ui.bootstrap.accordion", [ "ui.bootstrap.collapse" ]).constant("accordionConfig", { + closeOthers: true +}).controller("AccordionController", [ "$scope", "$attrs", "accordionConfig", function($scope, $attrs, accordionConfig) { + this.groups = []; + this.closeOthers = function(openGroup) { + var closeOthers = angular.isDefined($attrs.closeOthers) ? $scope.$eval($attrs.closeOthers) : accordionConfig.closeOthers; + if (closeOthers) { + angular.forEach(this.groups, function(group) { + if (group !== openGroup) { + group.isOpen = false; + } + }); } }; - ctrl.addTab = function addTab(tab) { - tabs.push(tab); - if (tabs.length === 1 && tab.active !== false) { - tab.active = true; - } else if (tab.active) { - ctrl.select(tab); - } else { - tab.active = false; - } + this.addGroup = function(groupScope) { + var that = this; + this.groups.push(groupScope); + groupScope.$on("$destroy", function(event) { + that.removeGroup(groupScope); + }); }; - ctrl.removeTab = function removeTab(tab) { - var index = tabs.indexOf(tab); - if (tab.active && tabs.length > 1 && !destroyed) { - var newActiveIndex = index == tabs.length - 1 ? index - 1 : index + 1; - ctrl.select(tabs[newActiveIndex]); + this.removeGroup = function(group) { + var index = this.groups.indexOf(group); + if (index !== -1) { + this.groups.splice(index, 1); } - tabs.splice(index, 1); }; - var destroyed; - $scope.$on("$destroy", function() { - destroyed = true; - }); -} ]).directive("tabset", function() { +} ]).directive("accordion", function() { return { restrict: "EA", + controller: "AccordionController", + controllerAs: "accordion", transclude: true, - replace: true, - scope: { - type: "@" - }, - controller: "TabsetController", - templateUrl: "template/tabs/tabset.html", - link: function(scope, element, attrs) { - scope.vertical = angular.isDefined(attrs.vertical) ? scope.$parent.$eval(attrs.vertical) : false; - scope.justified = angular.isDefined(attrs.justified) ? scope.$parent.$eval(attrs.justified) : false; + replace: false, + templateUrl: function(element, attrs) { + return attrs.templateUrl || "template/accordion/accordion.html"; } }; -}).directive("tab", [ "$parse", "$log", function($parse, $log) { +}).directive("accordionGroup", function() { return { - require: "^tabset", + require: "^accordion", restrict: "EA", - replace: true, - templateUrl: "template/tabs/tab.html", transclude: true, + replace: true, + templateUrl: function(element, attrs) { + return attrs.templateUrl || "template/accordion/accordion-group.html"; + }, scope: { - active: "=?", heading: "@", - onSelect: "&select", - onDeselect: "&deselect" + isOpen: "=?", + isDisabled: "=?" }, - controller: function() {}, - link: function(scope, elm, attrs, tabsetCtrl, transclude) { - scope.$watch("active", function(active) { - if (active) { - tabsetCtrl.select(scope); + controller: function() { + this.setHeading = function(element) { + this.heading = element; + }; + }, + link: function(scope, element, attrs, accordionCtrl) { + accordionCtrl.addGroup(scope); + scope.openClass = attrs.openClass || "panel-open"; + scope.panelClass = attrs.panelClass; + scope.$watch("isOpen", function(value) { + element.toggleClass(scope.openClass, value); + if (value) { + accordionCtrl.closeOthers(scope); } }); - scope.disabled = false; - if (attrs.disable) { - scope.$parent.$watch($parse(attrs.disable), function(value) { - scope.disabled = !!value; - }); - } - if (attrs.disabled) { - $log.warn('Use of "disabled" attribute has been deprecated, please use "disable"'); - scope.$parent.$watch($parse(attrs.disabled), function(value) { - scope.disabled = !!value; - }); - } - scope.select = function() { - if (!scope.disabled) { - scope.active = true; + scope.toggleOpen = function($event) { + if (!scope.isDisabled) { + if (!$event || $event.which === 32) { + scope.isOpen = !scope.isOpen; + } } }; - tabsetCtrl.addTab(scope); - scope.$on("$destroy", function() { - tabsetCtrl.removeTab(scope); - }); - scope.$transcludeFn = transclude; } }; -} ]).directive("tabHeadingTransclude", function() { +}).directive("accordionHeading", function() { return { - restrict: "A", - require: "^tab", - link: function(scope, elm, attrs, tabCtrl) { - scope.$watch("headingElement", function updateHeadingElement(heading) { - if (heading) { - elm.html(""); - elm.append(heading); - } - }); + restrict: "EA", + transclude: true, + template: "", + replace: true, + require: "^accordionGroup", + link: function(scope, element, attr, accordionGroupCtrl, transclude) { + accordionGroupCtrl.setHeading(transclude(scope, angular.noop)); } }; -}).directive("tabContentTransclude", function() { +}).directive("accordionTransclude", function() { return { - restrict: "A", - require: "^tabset", - link: function(scope, elm, attrs) { - var tab = scope.$eval(attrs.tabContentTransclude); - tab.$transcludeFn(tab.$parent, function(contents) { - angular.forEach(contents, function(node) { - if (isTabHeading(node)) { - tab.headingElement = node; - } else { - elm.append(node); - } - }); + require: "^accordionGroup", + link: function(scope, element, attr, controller) { + scope.$watch(function() { + return controller[attr.accordionTransclude]; + }, function(heading) { + if (heading) { + element.find("span").html(""); + element.find("span").append(heading); + } }); } }; - function isTabHeading(node) { - return node.tagName && (node.hasAttribute("tab-heading") || node.hasAttribute("data-tab-heading") || node.hasAttribute("x-tab-heading") || node.tagName.toLowerCase() === "tab-heading" || node.tagName.toLowerCase() === "data-tab-heading" || node.tagName.toLowerCase() === "x-tab-heading"); - } }); -angular.module("ui.bootstrap.timepicker", []).constant("timepickerConfig", { - hourStep: 1, - minuteStep: 1, - showMeridian: true, - meridians: null, - readonlyInput: false, - mousewheel: true, - arrowkeys: true, - showSpinners: true -}).controller("TimepickerController", [ "$scope", "$attrs", "$parse", "$log", "$locale", "timepickerConfig", function($scope, $attrs, $parse, $log, $locale, timepickerConfig) { - var selected = new Date(), ngModelCtrl = { - $setViewValue: angular.noop - }, meridians = angular.isDefined($attrs.meridians) ? $scope.$parent.$eval($attrs.meridians) : timepickerConfig.meridians || $locale.DATETIME_FORMATS.AMPMS; - this.init = function(ngModelCtrl_, inputs) { - ngModelCtrl = ngModelCtrl_; - ngModelCtrl.$render = this.render; - ngModelCtrl.$formatters.unshift(function(modelValue) { - return modelValue ? new Date(modelValue) : null; - }); - var hoursInputEl = inputs.eq(0), minutesInputEl = inputs.eq(1); - var mousewheel = angular.isDefined($attrs.mousewheel) ? $scope.$parent.$eval($attrs.mousewheel) : timepickerConfig.mousewheel; - if (mousewheel) { - this.setupMousewheelEvents(hoursInputEl, minutesInputEl); - } - var arrowkeys = angular.isDefined($attrs.arrowkeys) ? $scope.$parent.$eval($attrs.arrowkeys) : timepickerConfig.arrowkeys; - if (arrowkeys) { - this.setupArrowkeyEvents(hoursInputEl, minutesInputEl); - } - $scope.readonlyInput = angular.isDefined($attrs.readonlyInput) ? $scope.$parent.$eval($attrs.readonlyInput) : timepickerConfig.readonlyInput; - this.setupInputEvents(hoursInputEl, minutesInputEl); - }; - var hourStep = timepickerConfig.hourStep; - if ($attrs.hourStep) { - $scope.$parent.$watch($parse($attrs.hourStep), function(value) { - hourStep = parseInt(value, 10); - }); - } - var minuteStep = timepickerConfig.minuteStep; - if ($attrs.minuteStep) { - $scope.$parent.$watch($parse($attrs.minuteStep), function(value) { - minuteStep = parseInt(value, 10); - }); - } - var min; - $scope.$parent.$watch($parse($attrs.min), function(value) { - var dt = new Date(value); - min = isNaN(dt) ? undefined : dt; - }); - var max; - $scope.$parent.$watch($parse($attrs.max), function(value) { - var dt = new Date(value); - max = isNaN(dt) ? undefined : dt; - }); - $scope.noIncrementHours = function() { - var incrementedSelected = addMinutes(selected, hourStep * 60); - return incrementedSelected > max || incrementedSelected < selected && incrementedSelected < min; - }; - $scope.noDecrementHours = function() { - var decrementedSelected = addMinutes(selected, -hourStep * 60); - return decrementedSelected < min || decrementedSelected > selected && decrementedSelected > max; - }; - $scope.noIncrementMinutes = function() { - var incrementedSelected = addMinutes(selected, minuteStep); - return incrementedSelected > max || incrementedSelected < selected && incrementedSelected < min; - }; - $scope.noDecrementMinutes = function() { - var decrementedSelected = addMinutes(selected, -minuteStep); - return decrementedSelected < min || decrementedSelected > selected && decrementedSelected > max; - }; - $scope.noToggleMeridian = function() { - if (selected.getHours() < 13) { - return addMinutes(selected, 12 * 60) > max; - } else { - return addMinutes(selected, -12 * 60) < min; - } - }; - $scope.showMeridian = timepickerConfig.showMeridian; - if ($attrs.showMeridian) { - $scope.$parent.$watch($parse($attrs.showMeridian), function(value) { - $scope.showMeridian = !!value; - if (ngModelCtrl.$error.time) { - var hours = getHoursFromTemplate(), minutes = getMinutesFromTemplate(); - if (angular.isDefined(hours) && angular.isDefined(minutes)) { - selected.setHours(hours); - refresh(); - } - } else { - updateTemplate(); - } - }); - } - function getHoursFromTemplate() { - var hours = parseInt($scope.hours, 10); - var valid = $scope.showMeridian ? hours > 0 && hours < 13 : hours >= 0 && hours < 24; - if (!valid) { - return undefined; +angular.module("ui.bootstrap.alert", []).controller("AlertController", [ "$scope", "$attrs", function($scope, $attrs) { + $scope.closeable = !!$attrs.close; + this.close = $scope.close; +} ]).directive("alert", function() { + return { + controller: "AlertController", + controllerAs: "alert", + templateUrl: function(element, attrs) { + return attrs.templateUrl || "template/alert/alert.html"; + }, + transclude: true, + replace: true, + scope: { + type: "@", + close: "&" } - if ($scope.showMeridian) { - if (hours === 12) { - hours = 0; - } - if ($scope.meridian === meridians[1]) { - hours = hours + 12; - } + }; +}).directive("dismissOnTimeout", [ "$timeout", function($timeout) { + return { + require: "alert", + link: function(scope, element, attrs, alertCtrl) { + $timeout(function() { + alertCtrl.close(); + }, parseInt(attrs.dismissOnTimeout, 10)); } - return hours; - } - function getMinutesFromTemplate() { - var minutes = parseInt($scope.minutes, 10); - return minutes >= 0 && minutes < 60 ? minutes : undefined; - } - function pad(value) { - return angular.isDefined(value) && value.toString().length < 2 ? "0" + value : value.toString(); - } - this.setupMousewheelEvents = function(hoursInputEl, minutesInputEl) { - var isScrollingUp = function(e) { - if (e.originalEvent) { - e = e.originalEvent; - } - var delta = e.wheelDelta ? e.wheelDelta : -e.deltaY; - return e.detail || delta > 0; - }; - hoursInputEl.bind("mousewheel wheel", function(e) { - $scope.$apply(isScrollingUp(e) ? $scope.incrementHours() : $scope.decrementHours()); - e.preventDefault(); - }); - minutesInputEl.bind("mousewheel wheel", function(e) { - $scope.$apply(isScrollingUp(e) ? $scope.incrementMinutes() : $scope.decrementMinutes()); - e.preventDefault(); - }); }; - this.setupArrowkeyEvents = function(hoursInputEl, minutesInputEl) { - hoursInputEl.bind("keydown", function(e) { - if (e.which === 38) { - e.preventDefault(); - $scope.incrementHours(); - $scope.$apply(); - } else if (e.which === 40) { - e.preventDefault(); - $scope.decrementHours(); - $scope.$apply(); - } - }); - minutesInputEl.bind("keydown", function(e) { - if (e.which === 38) { - e.preventDefault(); - $scope.incrementMinutes(); - $scope.$apply(); - } else if (e.which === 40) { - e.preventDefault(); - $scope.decrementMinutes(); - $scope.$apply(); - } +} ]); + +angular.module("ui.bootstrap.bindHtml", []).value("$bindHtmlUnsafeSuppressDeprecated", false).directive("bindHtmlUnsafe", [ "$log", "$bindHtmlUnsafeSuppressDeprecated", function($log, $bindHtmlUnsafeSuppressDeprecated) { + return function(scope, element, attr) { + if (!$bindHtmlUnsafeSuppressDeprecated) { + $log.warn("bindHtmlUnsafe is now deprecated. Use ngBindHtml instead"); + } + element.addClass("ng-binding").data("$binding", attr.bindHtmlUnsafe); + scope.$watch(attr.bindHtmlUnsafe, function bindHtmlUnsafeWatchAction(value) { + element.html(value || ""); }); }; - this.setupInputEvents = function(hoursInputEl, minutesInputEl) { - if ($scope.readonlyInput) { - $scope.updateHours = angular.noop; - $scope.updateMinutes = angular.noop; - return; +} ]); + +angular.module("ui.bootstrap.buttons", []).constant("buttonConfig", { + activeClass: "active", + toggleEvent: "click" +}).controller("ButtonsController", [ "buttonConfig", function(buttonConfig) { + this.activeClass = buttonConfig.activeClass || "active"; + this.toggleEvent = buttonConfig.toggleEvent || "click"; +} ]).directive("btnRadio", function() { + return { + require: [ "btnRadio", "ngModel" ], + controller: "ButtonsController", + controllerAs: "buttons", + link: function(scope, element, attrs, ctrls) { + var buttonsCtrl = ctrls[0], ngModelCtrl = ctrls[1]; + element.find("input").css({ + display: "none" + }); + ngModelCtrl.$render = function() { + element.toggleClass(buttonsCtrl.activeClass, angular.equals(ngModelCtrl.$modelValue, scope.$eval(attrs.btnRadio))); + }; + element.bind(buttonsCtrl.toggleEvent, function() { + if (attrs.disabled) { + return; + } + var isActive = element.hasClass(buttonsCtrl.activeClass); + if (!isActive || angular.isDefined(attrs.uncheckable)) { + scope.$apply(function() { + ngModelCtrl.$setViewValue(isActive ? null : scope.$eval(attrs.btnRadio)); + ngModelCtrl.$render(); + }); + } + }); } - var invalidate = function(invalidHours, invalidMinutes) { - ngModelCtrl.$setViewValue(null); - ngModelCtrl.$setValidity("time", false); - if (angular.isDefined(invalidHours)) { - $scope.invalidHours = invalidHours; + }; +}).directive("btnCheckbox", [ "$document", function($document) { + return { + require: [ "btnCheckbox", "ngModel" ], + controller: "ButtonsController", + controllerAs: "button", + link: function(scope, element, attrs, ctrls) { + var buttonsCtrl = ctrls[0], ngModelCtrl = ctrls[1]; + element.find("input").css({ + display: "none" + }); + function getTrueValue() { + return getCheckboxValue(attrs.btnCheckboxTrue, true); } - if (angular.isDefined(invalidMinutes)) { - $scope.invalidMinutes = invalidMinutes; + function getFalseValue() { + return getCheckboxValue(attrs.btnCheckboxFalse, false); } - }; - $scope.updateHours = function() { - var hours = getHoursFromTemplate(), minutes = getMinutesFromTemplate(); - if (angular.isDefined(hours) && angular.isDefined(minutes)) { - selected.setHours(hours); - if (selected < min || selected > max) { - invalidate(true); - } else { - refresh("h"); - } - } else { - invalidate(true); + function getCheckboxValue(attributeValue, defaultValue) { + var val = scope.$eval(attributeValue); + return angular.isDefined(val) ? val : defaultValue; } - }; - hoursInputEl.bind("blur", function(e) { - if (!$scope.invalidHours && $scope.hours < 10) { - $scope.$apply(function() { - $scope.hours = pad($scope.hours); + ngModelCtrl.$render = function() { + element.toggleClass(buttonsCtrl.activeClass, angular.equals(ngModelCtrl.$modelValue, getTrueValue())); + }; + element.bind(buttonsCtrl.toggleEvent, function() { + if (attrs.disabled) { + return; + } + scope.$apply(function() { + ngModelCtrl.$setViewValue(element.hasClass(buttonsCtrl.activeClass) ? getFalseValue() : getTrueValue()); + ngModelCtrl.$render(); }); - } - }); - $scope.updateMinutes = function() { - var minutes = getMinutesFromTemplate(), hours = getHoursFromTemplate(); - if (angular.isDefined(minutes) && angular.isDefined(hours)) { - selected.setMinutes(minutes); - if (selected < min || selected > max) { - invalidate(undefined, true); - } else { - refresh("m"); + }); + element.on("keypress", function(e) { + if (attrs.disabled || e.which !== 32 || $document[0].activeElement !== element[0]) { + return; } - } else { - invalidate(undefined, true); - } - }; - minutesInputEl.bind("blur", function(e) { - if (!$scope.invalidMinutes && $scope.minutes < 10) { - $scope.$apply(function() { - $scope.minutes = pad($scope.minutes); + scope.$apply(function() { + ngModelCtrl.$setViewValue(element.hasClass(buttonsCtrl.activeClass) ? getFalseValue() : getTrueValue()); + ngModelCtrl.$render(); }); - } - }); + }); + } }; - this.render = function() { - var date = ngModelCtrl.$viewValue; - if (isNaN(date)) { - ngModelCtrl.$setValidity("time", false); - $log.error('Timepicker directive: "ng-model" value must be a Date object, a number of milliseconds since 01.01.1970 or a string representing an RFC2822 or ISO 8601 date.'); - } else { - if (date) { - selected = date; +} ]); + +angular.module("ui.bootstrap.carousel", []).controller("CarouselController", [ "$scope", "$element", "$interval", "$animate", function($scope, $element, $interval, $animate) { + var self = this, slides = self.slides = $scope.slides = [], NEW_ANIMATE = angular.version.minor >= 4, NO_TRANSITION = "uib-noTransition", SLIDE_DIRECTION = "uib-slideDirection", currentIndex = -1, currentInterval, isPlaying; + self.currentSlide = null; + var destroyed = false; + self.select = $scope.select = function(nextSlide, direction) { + var nextIndex = $scope.indexOfSlide(nextSlide); + if (direction === undefined) { + direction = nextIndex > self.getCurrentIndex() ? "next" : "prev"; + } + if (nextSlide && nextSlide !== self.currentSlide && !$scope.$currentTransition) { + goNext(nextSlide, nextIndex, direction); + } + }; + function goNext(slide, index, direction) { + if (destroyed) { + return; + } + angular.extend(slide, { + direction: direction, + active: true + }); + angular.extend(self.currentSlide || {}, { + direction: direction, + active: false + }); + if ($animate.enabled() && !$scope.noTransition && !$scope.$currentTransition && slide.$element && self.slides.length > 1) { + slide.$element.data(SLIDE_DIRECTION, slide.direction); + if (self.currentSlide && self.currentSlide.$element) { + self.currentSlide.$element.data(SLIDE_DIRECTION, slide.direction); } - if (selected < min || selected > max) { - ngModelCtrl.$setValidity("time", false); - $scope.invalidHours = true; - $scope.invalidMinutes = true; + $scope.$currentTransition = true; + if (NEW_ANIMATE) { + $animate.on("addClass", slide.$element, function(element, phase) { + if (phase === "close") { + $scope.$currentTransition = null; + $animate.off("addClass", element); + } + }); } else { - makeValid(); + slide.$element.one("$animate:close", function closeFn() { + $scope.$currentTransition = null; + }); + } + } + self.currentSlide = slide; + currentIndex = index; + restartTimer(); + } + $scope.$on("$destroy", function() { + destroyed = true; + }); + function getSlideByIndex(index) { + if (angular.isUndefined(slides[index].index)) { + return slides[index]; + } + var i, len = slides.length; + for (i = 0; i < slides.length; ++i) { + if (slides[i].index == index) { + return slides[i]; } - updateTemplate(); } - }; - function refresh(keyboardChange) { - makeValid(); - ngModelCtrl.$setViewValue(new Date(selected)); - updateTemplate(keyboardChange); - } - function makeValid() { - ngModelCtrl.$setValidity("time", true); - $scope.invalidHours = false; - $scope.invalidMinutes = false; } - function updateTemplate(keyboardChange) { - var hours = selected.getHours(), minutes = selected.getMinutes(); - if ($scope.showMeridian) { - hours = hours === 0 || hours === 12 ? 12 : hours % 12; + self.getCurrentIndex = function() { + if (self.currentSlide && angular.isDefined(self.currentSlide.index)) { + return +self.currentSlide.index; } - $scope.hours = keyboardChange === "h" ? hours : pad(hours); - if (keyboardChange !== "m") { - $scope.minutes = pad(minutes); + return currentIndex; + }; + $scope.indexOfSlide = function(slide) { + return angular.isDefined(slide.index) ? +slide.index : slides.indexOf(slide); + }; + $scope.next = function() { + var newIndex = (self.getCurrentIndex() + 1) % slides.length; + if (newIndex === 0 && $scope.noWrap()) { + $scope.pause(); + return; + } + return self.select(getSlideByIndex(newIndex), "next"); + }; + $scope.prev = function() { + var newIndex = self.getCurrentIndex() - 1 < 0 ? slides.length - 1 : self.getCurrentIndex() - 1; + if ($scope.noWrap() && newIndex === slides.length - 1) { + $scope.pause(); + return; + } + return self.select(getSlideByIndex(newIndex), "prev"); + }; + $scope.isActive = function(slide) { + return self.currentSlide === slide; + }; + $scope.$watch("interval", restartTimer); + $scope.$on("$destroy", resetTimer); + function restartTimer() { + resetTimer(); + var interval = +$scope.interval; + if (!isNaN(interval) && interval > 0) { + currentInterval = $interval(timerFn, interval); } - $scope.meridian = selected.getHours() < 12 ? meridians[0] : meridians[1]; } - function addMinutes(date, minutes) { - var dt = new Date(date.getTime() + minutes * 6e4); - var newDate = new Date(date); - newDate.setHours(dt.getHours(), dt.getMinutes()); - return newDate; + function resetTimer() { + if (currentInterval) { + $interval.cancel(currentInterval); + currentInterval = null; + } } - function addMinutesToSelected(minutes) { - selected = addMinutes(selected, minutes); - refresh(); + function timerFn() { + var interval = +$scope.interval; + if (isPlaying && !isNaN(interval) && interval > 0 && slides.length) { + $scope.next(); + } else { + $scope.pause(); + } } - $scope.showSpinners = angular.isDefined($attrs.showSpinners) ? $scope.$parent.$eval($attrs.showSpinners) : timepickerConfig.showSpinners; - $scope.incrementHours = function() { - if (!$scope.noIncrementHours()) { - addMinutesToSelected(hourStep * 60); + $scope.play = function() { + if (!isPlaying) { + isPlaying = true; + restartTimer(); } }; - $scope.decrementHours = function() { - if (!$scope.noDecrementHours()) { - addMinutesToSelected(-hourStep * 60); + $scope.pause = function() { + if (!$scope.noPause) { + isPlaying = false; + resetTimer(); } }; - $scope.incrementMinutes = function() { - if (!$scope.noIncrementMinutes()) { - addMinutesToSelected(minuteStep); + self.addSlide = function(slide, element) { + slide.$element = element; + slides.push(slide); + if (slides.length === 1 || slide.active) { + self.select(slides[slides.length - 1]); + if (slides.length == 1) { + $scope.play(); + } + } else { + slide.active = false; } }; - $scope.decrementMinutes = function() { - if (!$scope.noDecrementMinutes()) { - addMinutesToSelected(-minuteStep); + self.removeSlide = function(slide) { + if (angular.isDefined(slide.index)) { + slides.sort(function(a, b) { + return +a.index > +b.index; + }); + } + var index = slides.indexOf(slide); + slides.splice(index, 1); + if (slides.length > 0 && slide.active) { + if (index >= slides.length) { + self.select(slides[index - 1]); + } else { + self.select(slides[index]); + } + } else if (currentIndex > index) { + currentIndex--; + } + if (slides.length === 0) { + self.currentSlide = null; } }; - $scope.toggleMeridian = function() { - if (!$scope.noToggleMeridian()) { - addMinutesToSelected(12 * 60 * (selected.getHours() < 12 ? 1 : -1)); + $scope.$watch("noTransition", function(noTransition) { + $element.data(NO_TRANSITION, noTransition); + }); +} ]).directive("carousel", [ function() { + return { + restrict: "EA", + transclude: true, + replace: true, + controller: "CarouselController", + controllerAs: "carousel", + require: "carousel", + templateUrl: function(element, attrs) { + return attrs.templateUrl || "template/carousel/carousel.html"; + }, + scope: { + interval: "=", + noTransition: "=", + noPause: "=", + noWrap: "&" } }; -} ]).directive("timepicker", function() { +} ]).directive("slide", function() { return { + require: "^carousel", restrict: "EA", - require: [ "timepicker", "?^ngModel" ], - controller: "TimepickerController", - controllerAs: "timepicker", + transclude: true, replace: true, - scope: {}, templateUrl: function(element, attrs) { - return attrs.templateUrl || "template/timepicker/timepicker.html"; + return attrs.templateUrl || "template/carousel/slide.html"; + }, + scope: { + active: "=?", + actual: "=?", + index: "=?" + }, + link: function(scope, element, attrs, carouselCtrl) { + carouselCtrl.addSlide(scope, element); + scope.$on("$destroy", function() { + carouselCtrl.removeSlide(scope); + }); + scope.$watch("active", function(active) { + if (active) { + carouselCtrl.select(scope); + } + }); + } + }; +}).animation(".item", [ "$injector", "$animate", function($injector, $animate) { + var NO_TRANSITION = "uib-noTransition", SLIDE_DIRECTION = "uib-slideDirection", $animateCss = null; + if ($injector.has("$animateCss")) { + $animateCss = $injector.get("$animateCss"); + } + function removeClass(element, className, callback) { + element.removeClass(className); + if (callback) { + callback(); + } + } + return { + beforeAddClass: function(element, className, done) { + if (className == "active" && element.parent() && !element.parent().data(NO_TRANSITION)) { + var stopped = false; + var direction = element.data(SLIDE_DIRECTION); + var directionClass = direction == "next" ? "left" : "right"; + var removeClassFn = removeClass.bind(this, element, directionClass + " " + direction, done); + element.addClass(direction); + if ($animateCss) { + $animateCss(element, { + addClass: directionClass + }).start().done(removeClassFn); + } else { + $animate.addClass(element, directionClass).then(function() { + if (!stopped) { + removeClassFn(); + } + done(); + }); + } + return function() { + stopped = true; + }; + } + done(); + }, + beforeRemoveClass: function(element, className, done) { + if (className === "active" && element.parent() && !element.parent().data(NO_TRANSITION)) { + var stopped = false; + var direction = element.data(SLIDE_DIRECTION); + var directionClass = direction == "next" ? "left" : "right"; + var removeClassFn = removeClass.bind(this, element, directionClass, done); + if ($animateCss) { + $animateCss(element, { + addClass: directionClass + }).start().done(removeClassFn); + } else { + $animate.addClass(element, directionClass).then(function() { + if (!stopped) { + removeClassFn(); + } + done(); + }); + } + return function() { + stopped = true; + }; + } + done(); + } + }; +} ]); + +angular.module("ui.bootstrap.dateparser", []).service("dateParser", [ "$log", "$locale", "orderByFilter", function($log, $locale, orderByFilter) { + var SPECIAL_CHARACTERS_REGEXP = /[\\\^\$\*\+\?\|\[\]\(\)\.\{\}]/g; + this.parsers = {}; + var formatCodeToRegex = { + yyyy: { + regex: "\\d{4}", + apply: function(value) { + this.year = +value; + } + }, + yy: { + regex: "\\d{2}", + apply: function(value) { + this.year = +value + 2e3; + } }, - link: function(scope, element, attrs, ctrls) { - var timepickerCtrl = ctrls[0], ngModelCtrl = ctrls[1]; - if (ngModelCtrl) { - timepickerCtrl.init(ngModelCtrl, element.find("input")); + y: { + regex: "\\d{1,4}", + apply: function(value) { + this.year = +value; } - } - }; -}); - -angular.module("ui.bootstrap.transition", []).value("$transitionSuppressDeprecated", false).factory("$transition", [ "$q", "$timeout", "$rootScope", "$log", "$transitionSuppressDeprecated", function($q, $timeout, $rootScope, $log, $transitionSuppressDeprecated) { - if (!$transitionSuppressDeprecated) { - $log.warn("$transition is now deprecated. Use $animate from ngAnimate instead."); - } - var $transition = function(element, trigger, options) { - options = options || {}; - var deferred = $q.defer(); - var endEventName = $transition[options.animation ? "animationEndEventName" : "transitionEndEventName"]; - var transitionEndHandler = function(event) { - $rootScope.$apply(function() { - element.unbind(endEventName, transitionEndHandler); - deferred.resolve(element); - }); - }; - if (endEventName) { - element.bind(endEventName, transitionEndHandler); - } - $timeout(function() { - if (angular.isString(trigger)) { - element.addClass(trigger); - } else if (angular.isFunction(trigger)) { - trigger(element); - } else if (angular.isObject(trigger)) { - element.css(trigger); + }, + MMMM: { + regex: $locale.DATETIME_FORMATS.MONTH.join("|"), + apply: function(value) { + this.month = $locale.DATETIME_FORMATS.MONTH.indexOf(value); } - if (!endEventName) { - deferred.resolve(element); + }, + MMM: { + regex: $locale.DATETIME_FORMATS.SHORTMONTH.join("|"), + apply: function(value) { + this.month = $locale.DATETIME_FORMATS.SHORTMONTH.indexOf(value); } - }); - deferred.promise.cancel = function() { - if (endEventName) { - element.unbind(endEventName, transitionEndHandler); + }, + MM: { + regex: "0[1-9]|1[0-2]", + apply: function(value) { + this.month = value - 1; } - deferred.reject("Transition cancelled"); - }; - return deferred.promise; - }; - var transElement = document.createElement("trans"); - var transitionEndEventNames = { - WebkitTransition: "webkitTransitionEnd", - MozTransition: "transitionend", - OTransition: "oTransitionEnd", - transition: "transitionend" - }; - var animationEndEventNames = { - WebkitTransition: "webkitAnimationEnd", - MozTransition: "animationend", - OTransition: "oAnimationEnd", - transition: "animationend" - }; - function findEndEventName(endEventNames) { - for (var name in endEventNames) { - if (transElement.style[name] !== undefined) { - return endEventNames[name]; + }, + M: { + regex: "[1-9]|1[0-2]", + apply: function(value) { + this.month = value - 1; } - } - } - $transition.transitionEndEventName = findEndEventName(transitionEndEventNames); - $transition.animationEndEventName = findEndEventName(animationEndEventNames); - return $transition; -} ]); - -angular.module("ui.bootstrap.typeahead", [ "ui.bootstrap.position" ]).factory("typeaheadParser", [ "$parse", function($parse) { - var TYPEAHEAD_REGEXP = /^\s*([\s\S]+?)(?:\s+as\s+([\s\S]+?))?\s+for\s+(?:([\$\w][\$\w\d]*))\s+in\s+([\s\S]+?)$/; - return { - parse: function(input) { - var match = input.match(TYPEAHEAD_REGEXP); - if (!match) { - throw new Error('Expected typeahead specification in form of "_modelValue_ (as _label_)? for _item_ in _collection_"' + ' but got "' + input + '".'); + }, + dd: { + regex: "[0-2][0-9]{1}|3[0-1]{1}", + apply: function(value) { + this.date = +value; } - return { - itemName: match[3], - source: $parse(match[4]), - viewMapper: $parse(match[2] || match[1]), - modelMapper: $parse(match[1]) - }; - } - }; -} ]).directive("typeahead", [ "$compile", "$parse", "$q", "$timeout", "$document", "$window", "$rootScope", "$position", "typeaheadParser", function($compile, $parse, $q, $timeout, $document, $window, $rootScope, $position, typeaheadParser) { - var HOT_KEYS = [ 9, 13, 27, 38, 40 ]; - var eventDebounceTime = 200; - return { - require: [ "ngModel", "^?ngModelOptions" ], - link: function(originalScope, element, attrs, ctrls) { - var modelCtrl = ctrls[0]; - var ngModelOptions = ctrls[1]; - var minLength = originalScope.$eval(attrs.typeaheadMinLength); - if (!minLength && minLength !== 0) { - minLength = 1; + }, + d: { + regex: "[1-2]?[0-9]{1}|3[0-1]{1}", + apply: function(value) { + this.date = +value; } - var waitTime = originalScope.$eval(attrs.typeaheadWaitMs) || 0; - var isEditable = originalScope.$eval(attrs.typeaheadEditable) !== false; - var isLoadingSetter = $parse(attrs.typeaheadLoading).assign || angular.noop; - var onSelectCallback = $parse(attrs.typeaheadOnSelect); - var isSelectOnBlur = angular.isDefined(attrs.typeaheadSelectOnBlur) ? originalScope.$eval(attrs.typeaheadSelectOnBlur) : false; - var isNoResultsSetter = $parse(attrs.typeaheadNoResults).assign || angular.noop; - var inputFormatter = attrs.typeaheadInputFormatter ? $parse(attrs.typeaheadInputFormatter) : undefined; - var appendToBody = attrs.typeaheadAppendToBody ? originalScope.$eval(attrs.typeaheadAppendToBody) : false; - var focusFirst = originalScope.$eval(attrs.typeaheadFocusFirst) !== false; - var selectOnExact = attrs.typeaheadSelectOnExact ? originalScope.$eval(attrs.typeaheadSelectOnExact) : false; - var parsedModel = $parse(attrs.ngModel); - var invokeModelSetter = $parse(attrs.ngModel + "($$$p)"); - var $setModelValue = function(scope, newValue) { - if (angular.isFunction(parsedModel(originalScope)) && ngModelOptions && ngModelOptions.$options && ngModelOptions.$options.getterSetter) { - return invokeModelSetter(scope, { - $$$p: newValue - }); - } else { - return parsedModel.assign(scope, newValue); - } - }; - var parserResult = typeaheadParser.parse(attrs.typeahead); - var hasFocus; - var selected; - var scope = originalScope.$new(); - var offDestroy = originalScope.$on("$destroy", function() { - scope.$destroy(); - }); - scope.$on("$destroy", offDestroy); - var popupId = "typeahead-" + scope.$id + "-" + Math.floor(Math.random() * 1e4); - element.attr({ - "aria-autocomplete": "list", - "aria-expanded": false, - "aria-owns": popupId - }); - var popUpEl = angular.element("
        "); - popUpEl.attr({ - id: popupId, - matches: "matches", - active: "activeIdx", - select: "select(activeIdx)", - "move-in-progress": "moveInProgress", - query: "query", - position: "position" - }); - if (angular.isDefined(attrs.typeaheadTemplateUrl)) { - popUpEl.attr("template-url", attrs.typeaheadTemplateUrl); + }, + EEEE: { + regex: $locale.DATETIME_FORMATS.DAY.join("|") + }, + EEE: { + regex: $locale.DATETIME_FORMATS.SHORTDAY.join("|") + }, + HH: { + regex: "(?:0|1)[0-9]|2[0-3]", + apply: function(value) { + this.hours = +value; } - if (angular.isDefined(attrs.typeaheadPopupTemplateUrl)) { - popUpEl.attr("popup-template-url", attrs.typeaheadPopupTemplateUrl); + }, + hh: { + regex: "0[0-9]|1[0-2]", + apply: function(value) { + this.hours = +value; } - var resetMatches = function() { - scope.matches = []; - scope.activeIdx = -1; - element.attr("aria-expanded", false); - }; - var getMatchId = function(index) { - return popupId + "-option-" + index; - }; - scope.$watch("activeIdx", function(index) { - if (index < 0) { - element.removeAttr("aria-activedescendant"); - } else { - element.attr("aria-activedescendant", getMatchId(index)); + }, + H: { + regex: "1?[0-9]|2[0-3]", + apply: function(value) { + this.hours = +value; + } + }, + h: { + regex: "[0-9]|1[0-2]", + apply: function(value) { + this.hours = +value; + } + }, + mm: { + regex: "[0-5][0-9]", + apply: function(value) { + this.minutes = +value; + } + }, + m: { + regex: "[0-9]|[1-5][0-9]", + apply: function(value) { + this.minutes = +value; + } + }, + sss: { + regex: "[0-9][0-9][0-9]", + apply: function(value) { + this.milliseconds = +value; + } + }, + ss: { + regex: "[0-5][0-9]", + apply: function(value) { + this.seconds = +value; + } + }, + s: { + regex: "[0-9]|[1-5][0-9]", + apply: function(value) { + this.seconds = +value; + } + }, + a: { + regex: $locale.DATETIME_FORMATS.AMPMS.join("|"), + apply: function(value) { + if (this.hours === 12) { + this.hours = 0; } - }); - var inputIsExactMatch = function(inputValue, index) { - if (scope.matches.length > index && inputValue) { - return inputValue.toUpperCase() === scope.matches[index].label.toUpperCase(); + if (value === "PM") { + this.hours += 12; } - return false; - }; - var getMatchesAsync = function(inputValue) { - var locals = { - $viewValue: inputValue - }; - isLoadingSetter(originalScope, true); - isNoResultsSetter(originalScope, false); - $q.when(parserResult.source(originalScope, locals)).then(function(matches) { - var onCurrentRequest = inputValue === modelCtrl.$viewValue; - if (onCurrentRequest && hasFocus) { - if (matches && matches.length > 0) { - scope.activeIdx = focusFirst ? 0 : -1; - isNoResultsSetter(originalScope, false); - scope.matches.length = 0; - for (var i = 0; i < matches.length; i++) { - locals[parserResult.itemName] = matches[i]; - scope.matches.push({ - id: getMatchId(i), - label: parserResult.viewMapper(scope, locals), - model: matches[i] - }); - } - scope.query = inputValue; - recalculatePosition(); - element.attr("aria-expanded", true); - if (selectOnExact && scope.matches.length === 1 && inputIsExactMatch(inputValue, 0)) { - scope.select(0); - } - } else { - resetMatches(); - isNoResultsSetter(originalScope, true); - } - } - if (onCurrentRequest) { - isLoadingSetter(originalScope, false); - } - }, function() { - resetMatches(); - isLoadingSetter(originalScope, false); - isNoResultsSetter(originalScope, true); + } + } + }; + function createParser(format) { + var map = [], regex = format.split(""); + angular.forEach(formatCodeToRegex, function(data, code) { + var index = format.indexOf(code); + if (index > -1) { + format = format.split(""); + regex[index] = "(" + data.regex + ")"; + format[index] = "$"; + for (var i = index + 1, n = index + code.length; i < n; i++) { + regex[i] = ""; + format[i] = "$"; + } + format = format.join(""); + map.push({ + index: index, + apply: data.apply }); - }; - if (appendToBody) { - angular.element($window).bind("resize", fireRecalculating); - $document.find("body").bind("scroll", fireRecalculating); } - var timeoutEventPromise; - scope.moveInProgress = false; - function fireRecalculating() { - if (!scope.moveInProgress) { - scope.moveInProgress = true; - scope.$digest(); + }); + return { + regex: new RegExp("^" + regex.join("") + "$"), + map: orderByFilter(map, "index") + }; + } + this.parse = function(input, format, baseDate) { + if (!angular.isString(input) || !format) { + return input; + } + format = $locale.DATETIME_FORMATS[format] || format; + format = format.replace(SPECIAL_CHARACTERS_REGEXP, "\\$&"); + if (!this.parsers[format]) { + this.parsers[format] = createParser(format); + } + var parser = this.parsers[format], regex = parser.regex, map = parser.map, results = input.match(regex); + if (results && results.length) { + var fields, dt; + if (angular.isDate(baseDate) && !isNaN(baseDate.getTime())) { + fields = { + year: baseDate.getFullYear(), + month: baseDate.getMonth(), + date: baseDate.getDate(), + hours: baseDate.getHours(), + minutes: baseDate.getMinutes(), + seconds: baseDate.getSeconds(), + milliseconds: baseDate.getMilliseconds() + }; + } else { + if (baseDate) { + $log.warn("dateparser:", "baseDate is not a valid date"); } - if (timeoutEventPromise) { - $timeout.cancel(timeoutEventPromise); + fields = { + year: 1900, + month: 0, + date: 1, + hours: 0, + minutes: 0, + seconds: 0, + milliseconds: 0 + }; + } + for (var i = 1, n = results.length; i < n; i++) { + var mapper = map[i - 1]; + if (mapper.apply) { + mapper.apply.call(fields, results[i]); } - timeoutEventPromise = $timeout(function() { - if (scope.matches.length) { - recalculatePosition(); - } - scope.moveInProgress = false; - scope.$digest(); - }, eventDebounceTime); } - function recalculatePosition() { - scope.position = appendToBody ? $position.offset(element) : $position.position(element); - scope.position.top += element.prop("offsetHeight"); + if (isValid(fields.year, fields.month, fields.date)) { + dt = new Date(fields.year, fields.month, fields.date, fields.hours, fields.minutes, fields.seconds, fields.milliseconds || 0); } - resetMatches(); - scope.query = undefined; - var timeoutPromise; - var scheduleSearchWithTimeout = function(inputValue) { - timeoutPromise = $timeout(function() { - getMatchesAsync(inputValue); - }, waitTime); - }; - var cancelPreviousTimeout = function() { - if (timeoutPromise) { - $timeout.cancel(timeoutPromise); - } + return dt; + } + }; + function isValid(year, month, date) { + if (date < 1) { + return false; + } + if (month === 1 && date > 28) { + return date === 29 && (year % 4 === 0 && year % 100 !== 0 || year % 400 === 0); + } + if (month === 3 || month === 5 || month === 8 || month === 10) { + return date < 31; + } + return true; + } +} ]); + +angular.module("ui.bootstrap.position", []).factory("$position", [ "$document", "$window", function($document, $window) { + function getStyle(el, cssprop) { + if (el.currentStyle) { + return el.currentStyle[cssprop]; + } else if ($window.getComputedStyle) { + return $window.getComputedStyle(el)[cssprop]; + } + return el.style[cssprop]; + } + function isStaticPositioned(element) { + return (getStyle(element, "position") || "static") === "static"; + } + var parentOffsetEl = function(element) { + var docDomEl = $document[0]; + var offsetParent = element.offsetParent || docDomEl; + while (offsetParent && offsetParent !== docDomEl && isStaticPositioned(offsetParent)) { + offsetParent = offsetParent.offsetParent; + } + return offsetParent || docDomEl; + }; + return { + position: function(element) { + var elBCR = this.offset(element); + var offsetParentBCR = { + top: 0, + left: 0 }; - modelCtrl.$parsers.unshift(function(inputValue) { - hasFocus = true; - if (minLength === 0 || inputValue && inputValue.length >= minLength) { - if (waitTime > 0) { - cancelPreviousTimeout(); - scheduleSearchWithTimeout(inputValue); - } else { - getMatchesAsync(inputValue); - } - } else { - isLoadingSetter(originalScope, false); - cancelPreviousTimeout(); - resetMatches(); - } - if (isEditable) { - return inputValue; - } else { - if (!inputValue) { - modelCtrl.$setValidity("editable", true); - return null; - } else { - modelCtrl.$setValidity("editable", false); - return undefined; - } - } - }); - modelCtrl.$formatters.push(function(modelValue) { - var candidateViewValue, emptyViewValue; - var locals = {}; - if (!isEditable) { - modelCtrl.$setValidity("editable", true); - } - if (inputFormatter) { - locals.$model = modelValue; - return inputFormatter(originalScope, locals); - } else { - locals[parserResult.itemName] = modelValue; - candidateViewValue = parserResult.viewMapper(originalScope, locals); - locals[parserResult.itemName] = undefined; - emptyViewValue = parserResult.viewMapper(originalScope, locals); - return candidateViewValue !== emptyViewValue ? candidateViewValue : modelValue; - } - }); - scope.select = function(activeIdx) { - var locals = {}; - var model, item; - selected = true; - locals[parserResult.itemName] = item = scope.matches[activeIdx].model; - model = parserResult.modelMapper(originalScope, locals); - $setModelValue(originalScope, model); - modelCtrl.$setValidity("editable", true); - modelCtrl.$setValidity("parse", true); - onSelectCallback(originalScope, { - $item: item, - $model: model, - $label: parserResult.viewMapper(originalScope, locals) - }); - resetMatches(); - if (scope.$eval(attrs.typeaheadFocusOnSelect) !== false) { - $timeout(function() { - element[0].focus(); - }, 0, false); - } + var offsetParentEl = parentOffsetEl(element[0]); + if (offsetParentEl != $document[0]) { + offsetParentBCR = this.offset(angular.element(offsetParentEl)); + offsetParentBCR.top += offsetParentEl.clientTop - offsetParentEl.scrollTop; + offsetParentBCR.left += offsetParentEl.clientLeft - offsetParentEl.scrollLeft; + } + var boundingClientRect = element[0].getBoundingClientRect(); + return { + width: boundingClientRect.width || element.prop("offsetWidth"), + height: boundingClientRect.height || element.prop("offsetHeight"), + top: elBCR.top - offsetParentBCR.top, + left: elBCR.left - offsetParentBCR.left }; - element.bind("keydown", function(evt) { - if (scope.matches.length === 0 || HOT_KEYS.indexOf(evt.which) === -1) { - return; - } - if (scope.activeIdx === -1 && (evt.which === 9 || evt.which === 13)) { - resetMatches(); - scope.$digest(); - return; - } - evt.preventDefault(); - if (evt.which === 40) { - scope.activeIdx = (scope.activeIdx + 1) % scope.matches.length; - scope.$digest(); - } else if (evt.which === 38) { - scope.activeIdx = (scope.activeIdx > 0 ? scope.activeIdx : scope.matches.length) - 1; - scope.$digest(); - } else if (evt.which === 13 || evt.which === 9) { - scope.$apply(function() { - scope.select(scope.activeIdx); - }); - } else if (evt.which === 27) { - evt.stopPropagation(); - resetMatches(); - scope.$digest(); - } - }); - element.bind("blur", function() { - if (isSelectOnBlur && scope.matches.length && scope.activeIdx !== -1 && !selected) { - selected = true; - scope.$apply(function() { - scope.select(scope.activeIdx); - }); + }, + offset: function(element) { + var boundingClientRect = element[0].getBoundingClientRect(); + return { + width: boundingClientRect.width || element.prop("offsetWidth"), + height: boundingClientRect.height || element.prop("offsetHeight"), + top: boundingClientRect.top + ($window.pageYOffset || $document[0].documentElement.scrollTop), + left: boundingClientRect.left + ($window.pageXOffset || $document[0].documentElement.scrollLeft) + }; + }, + positionElements: function(hostEl, targetEl, positionStr, appendToBody) { + var positionStrParts = positionStr.split("-"); + var pos0 = positionStrParts[0], pos1 = positionStrParts[1] || "center"; + var hostElPos, targetElWidth, targetElHeight, targetElPos; + hostElPos = appendToBody ? this.offset(hostEl) : this.position(hostEl); + targetElWidth = targetEl.prop("offsetWidth"); + targetElHeight = targetEl.prop("offsetHeight"); + var shiftWidth = { + center: function() { + return hostElPos.left + hostElPos.width / 2 - targetElWidth / 2; + }, + left: function() { + return hostElPos.left; + }, + right: function() { + return hostElPos.left + hostElPos.width; } - hasFocus = false; - selected = false; - }); - var dismissClickHandler = function(evt) { - if (element[0] !== evt.target && evt.which !== 3 && scope.matches.length !== 0) { - resetMatches(); - if (!$rootScope.$$phase) { - scope.$digest(); - } + }; + var shiftHeight = { + center: function() { + return hostElPos.top + hostElPos.height / 2 - targetElHeight / 2; + }, + top: function() { + return hostElPos.top; + }, + bottom: function() { + return hostElPos.top + hostElPos.height; } }; - $document.bind("click", dismissClickHandler); - originalScope.$on("$destroy", function() { - $document.unbind("click", dismissClickHandler); - if (appendToBody) { - $popup.remove(); + switch (pos0) { + case "right": + targetElPos = { + top: shiftHeight[pos1](), + left: shiftWidth[pos0]() + }; + break; + + case "left": + targetElPos = { + top: shiftHeight[pos1](), + left: hostElPos.left - targetElWidth + }; + break; + + case "bottom": + targetElPos = { + top: shiftHeight[pos0](), + left: shiftWidth[pos1]() + }; + break; + + default: + targetElPos = { + top: hostElPos.top - targetElHeight, + left: shiftWidth[pos1]() + }; + break; + } + return targetElPos; + } + }; +} ]); + +angular.module("ui.bootstrap.datepicker", [ "ui.bootstrap.dateparser", "ui.bootstrap.position" ]).value("$datepickerSuppressError", false).constant("datepickerConfig", { + formatDay: "dd", + formatMonth: "MMMM", + formatYear: "yyyy", + formatDayHeader: "EEE", + formatDayTitle: "MMMM yyyy", + formatMonthTitle: "yyyy", + datepickerMode: "day", + minMode: "day", + maxMode: "year", + showWeeks: true, + startingDay: 0, + yearRange: 20, + minDate: null, + maxDate: null, + shortcutPropagation: false +}).controller("DatepickerController", [ "$scope", "$attrs", "$parse", "$interpolate", "$log", "dateFilter", "datepickerConfig", "$datepickerSuppressError", function($scope, $attrs, $parse, $interpolate, $log, dateFilter, datepickerConfig, $datepickerSuppressError) { + var self = this, ngModelCtrl = { + $setViewValue: angular.noop + }; + this.modes = [ "day", "month", "year" ]; + angular.forEach([ "formatDay", "formatMonth", "formatYear", "formatDayHeader", "formatDayTitle", "formatMonthTitle", "showWeeks", "startingDay", "yearRange", "shortcutPropagation" ], function(key, index) { + self[key] = angular.isDefined($attrs[key]) ? index < 6 ? $interpolate($attrs[key])($scope.$parent) : $scope.$parent.$eval($attrs[key]) : datepickerConfig[key]; + }); + angular.forEach([ "minDate", "maxDate" ], function(key) { + if ($attrs[key]) { + $scope.$parent.$watch($parse($attrs[key]), function(value) { + self[key] = value ? new Date(value) : null; + self.refreshView(); + }); + } else { + self[key] = datepickerConfig[key] ? new Date(datepickerConfig[key]) : null; + } + }); + angular.forEach([ "minMode", "maxMode" ], function(key) { + if ($attrs[key]) { + $scope.$parent.$watch($parse($attrs[key]), function(value) { + self[key] = angular.isDefined(value) ? value : $attrs[key]; + $scope[key] = self[key]; + if (key == "minMode" && self.modes.indexOf($scope.datepickerMode) < self.modes.indexOf(self[key]) || key == "maxMode" && self.modes.indexOf($scope.datepickerMode) > self.modes.indexOf(self[key])) { + $scope.datepickerMode = self[key]; } - popUpEl.remove(); }); - var $popup = $compile(popUpEl)(scope); - if (appendToBody) { - $document.find("body").append($popup); - } else { - element.after($popup); + } else { + self[key] = datepickerConfig[key] || null; + $scope[key] = self[key]; + } + }); + $scope.datepickerMode = $scope.datepickerMode || datepickerConfig.datepickerMode; + $scope.uniqueId = "datepicker-" + $scope.$id + "-" + Math.floor(Math.random() * 1e4); + if (angular.isDefined($attrs.initDate)) { + this.activeDate = $scope.$parent.$eval($attrs.initDate) || new Date(); + $scope.$parent.$watch($attrs.initDate, function(initDate) { + if (initDate && (ngModelCtrl.$isEmpty(ngModelCtrl.$modelValue) || ngModelCtrl.$invalid)) { + self.activeDate = initDate; + self.refreshView(); + } + }); + } else { + this.activeDate = new Date(); + } + $scope.isActive = function(dateObject) { + if (self.compare(dateObject.date, self.activeDate) === 0) { + $scope.activeDateId = dateObject.uid; + return true; + } + return false; + }; + this.init = function(ngModelCtrl_) { + ngModelCtrl = ngModelCtrl_; + ngModelCtrl.$render = function() { + self.render(); + }; + }; + this.render = function() { + if (ngModelCtrl.$viewValue) { + var date = new Date(ngModelCtrl.$viewValue), isValid = !isNaN(date); + if (isValid) { + this.activeDate = date; + } else if (!$datepickerSuppressError) { + $log.error('Datepicker directive: "ng-model" value must be a Date object, a number of milliseconds since 01.01.1970 or a string representing an RFC2822 or ISO 8601 date.'); + } + } + this.refreshView(); + }; + this.refreshView = function() { + if (this.element) { + this._refreshView(); + var date = ngModelCtrl.$viewValue ? new Date(ngModelCtrl.$viewValue) : null; + ngModelCtrl.$setValidity("dateDisabled", !date || this.element && !this.isDisabled(date)); + } + }; + this.createDateObject = function(date, format) { + var model = ngModelCtrl.$viewValue ? new Date(ngModelCtrl.$viewValue) : null; + return { + date: date, + label: dateFilter(date, format), + selected: model && this.compare(date, model) === 0, + disabled: this.isDisabled(date), + current: this.compare(date, new Date()) === 0, + customClass: this.customClass(date) + }; + }; + this.isDisabled = function(date) { + return this.minDate && this.compare(date, this.minDate) < 0 || this.maxDate && this.compare(date, this.maxDate) > 0 || $attrs.dateDisabled && $scope.dateDisabled({ + date: date, + mode: $scope.datepickerMode + }); + }; + this.customClass = function(date) { + return $scope.customClass({ + date: date, + mode: $scope.datepickerMode + }); + }; + this.split = function(arr, size) { + var arrays = []; + while (arr.length > 0) { + arrays.push(arr.splice(0, size)); + } + return arrays; + }; + this.fixTimeZone = function(date) { + var hours = date.getHours(); + date.setHours(hours === 23 ? hours + 2 : 0); + }; + $scope.select = function(date) { + if ($scope.datepickerMode === self.minMode) { + var dt = ngModelCtrl.$viewValue ? new Date(ngModelCtrl.$viewValue) : new Date(0, 0, 0, 0, 0, 0, 0); + dt.setFullYear(date.getFullYear(), date.getMonth(), date.getDate()); + ngModelCtrl.$setViewValue(dt); + ngModelCtrl.$render(); + } else { + self.activeDate = date; + $scope.datepickerMode = self.modes[self.modes.indexOf($scope.datepickerMode) - 1]; + } + }; + $scope.move = function(direction) { + var year = self.activeDate.getFullYear() + direction * (self.step.years || 0), month = self.activeDate.getMonth() + direction * (self.step.months || 0); + self.activeDate.setFullYear(year, month, 1); + self.refreshView(); + }; + $scope.toggleMode = function(direction) { + direction = direction || 1; + if ($scope.datepickerMode === self.maxMode && direction === 1 || $scope.datepickerMode === self.minMode && direction === -1) { + return; + } + $scope.datepickerMode = self.modes[self.modes.indexOf($scope.datepickerMode) + direction]; + }; + $scope.keys = { + 13: "enter", + 32: "space", + 33: "pageup", + 34: "pagedown", + 35: "end", + 36: "home", + 37: "left", + 38: "up", + 39: "right", + 40: "down" + }; + var focusElement = function() { + self.element[0].focus(); + }; + $scope.$on("datepicker.focus", focusElement); + $scope.keydown = function(evt) { + var key = $scope.keys[evt.which]; + if (!key || evt.shiftKey || evt.altKey) { + return; + } + evt.preventDefault(); + if (!self.shortcutPropagation) { + evt.stopPropagation(); + } + if (key === "enter" || key === "space") { + if (self.isDisabled(self.activeDate)) { + return; } + $scope.select(self.activeDate); + focusElement(); + } else if (evt.ctrlKey && (key === "up" || key === "down")) { + $scope.toggleMode(key === "up" ? 1 : -1); + focusElement(); + } else { + self.handleKeyDown(key, evt); + self.refreshView(); } }; -} ]).directive("typeaheadPopup", function() { +} ]).directive("datepicker", function() { return { restrict: "EA", - scope: { - matches: "=", - query: "=", - active: "=", - position: "&", - moveInProgress: "=", - select: "&" - }, replace: true, templateUrl: function(element, attrs) { - return attrs.popupTemplateUrl || "template/typeahead/typeahead-popup.html"; + return attrs.templateUrl || "template/datepicker/datepicker.html"; }, - link: function(scope, element, attrs) { - scope.templateUrl = attrs.templateUrl; - scope.isOpen = function() { - return scope.matches.length > 0; - }; - scope.isActive = function(matchIdx) { - return scope.active == matchIdx; - }; - scope.selectActive = function(matchIdx) { - scope.active = matchIdx; - }; - scope.selectMatch = function(activeIdx) { - scope.select({ - activeIdx: activeIdx - }); - }; - } - }; -}).directive("typeaheadMatch", [ "$templateRequest", "$compile", "$parse", function($templateRequest, $compile, $parse) { - return { - restrict: "EA", scope: { - index: "=", - match: "=", - query: "=" + datepickerMode: "=?", + dateDisabled: "&", + customClass: "&", + shortcutPropagation: "&?" }, - link: function(scope, element, attrs) { - var tplUrl = $parse(attrs.templateUrl)(scope.$parent) || "template/typeahead/typeahead-match.html"; - $templateRequest(tplUrl).then(function(tplContent) { - $compile(tplContent.trim())(scope, function(clonedElement) { - element.replaceWith(clonedElement); - }); - }); - } - }; -} ]).filter("typeaheadHighlight", [ "$sce", "$injector", "$log", function($sce, $injector, $log) { - var isSanitizePresent; - isSanitizePresent = $injector.has("$sanitize"); - function escapeRegexp(queryToEscape) { - return queryToEscape.replace(/([.?*+^$[\]\\(){}|-])/g, "\\$1"); - } - function containsHtml(matchItem) { - return /<.*>/g.test(matchItem); - } - return function(matchItem, query) { - if (!isSanitizePresent && containsHtml(matchItem)) { - $log.warn("Unsafe use of typeahead please use ngSanitize"); - } - matchItem = query ? ("" + matchItem).replace(new RegExp(escapeRegexp(query), "gi"), "$&") : matchItem; - if (!isSanitizePresent) { - matchItem = $sce.trustAsHtml(matchItem); + require: [ "datepicker", "^ngModel" ], + controller: "DatepickerController", + controllerAs: "datepicker", + link: function(scope, element, attrs, ctrls) { + var datepickerCtrl = ctrls[0], ngModelCtrl = ctrls[1]; + datepickerCtrl.init(ngModelCtrl); } - return matchItem; }; -} ]); - -!angular.$$csp() && angular.element(document).find("head").prepend(''); - -angular.module("ui.bootstrap", [ "ui.bootstrap.tpls", "ui.bootstrap.collapse", "ui.bootstrap.accordion", "ui.bootstrap.alert", "ui.bootstrap.bindHtml", "ui.bootstrap.buttons", "ui.bootstrap.carousel", "ui.bootstrap.dateparser", "ui.bootstrap.position", "ui.bootstrap.datepicker", "ui.bootstrap.dropdown", "ui.bootstrap.modal", "ui.bootstrap.pagination", "ui.bootstrap.tooltip", "ui.bootstrap.popover", "ui.bootstrap.progressbar", "ui.bootstrap.rating", "ui.bootstrap.tabs", "ui.bootstrap.timepicker", "ui.bootstrap.transition", "ui.bootstrap.typeahead" ]); - -angular.module("ui.bootstrap.tpls", [ "template/accordion/accordion-group.html", "template/accordion/accordion.html", "template/alert/alert.html", "template/carousel/carousel.html", "template/carousel/slide.html", "template/datepicker/datepicker.html", "template/datepicker/day.html", "template/datepicker/month.html", "template/datepicker/popup.html", "template/datepicker/year.html", "template/modal/backdrop.html", "template/modal/window.html", "template/pagination/pager.html", "template/pagination/pagination.html", "template/tooltip/tooltip-html-popup.html", "template/tooltip/tooltip-html-unsafe-popup.html", "template/tooltip/tooltip-popup.html", "template/tooltip/tooltip-template-popup.html", "template/popover/popover-html.html", "template/popover/popover-template.html", "template/popover/popover.html", "template/progressbar/bar.html", "template/progressbar/progress.html", "template/progressbar/progressbar.html", "template/rating/rating.html", "template/tabs/tab.html", "template/tabs/tabset.html", "template/timepicker/timepicker.html", "template/typeahead/typeahead-match.html", "template/typeahead/typeahead-popup.html" ]); - -angular.module("ui.bootstrap.collapse", []).directive("collapse", [ "$animate", function($animate) { +}).directive("daypicker", [ "dateFilter", function(dateFilter) { return { - link: function(scope, element, attrs) { - function expand() { - element.removeClass("collapse").addClass("collapsing").attr("aria-expanded", true).attr("aria-hidden", false); - $animate.addClass(element, "in", { - to: { - height: element[0].scrollHeight + "px" - } - }).then(expandDone); + restrict: "EA", + replace: true, + templateUrl: "template/datepicker/day.html", + require: "^datepicker", + link: function(scope, element, attrs, ctrl) { + scope.showWeeks = ctrl.showWeeks; + ctrl.step = { + months: 1 + }; + ctrl.element = element; + var DAYS_IN_MONTH = [ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 ]; + function getDaysInMonth(year, month) { + return month === 1 && year % 4 === 0 && (year % 100 !== 0 || year % 400 === 0) ? 29 : DAYS_IN_MONTH[month]; } - function expandDone() { - element.removeClass("collapsing"); - element.css({ - height: "auto" - }); + function getDates(startDate, n) { + var dates = new Array(n), current = new Date(startDate), i = 0, date; + while (i < n) { + date = new Date(current); + ctrl.fixTimeZone(date); + dates[i++] = date; + current.setDate(current.getDate() + 1); + } + return dates; } - function collapse() { - if (!element.hasClass("collapse") && !element.hasClass("in")) { - return collapseDone(); + ctrl._refreshView = function() { + var year = ctrl.activeDate.getFullYear(), month = ctrl.activeDate.getMonth(), firstDayOfMonth = new Date(year, month, 1), difference = ctrl.startingDay - firstDayOfMonth.getDay(), numDisplayedFromPreviousMonth = difference > 0 ? 7 - difference : -difference, firstDate = new Date(firstDayOfMonth); + if (numDisplayedFromPreviousMonth > 0) { + firstDate.setDate(-numDisplayedFromPreviousMonth + 1); } - element.css({ - height: element[0].scrollHeight + "px" - }).removeClass("collapse").addClass("collapsing").attr("aria-expanded", false).attr("aria-hidden", true); - $animate.removeClass(element, "in", { - to: { - height: "0" + var days = getDates(firstDate, 42); + for (var i = 0; i < 42; i++) { + days[i] = angular.extend(ctrl.createDateObject(days[i], ctrl.formatDay), { + secondary: days[i].getMonth() !== month, + uid: scope.uniqueId + "-" + i + }); + } + scope.labels = new Array(7); + for (var j = 0; j < 7; j++) { + scope.labels[j] = { + abbr: dateFilter(days[j].date, ctrl.formatDayHeader), + full: dateFilter(days[j].date, "EEEE") + }; + } + scope.title = dateFilter(ctrl.activeDate, ctrl.formatDayTitle); + scope.rows = ctrl.split(days, 7); + if (scope.showWeeks) { + scope.weekNumbers = []; + var thursdayIndex = (4 + 7 - ctrl.startingDay) % 7, numWeeks = scope.rows.length; + for (var curWeek = 0; curWeek < numWeeks; curWeek++) { + scope.weekNumbers.push(getISO8601WeekNumber(scope.rows[curWeek][thursdayIndex].date)); } - }).then(collapseDone); - } - function collapseDone() { - element.css({ - height: "0" - }); - element.removeClass("collapsing"); - element.addClass("collapse"); - } - scope.$watch(attrs.collapse, function(shouldCollapse) { - if (shouldCollapse) { - collapse(); - } else { - expand(); } - }); - } - }; -} ]); - -angular.module("ui.bootstrap.accordion", [ "ui.bootstrap.collapse" ]).constant("accordionConfig", { - closeOthers: true -}).controller("AccordionController", [ "$scope", "$attrs", "accordionConfig", function($scope, $attrs, accordionConfig) { - this.groups = []; - this.closeOthers = function(openGroup) { - var closeOthers = angular.isDefined($attrs.closeOthers) ? $scope.$eval($attrs.closeOthers) : accordionConfig.closeOthers; - if (closeOthers) { - angular.forEach(this.groups, function(group) { - if (group !== openGroup) { - group.isOpen = false; + }; + ctrl.compare = function(date1, date2) { + return new Date(date1.getFullYear(), date1.getMonth(), date1.getDate()) - new Date(date2.getFullYear(), date2.getMonth(), date2.getDate()); + }; + function getISO8601WeekNumber(date) { + var checkDate = new Date(date); + checkDate.setDate(checkDate.getDate() + 4 - (checkDate.getDay() || 7)); + var time = checkDate.getTime(); + checkDate.setMonth(0); + checkDate.setDate(1); + return Math.floor(Math.round((time - checkDate) / 864e5) / 7) + 1; + } + ctrl.handleKeyDown = function(key, evt) { + var date = ctrl.activeDate.getDate(); + if (key === "left") { + date = date - 1; + } else if (key === "up") { + date = date - 7; + } else if (key === "right") { + date = date + 1; + } else if (key === "down") { + date = date + 7; + } else if (key === "pageup" || key === "pagedown") { + var month = ctrl.activeDate.getMonth() + (key === "pageup" ? -1 : 1); + ctrl.activeDate.setMonth(month, 1); + date = Math.min(getDaysInMonth(ctrl.activeDate.getFullYear(), ctrl.activeDate.getMonth()), date); + } else if (key === "home") { + date = 1; + } else if (key === "end") { + date = getDaysInMonth(ctrl.activeDate.getFullYear(), ctrl.activeDate.getMonth()); } - }); + ctrl.activeDate.setDate(date); + }; + ctrl.refreshView(); } }; - this.addGroup = function(groupScope) { - var that = this; - this.groups.push(groupScope); - groupScope.$on("$destroy", function(event) { - that.removeGroup(groupScope); - }); - }; - this.removeGroup = function(group) { - var index = this.groups.indexOf(group); - if (index !== -1) { - this.groups.splice(index, 1); +} ]).directive("monthpicker", [ "dateFilter", function(dateFilter) { + return { + restrict: "EA", + replace: true, + templateUrl: "template/datepicker/month.html", + require: "^datepicker", + link: function(scope, element, attrs, ctrl) { + ctrl.step = { + years: 1 + }; + ctrl.element = element; + ctrl._refreshView = function() { + var months = new Array(12), year = ctrl.activeDate.getFullYear(), date; + for (var i = 0; i < 12; i++) { + date = new Date(year, i, 1); + ctrl.fixTimeZone(date); + months[i] = angular.extend(ctrl.createDateObject(date, ctrl.formatMonth), { + uid: scope.uniqueId + "-" + i + }); + } + scope.title = dateFilter(ctrl.activeDate, ctrl.formatMonthTitle); + scope.rows = ctrl.split(months, 3); + }; + ctrl.compare = function(date1, date2) { + return new Date(date1.getFullYear(), date1.getMonth()) - new Date(date2.getFullYear(), date2.getMonth()); + }; + ctrl.handleKeyDown = function(key, evt) { + var date = ctrl.activeDate.getMonth(); + if (key === "left") { + date = date - 1; + } else if (key === "up") { + date = date - 3; + } else if (key === "right") { + date = date + 1; + } else if (key === "down") { + date = date + 3; + } else if (key === "pageup" || key === "pagedown") { + var year = ctrl.activeDate.getFullYear() + (key === "pageup" ? -1 : 1); + ctrl.activeDate.setFullYear(year); + } else if (key === "home") { + date = 0; + } else if (key === "end") { + date = 11; + } + ctrl.activeDate.setMonth(date); + }; + ctrl.refreshView(); } }; -} ]).directive("accordion", function() { +} ]).directive("yearpicker", [ "dateFilter", function(dateFilter) { return { restrict: "EA", - controller: "AccordionController", - controllerAs: "accordion", - transclude: true, - replace: false, - templateUrl: function(element, attrs) { - return attrs.templateUrl || "template/accordion/accordion.html"; + replace: true, + templateUrl: "template/datepicker/year.html", + require: "^datepicker", + link: function(scope, element, attrs, ctrl) { + var range = ctrl.yearRange; + ctrl.step = { + years: range + }; + ctrl.element = element; + function getStartingYear(year) { + return parseInt((year - 1) / range, 10) * range + 1; + } + ctrl._refreshView = function() { + var years = new Array(range), date; + for (var i = 0, start = getStartingYear(ctrl.activeDate.getFullYear()); i < range; i++) { + date = new Date(start + i, 0, 1); + ctrl.fixTimeZone(date); + years[i] = angular.extend(ctrl.createDateObject(date, ctrl.formatYear), { + uid: scope.uniqueId + "-" + i + }); + } + scope.title = [ years[0].label, years[range - 1].label ].join(" - "); + scope.rows = ctrl.split(years, 5); + }; + ctrl.compare = function(date1, date2) { + return date1.getFullYear() - date2.getFullYear(); + }; + ctrl.handleKeyDown = function(key, evt) { + var date = ctrl.activeDate.getFullYear(); + if (key === "left") { + date = date - 1; + } else if (key === "up") { + date = date - 5; + } else if (key === "right") { + date = date + 1; + } else if (key === "down") { + date = date + 5; + } else if (key === "pageup" || key === "pagedown") { + date += (key === "pageup" ? -1 : 1) * ctrl.step.years; + } else if (key === "home") { + date = getStartingYear(ctrl.activeDate.getFullYear()); + } else if (key === "end") { + date = getStartingYear(ctrl.activeDate.getFullYear()) + range - 1; + } + ctrl.activeDate.setFullYear(date); + }; + ctrl.refreshView(); } }; -}).directive("accordionGroup", function() { +} ]).constant("datepickerPopupConfig", { + datepickerPopup: "yyyy-MM-dd", + datepickerPopupTemplateUrl: "template/datepicker/popup.html", + datepickerTemplateUrl: "template/datepicker/datepicker.html", + html5Types: { + date: "yyyy-MM-dd", + "datetime-local": "yyyy-MM-ddTHH:mm:ss.sss", + month: "yyyy-MM" + }, + currentText: "Today", + clearText: "Clear", + closeText: "Done", + closeOnDateSelection: true, + appendToBody: false, + showButtonBar: true, + onOpenFocus: true +}).directive("datepickerPopup", [ "$compile", "$parse", "$document", "$rootScope", "$position", "dateFilter", "dateParser", "datepickerPopupConfig", "$timeout", function($compile, $parse, $document, $rootScope, $position, dateFilter, dateParser, datepickerPopupConfig, $timeout) { return { - require: "^accordion", restrict: "EA", - transclude: true, - replace: true, - templateUrl: function(element, attrs) { - return attrs.templateUrl || "template/accordion/accordion-group.html"; - }, + require: "ngModel", scope: { - heading: "@", isOpen: "=?", - isDisabled: "=?" + currentText: "@", + clearText: "@", + closeText: "@", + dateDisabled: "&", + customClass: "&" }, - controller: function() { - this.setHeading = function(element) { - this.heading = element; + link: function(scope, element, attrs, ngModel) { + var dateFormat, closeOnDateSelection = angular.isDefined(attrs.closeOnDateSelection) ? scope.$parent.$eval(attrs.closeOnDateSelection) : datepickerPopupConfig.closeOnDateSelection, appendToBody = angular.isDefined(attrs.datepickerAppendToBody) ? scope.$parent.$eval(attrs.datepickerAppendToBody) : datepickerPopupConfig.appendToBody, onOpenFocus = angular.isDefined(attrs.onOpenFocus) ? scope.$parent.$eval(attrs.onOpenFocus) : datepickerPopupConfig.onOpenFocus, datepickerPopupTemplateUrl = angular.isDefined(attrs.datepickerPopupTemplateUrl) ? attrs.datepickerPopupTemplateUrl : datepickerPopupConfig.datepickerPopupTemplateUrl, datepickerTemplateUrl = angular.isDefined(attrs.datepickerTemplateUrl) ? attrs.datepickerTemplateUrl : datepickerPopupConfig.datepickerTemplateUrl, cache = {}; + scope.showButtonBar = angular.isDefined(attrs.showButtonBar) ? scope.$parent.$eval(attrs.showButtonBar) : datepickerPopupConfig.showButtonBar; + scope.getText = function(key) { + return scope[key + "Text"] || datepickerPopupConfig[key + "Text"]; }; - }, - link: function(scope, element, attrs, accordionCtrl) { - accordionCtrl.addGroup(scope); - scope.openClass = attrs.openClass || "panel-open"; - scope.panelClass = attrs.panelClass; - scope.$watch("isOpen", function(value) { - element.toggleClass(scope.openClass, value); - if (value) { - accordionCtrl.closeOthers(scope); + scope.isDisabled = function(date) { + if (date === "today") { + date = new Date(); + } + return scope.watchData.minDate && scope.compare(date, cache.minDate) < 0 || scope.watchData.maxDate && scope.compare(date, cache.maxDate) > 0; + }; + scope.compare = function(date1, date2) { + return new Date(date1.getFullYear(), date1.getMonth(), date1.getDate()) - new Date(date2.getFullYear(), date2.getMonth(), date2.getDate()); + }; + var isHtml5DateInput = false; + if (datepickerPopupConfig.html5Types[attrs.type]) { + dateFormat = datepickerPopupConfig.html5Types[attrs.type]; + isHtml5DateInput = true; + } else { + dateFormat = attrs.datepickerPopup || datepickerPopupConfig.datepickerPopup; + attrs.$observe("datepickerPopup", function(value, oldValue) { + var newDateFormat = value || datepickerPopupConfig.datepickerPopup; + if (newDateFormat !== dateFormat) { + dateFormat = newDateFormat; + ngModel.$modelValue = null; + if (!dateFormat) { + throw new Error("datepickerPopup must have a date format specified."); + } + } + }); + } + if (!dateFormat) { + throw new Error("datepickerPopup must have a date format specified."); + } + if (isHtml5DateInput && attrs.datepickerPopup) { + throw new Error("HTML5 date input types do not support custom formats."); + } + var popupEl = angular.element("
        "); + popupEl.attr({ + "ng-model": "date", + "ng-change": "dateSelection(date)", + "template-url": datepickerPopupTemplateUrl + }); + function cameltoDash(string) { + return string.replace(/([A-Z])/g, function($1) { + return "-" + $1.toLowerCase(); + }); + } + var datepickerEl = angular.element(popupEl.children()[0]); + datepickerEl.attr("template-url", datepickerTemplateUrl); + if (isHtml5DateInput) { + if (attrs.type === "month") { + datepickerEl.attr("datepicker-mode", '"month"'); + datepickerEl.attr("min-mode", "month"); + } + } + if (attrs.datepickerOptions) { + var options = scope.$parent.$eval(attrs.datepickerOptions); + if (options && options.initDate) { + scope.initDate = options.initDate; + datepickerEl.attr("init-date", "initDate"); + delete options.initDate; + } + angular.forEach(options, function(value, option) { + datepickerEl.attr(cameltoDash(option), value); + }); + } + scope.watchData = {}; + angular.forEach([ "minMode", "maxMode", "minDate", "maxDate", "datepickerMode", "initDate", "shortcutPropagation" ], function(key) { + if (attrs[key]) { + var getAttribute = $parse(attrs[key]); + scope.$parent.$watch(getAttribute, function(value) { + scope.watchData[key] = value; + if (key === "minDate" || key === "maxDate") { + cache[key] = new Date(value); + } + }); + datepickerEl.attr(cameltoDash(key), "watchData." + key); + if (key === "datepickerMode") { + var setAttribute = getAttribute.assign; + scope.$watch("watchData." + key, function(value, oldvalue) { + if (angular.isFunction(setAttribute) && value !== oldvalue) { + setAttribute(scope.$parent, value); + } + }); + } } }); - scope.toggleOpen = function($event) { - if (!scope.isDisabled) { - if (!$event || $event.which === 32) { - scope.isOpen = !scope.isOpen; + if (attrs.dateDisabled) { + datepickerEl.attr("date-disabled", "dateDisabled({ date: date, mode: mode })"); + } + if (attrs.showWeeks) { + datepickerEl.attr("show-weeks", attrs.showWeeks); + } + if (attrs.customClass) { + datepickerEl.attr("custom-class", "customClass({ date: date, mode: mode })"); + } + function parseDate(viewValue) { + if (angular.isNumber(viewValue)) { + viewValue = new Date(viewValue); + } + if (!viewValue) { + return null; + } else if (angular.isDate(viewValue) && !isNaN(viewValue)) { + return viewValue; + } else if (angular.isString(viewValue)) { + var date = dateParser.parse(viewValue, dateFormat, scope.date); + if (isNaN(date)) { + return undefined; + } else { + return date; } + } else { + return undefined; } - }; - } - }; -}).directive("accordionHeading", function() { - return { - restrict: "EA", - transclude: true, - template: "", - replace: true, - require: "^accordionGroup", - link: function(scope, element, attr, accordionGroupCtrl, transclude) { - accordionGroupCtrl.setHeading(transclude(scope, angular.noop)); - } - }; -}).directive("accordionTransclude", function() { - return { - require: "^accordionGroup", - link: function(scope, element, attr, controller) { - scope.$watch(function() { - return controller[attr.accordionTransclude]; - }, function(heading) { - if (heading) { - element.find("span").html(""); - element.find("span").append(heading); + } + function validator(modelValue, viewValue) { + var value = modelValue || viewValue; + if (!attrs.ngRequired && !value) { + return true; + } + if (angular.isNumber(value)) { + value = new Date(value); + } + if (!value) { + return true; + } else if (angular.isDate(value) && !isNaN(value)) { + return true; + } else if (angular.isString(value)) { + var date = dateParser.parse(value, dateFormat); + return !isNaN(date); + } else { + return false; + } + } + if (!isHtml5DateInput) { + ngModel.$$parserName = "date"; + ngModel.$validators.date = validator; + ngModel.$parsers.unshift(parseDate); + ngModel.$formatters.push(function(value) { + scope.date = value; + return ngModel.$isEmpty(value) ? value : dateFilter(value, dateFormat); + }); + } else { + ngModel.$formatters.push(function(value) { + scope.date = value; + return value; + }); + } + scope.dateSelection = function(dt) { + if (angular.isDefined(dt)) { + scope.date = dt; + } + var date = scope.date ? dateFilter(scope.date, dateFormat) : null; + element.val(date); + ngModel.$setViewValue(date); + if (closeOnDateSelection) { + scope.isOpen = false; + element[0].focus(); } - }); - } - }; -}); - -angular.module("ui.bootstrap.alert", []).controller("AlertController", [ "$scope", "$attrs", function($scope, $attrs) { - $scope.closeable = !!$attrs.close; - this.close = $scope.close; -} ]).directive("alert", function() { - return { - controller: "AlertController", - controllerAs: "alert", - templateUrl: function(element, attrs) { - return attrs.templateUrl || "template/alert/alert.html"; - }, - transclude: true, - replace: true, - scope: { - type: "@", - close: "&" - } - }; -}).directive("dismissOnTimeout", [ "$timeout", function($timeout) { - return { - require: "alert", - link: function(scope, element, attrs, alertCtrl) { - $timeout(function() { - alertCtrl.close(); - }, parseInt(attrs.dismissOnTimeout, 10)); - } - }; -} ]); - -angular.module("ui.bootstrap.bindHtml", []).value("$bindHtmlUnsafeSuppressDeprecated", false).directive("bindHtmlUnsafe", [ "$log", "$bindHtmlUnsafeSuppressDeprecated", function($log, $bindHtmlUnsafeSuppressDeprecated) { - return function(scope, element, attr) { - if (!$bindHtmlUnsafeSuppressDeprecated) { - $log.warn("bindHtmlUnsafe is now deprecated. Use ngBindHtml instead"); - } - element.addClass("ng-binding").data("$binding", attr.bindHtmlUnsafe); - scope.$watch(attr.bindHtmlUnsafe, function bindHtmlUnsafeWatchAction(value) { - element.html(value || ""); - }); - }; -} ]); - -angular.module("ui.bootstrap.buttons", []).constant("buttonConfig", { - activeClass: "active", - toggleEvent: "click" -}).controller("ButtonsController", [ "buttonConfig", function(buttonConfig) { - this.activeClass = buttonConfig.activeClass || "active"; - this.toggleEvent = buttonConfig.toggleEvent || "click"; -} ]).directive("btnRadio", function() { - return { - require: [ "btnRadio", "ngModel" ], - controller: "ButtonsController", - controllerAs: "buttons", - link: function(scope, element, attrs, ctrls) { - var buttonsCtrl = ctrls[0], ngModelCtrl = ctrls[1]; - element.find("input").css({ - display: "none" - }); - ngModelCtrl.$render = function() { - element.toggleClass(buttonsCtrl.activeClass, angular.equals(ngModelCtrl.$modelValue, scope.$eval(attrs.btnRadio))); }; - element.bind(buttonsCtrl.toggleEvent, function() { - if (attrs.disabled) { - return; + ngModel.$viewChangeListeners.push(function() { + scope.date = dateParser.parse(ngModel.$viewValue, dateFormat, scope.date); + }); + var documentClickBind = function(event) { + if (scope.isOpen && !(element[0].contains(event.target) || popupEl[0].contains(event.target))) { + scope.$apply(function() { + scope.isOpen = false; + }); } - var isActive = element.hasClass(buttonsCtrl.activeClass); - if (!isActive || angular.isDefined(attrs.uncheckable)) { + }; + var inputKeydownBind = function(evt) { + if (evt.which === 27 && scope.isOpen) { + evt.preventDefault(); + evt.stopPropagation(); scope.$apply(function() { - ngModelCtrl.$setViewValue(isActive ? null : scope.$eval(attrs.btnRadio)); - ngModelCtrl.$render(); + scope.isOpen = false; + }); + element[0].focus(); + } else if (evt.which === 40 && !scope.isOpen) { + evt.preventDefault(); + evt.stopPropagation(); + scope.$apply(function() { + scope.isOpen = true; }); } - }); - } - }; -}).directive("btnCheckbox", [ "$document", function($document) { - return { - require: [ "btnCheckbox", "ngModel" ], - controller: "ButtonsController", - controllerAs: "button", - link: function(scope, element, attrs, ctrls) { - var buttonsCtrl = ctrls[0], ngModelCtrl = ctrls[1]; - element.find("input").css({ - display: "none" - }); - function getTrueValue() { - return getCheckboxValue(attrs.btnCheckboxTrue, true); - } - function getFalseValue() { - return getCheckboxValue(attrs.btnCheckboxFalse, false); - } - function getCheckboxValue(attributeValue, defaultValue) { - var val = scope.$eval(attributeValue); - return angular.isDefined(val) ? val : defaultValue; - } - ngModelCtrl.$render = function() { - element.toggleClass(buttonsCtrl.activeClass, angular.equals(ngModelCtrl.$modelValue, getTrueValue())); }; - element.bind(buttonsCtrl.toggleEvent, function() { - if (attrs.disabled) { - return; + element.bind("keydown", inputKeydownBind); + scope.keydown = function(evt) { + if (evt.which === 27) { + scope.isOpen = false; + element[0].focus(); + } + }; + scope.$watch("isOpen", function(value) { + if (value) { + scope.position = appendToBody ? $position.offset(element) : $position.position(element); + scope.position.top = scope.position.top + element.prop("offsetHeight"); + $timeout(function() { + if (onOpenFocus) { + scope.$broadcast("datepicker.focus"); + } + $document.bind("click", documentClickBind); + }, 0, false); + } else { + $document.unbind("click", documentClickBind); } - scope.$apply(function() { - ngModelCtrl.$setViewValue(element.hasClass(buttonsCtrl.activeClass) ? getFalseValue() : getTrueValue()); - ngModelCtrl.$render(); - }); }); - element.on("keypress", function(e) { - if (attrs.disabled || e.which !== 32 || $document[0].activeElement !== element[0]) { - return; + scope.select = function(date) { + if (date === "today") { + var today = new Date(); + if (angular.isDate(scope.date)) { + date = new Date(scope.date); + date.setFullYear(today.getFullYear(), today.getMonth(), today.getDate()); + } else { + date = new Date(today.setHours(0, 0, 0, 0)); + } + } + scope.dateSelection(date); + }; + scope.close = function() { + scope.isOpen = false; + element[0].focus(); + }; + var $popup = $compile(popupEl)(scope); + popupEl.remove(); + if (appendToBody) { + $document.find("body").append($popup); + } else { + element.after($popup); + } + scope.$on("$destroy", function() { + if (scope.isOpen === true) { + if (!$rootScope.$$phase) { + scope.$apply(function() { + scope.isOpen = false; + }); + } } - scope.$apply(function() { - ngModelCtrl.$setViewValue(element.hasClass(buttonsCtrl.activeClass) ? getFalseValue() : getTrueValue()); - ngModelCtrl.$render(); - }); + $popup.remove(); + element.unbind("keydown", inputKeydownBind); + $document.unbind("click", documentClickBind); }); } }; -} ]); - -angular.module("ui.bootstrap.carousel", []).controller("CarouselController", [ "$scope", "$element", "$interval", "$animate", function($scope, $element, $interval, $animate) { - var self = this, slides = self.slides = $scope.slides = [], NEW_ANIMATE = angular.version.minor >= 4, NO_TRANSITION = "uib-noTransition", SLIDE_DIRECTION = "uib-slideDirection", currentIndex = -1, currentInterval, isPlaying; - self.currentSlide = null; - var destroyed = false; - self.select = $scope.select = function(nextSlide, direction) { - var nextIndex = $scope.indexOfSlide(nextSlide); - if (direction === undefined) { - direction = nextIndex > self.getCurrentIndex() ? "next" : "prev"; - } - if (nextSlide && nextSlide !== self.currentSlide && !$scope.$currentTransition) { - goNext(nextSlide, nextIndex, direction); +} ]).directive("datepickerPopupWrap", function() { + return { + restrict: "EA", + replace: true, + transclude: true, + templateUrl: function(element, attrs) { + return attrs.templateUrl || "template/datepicker/popup.html"; } }; - function goNext(slide, index, direction) { - if (destroyed) { - return; - } - angular.extend(slide, { - direction: direction, - active: true - }); - angular.extend(self.currentSlide || {}, { - direction: direction, - active: false - }); - if ($animate.enabled() && !$scope.noTransition && !$scope.$currentTransition && slide.$element && self.slides.length > 1) { - slide.$element.data(SLIDE_DIRECTION, slide.direction); - if (self.currentSlide && self.currentSlide.$element) { - self.currentSlide.$element.data(SLIDE_DIRECTION, slide.direction); - } - $scope.$currentTransition = true; - if (NEW_ANIMATE) { - $animate.on("addClass", slide.$element, function(element, phase) { - if (phase === "close") { - $scope.$currentTransition = null; - $animate.off("addClass", element); - } - }); - } else { - slide.$element.one("$animate:close", function closeFn() { - $scope.$currentTransition = null; - }); - } - } - self.currentSlide = slide; - currentIndex = index; - restartTimer(); - } - $scope.$on("$destroy", function() { - destroyed = true; - }); - function getSlideByIndex(index) { - if (angular.isUndefined(slides[index].index)) { - return slides[index]; - } - var i, len = slides.length; - for (i = 0; i < slides.length; ++i) { - if (slides[i].index == index) { - return slides[i]; - } +}); + +angular.module("ui.bootstrap.dropdown", [ "ui.bootstrap.position" ]).constant("dropdownConfig", { + openClass: "open" +}).service("dropdownService", [ "$document", "$rootScope", function($document, $rootScope) { + var openScope = null; + this.open = function(dropdownScope) { + if (!openScope) { + $document.bind("click", closeDropdown); + $document.bind("keydown", keybindFilter); } - } - self.getCurrentIndex = function() { - if (self.currentSlide && angular.isDefined(self.currentSlide.index)) { - return +self.currentSlide.index; + if (openScope && openScope !== dropdownScope) { + openScope.isOpen = false; } - return currentIndex; - }; - $scope.indexOfSlide = function(slide) { - return angular.isDefined(slide.index) ? +slide.index : slides.indexOf(slide); + openScope = dropdownScope; }; - $scope.next = function() { - var newIndex = (self.getCurrentIndex() + 1) % slides.length; - if (newIndex === 0 && $scope.noWrap()) { - $scope.pause(); - return; + this.close = function(dropdownScope) { + if (openScope === dropdownScope) { + openScope = null; + $document.unbind("click", closeDropdown); + $document.unbind("keydown", keybindFilter); } - return self.select(getSlideByIndex(newIndex), "next"); }; - $scope.prev = function() { - var newIndex = self.getCurrentIndex() - 1 < 0 ? slides.length - 1 : self.getCurrentIndex() - 1; - if ($scope.noWrap() && newIndex === slides.length - 1) { - $scope.pause(); + var closeDropdown = function(evt) { + if (!openScope) { return; } - return self.select(getSlideByIndex(newIndex), "prev"); - }; - $scope.isActive = function(slide) { - return self.currentSlide === slide; - }; - $scope.$watch("interval", restartTimer); - $scope.$on("$destroy", resetTimer); - function restartTimer() { - resetTimer(); - var interval = +$scope.interval; - if (!isNaN(interval) && interval > 0) { - currentInterval = $interval(timerFn, interval); - } - } - function resetTimer() { - if (currentInterval) { - $interval.cancel(currentInterval); - currentInterval = null; - } - } - function timerFn() { - var interval = +$scope.interval; - if (isPlaying && !isNaN(interval) && interval > 0 && slides.length) { - $scope.next(); - } else { - $scope.pause(); - } - } - $scope.play = function() { - if (!isPlaying) { - isPlaying = true; - restartTimer(); - } - }; - $scope.pause = function() { - if (!$scope.noPause) { - isPlaying = false; - resetTimer(); - } - }; - self.addSlide = function(slide, element) { - slide.$element = element; - slides.push(slide); - if (slides.length === 1 || slide.active) { - self.select(slides[slides.length - 1]); - if (slides.length == 1) { - $scope.play(); - } - } else { - slide.active = false; + if (evt && openScope.getAutoClose() === "disabled") { + return; } - }; - self.removeSlide = function(slide) { - if (angular.isDefined(slide.index)) { - slides.sort(function(a, b) { - return +a.index > +b.index; - }); + var toggleElement = openScope.getToggleElement(); + if (evt && toggleElement && toggleElement[0].contains(evt.target)) { + return; } - var index = slides.indexOf(slide); - slides.splice(index, 1); - if (slides.length > 0 && slide.active) { - if (index >= slides.length) { - self.select(slides[index - 1]); - } else { - self.select(slides[index]); - } - } else if (currentIndex > index) { - currentIndex--; + var dropdownElement = openScope.getDropdownElement(); + if (evt && openScope.getAutoClose() === "outsideClick" && dropdownElement && dropdownElement[0].contains(evt.target)) { + return; } - if (slides.length === 0) { - self.currentSlide = null; + openScope.isOpen = false; + if (!$rootScope.$$phase) { + openScope.$apply(); } }; - $scope.$watch("noTransition", function(noTransition) { - $element.data(NO_TRANSITION, noTransition); - }); -} ]).directive("carousel", [ function() { - return { - restrict: "EA", - transclude: true, - replace: true, - controller: "CarouselController", - controllerAs: "carousel", - require: "carousel", - templateUrl: function(element, attrs) { - return attrs.templateUrl || "template/carousel/carousel.html"; - }, - scope: { - interval: "=", - noTransition: "=", - noPause: "=", - noWrap: "&" + var keybindFilter = function(evt) { + if (evt.which === 27) { + openScope.focusToggleElement(); + closeDropdown(); + } else if (openScope.isKeynavEnabled() && /(38|40)/.test(evt.which) && openScope.isOpen) { + evt.preventDefault(); + evt.stopPropagation(); + openScope.focusDropdownEntry(evt.which); } }; -} ]).directive("slide", function() { - return { - require: "^carousel", - restrict: "EA", - transclude: true, - replace: true, - templateUrl: function(element, attrs) { - return attrs.templateUrl || "template/carousel/slide.html"; - }, - scope: { - active: "=?", - actual: "=?", - index: "=?" - }, - link: function(scope, element, attrs, carouselCtrl) { - carouselCtrl.addSlide(scope, element); - scope.$on("$destroy", function() { - carouselCtrl.removeSlide(scope); +} ]).controller("DropdownController", [ "$scope", "$attrs", "$parse", "dropdownConfig", "dropdownService", "$animate", "$position", "$document", "$compile", "$templateRequest", function($scope, $attrs, $parse, dropdownConfig, dropdownService, $animate, $position, $document, $compile, $templateRequest) { + var self = this, scope = $scope.$new(), templateScope, openClass = dropdownConfig.openClass, getIsOpen, setIsOpen = angular.noop, toggleInvoker = $attrs.onToggle ? $parse($attrs.onToggle) : angular.noop, appendToBody = false, keynavEnabled = false, selectedOption = null, body = $document.find("body"); + this.init = function(element) { + self.$element = element; + if ($attrs.isOpen) { + getIsOpen = $parse($attrs.isOpen); + setIsOpen = getIsOpen.assign; + $scope.$watch(getIsOpen, function(value) { + scope.isOpen = !!value; }); - scope.$watch("active", function(active) { - if (active) { - carouselCtrl.select(scope); - } + } + appendToBody = angular.isDefined($attrs.dropdownAppendToBody); + keynavEnabled = angular.isDefined($attrs.keyboardNav); + if (appendToBody && self.dropdownMenu) { + body.append(self.dropdownMenu); + body.addClass("dropdown"); + element.on("$destroy", function handleDestroyEvent() { + self.dropdownMenu.remove(); }); } }; -}).animation(".item", [ "$injector", "$animate", function($injector, $animate) { - var NO_TRANSITION = "uib-noTransition", SLIDE_DIRECTION = "uib-slideDirection", $animateCss = null; - if ($injector.has("$animateCss")) { - $animateCss = $injector.get("$animateCss"); - } - function removeClass(element, className, callback) { - element.removeClass(className); - if (callback) { - callback(); - } - } - return { - beforeAddClass: function(element, className, done) { - if (className == "active" && element.parent() && !element.parent().data(NO_TRANSITION)) { - var stopped = false; - var direction = element.data(SLIDE_DIRECTION); - var directionClass = direction == "next" ? "left" : "right"; - var removeClassFn = removeClass.bind(this, element, directionClass + " " + direction, done); - element.addClass(direction); - if ($animateCss) { - $animateCss(element, { - addClass: directionClass - }).start().done(removeClassFn); + this.toggle = function(open) { + return scope.isOpen = arguments.length ? !!open : !scope.isOpen; + }; + this.isOpen = function() { + return scope.isOpen; + }; + scope.getToggleElement = function() { + return self.toggleElement; + }; + scope.getAutoClose = function() { + return $attrs.autoClose || "always"; + }; + scope.getElement = function() { + return self.$element; + }; + scope.isKeynavEnabled = function() { + return keynavEnabled; + }; + scope.focusDropdownEntry = function(keyCode) { + var elems = self.dropdownMenu ? angular.element(self.dropdownMenu).find("a") : angular.element(self.$element).find("ul").eq(0).find("a"); + switch (keyCode) { + case 40: + { + if (!angular.isNumber(self.selectedOption)) { + self.selectedOption = 0; } else { - $animate.addClass(element, directionClass).then(function() { - if (!stopped) { - removeClassFn(); - } - done(); - }); + self.selectedOption = self.selectedOption === elems.length - 1 ? self.selectedOption : self.selectedOption + 1; } - return function() { - stopped = true; - }; + break; } - done(); - }, - beforeRemoveClass: function(element, className, done) { - if (className === "active" && element.parent() && !element.parent().data(NO_TRANSITION)) { - var stopped = false; - var direction = element.data(SLIDE_DIRECTION); - var directionClass = direction == "next" ? "left" : "right"; - var removeClassFn = removeClass.bind(this, element, directionClass, done); - if ($animateCss) { - $animateCss(element, { - addClass: directionClass - }).start().done(removeClassFn); + + case 38: + { + if (!angular.isNumber(self.selectedOption)) { + self.selectedOption = elems.length - 1; } else { - $animate.addClass(element, directionClass).then(function() { - if (!stopped) { - removeClassFn(); - } - done(); - }); + self.selectedOption = self.selectedOption === 0 ? 0 : self.selectedOption - 1; } - return function() { - stopped = true; - }; + break; } - done(); } + elems[self.selectedOption].focus(); }; -} ]); - -angular.module("ui.bootstrap.dateparser", []).service("dateParser", [ "$log", "$locale", "orderByFilter", function($log, $locale, orderByFilter) { - var SPECIAL_CHARACTERS_REGEXP = /[\\\^\$\*\+\?\|\[\]\(\)\.\{\}]/g; - this.parsers = {}; - var formatCodeToRegex = { - yyyy: { - regex: "\\d{4}", - apply: function(value) { - this.year = +value; - } - }, - yy: { - regex: "\\d{2}", - apply: function(value) { - this.year = +value + 2e3; - } - }, - y: { - regex: "\\d{1,4}", - apply: function(value) { - this.year = +value; - } - }, - MMMM: { - regex: $locale.DATETIME_FORMATS.MONTH.join("|"), - apply: function(value) { - this.month = $locale.DATETIME_FORMATS.MONTH.indexOf(value); - } - }, - MMM: { - regex: $locale.DATETIME_FORMATS.SHORTMONTH.join("|"), - apply: function(value) { - this.month = $locale.DATETIME_FORMATS.SHORTMONTH.indexOf(value); - } - }, - MM: { - regex: "0[1-9]|1[0-2]", - apply: function(value) { - this.month = value - 1; - } - }, - M: { - regex: "[1-9]|1[0-2]", - apply: function(value) { - this.month = value - 1; - } - }, - dd: { - regex: "[0-2][0-9]{1}|3[0-1]{1}", - apply: function(value) { - this.date = +value; - } - }, - d: { - regex: "[1-2]?[0-9]{1}|3[0-1]{1}", - apply: function(value) { - this.date = +value; - } - }, - EEEE: { - regex: $locale.DATETIME_FORMATS.DAY.join("|") - }, - EEE: { - regex: $locale.DATETIME_FORMATS.SHORTDAY.join("|") - }, - HH: { - regex: "(?:0|1)[0-9]|2[0-3]", - apply: function(value) { - this.hours = +value; - } - }, - hh: { - regex: "0[0-9]|1[0-2]", - apply: function(value) { - this.hours = +value; - } - }, - H: { - regex: "1?[0-9]|2[0-3]", - apply: function(value) { - this.hours = +value; - } - }, - h: { - regex: "[0-9]|1[0-2]", - apply: function(value) { - this.hours = +value; + scope.getDropdownElement = function() { + return self.dropdownMenu; + }; + scope.focusToggleElement = function() { + if (self.toggleElement) { + self.toggleElement[0].focus(); + } + }; + scope.$watch("isOpen", function(isOpen, wasOpen) { + if (appendToBody && self.dropdownMenu) { + var pos = $position.positionElements(self.$element, self.dropdownMenu, "bottom-left", true); + var css = { + top: pos.top + "px", + display: isOpen ? "block" : "none" + }; + var rightalign = self.dropdownMenu.hasClass("dropdown-menu-right"); + if (!rightalign) { + css.left = pos.left + "px"; + css.right = "auto"; + } else { + css.left = "auto"; + css.right = window.innerWidth - (pos.left + self.$element.prop("offsetWidth")) + "px"; } - }, - mm: { - regex: "[0-5][0-9]", - apply: function(value) { - this.minutes = +value; + self.dropdownMenu.css(css); + } + var openContainer = appendToBody ? body : self.$element; + $animate[isOpen ? "addClass" : "removeClass"](openContainer, openClass).then(function() { + if (angular.isDefined(isOpen) && isOpen !== wasOpen) { + toggleInvoker($scope, { + open: !!isOpen + }); } - }, - m: { - regex: "[0-9]|[1-5][0-9]", - apply: function(value) { - this.minutes = +value; + }); + if (isOpen) { + if (self.dropdownMenuTemplateUrl) { + $templateRequest(self.dropdownMenuTemplateUrl).then(function(tplContent) { + templateScope = scope.$new(); + $compile(tplContent.trim())(templateScope, function(dropdownElement) { + var newEl = dropdownElement; + self.dropdownMenu.replaceWith(newEl); + self.dropdownMenu = newEl; + }); + }); } - }, - sss: { - regex: "[0-9][0-9][0-9]", - apply: function(value) { - this.milliseconds = +value; + scope.focusToggleElement(); + dropdownService.open(scope); + } else { + if (self.dropdownMenuTemplateUrl) { + if (templateScope) { + templateScope.$destroy(); + } + var newEl = angular.element(''); + self.dropdownMenu.replaceWith(newEl); + self.dropdownMenu = newEl; } - }, - ss: { - regex: "[0-5][0-9]", - apply: function(value) { - this.seconds = +value; + dropdownService.close(scope); + self.selectedOption = null; + } + if (angular.isFunction(setIsOpen)) { + setIsOpen($scope, isOpen); + } + }); + $scope.$on("$locationChangeSuccess", function() { + if (scope.getAutoClose() !== "disabled") { + scope.isOpen = false; + } + }); + var offDestroy = $scope.$on("$destroy", function() { + scope.$destroy(); + }); + scope.$on("$destroy", offDestroy); +} ]).directive("dropdown", function() { + return { + controller: "DropdownController", + link: function(scope, element, attrs, dropdownCtrl) { + dropdownCtrl.init(element); + element.addClass("dropdown"); + } + }; +}).directive("dropdownMenu", function() { + return { + restrict: "AC", + require: "?^dropdown", + link: function(scope, element, attrs, dropdownCtrl) { + if (!dropdownCtrl) { + return; } - }, - s: { - regex: "[0-9]|[1-5][0-9]", - apply: function(value) { - this.seconds = +value; + var tplUrl = attrs.templateUrl; + if (tplUrl) { + dropdownCtrl.dropdownMenuTemplateUrl = tplUrl; } - }, - a: { - regex: $locale.DATETIME_FORMATS.AMPMS.join("|"), - apply: function(value) { - if (this.hours === 12) { - this.hours = 0; - } - if (value === "PM") { - this.hours += 12; - } + if (!dropdownCtrl.dropdownMenu) { + dropdownCtrl.dropdownMenu = element; } } }; - function createParser(format) { - var map = [], regex = format.split(""); - angular.forEach(formatCodeToRegex, function(data, code) { - var index = format.indexOf(code); - if (index > -1) { - format = format.split(""); - regex[index] = "(" + data.regex + ")"; - format[index] = "$"; - for (var i = index + 1, n = index + code.length; i < n; i++) { - regex[i] = ""; - format[i] = "$"; +}).directive("keyboardNav", function() { + return { + restrict: "A", + require: "?^dropdown", + link: function(scope, element, attrs, dropdownCtrl) { + element.bind("keydown", function(e) { + if ([ 38, 40 ].indexOf(e.which) !== -1) { + e.preventDefault(); + e.stopPropagation(); + var elems = dropdownCtrl.dropdownMenu.find("a"); + switch (e.which) { + case 40: + { + if (!angular.isNumber(dropdownCtrl.selectedOption)) { + dropdownCtrl.selectedOption = 0; + } else { + dropdownCtrl.selectedOption = dropdownCtrl.selectedOption === elems.length - 1 ? dropdownCtrl.selectedOption : dropdownCtrl.selectedOption + 1; + } + break; + } + + case 38: + { + if (!angular.isNumber(dropdownCtrl.selectedOption)) { + dropdownCtrl.selectedOption = elems.length - 1; + } else { + dropdownCtrl.selectedOption = dropdownCtrl.selectedOption === 0 ? 0 : dropdownCtrl.selectedOption - 1; + } + break; + } + } + elems[dropdownCtrl.selectedOption].focus(); } - format = format.join(""); - map.push({ - index: index, - apply: data.apply - }); - } - }); - return { - regex: new RegExp("^" + regex.join("") + "$"), - map: orderByFilter(map, "index") - }; - } - this.parse = function(input, format, baseDate) { - if (!angular.isString(input) || !format) { - return input; + }); } - format = $locale.DATETIME_FORMATS[format] || format; - format = format.replace(SPECIAL_CHARACTERS_REGEXP, "\\$&"); - if (!this.parsers[format]) { - this.parsers[format] = createParser(format); + }; +}).directive("dropdownToggle", function() { + return { + require: "?^dropdown", + link: function(scope, element, attrs, dropdownCtrl) { + if (!dropdownCtrl) { + return; + } + element.addClass("dropdown-toggle"); + dropdownCtrl.toggleElement = element; + var toggleDropdown = function(event) { + event.preventDefault(); + if (!element.hasClass("disabled") && !attrs.disabled) { + scope.$apply(function() { + dropdownCtrl.toggle(); + }); + } + }; + element.bind("click", toggleDropdown); + element.attr({ + "aria-haspopup": true, + "aria-expanded": false + }); + scope.$watch(dropdownCtrl.isOpen, function(isOpen) { + element.attr("aria-expanded", !!isOpen); + }); + scope.$on("$destroy", function() { + element.unbind("click", toggleDropdown); + }); } - var parser = this.parsers[format], regex = parser.regex, map = parser.map, results = input.match(regex); - if (results && results.length) { - var fields, dt; - if (angular.isDate(baseDate) && !isNaN(baseDate.getTime())) { - fields = { - year: baseDate.getFullYear(), - month: baseDate.getMonth(), - date: baseDate.getDate(), - hours: baseDate.getHours(), - minutes: baseDate.getMinutes(), - seconds: baseDate.getSeconds(), - milliseconds: baseDate.getMilliseconds() - }; - } else { - if (baseDate) { - $log.warn("dateparser:", "baseDate is not a valid date"); + }; +}); + +angular.module("ui.bootstrap.modal", []).factory("$$stackedMap", function() { + return { + createNew: function() { + var stack = []; + return { + add: function(key, value) { + stack.push({ + key: key, + value: value + }); + }, + get: function(key) { + for (var i = 0; i < stack.length; i++) { + if (key == stack[i].key) { + return stack[i]; + } + } + }, + keys: function() { + var keys = []; + for (var i = 0; i < stack.length; i++) { + keys.push(stack[i].key); + } + return keys; + }, + top: function() { + return stack[stack.length - 1]; + }, + remove: function(key) { + var idx = -1; + for (var i = 0; i < stack.length; i++) { + if (key == stack[i].key) { + idx = i; + break; + } + } + return stack.splice(idx, 1)[0]; + }, + removeTop: function() { + return stack.splice(stack.length - 1, 1)[0]; + }, + length: function() { + return stack.length; } - fields = { - year: 1900, - month: 0, - date: 1, - hours: 0, - minutes: 0, - seconds: 0, - milliseconds: 0 - }; - } - for (var i = 1, n = results.length; i < n; i++) { - var mapper = map[i - 1]; - if (mapper.apply) { - mapper.apply.call(fields, results[i]); + }; + } + }; +}).factory("$$multiMap", function() { + return { + createNew: function() { + var map = {}; + return { + entries: function() { + return Object.keys(map).map(function(key) { + return { + key: key, + value: map[key] + }; + }); + }, + get: function(key) { + return map[key]; + }, + hasKey: function(key) { + return !!map[key]; + }, + keys: function() { + return Object.keys(map); + }, + put: function(key, value) { + if (!map[key]) { + map[key] = []; + } + map[key].push(value); + }, + remove: function(key, value) { + var values = map[key]; + if (!values) { + return; + } + var idx = values.indexOf(value); + if (idx !== -1) { + values.splice(idx, 1); + } + if (!values.length) { + delete map[key]; + } } - } - if (isValid(fields.year, fields.month, fields.date)) { - dt = new Date(fields.year, fields.month, fields.date, fields.hours, fields.minutes, fields.seconds, fields.milliseconds || 0); - } - return dt; + }; } }; - function isValid(year, month, date) { - if (date < 1) { - return false; - } - if (month === 1 && date > 28) { - return date === 29 && (year % 4 === 0 && year % 100 !== 0 || year % 400 === 0); - } - if (month === 3 || month === 5 || month === 8 || month === 10) { - return date < 31; - } - return true; +}).directive("modalBackdrop", [ "$animate", "$injector", "$modalStack", function($animate, $injector, $modalStack) { + var $animateCss = null; + if ($injector.has("$animateCss")) { + $animateCss = $injector.get("$animateCss"); } -} ]); - -angular.module("ui.bootstrap.position", []).factory("$position", [ "$document", "$window", function($document, $window) { - function getStyle(el, cssprop) { - if (el.currentStyle) { - return el.currentStyle[cssprop]; - } else if ($window.getComputedStyle) { - return $window.getComputedStyle(el)[cssprop]; + return { + restrict: "EA", + replace: true, + templateUrl: "template/modal/backdrop.html", + compile: function(tElement, tAttrs) { + tElement.addClass(tAttrs.backdropClass); + return linkFn; + } + }; + function linkFn(scope, element, attrs) { + if (attrs.modalInClass) { + if ($animateCss) { + $animateCss(element, { + addClass: attrs.modalInClass + }).start(); + } else { + $animate.addClass(element, attrs.modalInClass); + } + scope.$on($modalStack.NOW_CLOSING_EVENT, function(e, setIsAsync) { + var done = setIsAsync(); + if ($animateCss) { + $animateCss(element, { + removeClass: attrs.modalInClass + }).start().then(done); + } else { + $animate.removeClass(element, attrs.modalInClass).then(done); + } + }); } - return el.style[cssprop]; } - function isStaticPositioned(element) { - return (getStyle(element, "position") || "static") === "static"; +} ]).directive("modalWindow", [ "$modalStack", "$q", "$animate", "$injector", function($modalStack, $q, $animate, $injector) { + var $animateCss = null; + if ($injector.has("$animateCss")) { + $animateCss = $injector.get("$animateCss"); } - var parentOffsetEl = function(element) { - var docDomEl = $document[0]; - var offsetParent = element.offsetParent || docDomEl; - while (offsetParent && offsetParent !== docDomEl && isStaticPositioned(offsetParent)) { - offsetParent = offsetParent.offsetParent; - } - return offsetParent || docDomEl; - }; return { - position: function(element) { - var elBCR = this.offset(element); - var offsetParentBCR = { - top: 0, - left: 0 - }; - var offsetParentEl = parentOffsetEl(element[0]); - if (offsetParentEl != $document[0]) { - offsetParentBCR = this.offset(angular.element(offsetParentEl)); - offsetParentBCR.top += offsetParentEl.clientTop - offsetParentEl.scrollTop; - offsetParentBCR.left += offsetParentEl.clientLeft - offsetParentEl.scrollLeft; - } - var boundingClientRect = element[0].getBoundingClientRect(); - return { - width: boundingClientRect.width || element.prop("offsetWidth"), - height: boundingClientRect.height || element.prop("offsetHeight"), - top: elBCR.top - offsetParentBCR.top, - left: elBCR.left - offsetParentBCR.left - }; + restrict: "EA", + scope: { + index: "@" }, - offset: function(element) { - var boundingClientRect = element[0].getBoundingClientRect(); - return { - width: boundingClientRect.width || element.prop("offsetWidth"), - height: boundingClientRect.height || element.prop("offsetHeight"), - top: boundingClientRect.top + ($window.pageYOffset || $document[0].documentElement.scrollTop), - left: boundingClientRect.left + ($window.pageXOffset || $document[0].documentElement.scrollLeft) - }; + replace: true, + transclude: true, + templateUrl: function(tElement, tAttrs) { + return tAttrs.templateUrl || "template/modal/window.html"; }, - positionElements: function(hostEl, targetEl, positionStr, appendToBody) { - var positionStrParts = positionStr.split("-"); - var pos0 = positionStrParts[0], pos1 = positionStrParts[1] || "center"; - var hostElPos, targetElWidth, targetElHeight, targetElPos; - hostElPos = appendToBody ? this.offset(hostEl) : this.position(hostEl); - targetElWidth = targetEl.prop("offsetWidth"); - targetElHeight = targetEl.prop("offsetHeight"); - var shiftWidth = { - center: function() { - return hostElPos.left + hostElPos.width / 2 - targetElWidth / 2; - }, - left: function() { - return hostElPos.left; - }, - right: function() { - return hostElPos.left + hostElPos.width; + link: function(scope, element, attrs) { + element.addClass(attrs.windowClass || ""); + scope.size = attrs.size; + scope.close = function(evt) { + var modal = $modalStack.getTop(); + if (modal && modal.value.backdrop && modal.value.backdrop !== "static" && evt.target === evt.currentTarget) { + evt.preventDefault(); + evt.stopPropagation(); + $modalStack.dismiss(modal.key, "backdrop click"); } }; - var shiftHeight = { - center: function() { - return hostElPos.top + hostElPos.height / 2 - targetElHeight / 2; - }, - top: function() { - return hostElPos.top; - }, - bottom: function() { - return hostElPos.top + hostElPos.height; + scope.$isRendered = true; + var modalRenderDeferObj = $q.defer(); + attrs.$observe("modalRender", function(value) { + if (value == "true") { + modalRenderDeferObj.resolve(); } - }; - switch (pos0) { - case "right": - targetElPos = { - top: shiftHeight[pos1](), - left: shiftWidth[pos0]() - }; - break; - - case "left": - targetElPos = { - top: shiftHeight[pos1](), - left: hostElPos.left - targetElWidth - }; - break; - - case "bottom": - targetElPos = { - top: shiftHeight[pos0](), - left: shiftWidth[pos1]() - }; - break; - - default: - targetElPos = { - top: hostElPos.top - targetElHeight, - left: shiftWidth[pos1]() - }; - break; + }); + modalRenderDeferObj.promise.then(function() { + var animationPromise = null; + if (attrs.modalInClass) { + if ($animateCss) { + animationPromise = $animateCss(element, { + addClass: attrs.modalInClass + }).start(); + } else { + animationPromise = $animate.addClass(element, attrs.modalInClass); + } + scope.$on($modalStack.NOW_CLOSING_EVENT, function(e, setIsAsync) { + var done = setIsAsync(); + if ($animateCss) { + $animateCss(element, { + removeClass: attrs.modalInClass + }).start().then(done); + } else { + $animate.removeClass(element, attrs.modalInClass).then(done); + } + }); + } + $q.when(animationPromise).then(function() { + var inputsWithAutofocus = element[0].querySelectorAll("[autofocus]"); + if (inputsWithAutofocus.length) { + inputsWithAutofocus[0].focus(); + } else { + element[0].focus(); + } + }); + var modal = $modalStack.getTop(); + if (modal) { + $modalStack.modalRendered(modal.key); + } + }); + } + }; +} ]).directive("modalAnimationClass", [ function() { + return { + compile: function(tElement, tAttrs) { + if (tAttrs.modalAnimation) { + tElement.addClass(tAttrs.modalAnimationClass); + } + } + }; +} ]).directive("modalTransclude", function() { + return { + link: function($scope, $element, $attrs, controller, $transclude) { + $transclude($scope.$parent, function(clone) { + $element.empty(); + $element.append(clone); + }); + } + }; +}).factory("$modalStack", [ "$animate", "$timeout", "$document", "$compile", "$rootScope", "$q", "$injector", "$$multiMap", "$$stackedMap", function($animate, $timeout, $document, $compile, $rootScope, $q, $injector, $$multiMap, $$stackedMap) { + var $animateCss = null; + if ($injector.has("$animateCss")) { + $animateCss = $injector.get("$animateCss"); + } + var OPENED_MODAL_CLASS = "modal-open"; + var backdropDomEl, backdropScope; + var openedWindows = $$stackedMap.createNew(); + var openedClasses = $$multiMap.createNew(); + var $modalStack = { + NOW_CLOSING_EVENT: "modal.stack.now-closing" + }; + var focusableElementList; + var focusIndex = 0; + var tababbleSelector = "a[href], area[href], input:not([disabled]), " + "button:not([disabled]),select:not([disabled]), textarea:not([disabled]), " + "iframe, object, embed, *[tabindex], *[contenteditable=true]"; + function backdropIndex() { + var topBackdropIndex = -1; + var opened = openedWindows.keys(); + for (var i = 0; i < opened.length; i++) { + if (openedWindows.get(opened[i]).value.backdrop) { + topBackdropIndex = i; } - return targetElPos; } - }; -} ]); - -angular.module("ui.bootstrap.datepicker", [ "ui.bootstrap.dateparser", "ui.bootstrap.position" ]).value("$datepickerSuppressError", false).constant("datepickerConfig", { - formatDay: "dd", - formatMonth: "MMMM", - formatYear: "yyyy", - formatDayHeader: "EEE", - formatDayTitle: "MMMM yyyy", - formatMonthTitle: "yyyy", - datepickerMode: "day", - minMode: "day", - maxMode: "year", - showWeeks: true, - startingDay: 0, - yearRange: 20, - minDate: null, - maxDate: null, - shortcutPropagation: false -}).controller("DatepickerController", [ "$scope", "$attrs", "$parse", "$interpolate", "$log", "dateFilter", "datepickerConfig", "$datepickerSuppressError", function($scope, $attrs, $parse, $interpolate, $log, dateFilter, datepickerConfig, $datepickerSuppressError) { - var self = this, ngModelCtrl = { - $setViewValue: angular.noop - }; - this.modes = [ "day", "month", "year" ]; - angular.forEach([ "formatDay", "formatMonth", "formatYear", "formatDayHeader", "formatDayTitle", "formatMonthTitle", "showWeeks", "startingDay", "yearRange", "shortcutPropagation" ], function(key, index) { - self[key] = angular.isDefined($attrs[key]) ? index < 6 ? $interpolate($attrs[key])($scope.$parent) : $scope.$parent.$eval($attrs[key]) : datepickerConfig[key]; + return topBackdropIndex; + } + $rootScope.$watch(backdropIndex, function(newBackdropIndex) { + if (backdropScope) { + backdropScope.index = newBackdropIndex; + } }); - angular.forEach([ "minDate", "maxDate" ], function(key) { - if ($attrs[key]) { - $scope.$parent.$watch($parse($attrs[key]), function(value) { - self[key] = value ? new Date(value) : null; - self.refreshView(); - }); + function removeModalWindow(modalInstance, elementToReceiveFocus) { + var body = $document.find("body").eq(0); + var modalWindow = openedWindows.get(modalInstance).value; + openedWindows.remove(modalInstance); + removeAfterAnimate(modalWindow.modalDomEl, modalWindow.modalScope, function() { + var modalBodyClass = modalWindow.openedClass || OPENED_MODAL_CLASS; + openedClasses.remove(modalBodyClass, modalInstance); + body.toggleClass(modalBodyClass, openedClasses.hasKey(modalBodyClass)); + }); + checkRemoveBackdrop(); + if (elementToReceiveFocus && elementToReceiveFocus.focus) { + elementToReceiveFocus.focus(); } else { - self[key] = datepickerConfig[key] ? new Date(datepickerConfig[key]) : null; + body.focus(); } - }); - angular.forEach([ "minMode", "maxMode" ], function(key) { - if ($attrs[key]) { - $scope.$parent.$watch($parse($attrs[key]), function(value) { - self[key] = angular.isDefined(value) ? value : $attrs[key]; - $scope[key] = self[key]; - if (key == "minMode" && self.modes.indexOf($scope.datepickerMode) < self.modes.indexOf(self[key]) || key == "maxMode" && self.modes.indexOf($scope.datepickerMode) > self.modes.indexOf(self[key])) { - $scope.datepickerMode = self[key]; - } + } + function checkRemoveBackdrop() { + if (backdropDomEl && backdropIndex() == -1) { + var backdropScopeRef = backdropScope; + removeAfterAnimate(backdropDomEl, backdropScope, function() { + backdropScopeRef = null; }); - } else { - self[key] = datepickerConfig[key] || null; - $scope[key] = self[key]; + backdropDomEl = undefined; + backdropScope = undefined; } - }); - $scope.datepickerMode = $scope.datepickerMode || datepickerConfig.datepickerMode; - $scope.uniqueId = "datepicker-" + $scope.$id + "-" + Math.floor(Math.random() * 1e4); - if (angular.isDefined($attrs.initDate)) { - this.activeDate = $scope.$parent.$eval($attrs.initDate) || new Date(); - $scope.$parent.$watch($attrs.initDate, function(initDate) { - if (initDate && (ngModelCtrl.$isEmpty(ngModelCtrl.$modelValue) || ngModelCtrl.$invalid)) { - self.activeDate = initDate; - self.refreshView(); + } + function removeAfterAnimate(domEl, scope, done) { + var asyncDeferred; + var asyncPromise = null; + var setIsAsync = function() { + if (!asyncDeferred) { + asyncDeferred = $q.defer(); + asyncPromise = asyncDeferred.promise; + } + return function asyncDone() { + asyncDeferred.resolve(); + }; + }; + scope.$broadcast($modalStack.NOW_CLOSING_EVENT, setIsAsync); + return $q.when(asyncPromise).then(afterAnimating); + function afterAnimating() { + if (afterAnimating.done) { + return; + } + afterAnimating.done = true; + if ($animateCss) { + $animateCss(domEl, { + event: "leave" + }).start().then(function() { + domEl.remove(); + }); + } else { + $animate.leave(domEl); + } + scope.$destroy(); + if (done) { + done(); + } + } + } + $document.bind("keydown", function(evt) { + if (evt.isDefaultPrevented()) { + return evt; + } + var modal = openedWindows.top(); + if (modal && modal.value.keyboard) { + switch (evt.which) { + case 27: + { + evt.preventDefault(); + $rootScope.$apply(function() { + $modalStack.dismiss(modal.key, "escape key press"); + }); + break; + } + + case 9: + { + $modalStack.loadFocusElementList(modal); + var focusChanged = false; + if (evt.shiftKey) { + if ($modalStack.isFocusInFirstItem(evt)) { + focusChanged = $modalStack.focusLastFocusableElement(); + } + } else { + if ($modalStack.isFocusInLastItem(evt)) { + focusChanged = $modalStack.focusFirstFocusableElement(); + } + } + if (focusChanged) { + evt.preventDefault(); + evt.stopPropagation(); + } + break; + } } + } + }); + $modalStack.open = function(modalInstance, modal) { + var modalOpener = $document[0].activeElement, modalBodyClass = modal.openedClass || OPENED_MODAL_CLASS; + openedWindows.add(modalInstance, { + deferred: modal.deferred, + renderDeferred: modal.renderDeferred, + modalScope: modal.scope, + backdrop: modal.backdrop, + keyboard: modal.keyboard, + openedClass: modal.openedClass }); - } else { - this.activeDate = new Date(); + openedClasses.put(modalBodyClass, modalInstance); + var body = $document.find("body").eq(0), currBackdropIndex = backdropIndex(); + if (currBackdropIndex >= 0 && !backdropDomEl) { + backdropScope = $rootScope.$new(true); + backdropScope.index = currBackdropIndex; + var angularBackgroundDomEl = angular.element('
        '); + angularBackgroundDomEl.attr("backdrop-class", modal.backdropClass); + if (modal.animation) { + angularBackgroundDomEl.attr("modal-animation", "true"); + } + backdropDomEl = $compile(angularBackgroundDomEl)(backdropScope); + body.append(backdropDomEl); + } + var angularDomEl = angular.element('
        '); + angularDomEl.attr({ + "template-url": modal.windowTemplateUrl, + "window-class": modal.windowClass, + size: modal.size, + index: openedWindows.length() - 1, + animate: "animate" + }).html(modal.content); + if (modal.animation) { + angularDomEl.attr("modal-animation", "true"); + } + var modalDomEl = $compile(angularDomEl)(modal.scope); + openedWindows.top().value.modalDomEl = modalDomEl; + openedWindows.top().value.modalOpener = modalOpener; + body.append(modalDomEl); + body.addClass(modalBodyClass); + $modalStack.clearFocusListCache(); + }; + function broadcastClosing(modalWindow, resultOrReason, closing) { + return !modalWindow.value.modalScope.$broadcast("modal.closing", resultOrReason, closing).defaultPrevented; } - $scope.isActive = function(dateObject) { - if (self.compare(dateObject.date, self.activeDate) === 0) { - $scope.activeDateId = dateObject.uid; + $modalStack.close = function(modalInstance, result) { + var modalWindow = openedWindows.get(modalInstance); + if (modalWindow && broadcastClosing(modalWindow, result, true)) { + modalWindow.value.modalScope.$$uibDestructionScheduled = true; + modalWindow.value.deferred.resolve(result); + removeModalWindow(modalInstance, modalWindow.value.modalOpener); return true; } - return false; + return !modalWindow; }; - this.init = function(ngModelCtrl_) { - ngModelCtrl = ngModelCtrl_; - ngModelCtrl.$render = function() { - self.render(); - }; + $modalStack.dismiss = function(modalInstance, reason) { + var modalWindow = openedWindows.get(modalInstance); + if (modalWindow && broadcastClosing(modalWindow, reason, false)) { + modalWindow.value.modalScope.$$uibDestructionScheduled = true; + modalWindow.value.deferred.reject(reason); + removeModalWindow(modalInstance, modalWindow.value.modalOpener); + return true; + } + return !modalWindow; }; - this.render = function() { - if (ngModelCtrl.$viewValue) { - var date = new Date(ngModelCtrl.$viewValue), isValid = !isNaN(date); - if (isValid) { - this.activeDate = date; - } else if (!$datepickerSuppressError) { - $log.error('Datepicker directive: "ng-model" value must be a Date object, a number of milliseconds since 01.01.1970 or a string representing an RFC2822 or ISO 8601 date.'); - } + $modalStack.dismissAll = function(reason) { + var topModal = this.getTop(); + while (topModal && this.dismiss(topModal.key, reason)) { + topModal = this.getTop(); + } + }; + $modalStack.getTop = function() { + return openedWindows.top(); + }; + $modalStack.modalRendered = function(modalInstance) { + var modalWindow = openedWindows.get(modalInstance); + if (modalWindow) { + modalWindow.value.renderDeferred.resolve(); } - this.refreshView(); }; - this.refreshView = function() { - if (this.element) { - this._refreshView(); - var date = ngModelCtrl.$viewValue ? new Date(ngModelCtrl.$viewValue) : null; - ngModelCtrl.$setValidity("dateDisabled", !date || this.element && !this.isDisabled(date)); + $modalStack.focusFirstFocusableElement = function() { + if (focusableElementList.length > 0) { + focusableElementList[0].focus(); + return true; } + return false; }; - this.createDateObject = function(date, format) { - var model = ngModelCtrl.$viewValue ? new Date(ngModelCtrl.$viewValue) : null; - return { - date: date, - label: dateFilter(date, format), - selected: model && this.compare(date, model) === 0, - disabled: this.isDisabled(date), - current: this.compare(date, new Date()) === 0, - customClass: this.customClass(date) - }; - }; - this.isDisabled = function(date) { - return this.minDate && this.compare(date, this.minDate) < 0 || this.maxDate && this.compare(date, this.maxDate) > 0 || $attrs.dateDisabled && $scope.dateDisabled({ - date: date, - mode: $scope.datepickerMode - }); + $modalStack.focusLastFocusableElement = function() { + if (focusableElementList.length > 0) { + focusableElementList[focusableElementList.length - 1].focus(); + return true; + } + return false; }; - this.customClass = function(date) { - return $scope.customClass({ - date: date, - mode: $scope.datepickerMode - }); + $modalStack.isFocusInFirstItem = function(evt) { + if (focusableElementList.length > 0) { + return (evt.target || evt.srcElement) == focusableElementList[0]; + } + return false; }; - this.split = function(arr, size) { - var arrays = []; - while (arr.length > 0) { - arrays.push(arr.splice(0, size)); + $modalStack.isFocusInLastItem = function(evt) { + if (focusableElementList.length > 0) { + return (evt.target || evt.srcElement) == focusableElementList[focusableElementList.length - 1]; } - return arrays; + return false; }; - this.fixTimeZone = function(date) { - var hours = date.getHours(); - date.setHours(hours === 23 ? hours + 2 : 0); + $modalStack.clearFocusListCache = function() { + focusableElementList = []; + focusIndex = 0; }; - $scope.select = function(date) { - if ($scope.datepickerMode === self.minMode) { - var dt = ngModelCtrl.$viewValue ? new Date(ngModelCtrl.$viewValue) : new Date(0, 0, 0, 0, 0, 0, 0); - dt.setFullYear(date.getFullYear(), date.getMonth(), date.getDate()); - ngModelCtrl.$setViewValue(dt); - ngModelCtrl.$render(); - } else { - self.activeDate = date; - $scope.datepickerMode = self.modes[self.modes.indexOf($scope.datepickerMode) - 1]; + $modalStack.loadFocusElementList = function(modalWindow) { + if (focusableElementList === undefined || !focusableElementList.length0) { + if (modalWindow) { + var modalDomE1 = modalWindow.value.modalDomEl; + if (modalDomE1 && modalDomE1.length) { + focusableElementList = modalDomE1[0].querySelectorAll(tababbleSelector); + } + } } }; - $scope.move = function(direction) { - var year = self.activeDate.getFullYear() + direction * (self.step.years || 0), month = self.activeDate.getMonth() + direction * (self.step.months || 0); - self.activeDate.setFullYear(year, month, 1); - self.refreshView(); + return $modalStack; +} ]).provider("$modal", function() { + var $modalProvider = { + options: { + animation: true, + backdrop: true, + keyboard: true + }, + $get: [ "$injector", "$rootScope", "$q", "$templateRequest", "$controller", "$modalStack", function($injector, $rootScope, $q, $templateRequest, $controller, $modalStack) { + var $modal = {}; + function getTemplatePromise(options) { + return options.template ? $q.when(options.template) : $templateRequest(angular.isFunction(options.templateUrl) ? options.templateUrl() : options.templateUrl); + } + function getResolvePromises(resolves) { + var promisesArr = []; + angular.forEach(resolves, function(value) { + if (angular.isFunction(value) || angular.isArray(value)) { + promisesArr.push($q.when($injector.invoke(value))); + } else if (angular.isString(value)) { + promisesArr.push($q.when($injector.get(value))); + } else { + promisesArr.push($q.when(value)); + } + }); + return promisesArr; + } + var promiseChain = null; + $modal.getPromiseChain = function() { + return promiseChain; + }; + $modal.open = function(modalOptions) { + var modalResultDeferred = $q.defer(); + var modalOpenedDeferred = $q.defer(); + var modalRenderDeferred = $q.defer(); + var modalInstance = { + result: modalResultDeferred.promise, + opened: modalOpenedDeferred.promise, + rendered: modalRenderDeferred.promise, + close: function(result) { + return $modalStack.close(modalInstance, result); + }, + dismiss: function(reason) { + return $modalStack.dismiss(modalInstance, reason); + } + }; + modalOptions = angular.extend({}, $modalProvider.options, modalOptions); + modalOptions.resolve = modalOptions.resolve || {}; + if (!modalOptions.template && !modalOptions.templateUrl) { + throw new Error("One of template or templateUrl options is required."); + } + var templateAndResolvePromise = $q.all([ getTemplatePromise(modalOptions) ].concat(getResolvePromises(modalOptions.resolve))); + var samePromise; + samePromise = promiseChain = $q.all([ promiseChain ]).then(function() { + return templateAndResolvePromise; + }, function() { + return templateAndResolvePromise; + }).then(function resolveSuccess(tplAndVars) { + var modalScope = (modalOptions.scope || $rootScope).$new(); + modalScope.$close = modalInstance.close; + modalScope.$dismiss = modalInstance.dismiss; + modalScope.$on("$destroy", function() { + if (!modalScope.$$uibDestructionScheduled) { + modalScope.$dismiss("$uibUnscheduledDestruction"); + } + }); + var ctrlInstance, ctrlLocals = {}; + var resolveIter = 1; + if (modalOptions.controller) { + ctrlLocals.$scope = modalScope; + ctrlLocals.$modalInstance = modalInstance; + angular.forEach(modalOptions.resolve, function(value, key) { + ctrlLocals[key] = tplAndVars[resolveIter++]; + }); + ctrlInstance = $controller(modalOptions.controller, ctrlLocals); + if (modalOptions.controllerAs) { + if (modalOptions.bindToController) { + angular.extend(ctrlInstance, modalScope); + } + modalScope[modalOptions.controllerAs] = ctrlInstance; + } + } + $modalStack.open(modalInstance, { + scope: modalScope, + deferred: modalResultDeferred, + renderDeferred: modalRenderDeferred, + content: tplAndVars[0], + animation: modalOptions.animation, + backdrop: modalOptions.backdrop, + keyboard: modalOptions.keyboard, + backdropClass: modalOptions.backdropClass, + windowClass: modalOptions.windowClass, + windowTemplateUrl: modalOptions.windowTemplateUrl, + size: modalOptions.size, + openedClass: modalOptions.openedClass + }); + modalOpenedDeferred.resolve(true); + }, function resolveError(reason) { + modalOpenedDeferred.reject(reason); + modalResultDeferred.reject(reason); + }).finally(function() { + if (promiseChain === samePromise) { + promiseChain = null; + } + }); + return modalInstance; + }; + return $modal; + } ] }; - $scope.toggleMode = function(direction) { - direction = direction || 1; - if ($scope.datepickerMode === self.maxMode && direction === 1 || $scope.datepickerMode === self.minMode && direction === -1) { - return; + return $modalProvider; +}); + +angular.module("ui.bootstrap.pagination", []).controller("PaginationController", [ "$scope", "$attrs", "$parse", function($scope, $attrs, $parse) { + var self = this, ngModelCtrl = { + $setViewValue: angular.noop + }, setNumPages = $attrs.numPages ? $parse($attrs.numPages).assign : angular.noop; + this.init = function(ngModelCtrl_, config) { + ngModelCtrl = ngModelCtrl_; + this.config = config; + ngModelCtrl.$render = function() { + self.render(); + }; + if ($attrs.itemsPerPage) { + $scope.$parent.$watch($parse($attrs.itemsPerPage), function(value) { + self.itemsPerPage = parseInt(value, 10); + $scope.totalPages = self.calculateTotalPages(); + }); + } else { + this.itemsPerPage = config.itemsPerPage; } - $scope.datepickerMode = self.modes[self.modes.indexOf($scope.datepickerMode) + direction]; + $scope.$watch("totalItems", function() { + $scope.totalPages = self.calculateTotalPages(); + }); + $scope.$watch("totalPages", function(value) { + setNumPages($scope.$parent, value); + if ($scope.page > value) { + $scope.selectPage(value); + } else { + ngModelCtrl.$render(); + } + }); }; - $scope.keys = { - 13: "enter", - 32: "space", - 33: "pageup", - 34: "pagedown", - 35: "end", - 36: "home", - 37: "left", - 38: "up", - 39: "right", - 40: "down" + this.calculateTotalPages = function() { + var totalPages = this.itemsPerPage < 1 ? 1 : Math.ceil($scope.totalItems / this.itemsPerPage); + return Math.max(totalPages || 0, 1); }; - var focusElement = function() { - self.element[0].focus(); + this.render = function() { + $scope.page = parseInt(ngModelCtrl.$viewValue, 10) || 1; }; - $scope.$on("datepicker.focus", focusElement); - $scope.keydown = function(evt) { - var key = $scope.keys[evt.which]; - if (!key || evt.shiftKey || evt.altKey) { - return; - } - evt.preventDefault(); - if (!self.shortcutPropagation) { - evt.stopPropagation(); - } - if (key === "enter" || key === "space") { - if (self.isDisabled(self.activeDate)) { - return; + $scope.selectPage = function(page, evt) { + if (evt) { + evt.preventDefault(); + } + var clickAllowed = !$scope.ngDisabled || !evt; + if (clickAllowed && $scope.page !== page && page > 0 && page <= $scope.totalPages) { + if (evt && evt.target) { + evt.target.blur(); } - $scope.select(self.activeDate); - focusElement(); - } else if (evt.ctrlKey && (key === "up" || key === "down")) { - $scope.toggleMode(key === "up" ? 1 : -1); - focusElement(); - } else { - self.handleKeyDown(key, evt); - self.refreshView(); + ngModelCtrl.$setViewValue(page); + ngModelCtrl.$render(); } }; -} ]).directive("datepicker", function() { + $scope.getText = function(key) { + return $scope[key + "Text"] || self.config[key + "Text"]; + }; + $scope.noPrevious = function() { + return $scope.page === 1; + }; + $scope.noNext = function() { + return $scope.page === $scope.totalPages; + }; +} ]).constant("paginationConfig", { + itemsPerPage: 10, + boundaryLinks: false, + directionLinks: true, + firstText: "First", + previousText: "Previous", + nextText: "Next", + lastText: "Last", + rotate: true +}).directive("pagination", [ "$parse", "paginationConfig", function($parse, paginationConfig) { return { restrict: "EA", - replace: true, - templateUrl: function(element, attrs) { - return attrs.templateUrl || "template/datepicker/datepicker.html"; - }, scope: { - datepickerMode: "=?", - dateDisabled: "&", - customClass: "&", - shortcutPropagation: "&?" + totalItems: "=", + firstText: "@", + previousText: "@", + nextText: "@", + lastText: "@", + ngDisabled: "=" + }, + require: [ "pagination", "?ngModel" ], + controller: "PaginationController", + controllerAs: "pagination", + templateUrl: function(element, attrs) { + return attrs.templateUrl || "template/pagination/pagination.html"; }, - require: [ "datepicker", "^ngModel" ], - controller: "DatepickerController", - controllerAs: "datepicker", - link: function(scope, element, attrs, ctrls) { - var datepickerCtrl = ctrls[0], ngModelCtrl = ctrls[1]; - datepickerCtrl.init(ngModelCtrl); - } - }; -}).directive("daypicker", [ "dateFilter", function(dateFilter) { - return { - restrict: "EA", replace: true, - templateUrl: "template/datepicker/day.html", - require: "^datepicker", - link: function(scope, element, attrs, ctrl) { - scope.showWeeks = ctrl.showWeeks; - ctrl.step = { - months: 1 - }; - ctrl.element = element; - var DAYS_IN_MONTH = [ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 ]; - function getDaysInMonth(year, month) { - return month === 1 && year % 4 === 0 && (year % 100 !== 0 || year % 400 === 0) ? 29 : DAYS_IN_MONTH[month]; + link: function(scope, element, attrs, ctrls) { + var paginationCtrl = ctrls[0], ngModelCtrl = ctrls[1]; + if (!ngModelCtrl) { + return; } - function getDates(startDate, n) { - var dates = new Array(n), current = new Date(startDate), i = 0, date; - while (i < n) { - date = new Date(current); - ctrl.fixTimeZone(date); - dates[i++] = date; - current.setDate(current.getDate() + 1); - } - return dates; + var maxSize = angular.isDefined(attrs.maxSize) ? scope.$parent.$eval(attrs.maxSize) : paginationConfig.maxSize, rotate = angular.isDefined(attrs.rotate) ? scope.$parent.$eval(attrs.rotate) : paginationConfig.rotate; + scope.boundaryLinks = angular.isDefined(attrs.boundaryLinks) ? scope.$parent.$eval(attrs.boundaryLinks) : paginationConfig.boundaryLinks; + scope.directionLinks = angular.isDefined(attrs.directionLinks) ? scope.$parent.$eval(attrs.directionLinks) : paginationConfig.directionLinks; + paginationCtrl.init(ngModelCtrl, paginationConfig); + if (attrs.maxSize) { + scope.$parent.$watch($parse(attrs.maxSize), function(value) { + maxSize = parseInt(value, 10); + paginationCtrl.render(); + }); } - ctrl._refreshView = function() { - var year = ctrl.activeDate.getFullYear(), month = ctrl.activeDate.getMonth(), firstDayOfMonth = new Date(year, month, 1), difference = ctrl.startingDay - firstDayOfMonth.getDay(), numDisplayedFromPreviousMonth = difference > 0 ? 7 - difference : -difference, firstDate = new Date(firstDayOfMonth); - if (numDisplayedFromPreviousMonth > 0) { - firstDate.setDate(-numDisplayedFromPreviousMonth + 1); - } - var days = getDates(firstDate, 42); - for (var i = 0; i < 42; i++) { - days[i] = angular.extend(ctrl.createDateObject(days[i], ctrl.formatDay), { - secondary: days[i].getMonth() !== month, - uid: scope.uniqueId + "-" + i - }); - } - scope.labels = new Array(7); - for (var j = 0; j < 7; j++) { - scope.labels[j] = { - abbr: dateFilter(days[j].date, ctrl.formatDayHeader), - full: dateFilter(days[j].date, "EEEE") - }; - } - scope.title = dateFilter(ctrl.activeDate, ctrl.formatDayTitle); - scope.rows = ctrl.split(days, 7); - if (scope.showWeeks) { - scope.weekNumbers = []; - var thursdayIndex = (4 + 7 - ctrl.startingDay) % 7, numWeeks = scope.rows.length; - for (var curWeek = 0; curWeek < numWeeks; curWeek++) { - scope.weekNumbers.push(getISO8601WeekNumber(scope.rows[curWeek][thursdayIndex].date)); - } - } - }; - ctrl.compare = function(date1, date2) { - return new Date(date1.getFullYear(), date1.getMonth(), date1.getDate()) - new Date(date2.getFullYear(), date2.getMonth(), date2.getDate()); - }; - function getISO8601WeekNumber(date) { - var checkDate = new Date(date); - checkDate.setDate(checkDate.getDate() + 4 - (checkDate.getDay() || 7)); - var time = checkDate.getTime(); - checkDate.setMonth(0); - checkDate.setDate(1); - return Math.floor(Math.round((time - checkDate) / 864e5) / 7) + 1; + function makePage(number, text, isActive) { + return { + number: number, + text: text, + active: isActive + }; } - ctrl.handleKeyDown = function(key, evt) { - var date = ctrl.activeDate.getDate(); - if (key === "left") { - date = date - 1; - } else if (key === "up") { - date = date - 7; - } else if (key === "right") { - date = date + 1; - } else if (key === "down") { - date = date + 7; - } else if (key === "pageup" || key === "pagedown") { - var month = ctrl.activeDate.getMonth() + (key === "pageup" ? -1 : 1); - ctrl.activeDate.setMonth(month, 1); - date = Math.min(getDaysInMonth(ctrl.activeDate.getFullYear(), ctrl.activeDate.getMonth()), date); - } else if (key === "home") { - date = 1; - } else if (key === "end") { - date = getDaysInMonth(ctrl.activeDate.getFullYear(), ctrl.activeDate.getMonth()); - } - ctrl.activeDate.setDate(date); - }; - ctrl.refreshView(); - } - }; -} ]).directive("monthpicker", [ "dateFilter", function(dateFilter) { - return { - restrict: "EA", - replace: true, - templateUrl: "template/datepicker/month.html", - require: "^datepicker", - link: function(scope, element, attrs, ctrl) { - ctrl.step = { - years: 1 - }; - ctrl.element = element; - ctrl._refreshView = function() { - var months = new Array(12), year = ctrl.activeDate.getFullYear(), date; - for (var i = 0; i < 12; i++) { - date = new Date(year, i, 1); - ctrl.fixTimeZone(date); - months[i] = angular.extend(ctrl.createDateObject(date, ctrl.formatMonth), { - uid: scope.uniqueId + "-" + i - }); - } - scope.title = dateFilter(ctrl.activeDate, ctrl.formatMonthTitle); - scope.rows = ctrl.split(months, 3); - }; - ctrl.compare = function(date1, date2) { - return new Date(date1.getFullYear(), date1.getMonth()) - new Date(date2.getFullYear(), date2.getMonth()); - }; - ctrl.handleKeyDown = function(key, evt) { - var date = ctrl.activeDate.getMonth(); - if (key === "left") { - date = date - 1; - } else if (key === "up") { - date = date - 3; - } else if (key === "right") { - date = date + 1; - } else if (key === "down") { - date = date + 3; - } else if (key === "pageup" || key === "pagedown") { - var year = ctrl.activeDate.getFullYear() + (key === "pageup" ? -1 : 1); - ctrl.activeDate.setFullYear(year); - } else if (key === "home") { - date = 0; - } else if (key === "end") { - date = 11; + function getPages(currentPage, totalPages) { + var pages = []; + var startPage = 1, endPage = totalPages; + var isMaxSized = angular.isDefined(maxSize) && maxSize < totalPages; + if (isMaxSized) { + if (rotate) { + startPage = Math.max(currentPage - Math.floor(maxSize / 2), 1); + endPage = startPage + maxSize - 1; + if (endPage > totalPages) { + endPage = totalPages; + startPage = endPage - maxSize + 1; + } + } else { + startPage = (Math.ceil(currentPage / maxSize) - 1) * maxSize + 1; + endPage = Math.min(startPage + maxSize - 1, totalPages); + } } - ctrl.activeDate.setMonth(date); - }; - ctrl.refreshView(); - } - }; -} ]).directive("yearpicker", [ "dateFilter", function(dateFilter) { - return { - restrict: "EA", - replace: true, - templateUrl: "template/datepicker/year.html", - require: "^datepicker", - link: function(scope, element, attrs, ctrl) { - var range = ctrl.yearRange; - ctrl.step = { - years: range - }; - ctrl.element = element; - function getStartingYear(year) { - return parseInt((year - 1) / range, 10) * range + 1; - } - ctrl._refreshView = function() { - var years = new Array(range), date; - for (var i = 0, start = getStartingYear(ctrl.activeDate.getFullYear()); i < range; i++) { - date = new Date(start + i, 0, 1); - ctrl.fixTimeZone(date); - years[i] = angular.extend(ctrl.createDateObject(date, ctrl.formatYear), { - uid: scope.uniqueId + "-" + i - }); + for (var number = startPage; number <= endPage; number++) { + var page = makePage(number, number, number === currentPage); + pages.push(page); } - scope.title = [ years[0].label, years[range - 1].label ].join(" - "); - scope.rows = ctrl.split(years, 5); - }; - ctrl.compare = function(date1, date2) { - return date1.getFullYear() - date2.getFullYear(); - }; - ctrl.handleKeyDown = function(key, evt) { - var date = ctrl.activeDate.getFullYear(); - if (key === "left") { - date = date - 1; - } else if (key === "up") { - date = date - 5; - } else if (key === "right") { - date = date + 1; - } else if (key === "down") { - date = date + 5; - } else if (key === "pageup" || key === "pagedown") { - date += (key === "pageup" ? -1 : 1) * ctrl.step.years; - } else if (key === "home") { - date = getStartingYear(ctrl.activeDate.getFullYear()); - } else if (key === "end") { - date = getStartingYear(ctrl.activeDate.getFullYear()) + range - 1; + if (isMaxSized && !rotate) { + if (startPage > 1) { + var previousPageSet = makePage(startPage - 1, "...", false); + pages.unshift(previousPageSet); + } + if (endPage < totalPages) { + var nextPageSet = makePage(endPage + 1, "...", false); + pages.push(nextPageSet); + } + } + return pages; + } + var originalRender = paginationCtrl.render; + paginationCtrl.render = function() { + originalRender(); + if (scope.page > 0 && scope.page <= scope.totalPages) { + scope.pages = getPages(scope.page, scope.totalPages); } - ctrl.activeDate.setFullYear(date); }; - ctrl.refreshView(); } }; -} ]).constant("datepickerPopupConfig", { - datepickerPopup: "yyyy-MM-dd", - datepickerPopupTemplateUrl: "template/datepicker/popup.html", - datepickerTemplateUrl: "template/datepicker/datepicker.html", - html5Types: { - date: "yyyy-MM-dd", - "datetime-local": "yyyy-MM-ddTHH:mm:ss.sss", - month: "yyyy-MM" - }, - currentText: "Today", - clearText: "Clear", - closeText: "Done", - closeOnDateSelection: true, - appendToBody: false, - showButtonBar: true, - onOpenFocus: true -}).directive("datepickerPopup", [ "$compile", "$parse", "$document", "$rootScope", "$position", "dateFilter", "dateParser", "datepickerPopupConfig", "$timeout", function($compile, $parse, $document, $rootScope, $position, dateFilter, dateParser, datepickerPopupConfig, $timeout) { +} ]).constant("pagerConfig", { + itemsPerPage: 10, + previousText: "« Previous", + nextText: "Next »", + align: true +}).directive("pager", [ "pagerConfig", function(pagerConfig) { return { restrict: "EA", - require: "ngModel", scope: { - isOpen: "=?", - currentText: "@", - clearText: "@", - closeText: "@", - dateDisabled: "&", - customClass: "&" + totalItems: "=", + previousText: "@", + nextText: "@", + ngDisabled: "=" }, - link: function(scope, element, attrs, ngModel) { - var dateFormat, closeOnDateSelection = angular.isDefined(attrs.closeOnDateSelection) ? scope.$parent.$eval(attrs.closeOnDateSelection) : datepickerPopupConfig.closeOnDateSelection, appendToBody = angular.isDefined(attrs.datepickerAppendToBody) ? scope.$parent.$eval(attrs.datepickerAppendToBody) : datepickerPopupConfig.appendToBody, onOpenFocus = angular.isDefined(attrs.onOpenFocus) ? scope.$parent.$eval(attrs.onOpenFocus) : datepickerPopupConfig.onOpenFocus, datepickerPopupTemplateUrl = angular.isDefined(attrs.datepickerPopupTemplateUrl) ? attrs.datepickerPopupTemplateUrl : datepickerPopupConfig.datepickerPopupTemplateUrl, datepickerTemplateUrl = angular.isDefined(attrs.datepickerTemplateUrl) ? attrs.datepickerTemplateUrl : datepickerPopupConfig.datepickerTemplateUrl, cache = {}; - scope.showButtonBar = angular.isDefined(attrs.showButtonBar) ? scope.$parent.$eval(attrs.showButtonBar) : datepickerPopupConfig.showButtonBar; - scope.getText = function(key) { - return scope[key + "Text"] || datepickerPopupConfig[key + "Text"]; - }; - scope.isDisabled = function(date) { - if (date === "today") { - date = new Date(); - } - return scope.watchData.minDate && scope.compare(date, cache.minDate) < 0 || scope.watchData.maxDate && scope.compare(date, cache.maxDate) > 0; - }; - scope.compare = function(date1, date2) { - return new Date(date1.getFullYear(), date1.getMonth(), date1.getDate()) - new Date(date2.getFullYear(), date2.getMonth(), date2.getDate()); - }; - var isHtml5DateInput = false; - if (datepickerPopupConfig.html5Types[attrs.type]) { - dateFormat = datepickerPopupConfig.html5Types[attrs.type]; - isHtml5DateInput = true; - } else { - dateFormat = attrs.datepickerPopup || datepickerPopupConfig.datepickerPopup; - attrs.$observe("datepickerPopup", function(value, oldValue) { - var newDateFormat = value || datepickerPopupConfig.datepickerPopup; - if (newDateFormat !== dateFormat) { - dateFormat = newDateFormat; - ngModel.$modelValue = null; - if (!dateFormat) { - throw new Error("datepickerPopup must have a date format specified."); + require: [ "pager", "?ngModel" ], + controller: "PaginationController", + controllerAs: "pagination", + templateUrl: function(element, attrs) { + return attrs.templateUrl || "template/pagination/pager.html"; + }, + replace: true, + link: function(scope, element, attrs, ctrls) { + var paginationCtrl = ctrls[0], ngModelCtrl = ctrls[1]; + if (!ngModelCtrl) { + return; + } + scope.align = angular.isDefined(attrs.align) ? scope.$parent.$eval(attrs.align) : pagerConfig.align; + paginationCtrl.init(ngModelCtrl, pagerConfig); + } + }; +} ]); + +angular.module("ui.bootstrap.tooltip", [ "ui.bootstrap.position", "ui.bootstrap.bindHtml" ]).provider("$tooltip", function() { + var defaultOptions = { + placement: "top", + animation: true, + popupDelay: 0, + useContentExp: false + }; + var triggerMap = { + mouseenter: "mouseleave", + click: "click", + focus: "blur", + none: "" + }; + var globalOptions = {}; + this.options = function(value) { + angular.extend(globalOptions, value); + }; + this.setTriggers = function setTriggers(triggers) { + angular.extend(triggerMap, triggers); + }; + function snake_case(name) { + var regexp = /[A-Z]/g; + var separator = "-"; + return name.replace(regexp, function(letter, pos) { + return (pos ? separator : "") + letter.toLowerCase(); + }); + } + this.$get = [ "$window", "$compile", "$timeout", "$document", "$position", "$interpolate", "$rootScope", "$parse", function($window, $compile, $timeout, $document, $position, $interpolate, $rootScope, $parse) { + return function $tooltip(type, prefix, defaultTriggerShow, options) { + options = angular.extend({}, defaultOptions, globalOptions, options); + function getTriggers(trigger) { + var show = (trigger || options.trigger || defaultTriggerShow).split(" "); + var hide = show.map(function(trigger) { + return triggerMap[trigger] || trigger; + }); + return { + show: show, + hide: hide + }; + } + var directiveName = snake_case(type); + var startSym = $interpolate.startSymbol(); + var endSym = $interpolate.endSymbol(); + var template = "
        " + "
        "; + return { + restrict: "EA", + compile: function(tElem, tAttrs) { + var tooltipLinker = $compile(template); + return function link(scope, element, attrs, tooltipCtrl) { + var tooltip; + var tooltipLinkedScope; + var transitionTimeout; + var popupTimeout; + var positionTimeout; + var appendToBody = angular.isDefined(options.appendToBody) ? options.appendToBody : false; + var triggers = getTriggers(undefined); + var hasEnableExp = angular.isDefined(attrs[prefix + "Enable"]); + var ttScope = scope.$new(true); + var repositionScheduled = false; + var isOpenExp = angular.isDefined(attrs[prefix + "IsOpen"]) ? $parse(attrs[prefix + "IsOpen"]) : false; + var positionTooltip = function() { + if (!tooltip) { + return; + } + if (!positionTimeout) { + positionTimeout = $timeout(function() { + tooltip.css({ + top: 0, + left: 0, + width: "auto", + height: "auto" + }); + var ttBox = $position.position(tooltip); + var ttCss = $position.positionElements(element, tooltip, ttScope.placement, appendToBody); + ttCss.top += "px"; + ttCss.left += "px"; + ttCss.width = ttBox.width + "px"; + ttCss.height = ttBox.height + "px"; + tooltip.css(ttCss); + positionTimeout = null; + }, 0, false); + } + }; + ttScope.origScope = scope; + ttScope.isOpen = false; + function toggleTooltipBind() { + if (!ttScope.isOpen) { + showTooltipBind(); + } else { + hideTooltipBind(); + } + } + function showTooltipBind() { + if (hasEnableExp && !scope.$eval(attrs[prefix + "Enable"])) { + return; + } + prepareTooltip(); + if (ttScope.popupDelay) { + if (!popupTimeout) { + popupTimeout = $timeout(show, ttScope.popupDelay, false); + } + } else { + show(); + } + } + function hideTooltipBind() { + hide(); + if (!$rootScope.$$phase) { + $rootScope.$digest(); + } + } + function show() { + popupTimeout = null; + if (transitionTimeout) { + $timeout.cancel(transitionTimeout); + transitionTimeout = null; + } + if (!(options.useContentExp ? ttScope.contentExp() : ttScope.content)) { + return angular.noop; + } + createTooltip(); + ttScope.isOpen = true; + if (isOpenExp) { + isOpenExp.assign(ttScope.origScope, ttScope.isOpen); + } + if (!$rootScope.$$phase) { + ttScope.$apply(); + } + tooltip.css({ + display: "block" + }); + positionTooltip(); } - } - }); - } - if (!dateFormat) { - throw new Error("datepickerPopup must have a date format specified."); - } - if (isHtml5DateInput && attrs.datepickerPopup) { - throw new Error("HTML5 date input types do not support custom formats."); - } - var popupEl = angular.element("
        "); - popupEl.attr({ - "ng-model": "date", - "ng-change": "dateSelection(date)", - "template-url": datepickerPopupTemplateUrl - }); - function cameltoDash(string) { - return string.replace(/([A-Z])/g, function($1) { - return "-" + $1.toLowerCase(); - }); - } - var datepickerEl = angular.element(popupEl.children()[0]); - datepickerEl.attr("template-url", datepickerTemplateUrl); - if (isHtml5DateInput) { - if (attrs.type === "month") { - datepickerEl.attr("datepicker-mode", '"month"'); - datepickerEl.attr("min-mode", "month"); - } - } - if (attrs.datepickerOptions) { - var options = scope.$parent.$eval(attrs.datepickerOptions); - if (options && options.initDate) { - scope.initDate = options.initDate; - datepickerEl.attr("init-date", "initDate"); - delete options.initDate; - } - angular.forEach(options, function(value, option) { - datepickerEl.attr(cameltoDash(option), value); - }); - } - scope.watchData = {}; - angular.forEach([ "minMode", "maxMode", "minDate", "maxDate", "datepickerMode", "initDate", "shortcutPropagation" ], function(key) { - if (attrs[key]) { - var getAttribute = $parse(attrs[key]); - scope.$parent.$watch(getAttribute, function(value) { - scope.watchData[key] = value; - if (key === "minDate" || key === "maxDate") { - cache[key] = new Date(value); + function hide() { + ttScope.isOpen = false; + if (isOpenExp) { + isOpenExp.assign(ttScope.origScope, ttScope.isOpen); + } + $timeout.cancel(popupTimeout); + popupTimeout = null; + $timeout.cancel(positionTimeout); + positionTimeout = null; + if (ttScope.animation) { + if (!transitionTimeout) { + transitionTimeout = $timeout(removeTooltip, 500); + } + } else { + removeTooltip(); + } } - }); - datepickerEl.attr(cameltoDash(key), "watchData." + key); - if (key === "datepickerMode") { - var setAttribute = getAttribute.assign; - scope.$watch("watchData." + key, function(value, oldvalue) { - if (angular.isFunction(setAttribute) && value !== oldvalue) { - setAttribute(scope.$parent, value); + function createTooltip() { + if (tooltip) { + removeTooltip(); + } + tooltipLinkedScope = ttScope.$new(); + tooltip = tooltipLinker(tooltipLinkedScope, function(tooltip) { + if (appendToBody) { + $document.find("body").append(tooltip); + } else { + element.after(tooltip); + } + }); + if (options.useContentExp) { + tooltipLinkedScope.$watch("contentExp()", function(val) { + if (!val && ttScope.isOpen) { + hide(); + } + }); + tooltipLinkedScope.$watch(function() { + if (!repositionScheduled) { + repositionScheduled = true; + tooltipLinkedScope.$$postDigest(function() { + repositionScheduled = false; + if (ttScope.isOpen) { + positionTooltip(); + } + }); + } + }); + } + } + function removeTooltip() { + transitionTimeout = null; + if (tooltip) { + tooltip.remove(); + tooltip = null; + } + if (tooltipLinkedScope) { + tooltipLinkedScope.$destroy(); + tooltipLinkedScope = null; + } + } + function prepareTooltip() { + prepPopupClass(); + prepPlacement(); + prepPopupDelay(); + } + ttScope.contentExp = function() { + return scope.$eval(attrs[type]); + }; + if (!options.useContentExp) { + attrs.$observe(type, function(val) { + ttScope.content = val; + if (!val && ttScope.isOpen) { + hide(); + } else { + positionTooltip(); + } + }); + } + attrs.$observe("disabled", function(val) { + if (popupTimeout && val) { + $timeout.cancel(popupTimeout); + popupTimeout = null; + } + if (val && ttScope.isOpen) { + hide(); } }); - } - } - }); - if (attrs.dateDisabled) { - datepickerEl.attr("date-disabled", "dateDisabled({ date: date, mode: mode })"); - } - if (attrs.showWeeks) { - datepickerEl.attr("show-weeks", attrs.showWeeks); - } - if (attrs.customClass) { - datepickerEl.attr("custom-class", "customClass({ date: date, mode: mode })"); - } - function parseDate(viewValue) { - if (angular.isNumber(viewValue)) { - viewValue = new Date(viewValue); - } - if (!viewValue) { - return null; - } else if (angular.isDate(viewValue) && !isNaN(viewValue)) { - return viewValue; - } else if (angular.isString(viewValue)) { - var date = dateParser.parse(viewValue, dateFormat, scope.date); - if (isNaN(date)) { - return undefined; - } else { - return date; - } - } else { - return undefined; - } - } - function validator(modelValue, viewValue) { - var value = modelValue || viewValue; - if (!attrs.ngRequired && !value) { - return true; - } - if (angular.isNumber(value)) { - value = new Date(value); - } - if (!value) { - return true; - } else if (angular.isDate(value) && !isNaN(value)) { - return true; - } else if (angular.isString(value)) { - var date = dateParser.parse(value, dateFormat); - return !isNaN(date); - } else { - return false; - } - } - if (!isHtml5DateInput) { - ngModel.$$parserName = "date"; - ngModel.$validators.date = validator; - ngModel.$parsers.unshift(parseDate); - ngModel.$formatters.push(function(value) { - scope.date = value; - return ngModel.$isEmpty(value) ? value : dateFilter(value, dateFormat); - }); - } else { - ngModel.$formatters.push(function(value) { - scope.date = value; - return value; - }); - } - scope.dateSelection = function(dt) { - if (angular.isDefined(dt)) { - scope.date = dt; - } - var date = scope.date ? dateFilter(scope.date, dateFormat) : null; - element.val(date); - ngModel.$setViewValue(date); - if (closeOnDateSelection) { - scope.isOpen = false; - element[0].focus(); - } - }; - ngModel.$viewChangeListeners.push(function() { - scope.date = dateParser.parse(ngModel.$viewValue, dateFormat, scope.date); - }); - var documentClickBind = function(event) { - if (scope.isOpen && !(element[0].contains(event.target) || popupEl[0].contains(event.target))) { - scope.$apply(function() { - scope.isOpen = false; - }); - } - }; - var inputKeydownBind = function(evt) { - if (evt.which === 27 && scope.isOpen) { - evt.preventDefault(); - evt.stopPropagation(); - scope.$apply(function() { - scope.isOpen = false; - }); - element[0].focus(); - } else if (evt.which === 40 && !scope.isOpen) { - evt.preventDefault(); - evt.stopPropagation(); - scope.$apply(function() { - scope.isOpen = true; - }); - } - }; - element.bind("keydown", inputKeydownBind); - scope.keydown = function(evt) { - if (evt.which === 27) { - scope.isOpen = false; - element[0].focus(); - } - }; - scope.$watch("isOpen", function(value) { - if (value) { - scope.position = appendToBody ? $position.offset(element) : $position.position(element); - scope.position.top = scope.position.top + element.prop("offsetHeight"); - $timeout(function() { - if (onOpenFocus) { - scope.$broadcast("datepicker.focus"); + attrs.$observe(prefix + "Title", function(val) { + ttScope.title = val; + positionTooltip(); + }); + attrs.$observe(prefix + "Placement", function() { + if (ttScope.isOpen) { + prepPlacement(); + positionTooltip(); + } + }); + if (isOpenExp) { + scope.$watch(isOpenExp, function(val) { + if (val !== ttScope.isOpen) { + toggleTooltipBind(); + } + }); } - $document.bind("click", documentClickBind); - }, 0, false); - } else { - $document.unbind("click", documentClickBind); - } - }); - scope.select = function(date) { - if (date === "today") { - var today = new Date(); - if (angular.isDate(scope.date)) { - date = new Date(scope.date); - date.setFullYear(today.getFullYear(), today.getMonth(), today.getDate()); - } else { - date = new Date(today.setHours(0, 0, 0, 0)); - } - } - scope.dateSelection(date); - }; - scope.close = function() { - scope.isOpen = false; - element[0].focus(); - }; - var $popup = $compile(popupEl)(scope); - popupEl.remove(); - if (appendToBody) { - $document.find("body").append($popup); - } else { - element.after($popup); - } - scope.$on("$destroy", function() { - if (scope.isOpen === true) { - if (!$rootScope.$$phase) { - scope.$apply(function() { - scope.isOpen = false; + function prepPopupClass() { + ttScope.popupClass = attrs[prefix + "Class"]; + } + function prepPlacement() { + var val = attrs[prefix + "Placement"]; + ttScope.placement = angular.isDefined(val) ? val : options.placement; + } + function prepPopupDelay() { + var val = attrs[prefix + "PopupDelay"]; + var delay = parseInt(val, 10); + ttScope.popupDelay = !isNaN(delay) ? delay : options.popupDelay; + } + var unregisterTriggers = function() { + triggers.show.forEach(function(trigger) { + element.unbind(trigger, showTooltipBind); + }); + triggers.hide.forEach(function(trigger) { + element.unbind(trigger, hideTooltipBind); + }); + }; + function prepTriggers() { + var val = attrs[prefix + "Trigger"]; + unregisterTriggers(); + triggers = getTriggers(val); + if (triggers.show !== "none") { + triggers.show.forEach(function(trigger, idx) { + if (trigger === triggers.hide[idx]) { + element[0].addEventListener(trigger, toggleTooltipBind); + } else if (trigger) { + element[0].addEventListener(trigger, showTooltipBind); + element[0].addEventListener(triggers.hide[idx], hideTooltipBind); + } + }); + } + } + prepTriggers(); + var animation = scope.$eval(attrs[prefix + "Animation"]); + ttScope.animation = angular.isDefined(animation) ? !!animation : options.animation; + var appendToBodyVal = scope.$eval(attrs[prefix + "AppendToBody"]); + appendToBody = angular.isDefined(appendToBodyVal) ? appendToBodyVal : appendToBody; + if (appendToBody) { + scope.$on("$locationChangeSuccess", function closeTooltipOnLocationChangeSuccess() { + if (ttScope.isOpen) { + hide(); + } + }); + } + scope.$on("$destroy", function onDestroyTooltip() { + $timeout.cancel(transitionTimeout); + $timeout.cancel(popupTimeout); + $timeout.cancel(positionTimeout); + unregisterTriggers(); + removeTooltip(); + ttScope = null; }); - } + }; } - $popup.remove(); - element.unbind("keydown", inputKeydownBind); - $document.unbind("click", documentClickBind); - }); - } - }; -} ]).directive("datepickerPopupWrap", function() { + }; + }; + } ]; +}).directive("tooltipTemplateTransclude", [ "$animate", "$sce", "$compile", "$templateRequest", function($animate, $sce, $compile, $templateRequest) { return { - restrict: "EA", - replace: true, - transclude: true, - templateUrl: function(element, attrs) { - return attrs.templateUrl || "template/datepicker/popup.html"; - } - }; -}); - -angular.module("ui.bootstrap.dropdown", [ "ui.bootstrap.position" ]).constant("dropdownConfig", { - openClass: "open" -}).service("dropdownService", [ "$document", "$rootScope", function($document, $rootScope) { - var openScope = null; - this.open = function(dropdownScope) { - if (!openScope) { - $document.bind("click", closeDropdown); - $document.bind("keydown", keybindFilter); - } - if (openScope && openScope !== dropdownScope) { - openScope.isOpen = false; - } - openScope = dropdownScope; - }; - this.close = function(dropdownScope) { - if (openScope === dropdownScope) { - openScope = null; - $document.unbind("click", closeDropdown); - $document.unbind("keydown", keybindFilter); - } - }; - var closeDropdown = function(evt) { - if (!openScope) { - return; - } - if (evt && openScope.getAutoClose() === "disabled") { - return; - } - var toggleElement = openScope.getToggleElement(); - if (evt && toggleElement && toggleElement[0].contains(evt.target)) { - return; - } - var dropdownElement = openScope.getDropdownElement(); - if (evt && openScope.getAutoClose() === "outsideClick" && dropdownElement && dropdownElement[0].contains(evt.target)) { - return; - } - openScope.isOpen = false; - if (!$rootScope.$$phase) { - openScope.$apply(); - } - }; - var keybindFilter = function(evt) { - if (evt.which === 27) { - openScope.focusToggleElement(); - closeDropdown(); - } else if (openScope.isKeynavEnabled() && /(38|40)/.test(evt.which) && openScope.isOpen) { - evt.preventDefault(); - evt.stopPropagation(); - openScope.focusDropdownEntry(evt.which); - } - }; -} ]).controller("DropdownController", [ "$scope", "$attrs", "$parse", "dropdownConfig", "dropdownService", "$animate", "$position", "$document", "$compile", "$templateRequest", function($scope, $attrs, $parse, dropdownConfig, dropdownService, $animate, $position, $document, $compile, $templateRequest) { - var self = this, scope = $scope.$new(), templateScope, openClass = dropdownConfig.openClass, getIsOpen, setIsOpen = angular.noop, toggleInvoker = $attrs.onToggle ? $parse($attrs.onToggle) : angular.noop, appendToBody = false, keynavEnabled = false, selectedOption = null, body = $document.find("body"); - this.init = function(element) { - self.$element = element; - if ($attrs.isOpen) { - getIsOpen = $parse($attrs.isOpen); - setIsOpen = getIsOpen.assign; - $scope.$watch(getIsOpen, function(value) { - scope.isOpen = !!value; - }); - } - appendToBody = angular.isDefined($attrs.dropdownAppendToBody); - keynavEnabled = angular.isDefined($attrs.keyboardNav); - if (appendToBody && self.dropdownMenu) { - body.append(self.dropdownMenu); - body.addClass("dropdown"); - element.on("$destroy", function handleDestroyEvent() { - self.dropdownMenu.remove(); - }); - } - }; - this.toggle = function(open) { - return scope.isOpen = arguments.length ? !!open : !scope.isOpen; - }; - this.isOpen = function() { - return scope.isOpen; - }; - scope.getToggleElement = function() { - return self.toggleElement; - }; - scope.getAutoClose = function() { - return $attrs.autoClose || "always"; - }; - scope.getElement = function() { - return self.$element; - }; - scope.isKeynavEnabled = function() { - return keynavEnabled; - }; - scope.focusDropdownEntry = function(keyCode) { - var elems = self.dropdownMenu ? angular.element(self.dropdownMenu).find("a") : angular.element(self.$element).find("ul").eq(0).find("a"); - switch (keyCode) { - case 40: - { - if (!angular.isNumber(self.selectedOption)) { - self.selectedOption = 0; - } else { - self.selectedOption = self.selectedOption === elems.length - 1 ? self.selectedOption : self.selectedOption + 1; - } - break; - } - - case 38: - { - if (!angular.isNumber(self.selectedOption)) { - self.selectedOption = elems.length - 1; - } else { - self.selectedOption = self.selectedOption === 0 ? 0 : self.selectedOption - 1; - } - break; - } - } - elems[self.selectedOption].focus(); - }; - scope.getDropdownElement = function() { - return self.dropdownMenu; - }; - scope.focusToggleElement = function() { - if (self.toggleElement) { - self.toggleElement[0].focus(); - } - }; - scope.$watch("isOpen", function(isOpen, wasOpen) { - if (appendToBody && self.dropdownMenu) { - var pos = $position.positionElements(self.$element, self.dropdownMenu, "bottom-left", true); - var css = { - top: pos.top + "px", - display: isOpen ? "block" : "none" + link: function(scope, elem, attrs) { + var origScope = scope.$eval(attrs.tooltipTemplateTranscludeScope); + var changeCounter = 0, currentScope, previousElement, currentElement; + var cleanupLastIncludeContent = function() { + if (previousElement) { + previousElement.remove(); + previousElement = null; + } + if (currentScope) { + currentScope.$destroy(); + currentScope = null; + } + if (currentElement) { + $animate.leave(currentElement).then(function() { + previousElement = null; + }); + previousElement = currentElement; + currentElement = null; + } }; - var rightalign = self.dropdownMenu.hasClass("dropdown-menu-right"); - if (!rightalign) { - css.left = pos.left + "px"; - css.right = "auto"; - } else { - css.left = "auto"; - css.right = window.innerWidth - (pos.left + self.$element.prop("offsetWidth")) + "px"; - } - self.dropdownMenu.css(css); - } - var openContainer = appendToBody ? body : self.$element; - $animate[isOpen ? "addClass" : "removeClass"](openContainer, openClass).then(function() { - if (angular.isDefined(isOpen) && isOpen !== wasOpen) { - toggleInvoker($scope, { - open: !!isOpen - }); - } - }); - if (isOpen) { - if (self.dropdownMenuTemplateUrl) { - $templateRequest(self.dropdownMenuTemplateUrl).then(function(tplContent) { - templateScope = scope.$new(); - $compile(tplContent.trim())(templateScope, function(dropdownElement) { - var newEl = dropdownElement; - self.dropdownMenu.replaceWith(newEl); - self.dropdownMenu = newEl; + scope.$watch($sce.parseAsResourceUrl(attrs.tooltipTemplateTransclude), function(src) { + var thisChangeId = ++changeCounter; + if (src) { + $templateRequest(src, true).then(function(response) { + if (thisChangeId !== changeCounter) { + return; + } + var newScope = origScope.$new(); + var template = response; + var clone = $compile(template)(newScope, function(clone) { + cleanupLastIncludeContent(); + $animate.enter(clone, elem); + }); + currentScope = newScope; + currentElement = clone; + currentScope.$emit("$includeContentLoaded", src); + }, function() { + if (thisChangeId === changeCounter) { + cleanupLastIncludeContent(); + scope.$emit("$includeContentError", src); + } }); - }); - } - scope.focusToggleElement(); - dropdownService.open(scope); - } else { - if (self.dropdownMenuTemplateUrl) { - if (templateScope) { - templateScope.$destroy(); + scope.$emit("$includeContentRequested", src); + } else { + cleanupLastIncludeContent(); } - var newEl = angular.element(''); - self.dropdownMenu.replaceWith(newEl); - self.dropdownMenu = newEl; - } - dropdownService.close(scope); - self.selectedOption = null; - } - if (angular.isFunction(setIsOpen)) { - setIsOpen($scope, isOpen); - } - }); - $scope.$on("$locationChangeSuccess", function() { - if (scope.getAutoClose() !== "disabled") { - scope.isOpen = false; - } - }); - var offDestroy = $scope.$on("$destroy", function() { - scope.$destroy(); - }); - scope.$on("$destroy", offDestroy); -} ]).directive("dropdown", function() { - return { - controller: "DropdownController", - link: function(scope, element, attrs, dropdownCtrl) { - dropdownCtrl.init(element); - element.addClass("dropdown"); + }); + scope.$on("$destroy", cleanupLastIncludeContent); } }; -}).directive("dropdownMenu", function() { +} ]).directive("tooltipClasses", function() { return { - restrict: "AC", - require: "?^dropdown", - link: function(scope, element, attrs, dropdownCtrl) { - if (!dropdownCtrl) { - return; + restrict: "A", + link: function(scope, element, attrs) { + if (scope.placement) { + element.addClass(scope.placement); } - var tplUrl = attrs.templateUrl; - if (tplUrl) { - dropdownCtrl.dropdownMenuTemplateUrl = tplUrl; + if (scope.popupClass) { + element.addClass(scope.popupClass); } - if (!dropdownCtrl.dropdownMenu) { - dropdownCtrl.dropdownMenu = element; + if (scope.animation()) { + element.addClass(attrs.tooltipAnimationClass); } } }; -}).directive("keyboardNav", function() { +}).directive("tooltipPopup", function() { return { - restrict: "A", - require: "?^dropdown", - link: function(scope, element, attrs, dropdownCtrl) { - element.bind("keydown", function(e) { - if ([ 38, 40 ].indexOf(e.which) !== -1) { - e.preventDefault(); - e.stopPropagation(); - var elems = dropdownCtrl.dropdownMenu.find("a"); - switch (e.which) { - case 40: - { - if (!angular.isNumber(dropdownCtrl.selectedOption)) { - dropdownCtrl.selectedOption = 0; - } else { - dropdownCtrl.selectedOption = dropdownCtrl.selectedOption === elems.length - 1 ? dropdownCtrl.selectedOption : dropdownCtrl.selectedOption + 1; - } - break; - } - - case 38: - { - if (!angular.isNumber(dropdownCtrl.selectedOption)) { - dropdownCtrl.selectedOption = elems.length - 1; - } else { - dropdownCtrl.selectedOption = dropdownCtrl.selectedOption === 0 ? 0 : dropdownCtrl.selectedOption - 1; - } - break; - } - } - elems[dropdownCtrl.selectedOption].focus(); - } - }); - } + restrict: "EA", + replace: true, + scope: { + content: "@", + placement: "@", + popupClass: "@", + animation: "&", + isOpen: "&" + }, + templateUrl: "template/tooltip/tooltip-popup.html" }; -}).directive("dropdownToggle", function() { +}).directive("tooltip", [ "$tooltip", function($tooltip) { + return $tooltip("tooltip", "tooltip", "mouseenter"); +} ]).directive("tooltipTemplatePopup", function() { return { - require: "?^dropdown", - link: function(scope, element, attrs, dropdownCtrl) { - if (!dropdownCtrl) { - return; - } - element.addClass("dropdown-toggle"); - dropdownCtrl.toggleElement = element; - var toggleDropdown = function(event) { - event.preventDefault(); - if (!element.hasClass("disabled") && !attrs.disabled) { - scope.$apply(function() { - dropdownCtrl.toggle(); - }); - } - }; - element.bind("click", toggleDropdown); - element.attr({ - "aria-haspopup": true, - "aria-expanded": false - }); - scope.$watch(dropdownCtrl.isOpen, function(isOpen) { - element.attr("aria-expanded", !!isOpen); - }); - scope.$on("$destroy", function() { - element.unbind("click", toggleDropdown); - }); - } + restrict: "EA", + replace: true, + scope: { + contentExp: "&", + placement: "@", + popupClass: "@", + animation: "&", + isOpen: "&", + originScope: "&" + }, + templateUrl: "template/tooltip/tooltip-template-popup.html" }; -}); - -angular.module("ui.bootstrap.modal", []).factory("$$stackedMap", function() { - return { - createNew: function() { - var stack = []; - return { - add: function(key, value) { - stack.push({ - key: key, - value: value - }); - }, - get: function(key) { - for (var i = 0; i < stack.length; i++) { - if (key == stack[i].key) { - return stack[i]; - } - } - }, - keys: function() { - var keys = []; - for (var i = 0; i < stack.length; i++) { - keys.push(stack[i].key); - } - return keys; - }, - top: function() { - return stack[stack.length - 1]; - }, - remove: function(key) { - var idx = -1; - for (var i = 0; i < stack.length; i++) { - if (key == stack[i].key) { - idx = i; - break; - } - } - return stack.splice(idx, 1)[0]; - }, - removeTop: function() { - return stack.splice(stack.length - 1, 1)[0]; - }, - length: function() { - return stack.length; - } - }; - } +}).directive("tooltipTemplate", [ "$tooltip", function($tooltip) { + return $tooltip("tooltipTemplate", "tooltip", "mouseenter", { + useContentExp: true + }); +} ]).directive("tooltipHtmlPopup", function() { + return { + restrict: "EA", + replace: true, + scope: { + contentExp: "&", + placement: "@", + popupClass: "@", + animation: "&", + isOpen: "&" + }, + templateUrl: "template/tooltip/tooltip-html-popup.html" }; -}).factory("$$multiMap", function() { +}).directive("tooltipHtml", [ "$tooltip", function($tooltip) { + return $tooltip("tooltipHtml", "tooltip", "mouseenter", { + useContentExp: true + }); +} ]).directive("tooltipHtmlUnsafePopup", function() { return { - createNew: function() { - var map = {}; - return { - entries: function() { - return Object.keys(map).map(function(key) { - return { - key: key, - value: map[key] - }; - }); - }, - get: function(key) { - return map[key]; - }, - hasKey: function(key) { - return !!map[key]; - }, - keys: function() { - return Object.keys(map); - }, - put: function(key, value) { - if (!map[key]) { - map[key] = []; - } - map[key].push(value); - }, - remove: function(key, value) { - var values = map[key]; - if (!values) { - return; - } - var idx = values.indexOf(value); - if (idx !== -1) { - values.splice(idx, 1); - } - if (!values.length) { - delete map[key]; - } - } - }; - } + restrict: "EA", + replace: true, + scope: { + content: "@", + placement: "@", + popupClass: "@", + animation: "&", + isOpen: "&" + }, + templateUrl: "template/tooltip/tooltip-html-unsafe-popup.html" }; -}).directive("modalBackdrop", [ "$animate", "$injector", "$modalStack", function($animate, $injector, $modalStack) { - var $animateCss = null; - if ($injector.has("$animateCss")) { - $animateCss = $injector.get("$animateCss"); +}).value("tooltipHtmlUnsafeSuppressDeprecated", false).directive("tooltipHtmlUnsafe", [ "$tooltip", "tooltipHtmlUnsafeSuppressDeprecated", "$log", function($tooltip, tooltipHtmlUnsafeSuppressDeprecated, $log) { + if (!tooltipHtmlUnsafeSuppressDeprecated) { + $log.warn("tooltip-html-unsafe is now deprecated. Use tooltip-html or tooltip-template instead."); } + return $tooltip("tooltipHtmlUnsafe", "tooltip", "mouseenter"); +} ]); + +angular.module("ui.bootstrap.popover", [ "ui.bootstrap.tooltip" ]).directive("popoverTemplatePopup", function() { return { restrict: "EA", replace: true, - templateUrl: "template/modal/backdrop.html", - compile: function(tElement, tAttrs) { - tElement.addClass(tAttrs.backdropClass); - return linkFn; - } + scope: { + title: "@", + contentExp: "&", + placement: "@", + popupClass: "@", + animation: "&", + isOpen: "&", + originScope: "&" + }, + templateUrl: "template/popover/popover-template.html" }; - function linkFn(scope, element, attrs) { - if (attrs.modalInClass) { - if ($animateCss) { - $animateCss(element, { - addClass: attrs.modalInClass - }).start(); - } else { - $animate.addClass(element, attrs.modalInClass); - } - scope.$on($modalStack.NOW_CLOSING_EVENT, function(e, setIsAsync) { - var done = setIsAsync(); - if ($animateCss) { - $animateCss(element, { - removeClass: attrs.modalInClass - }).start().then(done); - } else { - $animate.removeClass(element, attrs.modalInClass).then(done); - } - }); - } - } -} ]).directive("modalWindow", [ "$modalStack", "$q", "$animate", "$injector", function($modalStack, $q, $animate, $injector) { - var $animateCss = null; - if ($injector.has("$animateCss")) { - $animateCss = $injector.get("$animateCss"); - } +}).directive("popoverTemplate", [ "$tooltip", function($tooltip) { + return $tooltip("popoverTemplate", "popover", "click", { + useContentExp: true + }); +} ]).directive("popoverHtmlPopup", function() { return { restrict: "EA", + replace: true, scope: { - index: "@" + contentExp: "&", + title: "@", + placement: "@", + popupClass: "@", + animation: "&", + isOpen: "&" }, + templateUrl: "template/popover/popover-html.html" + }; +}).directive("popoverHtml", [ "$tooltip", function($tooltip) { + return $tooltip("popoverHtml", "popover", "click", { + useContentExp: true + }); +} ]).directive("popoverPopup", function() { + return { + restrict: "EA", replace: true, - transclude: true, - templateUrl: function(tElement, tAttrs) { - return tAttrs.templateUrl || "template/modal/window.html"; + scope: { + title: "@", + content: "@", + placement: "@", + popupClass: "@", + animation: "&", + isOpen: "&" }, - link: function(scope, element, attrs) { - element.addClass(attrs.windowClass || ""); - scope.size = attrs.size; - scope.close = function(evt) { - var modal = $modalStack.getTop(); - if (modal && modal.value.backdrop && modal.value.backdrop !== "static" && evt.target === evt.currentTarget) { - evt.preventDefault(); - evt.stopPropagation(); - $modalStack.dismiss(modal.key, "backdrop click"); - } - }; - scope.$isRendered = true; - var modalRenderDeferObj = $q.defer(); - attrs.$observe("modalRender", function(value) { - if (value == "true") { - modalRenderDeferObj.resolve(); - } - }); - modalRenderDeferObj.promise.then(function() { - var animationPromise = null; - if (attrs.modalInClass) { - if ($animateCss) { - animationPromise = $animateCss(element, { - addClass: attrs.modalInClass - }).start(); - } else { - animationPromise = $animate.addClass(element, attrs.modalInClass); - } - scope.$on($modalStack.NOW_CLOSING_EVENT, function(e, setIsAsync) { - var done = setIsAsync(); - if ($animateCss) { - $animateCss(element, { - removeClass: attrs.modalInClass - }).start().then(done); - } else { - $animate.removeClass(element, attrs.modalInClass).then(done); - } - }); - } - $q.when(animationPromise).then(function() { - var inputsWithAutofocus = element[0].querySelectorAll("[autofocus]"); - if (inputsWithAutofocus.length) { - inputsWithAutofocus[0].focus(); - } else { - element[0].focus(); - } - }); - var modal = $modalStack.getTop(); - if (modal) { - $modalStack.modalRendered(modal.key); - } + templateUrl: "template/popover/popover.html" + }; +}).directive("popover", [ "$tooltip", function($tooltip) { + return $tooltip("popover", "popover", "click"); +} ]); + +angular.module("ui.bootstrap.progressbar", []).constant("progressConfig", { + animate: true, + max: 100 +}).value("$progressSuppressWarning", false).controller("ProgressController", [ "$scope", "$attrs", "progressConfig", function($scope, $attrs, progressConfig) { + var self = this, animate = angular.isDefined($attrs.animate) ? $scope.$parent.$eval($attrs.animate) : progressConfig.animate; + this.bars = []; + $scope.max = angular.isDefined($scope.max) ? $scope.max : progressConfig.max; + this.addBar = function(bar, element) { + if (!animate) { + element.css({ + transition: "none" }); } + this.bars.push(bar); + bar.max = $scope.max; + bar.$watch("value", function(value) { + bar.recalculatePercentage(); + }); + bar.recalculatePercentage = function() { + bar.percent = +(100 * bar.value / bar.max).toFixed(2); + var totalPercentage = self.bars.reduce(function(total, bar) { + return total + bar.percent; + }, 0); + if (totalPercentage > 100) { + bar.percent -= totalPercentage - 100; + } + }; + bar.$on("$destroy", function() { + element = null; + self.removeBar(bar); + }); + }; + this.removeBar = function(bar) { + this.bars.splice(this.bars.indexOf(bar), 1); + }; + $scope.$watch("max", function(max) { + self.bars.forEach(function(bar) { + bar.max = $scope.max; + bar.recalculatePercentage(); + }); + }); +} ]).directive("uibProgress", function() { + return { + restrict: "EA", + replace: true, + transclude: true, + controller: "ProgressController", + require: "uibProgress", + scope: { + max: "=?" + }, + templateUrl: "template/progressbar/progress.html" }; -} ]).directive("modalAnimationClass", [ function() { +}).directive("progress", [ "$log", "$progressSuppressWarning", function($log, $progressSuppressWarning) { return { - compile: function(tElement, tAttrs) { - if (tAttrs.modalAnimation) { - tElement.addClass(tAttrs.modalAnimationClass); + restrict: "EA", + replace: true, + transclude: true, + controller: "ProgressController", + require: "progress", + scope: { + max: "=?" + }, + templateUrl: "template/progressbar/progress.html", + link: function() { + if ($progressSuppressWarning) { + $log.warn("progress is now deprecated. Use uib-progress instead"); } } }; -} ]).directive("modalTransclude", function() { +} ]).directive("uibBar", function() { return { - link: function($scope, $element, $attrs, controller, $transclude) { - $transclude($scope.$parent, function(clone) { - $element.empty(); - $element.append(clone); - }); + restrict: "EA", + replace: true, + transclude: true, + require: "^uibProgress", + scope: { + value: "=", + type: "@" + }, + templateUrl: "template/progressbar/bar.html", + link: function(scope, element, attrs, progressCtrl) { + progressCtrl.addBar(scope, element); } }; -}).factory("$modalStack", [ "$animate", "$timeout", "$document", "$compile", "$rootScope", "$q", "$injector", "$$multiMap", "$$stackedMap", function($animate, $timeout, $document, $compile, $rootScope, $q, $injector, $$multiMap, $$stackedMap) { - var $animateCss = null; - if ($injector.has("$animateCss")) { - $animateCss = $injector.get("$animateCss"); - } - var OPENED_MODAL_CLASS = "modal-open"; - var backdropDomEl, backdropScope; - var openedWindows = $$stackedMap.createNew(); - var openedClasses = $$multiMap.createNew(); - var $modalStack = { - NOW_CLOSING_EVENT: "modal.stack.now-closing" - }; - var focusableElementList; - var focusIndex = 0; - var tababbleSelector = "a[href], area[href], input:not([disabled]), " + "button:not([disabled]),select:not([disabled]), textarea:not([disabled]), " + "iframe, object, embed, *[tabindex], *[contenteditable=true]"; - function backdropIndex() { - var topBackdropIndex = -1; - var opened = openedWindows.keys(); - for (var i = 0; i < opened.length; i++) { - if (openedWindows.get(opened[i]).value.backdrop) { - topBackdropIndex = i; +}).directive("bar", [ "$log", "$progressSuppressWarning", function($log, $progressSuppressWarning) { + return { + restrict: "EA", + replace: true, + transclude: true, + require: "^progress", + scope: { + value: "=", + type: "@" + }, + templateUrl: "template/progressbar/bar.html", + link: function(scope, element, attrs, progressCtrl) { + if ($progressSuppressWarning) { + $log.warn("bar is now deprecated. Use uib-bar instead"); } + progressCtrl.addBar(scope, element); } - return topBackdropIndex; - } - $rootScope.$watch(backdropIndex, function(newBackdropIndex) { - if (backdropScope) { - backdropScope.index = newBackdropIndex; + }; +} ]).directive("progressbar", function() { + return { + restrict: "EA", + replace: true, + transclude: true, + controller: "ProgressController", + scope: { + value: "=", + max: "=?", + type: "@" + }, + templateUrl: "template/progressbar/progressbar.html", + link: function(scope, element, attrs, progressCtrl) { + progressCtrl.addBar(scope, angular.element(element.children()[0])); } - }); - function removeModalWindow(modalInstance, elementToReceiveFocus) { - var body = $document.find("body").eq(0); - var modalWindow = openedWindows.get(modalInstance).value; - openedWindows.remove(modalInstance); - removeAfterAnimate(modalWindow.modalDomEl, modalWindow.modalScope, function() { - var modalBodyClass = modalWindow.openedClass || OPENED_MODAL_CLASS; - openedClasses.remove(modalBodyClass, modalInstance); - body.toggleClass(modalBodyClass, openedClasses.hasKey(modalBodyClass)); + }; +}); + +angular.module("ui.bootstrap.rating", []).constant("ratingConfig", { + max: 5, + stateOn: null, + stateOff: null, + titles: [ "one", "two", "three", "four", "five" ] +}).controller("RatingController", [ "$scope", "$attrs", "ratingConfig", function($scope, $attrs, ratingConfig) { + var ngModelCtrl = { + $setViewValue: angular.noop + }; + this.init = function(ngModelCtrl_) { + ngModelCtrl = ngModelCtrl_; + ngModelCtrl.$render = this.render; + ngModelCtrl.$formatters.push(function(value) { + if (angular.isNumber(value) && value << 0 !== value) { + value = Math.round(value); + } + return value; }); - checkRemoveBackdrop(); - if (elementToReceiveFocus && elementToReceiveFocus.focus) { - elementToReceiveFocus.focus(); + this.stateOn = angular.isDefined($attrs.stateOn) ? $scope.$parent.$eval($attrs.stateOn) : ratingConfig.stateOn; + this.stateOff = angular.isDefined($attrs.stateOff) ? $scope.$parent.$eval($attrs.stateOff) : ratingConfig.stateOff; + var tmpTitles = angular.isDefined($attrs.titles) ? $scope.$parent.$eval($attrs.titles) : ratingConfig.titles; + this.titles = angular.isArray(tmpTitles) && tmpTitles.length > 0 ? tmpTitles : ratingConfig.titles; + var ratingStates = angular.isDefined($attrs.ratingStates) ? $scope.$parent.$eval($attrs.ratingStates) : new Array(angular.isDefined($attrs.max) ? $scope.$parent.$eval($attrs.max) : ratingConfig.max); + $scope.range = this.buildTemplateObjects(ratingStates); + }; + this.buildTemplateObjects = function(states) { + for (var i = 0, n = states.length; i < n; i++) { + states[i] = angular.extend({ + index: i + }, { + stateOn: this.stateOn, + stateOff: this.stateOff, + title: this.getTitle(i) + }, states[i]); + } + return states; + }; + this.getTitle = function(index) { + if (index >= this.titles.length) { + return index + 1; } else { - body.focus(); + return this.titles[index]; } - } - function checkRemoveBackdrop() { - if (backdropDomEl && backdropIndex() == -1) { - var backdropScopeRef = backdropScope; - removeAfterAnimate(backdropDomEl, backdropScope, function() { - backdropScopeRef = null; - }); - backdropDomEl = undefined; - backdropScope = undefined; + }; + $scope.rate = function(value) { + if (!$scope.readonly && value >= 0 && value <= $scope.range.length) { + ngModelCtrl.$setViewValue(ngModelCtrl.$viewValue === value ? 0 : value); + ngModelCtrl.$render(); } - } - function removeAfterAnimate(domEl, scope, done) { - var asyncDeferred; - var asyncPromise = null; - var setIsAsync = function() { - if (!asyncDeferred) { - asyncDeferred = $q.defer(); - asyncPromise = asyncDeferred.promise; - } - return function asyncDone() { - asyncDeferred.resolve(); - }; - }; - scope.$broadcast($modalStack.NOW_CLOSING_EVENT, setIsAsync); - return $q.when(asyncPromise).then(afterAnimating); - function afterAnimating() { - if (afterAnimating.done) { - return; - } - afterAnimating.done = true; - if ($animateCss) { - $animateCss(domEl, { - event: "leave" - }).start().then(function() { - domEl.remove(); - }); - } else { - $animate.leave(domEl); - } - scope.$destroy(); - if (done) { - done(); - } + }; + $scope.enter = function(value) { + if (!$scope.readonly) { + $scope.value = value; } - } - $document.bind("keydown", function(evt) { - if (evt.isDefaultPrevented()) { - return evt; + $scope.onHover({ + value: value + }); + }; + $scope.reset = function() { + $scope.value = ngModelCtrl.$viewValue; + $scope.onLeave(); + }; + $scope.onKeydown = function(evt) { + if (/(37|38|39|40)/.test(evt.which)) { + evt.preventDefault(); + evt.stopPropagation(); + $scope.rate($scope.value + (evt.which === 38 || evt.which === 39 ? 1 : -1)); } - var modal = openedWindows.top(); - if (modal && modal.value.keyboard) { - switch (evt.which) { - case 27: - { - evt.preventDefault(); - $rootScope.$apply(function() { - $modalStack.dismiss(modal.key, "escape key press"); - }); - break; - } + }; + this.render = function() { + $scope.value = ngModelCtrl.$viewValue; + }; +} ]).directive("rating", function() { + return { + restrict: "EA", + require: [ "rating", "ngModel" ], + scope: { + readonly: "=?", + onHover: "&", + onLeave: "&" + }, + controller: "RatingController", + templateUrl: "template/rating/rating.html", + replace: true, + link: function(scope, element, attrs, ctrls) { + var ratingCtrl = ctrls[0], ngModelCtrl = ctrls[1]; + ratingCtrl.init(ngModelCtrl); + } + }; +}); - case 9: - { - $modalStack.loadFocusElementList(modal); - var focusChanged = false; - if (evt.shiftKey) { - if ($modalStack.isFocusInFirstItem(evt)) { - focusChanged = $modalStack.focusLastFocusableElement(); - } - } else { - if ($modalStack.isFocusInLastItem(evt)) { - focusChanged = $modalStack.focusFirstFocusableElement(); - } - } - if (focusChanged) { - evt.preventDefault(); - evt.stopPropagation(); - } - break; - } +angular.module("ui.bootstrap.tabs", []).controller("TabsetController", [ "$scope", function TabsetCtrl($scope) { + var ctrl = this, tabs = ctrl.tabs = $scope.tabs = []; + ctrl.select = function(selectedTab) { + angular.forEach(tabs, function(tab) { + if (tab.active && tab !== selectedTab) { + tab.active = false; + tab.onDeselect(); + selectedTab.selectCalled = false; } - } - }); - $modalStack.open = function(modalInstance, modal) { - var modalOpener = $document[0].activeElement, modalBodyClass = modal.openedClass || OPENED_MODAL_CLASS; - openedWindows.add(modalInstance, { - deferred: modal.deferred, - renderDeferred: modal.renderDeferred, - modalScope: modal.scope, - backdrop: modal.backdrop, - keyboard: modal.keyboard, - openedClass: modal.openedClass }); - openedClasses.put(modalBodyClass, modalInstance); - var body = $document.find("body").eq(0), currBackdropIndex = backdropIndex(); - if (currBackdropIndex >= 0 && !backdropDomEl) { - backdropScope = $rootScope.$new(true); - backdropScope.index = currBackdropIndex; - var angularBackgroundDomEl = angular.element('
        '); - angularBackgroundDomEl.attr("backdrop-class", modal.backdropClass); - if (modal.animation) { - angularBackgroundDomEl.attr("modal-animation", "true"); - } - backdropDomEl = $compile(angularBackgroundDomEl)(backdropScope); - body.append(backdropDomEl); + selectedTab.active = true; + if (!selectedTab.selectCalled) { + selectedTab.onSelect(); + selectedTab.selectCalled = true; } - var angularDomEl = angular.element('
        '); - angularDomEl.attr({ - "template-url": modal.windowTemplateUrl, - "window-class": modal.windowClass, - size: modal.size, - index: openedWindows.length() - 1, - animate: "animate" - }).html(modal.content); - if (modal.animation) { - angularDomEl.attr("modal-animation", "true"); + }; + ctrl.addTab = function addTab(tab) { + tabs.push(tab); + if (tabs.length === 1 && tab.active !== false) { + tab.active = true; + } else if (tab.active) { + ctrl.select(tab); + } else { + tab.active = false; } - var modalDomEl = $compile(angularDomEl)(modal.scope); - openedWindows.top().value.modalDomEl = modalDomEl; - openedWindows.top().value.modalOpener = modalOpener; - body.append(modalDomEl); - body.addClass(modalBodyClass); - $modalStack.clearFocusListCache(); }; - function broadcastClosing(modalWindow, resultOrReason, closing) { - return !modalWindow.value.modalScope.$broadcast("modal.closing", resultOrReason, closing).defaultPrevented; - } - $modalStack.close = function(modalInstance, result) { - var modalWindow = openedWindows.get(modalInstance); - if (modalWindow && broadcastClosing(modalWindow, result, true)) { - modalWindow.value.modalScope.$$uibDestructionScheduled = true; - modalWindow.value.deferred.resolve(result); - removeModalWindow(modalInstance, modalWindow.value.modalOpener); - return true; + ctrl.removeTab = function removeTab(tab) { + var index = tabs.indexOf(tab); + if (tab.active && tabs.length > 1 && !destroyed) { + var newActiveIndex = index == tabs.length - 1 ? index - 1 : index + 1; + ctrl.select(tabs[newActiveIndex]); } - return !modalWindow; + tabs.splice(index, 1); }; - $modalStack.dismiss = function(modalInstance, reason) { - var modalWindow = openedWindows.get(modalInstance); - if (modalWindow && broadcastClosing(modalWindow, reason, false)) { - modalWindow.value.modalScope.$$uibDestructionScheduled = true; - modalWindow.value.deferred.reject(reason); - removeModalWindow(modalInstance, modalWindow.value.modalOpener); - return true; + var destroyed; + $scope.$on("$destroy", function() { + destroyed = true; + }); +} ]).directive("tabset", function() { + return { + restrict: "EA", + transclude: true, + replace: true, + scope: { + type: "@" + }, + controller: "TabsetController", + templateUrl: "template/tabs/tabset.html", + link: function(scope, element, attrs) { + scope.vertical = angular.isDefined(attrs.vertical) ? scope.$parent.$eval(attrs.vertical) : false; + scope.justified = angular.isDefined(attrs.justified) ? scope.$parent.$eval(attrs.justified) : false; } - return !modalWindow; }; - $modalStack.dismissAll = function(reason) { - var topModal = this.getTop(); - while (topModal && this.dismiss(topModal.key, reason)) { - topModal = this.getTop(); +}).directive("tab", [ "$parse", "$log", function($parse, $log) { + return { + require: "^tabset", + restrict: "EA", + replace: true, + templateUrl: "template/tabs/tab.html", + transclude: true, + scope: { + active: "=?", + heading: "@", + onSelect: "&select", + onDeselect: "&deselect" + }, + controller: function() {}, + link: function(scope, elm, attrs, tabsetCtrl, transclude) { + scope.$watch("active", function(active) { + if (active) { + tabsetCtrl.select(scope); + } + }); + scope.disabled = false; + if (attrs.disable) { + scope.$parent.$watch($parse(attrs.disable), function(value) { + scope.disabled = !!value; + }); + } + if (attrs.disabled) { + $log.warn('Use of "disabled" attribute has been deprecated, please use "disable"'); + scope.$parent.$watch($parse(attrs.disabled), function(value) { + scope.disabled = !!value; + }); + } + scope.select = function() { + if (!scope.disabled) { + scope.active = true; + } + }; + tabsetCtrl.addTab(scope); + scope.$on("$destroy", function() { + tabsetCtrl.removeTab(scope); + }); + scope.$transcludeFn = transclude; } }; - $modalStack.getTop = function() { - return openedWindows.top(); +} ]).directive("tabHeadingTransclude", function() { + return { + restrict: "A", + require: "^tab", + link: function(scope, elm, attrs, tabCtrl) { + scope.$watch("headingElement", function updateHeadingElement(heading) { + if (heading) { + elm.html(""); + elm.append(heading); + } + }); + } }; - $modalStack.modalRendered = function(modalInstance) { - var modalWindow = openedWindows.get(modalInstance); - if (modalWindow) { - modalWindow.value.renderDeferred.resolve(); +}).directive("tabContentTransclude", function() { + return { + restrict: "A", + require: "^tabset", + link: function(scope, elm, attrs) { + var tab = scope.$eval(attrs.tabContentTransclude); + tab.$transcludeFn(tab.$parent, function(contents) { + angular.forEach(contents, function(node) { + if (isTabHeading(node)) { + tab.headingElement = node; + } else { + elm.append(node); + } + }); + }); + } + }; + function isTabHeading(node) { + return node.tagName && (node.hasAttribute("tab-heading") || node.hasAttribute("data-tab-heading") || node.hasAttribute("x-tab-heading") || node.tagName.toLowerCase() === "tab-heading" || node.tagName.toLowerCase() === "data-tab-heading" || node.tagName.toLowerCase() === "x-tab-heading"); + } +}); + +angular.module("ui.bootstrap.timepicker", []).constant("timepickerConfig", { + hourStep: 1, + minuteStep: 1, + showMeridian: true, + meridians: null, + readonlyInput: false, + mousewheel: true, + arrowkeys: true, + showSpinners: true +}).controller("TimepickerController", [ "$scope", "$attrs", "$parse", "$log", "$locale", "timepickerConfig", function($scope, $attrs, $parse, $log, $locale, timepickerConfig) { + var selected = new Date(), ngModelCtrl = { + $setViewValue: angular.noop + }, meridians = angular.isDefined($attrs.meridians) ? $scope.$parent.$eval($attrs.meridians) : timepickerConfig.meridians || $locale.DATETIME_FORMATS.AMPMS; + this.init = function(ngModelCtrl_, inputs) { + ngModelCtrl = ngModelCtrl_; + ngModelCtrl.$render = this.render; + ngModelCtrl.$formatters.unshift(function(modelValue) { + return modelValue ? new Date(modelValue) : null; + }); + var hoursInputEl = inputs.eq(0), minutesInputEl = inputs.eq(1); + var mousewheel = angular.isDefined($attrs.mousewheel) ? $scope.$parent.$eval($attrs.mousewheel) : timepickerConfig.mousewheel; + if (mousewheel) { + this.setupMousewheelEvents(hoursInputEl, minutesInputEl); + } + var arrowkeys = angular.isDefined($attrs.arrowkeys) ? $scope.$parent.$eval($attrs.arrowkeys) : timepickerConfig.arrowkeys; + if (arrowkeys) { + this.setupArrowkeyEvents(hoursInputEl, minutesInputEl); } + $scope.readonlyInput = angular.isDefined($attrs.readonlyInput) ? $scope.$parent.$eval($attrs.readonlyInput) : timepickerConfig.readonlyInput; + this.setupInputEvents(hoursInputEl, minutesInputEl); + }; + var hourStep = timepickerConfig.hourStep; + if ($attrs.hourStep) { + $scope.$parent.$watch($parse($attrs.hourStep), function(value) { + hourStep = parseInt(value, 10); + }); + } + var minuteStep = timepickerConfig.minuteStep; + if ($attrs.minuteStep) { + $scope.$parent.$watch($parse($attrs.minuteStep), function(value) { + minuteStep = parseInt(value, 10); + }); + } + var min; + $scope.$parent.$watch($parse($attrs.min), function(value) { + var dt = new Date(value); + min = isNaN(dt) ? undefined : dt; + }); + var max; + $scope.$parent.$watch($parse($attrs.max), function(value) { + var dt = new Date(value); + max = isNaN(dt) ? undefined : dt; + }); + $scope.noIncrementHours = function() { + var incrementedSelected = addMinutes(selected, hourStep * 60); + return incrementedSelected > max || incrementedSelected < selected && incrementedSelected < min; }; - $modalStack.focusFirstFocusableElement = function() { - if (focusableElementList.length > 0) { - focusableElementList[0].focus(); - return true; - } - return false; + $scope.noDecrementHours = function() { + var decrementedSelected = addMinutes(selected, -hourStep * 60); + return decrementedSelected < min || decrementedSelected > selected && decrementedSelected > max; }; - $modalStack.focusLastFocusableElement = function() { - if (focusableElementList.length > 0) { - focusableElementList[focusableElementList.length - 1].focus(); - return true; - } - return false; + $scope.noIncrementMinutes = function() { + var incrementedSelected = addMinutes(selected, minuteStep); + return incrementedSelected > max || incrementedSelected < selected && incrementedSelected < min; }; - $modalStack.isFocusInFirstItem = function(evt) { - if (focusableElementList.length > 0) { - return (evt.target || evt.srcElement) == focusableElementList[0]; - } - return false; + $scope.noDecrementMinutes = function() { + var decrementedSelected = addMinutes(selected, -minuteStep); + return decrementedSelected < min || decrementedSelected > selected && decrementedSelected > max; }; - $modalStack.isFocusInLastItem = function(evt) { - if (focusableElementList.length > 0) { - return (evt.target || evt.srcElement) == focusableElementList[focusableElementList.length - 1]; + $scope.noToggleMeridian = function() { + if (selected.getHours() < 13) { + return addMinutes(selected, 12 * 60) > max; + } else { + return addMinutes(selected, -12 * 60) < min; } - return false; - }; - $modalStack.clearFocusListCache = function() { - focusableElementList = []; - focusIndex = 0; }; - $modalStack.loadFocusElementList = function(modalWindow) { - if (focusableElementList === undefined || !focusableElementList.length0) { - if (modalWindow) { - var modalDomE1 = modalWindow.value.modalDomEl; - if (modalDomE1 && modalDomE1.length) { - focusableElementList = modalDomE1[0].querySelectorAll(tababbleSelector); + $scope.showMeridian = timepickerConfig.showMeridian; + if ($attrs.showMeridian) { + $scope.$parent.$watch($parse($attrs.showMeridian), function(value) { + $scope.showMeridian = !!value; + if (ngModelCtrl.$error.time) { + var hours = getHoursFromTemplate(), minutes = getMinutesFromTemplate(); + if (angular.isDefined(hours) && angular.isDefined(minutes)) { + selected.setHours(hours); + refresh(); } + } else { + updateTemplate(); + } + }); + } + function getHoursFromTemplate() { + var hours = parseInt($scope.hours, 10); + var valid = $scope.showMeridian ? hours > 0 && hours < 13 : hours >= 0 && hours < 24; + if (!valid) { + return undefined; + } + if ($scope.showMeridian) { + if (hours === 12) { + hours = 0; + } + if ($scope.meridian === meridians[1]) { + hours = hours + 12; } } + return hours; + } + function getMinutesFromTemplate() { + var minutes = parseInt($scope.minutes, 10); + return minutes >= 0 && minutes < 60 ? minutes : undefined; + } + function pad(value) { + return angular.isDefined(value) && value.toString().length < 2 ? "0" + value : value.toString(); + } + this.setupMousewheelEvents = function(hoursInputEl, minutesInputEl) { + var isScrollingUp = function(e) { + if (e.originalEvent) { + e = e.originalEvent; + } + var delta = e.wheelDelta ? e.wheelDelta : -e.deltaY; + return e.detail || delta > 0; + }; + hoursInputEl.bind("mousewheel wheel", function(e) { + $scope.$apply(isScrollingUp(e) ? $scope.incrementHours() : $scope.decrementHours()); + e.preventDefault(); + }); + minutesInputEl.bind("mousewheel wheel", function(e) { + $scope.$apply(isScrollingUp(e) ? $scope.incrementMinutes() : $scope.decrementMinutes()); + e.preventDefault(); + }); }; - return $modalStack; -} ]).provider("$modal", function() { - var $modalProvider = { - options: { - animation: true, - backdrop: true, - keyboard: true - }, - $get: [ "$injector", "$rootScope", "$q", "$templateRequest", "$controller", "$modalStack", function($injector, $rootScope, $q, $templateRequest, $controller, $modalStack) { - var $modal = {}; - function getTemplatePromise(options) { - return options.template ? $q.when(options.template) : $templateRequest(angular.isFunction(options.templateUrl) ? options.templateUrl() : options.templateUrl); + this.setupArrowkeyEvents = function(hoursInputEl, minutesInputEl) { + hoursInputEl.bind("keydown", function(e) { + if (e.which === 38) { + e.preventDefault(); + $scope.incrementHours(); + $scope.$apply(); + } else if (e.which === 40) { + e.preventDefault(); + $scope.decrementHours(); + $scope.$apply(); } - function getResolvePromises(resolves) { - var promisesArr = []; - angular.forEach(resolves, function(value) { - if (angular.isFunction(value) || angular.isArray(value)) { - promisesArr.push($q.when($injector.invoke(value))); - } else if (angular.isString(value)) { - promisesArr.push($q.when($injector.get(value))); - } else { - promisesArr.push($q.when(value)); - } - }); - return promisesArr; + }); + minutesInputEl.bind("keydown", function(e) { + if (e.which === 38) { + e.preventDefault(); + $scope.incrementMinutes(); + $scope.$apply(); + } else if (e.which === 40) { + e.preventDefault(); + $scope.decrementMinutes(); + $scope.$apply(); } - var promiseChain = null; - $modal.getPromiseChain = function() { - return promiseChain; - }; - $modal.open = function(modalOptions) { - var modalResultDeferred = $q.defer(); - var modalOpenedDeferred = $q.defer(); - var modalRenderDeferred = $q.defer(); - var modalInstance = { - result: modalResultDeferred.promise, - opened: modalOpenedDeferred.promise, - rendered: modalRenderDeferred.promise, - close: function(result) { - return $modalStack.close(modalInstance, result); - }, - dismiss: function(reason) { - return $modalStack.dismiss(modalInstance, reason); - } - }; - modalOptions = angular.extend({}, $modalProvider.options, modalOptions); - modalOptions.resolve = modalOptions.resolve || {}; - if (!modalOptions.template && !modalOptions.templateUrl) { - throw new Error("One of template or templateUrl options is required."); - } - var templateAndResolvePromise = $q.all([ getTemplatePromise(modalOptions) ].concat(getResolvePromises(modalOptions.resolve))); - var samePromise; - samePromise = promiseChain = $q.all([ promiseChain ]).then(function() { - return templateAndResolvePromise; - }, function() { - return templateAndResolvePromise; - }).then(function resolveSuccess(tplAndVars) { - var modalScope = (modalOptions.scope || $rootScope).$new(); - modalScope.$close = modalInstance.close; - modalScope.$dismiss = modalInstance.dismiss; - modalScope.$on("$destroy", function() { - if (!modalScope.$$uibDestructionScheduled) { - modalScope.$dismiss("$uibUnscheduledDestruction"); - } - }); - var ctrlInstance, ctrlLocals = {}; - var resolveIter = 1; - if (modalOptions.controller) { - ctrlLocals.$scope = modalScope; - ctrlLocals.$modalInstance = modalInstance; - angular.forEach(modalOptions.resolve, function(value, key) { - ctrlLocals[key] = tplAndVars[resolveIter++]; - }); - ctrlInstance = $controller(modalOptions.controller, ctrlLocals); - if (modalOptions.controllerAs) { - if (modalOptions.bindToController) { - angular.extend(ctrlInstance, modalScope); - } - modalScope[modalOptions.controllerAs] = ctrlInstance; - } - } - $modalStack.open(modalInstance, { - scope: modalScope, - deferred: modalResultDeferred, - renderDeferred: modalRenderDeferred, - content: tplAndVars[0], - animation: modalOptions.animation, - backdrop: modalOptions.backdrop, - keyboard: modalOptions.keyboard, - backdropClass: modalOptions.backdropClass, - windowClass: modalOptions.windowClass, - windowTemplateUrl: modalOptions.windowTemplateUrl, - size: modalOptions.size, - openedClass: modalOptions.openedClass - }); - modalOpenedDeferred.resolve(true); - }, function resolveError(reason) { - modalOpenedDeferred.reject(reason); - modalResultDeferred.reject(reason); - }).finally(function() { - if (promiseChain === samePromise) { - promiseChain = null; - } - }); - return modalInstance; - }; - return $modal; - } ] + }); }; - return $modalProvider; -}); - -angular.module("ui.bootstrap.pagination", []).controller("PaginationController", [ "$scope", "$attrs", "$parse", function($scope, $attrs, $parse) { - var self = this, ngModelCtrl = { - $setViewValue: angular.noop - }, setNumPages = $attrs.numPages ? $parse($attrs.numPages).assign : angular.noop; - this.init = function(ngModelCtrl_, config) { - ngModelCtrl = ngModelCtrl_; - this.config = config; - ngModelCtrl.$render = function() { - self.render(); + this.setupInputEvents = function(hoursInputEl, minutesInputEl) { + if ($scope.readonlyInput) { + $scope.updateHours = angular.noop; + $scope.updateMinutes = angular.noop; + return; + } + var invalidate = function(invalidHours, invalidMinutes) { + ngModelCtrl.$setViewValue(null); + ngModelCtrl.$setValidity("time", false); + if (angular.isDefined(invalidHours)) { + $scope.invalidHours = invalidHours; + } + if (angular.isDefined(invalidMinutes)) { + $scope.invalidMinutes = invalidMinutes; + } }; - if ($attrs.itemsPerPage) { - $scope.$parent.$watch($parse($attrs.itemsPerPage), function(value) { - self.itemsPerPage = parseInt(value, 10); - $scope.totalPages = self.calculateTotalPages(); - }); - } else { - this.itemsPerPage = config.itemsPerPage; - } - $scope.$watch("totalItems", function() { - $scope.totalPages = self.calculateTotalPages(); + $scope.updateHours = function() { + var hours = getHoursFromTemplate(), minutes = getMinutesFromTemplate(); + if (angular.isDefined(hours) && angular.isDefined(minutes)) { + selected.setHours(hours); + if (selected < min || selected > max) { + invalidate(true); + } else { + refresh("h"); + } + } else { + invalidate(true); + } + }; + hoursInputEl.bind("blur", function(e) { + if (!$scope.invalidHours && $scope.hours < 10) { + $scope.$apply(function() { + $scope.hours = pad($scope.hours); + }); + } }); - $scope.$watch("totalPages", function(value) { - setNumPages($scope.$parent, value); - if ($scope.page > value) { - $scope.selectPage(value); + $scope.updateMinutes = function() { + var minutes = getMinutesFromTemplate(), hours = getHoursFromTemplate(); + if (angular.isDefined(minutes) && angular.isDefined(hours)) { + selected.setMinutes(minutes); + if (selected < min || selected > max) { + invalidate(undefined, true); + } else { + refresh("m"); + } } else { - ngModelCtrl.$render(); + invalidate(undefined, true); + } + }; + minutesInputEl.bind("blur", function(e) { + if (!$scope.invalidMinutes && $scope.minutes < 10) { + $scope.$apply(function() { + $scope.minutes = pad($scope.minutes); + }); } }); }; - this.calculateTotalPages = function() { - var totalPages = this.itemsPerPage < 1 ? 1 : Math.ceil($scope.totalItems / this.itemsPerPage); - return Math.max(totalPages || 0, 1); - }; this.render = function() { - $scope.page = parseInt(ngModelCtrl.$viewValue, 10) || 1; + var date = ngModelCtrl.$viewValue; + if (isNaN(date)) { + ngModelCtrl.$setValidity("time", false); + $log.error('Timepicker directive: "ng-model" value must be a Date object, a number of milliseconds since 01.01.1970 or a string representing an RFC2822 or ISO 8601 date.'); + } else { + if (date) { + selected = date; + } + if (selected < min || selected > max) { + ngModelCtrl.$setValidity("time", false); + $scope.invalidHours = true; + $scope.invalidMinutes = true; + } else { + makeValid(); + } + updateTemplate(); + } }; - $scope.selectPage = function(page, evt) { - if (evt) { - evt.preventDefault(); + function refresh(keyboardChange) { + makeValid(); + ngModelCtrl.$setViewValue(new Date(selected)); + updateTemplate(keyboardChange); + } + function makeValid() { + ngModelCtrl.$setValidity("time", true); + $scope.invalidHours = false; + $scope.invalidMinutes = false; + } + function updateTemplate(keyboardChange) { + var hours = selected.getHours(), minutes = selected.getMinutes(); + if ($scope.showMeridian) { + hours = hours === 0 || hours === 12 ? 12 : hours % 12; } - var clickAllowed = !$scope.ngDisabled || !evt; - if (clickAllowed && $scope.page !== page && page > 0 && page <= $scope.totalPages) { - if (evt && evt.target) { - evt.target.blur(); - } - ngModelCtrl.$setViewValue(page); - ngModelCtrl.$render(); + $scope.hours = keyboardChange === "h" ? hours : pad(hours); + if (keyboardChange !== "m") { + $scope.minutes = pad(minutes); + } + $scope.meridian = selected.getHours() < 12 ? meridians[0] : meridians[1]; + } + function addMinutes(date, minutes) { + var dt = new Date(date.getTime() + minutes * 6e4); + var newDate = new Date(date); + newDate.setHours(dt.getHours(), dt.getMinutes()); + return newDate; + } + function addMinutesToSelected(minutes) { + selected = addMinutes(selected, minutes); + refresh(); + } + $scope.showSpinners = angular.isDefined($attrs.showSpinners) ? $scope.$parent.$eval($attrs.showSpinners) : timepickerConfig.showSpinners; + $scope.incrementHours = function() { + if (!$scope.noIncrementHours()) { + addMinutesToSelected(hourStep * 60); } }; - $scope.getText = function(key) { - return $scope[key + "Text"] || self.config[key + "Text"]; + $scope.decrementHours = function() { + if (!$scope.noDecrementHours()) { + addMinutesToSelected(-hourStep * 60); + } }; - $scope.noPrevious = function() { - return $scope.page === 1; + $scope.incrementMinutes = function() { + if (!$scope.noIncrementMinutes()) { + addMinutesToSelected(minuteStep); + } }; - $scope.noNext = function() { - return $scope.page === $scope.totalPages; + $scope.decrementMinutes = function() { + if (!$scope.noDecrementMinutes()) { + addMinutesToSelected(-minuteStep); + } }; -} ]).constant("paginationConfig", { - itemsPerPage: 10, - boundaryLinks: false, - directionLinks: true, - firstText: "First", - previousText: "Previous", - nextText: "Next", - lastText: "Last", - rotate: true -}).directive("pagination", [ "$parse", "paginationConfig", function($parse, paginationConfig) { - return { - restrict: "EA", - scope: { - totalItems: "=", - firstText: "@", - previousText: "@", - nextText: "@", - lastText: "@", - ngDisabled: "=" - }, - require: [ "pagination", "?ngModel" ], - controller: "PaginationController", - controllerAs: "pagination", - templateUrl: function(element, attrs) { - return attrs.templateUrl || "template/pagination/pagination.html"; - }, - replace: true, - link: function(scope, element, attrs, ctrls) { - var paginationCtrl = ctrls[0], ngModelCtrl = ctrls[1]; - if (!ngModelCtrl) { - return; - } - var maxSize = angular.isDefined(attrs.maxSize) ? scope.$parent.$eval(attrs.maxSize) : paginationConfig.maxSize, rotate = angular.isDefined(attrs.rotate) ? scope.$parent.$eval(attrs.rotate) : paginationConfig.rotate; - scope.boundaryLinks = angular.isDefined(attrs.boundaryLinks) ? scope.$parent.$eval(attrs.boundaryLinks) : paginationConfig.boundaryLinks; - scope.directionLinks = angular.isDefined(attrs.directionLinks) ? scope.$parent.$eval(attrs.directionLinks) : paginationConfig.directionLinks; - paginationCtrl.init(ngModelCtrl, paginationConfig); - if (attrs.maxSize) { - scope.$parent.$watch($parse(attrs.maxSize), function(value) { - maxSize = parseInt(value, 10); - paginationCtrl.render(); - }); - } - function makePage(number, text, isActive) { - return { - number: number, - text: text, - active: isActive - }; - } - function getPages(currentPage, totalPages) { - var pages = []; - var startPage = 1, endPage = totalPages; - var isMaxSized = angular.isDefined(maxSize) && maxSize < totalPages; - if (isMaxSized) { - if (rotate) { - startPage = Math.max(currentPage - Math.floor(maxSize / 2), 1); - endPage = startPage + maxSize - 1; - if (endPage > totalPages) { - endPage = totalPages; - startPage = endPage - maxSize + 1; - } - } else { - startPage = (Math.ceil(currentPage / maxSize) - 1) * maxSize + 1; - endPage = Math.min(startPage + maxSize - 1, totalPages); - } - } - for (var number = startPage; number <= endPage; number++) { - var page = makePage(number, number, number === currentPage); - pages.push(page); - } - if (isMaxSized && !rotate) { - if (startPage > 1) { - var previousPageSet = makePage(startPage - 1, "...", false); - pages.unshift(previousPageSet); - } - if (endPage < totalPages) { - var nextPageSet = makePage(endPage + 1, "...", false); - pages.push(nextPageSet); - } - } - return pages; - } - var originalRender = paginationCtrl.render; - paginationCtrl.render = function() { - originalRender(); - if (scope.page > 0 && scope.page <= scope.totalPages) { - scope.pages = getPages(scope.page, scope.totalPages); - } - }; + $scope.toggleMeridian = function() { + if (!$scope.noToggleMeridian()) { + addMinutesToSelected(12 * 60 * (selected.getHours() < 12 ? 1 : -1)); } }; -} ]).constant("pagerConfig", { - itemsPerPage: 10, - previousText: "« Previous", - nextText: "Next »", - align: true -}).directive("pager", [ "pagerConfig", function(pagerConfig) { +} ]).directive("timepicker", function() { return { restrict: "EA", - scope: { - totalItems: "=", - previousText: "@", - nextText: "@", - ngDisabled: "=" - }, - require: [ "pager", "?ngModel" ], - controller: "PaginationController", - controllerAs: "pagination", + require: [ "timepicker", "?^ngModel" ], + controller: "TimepickerController", + controllerAs: "timepicker", + replace: true, + scope: {}, templateUrl: function(element, attrs) { - return attrs.templateUrl || "template/pagination/pager.html"; + return attrs.templateUrl || "template/timepicker/timepicker.html"; }, - replace: true, link: function(scope, element, attrs, ctrls) { - var paginationCtrl = ctrls[0], ngModelCtrl = ctrls[1]; - if (!ngModelCtrl) { - return; + var timepickerCtrl = ctrls[0], ngModelCtrl = ctrls[1]; + if (ngModelCtrl) { + timepickerCtrl.init(ngModelCtrl, element.find("input")); } - scope.align = angular.isDefined(attrs.align) ? scope.$parent.$eval(attrs.align) : pagerConfig.align; - paginationCtrl.init(ngModelCtrl, pagerConfig); } }; -} ]); +}); -angular.module("ui.bootstrap.tooltip", [ "ui.bootstrap.position", "ui.bootstrap.bindHtml" ]).provider("$tooltip", function() { - var defaultOptions = { - placement: "top", - animation: true, - popupDelay: 0, - useContentExp: false - }; - var triggerMap = { - mouseenter: "mouseleave", - click: "click", - focus: "blur", - none: "" +angular.module("ui.bootstrap.transition", []).value("$transitionSuppressDeprecated", false).factory("$transition", [ "$q", "$timeout", "$rootScope", "$log", "$transitionSuppressDeprecated", function($q, $timeout, $rootScope, $log, $transitionSuppressDeprecated) { + if (!$transitionSuppressDeprecated) { + $log.warn("$transition is now deprecated. Use $animate from ngAnimate instead."); + } + var $transition = function(element, trigger, options) { + options = options || {}; + var deferred = $q.defer(); + var endEventName = $transition[options.animation ? "animationEndEventName" : "transitionEndEventName"]; + var transitionEndHandler = function(event) { + $rootScope.$apply(function() { + element.unbind(endEventName, transitionEndHandler); + deferred.resolve(element); + }); + }; + if (endEventName) { + element.bind(endEventName, transitionEndHandler); + } + $timeout(function() { + if (angular.isString(trigger)) { + element.addClass(trigger); + } else if (angular.isFunction(trigger)) { + trigger(element); + } else if (angular.isObject(trigger)) { + element.css(trigger); + } + if (!endEventName) { + deferred.resolve(element); + } + }); + deferred.promise.cancel = function() { + if (endEventName) { + element.unbind(endEventName, transitionEndHandler); + } + deferred.reject("Transition cancelled"); + }; + return deferred.promise; }; - var globalOptions = {}; - this.options = function(value) { - angular.extend(globalOptions, value); + var transElement = document.createElement("trans"); + var transitionEndEventNames = { + WebkitTransition: "webkitTransitionEnd", + MozTransition: "transitionend", + OTransition: "oTransitionEnd", + transition: "transitionend" }; - this.setTriggers = function setTriggers(triggers) { - angular.extend(triggerMap, triggers); + var animationEndEventNames = { + WebkitTransition: "webkitAnimationEnd", + MozTransition: "animationend", + OTransition: "oAnimationEnd", + transition: "animationend" }; - function snake_case(name) { - var regexp = /[A-Z]/g; - var separator = "-"; - return name.replace(regexp, function(letter, pos) { - return (pos ? separator : "") + letter.toLowerCase(); - }); + function findEndEventName(endEventNames) { + for (var name in endEventNames) { + if (transElement.style[name] !== undefined) { + return endEventNames[name]; + } + } } - this.$get = [ "$window", "$compile", "$timeout", "$document", "$position", "$interpolate", "$rootScope", "$parse", function($window, $compile, $timeout, $document, $position, $interpolate, $rootScope, $parse) { - return function $tooltip(type, prefix, defaultTriggerShow, options) { - options = angular.extend({}, defaultOptions, globalOptions, options); - function getTriggers(trigger) { - var show = (trigger || options.trigger || defaultTriggerShow).split(" "); - var hide = show.map(function(trigger) { - return triggerMap[trigger] || trigger; - }); - return { - show: show, - hide: hide - }; + $transition.transitionEndEventName = findEndEventName(transitionEndEventNames); + $transition.animationEndEventName = findEndEventName(animationEndEventNames); + return $transition; +} ]); + +angular.module("ui.bootstrap.typeahead", [ "ui.bootstrap.position" ]).factory("typeaheadParser", [ "$parse", function($parse) { + var TYPEAHEAD_REGEXP = /^\s*([\s\S]+?)(?:\s+as\s+([\s\S]+?))?\s+for\s+(?:([\$\w][\$\w\d]*))\s+in\s+([\s\S]+?)$/; + return { + parse: function(input) { + var match = input.match(TYPEAHEAD_REGEXP); + if (!match) { + throw new Error('Expected typeahead specification in form of "_modelValue_ (as _label_)? for _item_ in _collection_"' + ' but got "' + input + '".'); } - var directiveName = snake_case(type); - var startSym = $interpolate.startSymbol(); - var endSym = $interpolate.endSymbol(); - var template = "
        " + "
        "; return { - restrict: "EA", - compile: function(tElem, tAttrs) { - var tooltipLinker = $compile(template); - return function link(scope, element, attrs, tooltipCtrl) { - var tooltip; - var tooltipLinkedScope; - var transitionTimeout; - var popupTimeout; - var positionTimeout; - var appendToBody = angular.isDefined(options.appendToBody) ? options.appendToBody : false; - var triggers = getTriggers(undefined); - var hasEnableExp = angular.isDefined(attrs[prefix + "Enable"]); - var ttScope = scope.$new(true); - var repositionScheduled = false; - var isOpenExp = angular.isDefined(attrs[prefix + "IsOpen"]) ? $parse(attrs[prefix + "IsOpen"]) : false; - var positionTooltip = function() { - if (!tooltip) { - return; - } - if (!positionTimeout) { - positionTimeout = $timeout(function() { - tooltip.css({ - top: 0, - left: 0, - width: "auto", - height: "auto" - }); - var ttBox = $position.position(tooltip); - var ttCss = $position.positionElements(element, tooltip, ttScope.placement, appendToBody); - ttCss.top += "px"; - ttCss.left += "px"; - ttCss.width = ttBox.width + "px"; - ttCss.height = ttBox.height + "px"; - tooltip.css(ttCss); - positionTimeout = null; - }, 0, false); - } - }; - ttScope.origScope = scope; - ttScope.isOpen = false; - function toggleTooltipBind() { - if (!ttScope.isOpen) { - showTooltipBind(); - } else { - hideTooltipBind(); - } - } - function showTooltipBind() { - if (hasEnableExp && !scope.$eval(attrs[prefix + "Enable"])) { - return; - } - prepareTooltip(); - if (ttScope.popupDelay) { - if (!popupTimeout) { - popupTimeout = $timeout(show, ttScope.popupDelay, false); - } - } else { - show(); - } - } - function hideTooltipBind() { - hide(); - if (!$rootScope.$$phase) { - $rootScope.$digest(); - } - } - function show() { - popupTimeout = null; - if (transitionTimeout) { - $timeout.cancel(transitionTimeout); - transitionTimeout = null; - } - if (!(options.useContentExp ? ttScope.contentExp() : ttScope.content)) { - return angular.noop; - } - createTooltip(); - ttScope.isOpen = true; - if (isOpenExp) { - isOpenExp.assign(ttScope.origScope, ttScope.isOpen); - } - if (!$rootScope.$$phase) { - ttScope.$apply(); - } - tooltip.css({ - display: "block" - }); - positionTooltip(); - } - function hide() { - ttScope.isOpen = false; - if (isOpenExp) { - isOpenExp.assign(ttScope.origScope, ttScope.isOpen); - } - $timeout.cancel(popupTimeout); - popupTimeout = null; - $timeout.cancel(positionTimeout); - positionTimeout = null; - if (ttScope.animation) { - if (!transitionTimeout) { - transitionTimeout = $timeout(removeTooltip, 500); - } - } else { - removeTooltip(); - } - } - function createTooltip() { - if (tooltip) { - removeTooltip(); - } - tooltipLinkedScope = ttScope.$new(); - tooltip = tooltipLinker(tooltipLinkedScope, function(tooltip) { - if (appendToBody) { - $document.find("body").append(tooltip); - } else { - element.after(tooltip); - } - }); - if (options.useContentExp) { - tooltipLinkedScope.$watch("contentExp()", function(val) { - if (!val && ttScope.isOpen) { - hide(); - } - }); - tooltipLinkedScope.$watch(function() { - if (!repositionScheduled) { - repositionScheduled = true; - tooltipLinkedScope.$$postDigest(function() { - repositionScheduled = false; - if (ttScope.isOpen) { - positionTooltip(); - } - }); - } + itemName: match[3], + source: $parse(match[4]), + viewMapper: $parse(match[2] || match[1]), + modelMapper: $parse(match[1]) + }; + } + }; +} ]).directive("typeahead", [ "$compile", "$parse", "$q", "$timeout", "$document", "$window", "$rootScope", "$position", "typeaheadParser", function($compile, $parse, $q, $timeout, $document, $window, $rootScope, $position, typeaheadParser) { + var HOT_KEYS = [ 9, 13, 27, 38, 40 ]; + var eventDebounceTime = 200; + return { + require: [ "ngModel", "^?ngModelOptions" ], + link: function(originalScope, element, attrs, ctrls) { + var modelCtrl = ctrls[0]; + var ngModelOptions = ctrls[1]; + var minLength = originalScope.$eval(attrs.typeaheadMinLength); + if (!minLength && minLength !== 0) { + minLength = 1; + } + var waitTime = originalScope.$eval(attrs.typeaheadWaitMs) || 0; + var isEditable = originalScope.$eval(attrs.typeaheadEditable) !== false; + var isLoadingSetter = $parse(attrs.typeaheadLoading).assign || angular.noop; + var onSelectCallback = $parse(attrs.typeaheadOnSelect); + var isSelectOnBlur = angular.isDefined(attrs.typeaheadSelectOnBlur) ? originalScope.$eval(attrs.typeaheadSelectOnBlur) : false; + var isNoResultsSetter = $parse(attrs.typeaheadNoResults).assign || angular.noop; + var inputFormatter = attrs.typeaheadInputFormatter ? $parse(attrs.typeaheadInputFormatter) : undefined; + var appendToBody = attrs.typeaheadAppendToBody ? originalScope.$eval(attrs.typeaheadAppendToBody) : false; + var focusFirst = originalScope.$eval(attrs.typeaheadFocusFirst) !== false; + var selectOnExact = attrs.typeaheadSelectOnExact ? originalScope.$eval(attrs.typeaheadSelectOnExact) : false; + var parsedModel = $parse(attrs.ngModel); + var invokeModelSetter = $parse(attrs.ngModel + "($$$p)"); + var $setModelValue = function(scope, newValue) { + if (angular.isFunction(parsedModel(originalScope)) && ngModelOptions && ngModelOptions.$options && ngModelOptions.$options.getterSetter) { + return invokeModelSetter(scope, { + $$$p: newValue + }); + } else { + return parsedModel.assign(scope, newValue); + } + }; + var parserResult = typeaheadParser.parse(attrs.typeahead); + var hasFocus; + var selected; + var scope = originalScope.$new(); + var offDestroy = originalScope.$on("$destroy", function() { + scope.$destroy(); + }); + scope.$on("$destroy", offDestroy); + var popupId = "typeahead-" + scope.$id + "-" + Math.floor(Math.random() * 1e4); + element.attr({ + "aria-autocomplete": "list", + "aria-expanded": false, + "aria-owns": popupId + }); + var popUpEl = angular.element("
        "); + popUpEl.attr({ + id: popupId, + matches: "matches", + active: "activeIdx", + select: "select(activeIdx)", + "move-in-progress": "moveInProgress", + query: "query", + position: "position" + }); + if (angular.isDefined(attrs.typeaheadTemplateUrl)) { + popUpEl.attr("template-url", attrs.typeaheadTemplateUrl); + } + if (angular.isDefined(attrs.typeaheadPopupTemplateUrl)) { + popUpEl.attr("popup-template-url", attrs.typeaheadPopupTemplateUrl); + } + var resetMatches = function() { + scope.matches = []; + scope.activeIdx = -1; + element.attr("aria-expanded", false); + }; + var getMatchId = function(index) { + return popupId + "-option-" + index; + }; + scope.$watch("activeIdx", function(index) { + if (index < 0) { + element.removeAttr("aria-activedescendant"); + } else { + element.attr("aria-activedescendant", getMatchId(index)); + } + }); + var inputIsExactMatch = function(inputValue, index) { + if (scope.matches.length > index && inputValue) { + return inputValue.toUpperCase() === scope.matches[index].label.toUpperCase(); + } + return false; + }; + var getMatchesAsync = function(inputValue) { + var locals = { + $viewValue: inputValue + }; + isLoadingSetter(originalScope, true); + isNoResultsSetter(originalScope, false); + $q.when(parserResult.source(originalScope, locals)).then(function(matches) { + var onCurrentRequest = inputValue === modelCtrl.$viewValue; + if (onCurrentRequest && hasFocus) { + if (matches && matches.length > 0) { + scope.activeIdx = focusFirst ? 0 : -1; + isNoResultsSetter(originalScope, false); + scope.matches.length = 0; + for (var i = 0; i < matches.length; i++) { + locals[parserResult.itemName] = matches[i]; + scope.matches.push({ + id: getMatchId(i), + label: parserResult.viewMapper(scope, locals), + model: matches[i] }); } - } - function removeTooltip() { - transitionTimeout = null; - if (tooltip) { - tooltip.remove(); - tooltip = null; - } - if (tooltipLinkedScope) { - tooltipLinkedScope.$destroy(); - tooltipLinkedScope = null; - } - } - function prepareTooltip() { - prepPopupClass(); - prepPlacement(); - prepPopupDelay(); - } - ttScope.contentExp = function() { - return scope.$eval(attrs[type]); - }; - if (!options.useContentExp) { - attrs.$observe(type, function(val) { - ttScope.content = val; - if (!val && ttScope.isOpen) { - hide(); - } else { - positionTooltip(); - } - }); - } - attrs.$observe("disabled", function(val) { - if (popupTimeout && val) { - $timeout.cancel(popupTimeout); - popupTimeout = null; - } - if (val && ttScope.isOpen) { - hide(); - } - }); - attrs.$observe(prefix + "Title", function(val) { - ttScope.title = val; - positionTooltip(); - }); - attrs.$observe(prefix + "Placement", function() { - if (ttScope.isOpen) { - prepPlacement(); - positionTooltip(); - } - }); - if (isOpenExp) { - scope.$watch(isOpenExp, function(val) { - if (val !== ttScope.isOpen) { - toggleTooltipBind(); - } - }); - } - function prepPopupClass() { - ttScope.popupClass = attrs[prefix + "Class"]; - } - function prepPlacement() { - var val = attrs[prefix + "Placement"]; - ttScope.placement = angular.isDefined(val) ? val : options.placement; - } - function prepPopupDelay() { - var val = attrs[prefix + "PopupDelay"]; - var delay = parseInt(val, 10); - ttScope.popupDelay = !isNaN(delay) ? delay : options.popupDelay; - } - var unregisterTriggers = function() { - triggers.show.forEach(function(trigger) { - element.unbind(trigger, showTooltipBind); - }); - triggers.hide.forEach(function(trigger) { - element.unbind(trigger, hideTooltipBind); - }); - }; - function prepTriggers() { - var val = attrs[prefix + "Trigger"]; - unregisterTriggers(); - triggers = getTriggers(val); - if (triggers.show !== "none") { - triggers.show.forEach(function(trigger, idx) { - if (trigger === triggers.hide[idx]) { - element[0].addEventListener(trigger, toggleTooltipBind); - } else if (trigger) { - element[0].addEventListener(trigger, showTooltipBind); - element[0].addEventListener(triggers.hide[idx], hideTooltipBind); - } - }); + scope.query = inputValue; + recalculatePosition(); + element.attr("aria-expanded", true); + if (selectOnExact && scope.matches.length === 1 && inputIsExactMatch(inputValue, 0)) { + scope.select(0); } + } else { + resetMatches(); + isNoResultsSetter(originalScope, true); } - prepTriggers(); - var animation = scope.$eval(attrs[prefix + "Animation"]); - ttScope.animation = angular.isDefined(animation) ? !!animation : options.animation; - var appendToBodyVal = scope.$eval(attrs[prefix + "AppendToBody"]); - appendToBody = angular.isDefined(appendToBodyVal) ? appendToBodyVal : appendToBody; - if (appendToBody) { - scope.$on("$locationChangeSuccess", function closeTooltipOnLocationChangeSuccess() { - if (ttScope.isOpen) { - hide(); - } - }); - } - scope.$on("$destroy", function onDestroyTooltip() { - $timeout.cancel(transitionTimeout); - $timeout.cancel(popupTimeout); - $timeout.cancel(positionTimeout); - unregisterTriggers(); - removeTooltip(); - ttScope = null; - }); - }; + } + if (onCurrentRequest) { + isLoadingSetter(originalScope, false); + } + }, function() { + resetMatches(); + isLoadingSetter(originalScope, false); + isNoResultsSetter(originalScope, true); + }); + }; + if (appendToBody) { + angular.element($window).bind("resize", fireRecalculating); + $document.find("body").bind("scroll", fireRecalculating); + } + var timeoutEventPromise; + scope.moveInProgress = false; + function fireRecalculating() { + if (!scope.moveInProgress) { + scope.moveInProgress = true; + scope.$digest(); + } + if (timeoutEventPromise) { + $timeout.cancel(timeoutEventPromise); + } + timeoutEventPromise = $timeout(function() { + if (scope.matches.length) { + recalculatePosition(); + } + scope.moveInProgress = false; + scope.$digest(); + }, eventDebounceTime); + } + function recalculatePosition() { + scope.position = appendToBody ? $position.offset(element) : $position.position(element); + scope.position.top += element.prop("offsetHeight"); + } + resetMatches(); + scope.query = undefined; + var timeoutPromise; + var scheduleSearchWithTimeout = function(inputValue) { + timeoutPromise = $timeout(function() { + getMatchesAsync(inputValue); + }, waitTime); + }; + var cancelPreviousTimeout = function() { + if (timeoutPromise) { + $timeout.cancel(timeoutPromise); + } + }; + modelCtrl.$parsers.unshift(function(inputValue) { + hasFocus = true; + if (minLength === 0 || inputValue && inputValue.length >= minLength) { + if (waitTime > 0) { + cancelPreviousTimeout(); + scheduleSearchWithTimeout(inputValue); + } else { + getMatchesAsync(inputValue); + } + } else { + isLoadingSetter(originalScope, false); + cancelPreviousTimeout(); + resetMatches(); + } + if (isEditable) { + return inputValue; + } else { + if (!inputValue) { + modelCtrl.$setValidity("editable", true); + return null; + } else { + modelCtrl.$setValidity("editable", false); + return undefined; + } + } + }); + modelCtrl.$formatters.push(function(modelValue) { + var candidateViewValue, emptyViewValue; + var locals = {}; + if (!isEditable) { + modelCtrl.$setValidity("editable", true); + } + if (inputFormatter) { + locals.$model = modelValue; + return inputFormatter(originalScope, locals); + } else { + locals[parserResult.itemName] = modelValue; + candidateViewValue = parserResult.viewMapper(originalScope, locals); + locals[parserResult.itemName] = undefined; + emptyViewValue = parserResult.viewMapper(originalScope, locals); + return candidateViewValue !== emptyViewValue ? candidateViewValue : modelValue; + } + }); + scope.select = function(activeIdx) { + var locals = {}; + var model, item; + selected = true; + locals[parserResult.itemName] = item = scope.matches[activeIdx].model; + model = parserResult.modelMapper(originalScope, locals); + $setModelValue(originalScope, model); + modelCtrl.$setValidity("editable", true); + modelCtrl.$setValidity("parse", true); + onSelectCallback(originalScope, { + $item: item, + $model: model, + $label: parserResult.viewMapper(originalScope, locals) + }); + resetMatches(); + if (scope.$eval(attrs.typeaheadFocusOnSelect) !== false) { + $timeout(function() { + element[0].focus(); + }, 0, false); + } + }; + element.bind("keydown", function(evt) { + if (scope.matches.length === 0 || HOT_KEYS.indexOf(evt.which) === -1) { + return; + } + if (scope.activeIdx === -1 && (evt.which === 9 || evt.which === 13)) { + resetMatches(); + scope.$digest(); + return; + } + evt.preventDefault(); + if (evt.which === 40) { + scope.activeIdx = (scope.activeIdx + 1) % scope.matches.length; + scope.$digest(); + } else if (evt.which === 38) { + scope.activeIdx = (scope.activeIdx > 0 ? scope.activeIdx : scope.matches.length) - 1; + scope.$digest(); + } else if (evt.which === 13 || evt.which === 9) { + scope.$apply(function() { + scope.select(scope.activeIdx); + }); + } else if (evt.which === 27) { + evt.stopPropagation(); + resetMatches(); + scope.$digest(); + } + }); + element.bind("blur", function() { + if (isSelectOnBlur && scope.matches.length && scope.activeIdx !== -1 && !selected) { + selected = true; + scope.$apply(function() { + scope.select(scope.activeIdx); + }); + } + hasFocus = false; + selected = false; + }); + var dismissClickHandler = function(evt) { + if (element[0] !== evt.target && evt.which !== 3 && scope.matches.length !== 0) { + resetMatches(); + if (!$rootScope.$$phase) { + scope.$digest(); + } + } + }; + $document.bind("click", dismissClickHandler); + originalScope.$on("$destroy", function() { + $document.unbind("click", dismissClickHandler); + if (appendToBody) { + $popup.remove(); + } + popUpEl.remove(); + }); + var $popup = $compile(popUpEl)(scope); + if (appendToBody) { + $document.find("body").append($popup); + } else { + element.after($popup); + } + } + }; +} ]).directive("typeaheadPopup", function() { + return { + restrict: "EA", + scope: { + matches: "=", + query: "=", + active: "=", + position: "&", + moveInProgress: "=", + select: "&" + }, + replace: true, + templateUrl: function(element, attrs) { + return attrs.popupTemplateUrl || "template/typeahead/typeahead-popup.html"; + }, + link: function(scope, element, attrs) { + scope.templateUrl = attrs.templateUrl; + scope.isOpen = function() { + return scope.matches.length > 0; + }; + scope.isActive = function(matchIdx) { + return scope.active == matchIdx; + }; + scope.selectActive = function(matchIdx) { + scope.active = matchIdx; + }; + scope.selectMatch = function(activeIdx) { + scope.select({ + activeIdx: activeIdx + }); + }; + } + }; +}).directive("typeaheadMatch", [ "$templateRequest", "$compile", "$parse", function($templateRequest, $compile, $parse) { + return { + restrict: "EA", + scope: { + index: "=", + match: "=", + query: "=" + }, + link: function(scope, element, attrs) { + var tplUrl = $parse(attrs.templateUrl)(scope.$parent) || "template/typeahead/typeahead-match.html"; + $templateRequest(tplUrl).then(function(tplContent) { + $compile(tplContent.trim())(scope, function(clonedElement) { + element.replaceWith(clonedElement); + }); + }); + } + }; +} ]).filter("typeaheadHighlight", [ "$sce", "$injector", "$log", function($sce, $injector, $log) { + var isSanitizePresent; + isSanitizePresent = $injector.has("$sanitize"); + function escapeRegexp(queryToEscape) { + return queryToEscape.replace(/([.?*+^$[\]\\(){}|-])/g, "\\$1"); + } + function containsHtml(matchItem) { + return /<.*>/g.test(matchItem); + } + return function(matchItem, query) { + if (!isSanitizePresent && containsHtml(matchItem)) { + $log.warn("Unsafe use of typeahead please use ngSanitize"); + } + matchItem = query ? ("" + matchItem).replace(new RegExp(escapeRegexp(query), "gi"), "$&") : matchItem; + if (!isSanitizePresent) { + matchItem = $sce.trustAsHtml(matchItem); + } + return matchItem; + }; +} ]); + +!angular.$$csp() && angular.element(document).find("head").prepend(''); + +angular.module("ui.bootstrap", [ "ui.bootstrap.tpls", "ui.bootstrap.collapse", "ui.bootstrap.accordion", "ui.bootstrap.alert", "ui.bootstrap.bindHtml", "ui.bootstrap.buttons", "ui.bootstrap.carousel", "ui.bootstrap.dateparser", "ui.bootstrap.position", "ui.bootstrap.datepicker", "ui.bootstrap.dropdown", "ui.bootstrap.modal", "ui.bootstrap.pagination", "ui.bootstrap.tooltip", "ui.bootstrap.popover", "ui.bootstrap.progressbar", "ui.bootstrap.rating", "ui.bootstrap.tabs", "ui.bootstrap.timepicker", "ui.bootstrap.transition", "ui.bootstrap.typeahead" ]); + +angular.module("ui.bootstrap.tpls", [ "template/accordion/accordion-group.html", "template/accordion/accordion.html", "template/alert/alert.html", "template/carousel/carousel.html", "template/carousel/slide.html", "template/datepicker/datepicker.html", "template/datepicker/day.html", "template/datepicker/month.html", "template/datepicker/popup.html", "template/datepicker/year.html", "template/modal/backdrop.html", "template/modal/window.html", "template/pagination/pager.html", "template/pagination/pagination.html", "template/tooltip/tooltip-html-popup.html", "template/tooltip/tooltip-html-unsafe-popup.html", "template/tooltip/tooltip-popup.html", "template/tooltip/tooltip-template-popup.html", "template/popover/popover-html.html", "template/popover/popover-template.html", "template/popover/popover.html", "template/progressbar/bar.html", "template/progressbar/progress.html", "template/progressbar/progressbar.html", "template/rating/rating.html", "template/tabs/tab.html", "template/tabs/tabset.html", "template/timepicker/timepicker.html", "template/typeahead/typeahead-match.html", "template/typeahead/typeahead-popup.html" ]); + +angular.module("ui.bootstrap.collapse", []).directive("collapse", [ "$animate", function($animate) { + return { + link: function(scope, element, attrs) { + function expand() { + element.removeClass("collapse").addClass("collapsing").attr("aria-expanded", true).attr("aria-hidden", false); + $animate.addClass(element, "in", { + to: { + height: element[0].scrollHeight + "px" + } + }).then(expandDone); + } + function expandDone() { + element.removeClass("collapsing"); + element.css({ + height: "auto" + }); + } + function collapse() { + if (!element.hasClass("collapse") && !element.hasClass("in")) { + return collapseDone(); + } + element.css({ + height: element[0].scrollHeight + "px" + }).removeClass("collapse").addClass("collapsing").attr("aria-expanded", false).attr("aria-hidden", true); + $animate.removeClass(element, "in", { + to: { + height: "0" + } + }).then(collapseDone); + } + function collapseDone() { + element.css({ + height: "0" + }); + element.removeClass("collapsing"); + element.addClass("collapse"); + } + scope.$watch(attrs.collapse, function(shouldCollapse) { + if (shouldCollapse) { + collapse(); + } else { + expand(); + } + }); + } + }; +} ]); + +angular.module("ui.bootstrap.accordion", [ "ui.bootstrap.collapse" ]).constant("accordionConfig", { + closeOthers: true +}).controller("AccordionController", [ "$scope", "$attrs", "accordionConfig", function($scope, $attrs, accordionConfig) { + this.groups = []; + this.closeOthers = function(openGroup) { + var closeOthers = angular.isDefined($attrs.closeOthers) ? $scope.$eval($attrs.closeOthers) : accordionConfig.closeOthers; + if (closeOthers) { + angular.forEach(this.groups, function(group) { + if (group !== openGroup) { + group.isOpen = false; } + }); + } + }; + this.addGroup = function(groupScope) { + var that = this; + this.groups.push(groupScope); + groupScope.$on("$destroy", function(event) { + that.removeGroup(groupScope); + }); + }; + this.removeGroup = function(group) { + var index = this.groups.indexOf(group); + if (index !== -1) { + this.groups.splice(index, 1); + } + }; +} ]).directive("accordion", function() { + return { + restrict: "EA", + controller: "AccordionController", + controllerAs: "accordion", + transclude: true, + replace: false, + templateUrl: function(element, attrs) { + return attrs.templateUrl || "template/accordion/accordion.html"; + } + }; +}).directive("accordionGroup", function() { + return { + require: "^accordion", + restrict: "EA", + transclude: true, + replace: true, + templateUrl: function(element, attrs) { + return attrs.templateUrl || "template/accordion/accordion-group.html"; + }, + scope: { + heading: "@", + isOpen: "=?", + isDisabled: "=?" + }, + controller: function() { + this.setHeading = function(element) { + this.heading = element; }; - }; - } ]; -}).directive("tooltipTemplateTransclude", [ "$animate", "$sce", "$compile", "$templateRequest", function($animate, $sce, $compile, $templateRequest) { + }, + link: function(scope, element, attrs, accordionCtrl) { + accordionCtrl.addGroup(scope); + scope.openClass = attrs.openClass || "panel-open"; + scope.panelClass = attrs.panelClass; + scope.$watch("isOpen", function(value) { + element.toggleClass(scope.openClass, value); + if (value) { + accordionCtrl.closeOthers(scope); + } + }); + scope.toggleOpen = function($event) { + if (!scope.isDisabled) { + if (!$event || $event.which === 32) { + scope.isOpen = !scope.isOpen; + } + } + }; + } + }; +}).directive("accordionHeading", function() { + return { + restrict: "EA", + transclude: true, + template: "", + replace: true, + require: "^accordionGroup", + link: function(scope, element, attr, accordionGroupCtrl, transclude) { + accordionGroupCtrl.setHeading(transclude(scope, angular.noop)); + } + }; +}).directive("accordionTransclude", function() { + return { + require: "^accordionGroup", + link: function(scope, element, attr, controller) { + scope.$watch(function() { + return controller[attr.accordionTransclude]; + }, function(heading) { + if (heading) { + element.find("span").html(""); + element.find("span").append(heading); + } + }); + } + }; +}); + +angular.module("ui.bootstrap.alert", []).controller("AlertController", [ "$scope", "$attrs", function($scope, $attrs) { + $scope.closeable = !!$attrs.close; + this.close = $scope.close; +} ]).directive("alert", function() { + return { + controller: "AlertController", + controllerAs: "alert", + templateUrl: function(element, attrs) { + return attrs.templateUrl || "template/alert/alert.html"; + }, + transclude: true, + replace: true, + scope: { + type: "@", + close: "&" + } + }; +}).directive("dismissOnTimeout", [ "$timeout", function($timeout) { + return { + require: "alert", + link: function(scope, element, attrs, alertCtrl) { + $timeout(function() { + alertCtrl.close(); + }, parseInt(attrs.dismissOnTimeout, 10)); + } + }; +} ]); + +angular.module("ui.bootstrap.bindHtml", []).value("$bindHtmlUnsafeSuppressDeprecated", false).directive("bindHtmlUnsafe", [ "$log", "$bindHtmlUnsafeSuppressDeprecated", function($log, $bindHtmlUnsafeSuppressDeprecated) { + return function(scope, element, attr) { + if (!$bindHtmlUnsafeSuppressDeprecated) { + $log.warn("bindHtmlUnsafe is now deprecated. Use ngBindHtml instead"); + } + element.addClass("ng-binding").data("$binding", attr.bindHtmlUnsafe); + scope.$watch(attr.bindHtmlUnsafe, function bindHtmlUnsafeWatchAction(value) { + element.html(value || ""); + }); + }; +} ]); + +angular.module("ui.bootstrap.buttons", []).constant("buttonConfig", { + activeClass: "active", + toggleEvent: "click" +}).controller("ButtonsController", [ "buttonConfig", function(buttonConfig) { + this.activeClass = buttonConfig.activeClass || "active"; + this.toggleEvent = buttonConfig.toggleEvent || "click"; +} ]).directive("btnRadio", function() { + return { + require: [ "btnRadio", "ngModel" ], + controller: "ButtonsController", + controllerAs: "buttons", + link: function(scope, element, attrs, ctrls) { + var buttonsCtrl = ctrls[0], ngModelCtrl = ctrls[1]; + element.find("input").css({ + display: "none" + }); + ngModelCtrl.$render = function() { + element.toggleClass(buttonsCtrl.activeClass, angular.equals(ngModelCtrl.$modelValue, scope.$eval(attrs.btnRadio))); + }; + element.bind(buttonsCtrl.toggleEvent, function() { + if (attrs.disabled) { + return; + } + var isActive = element.hasClass(buttonsCtrl.activeClass); + if (!isActive || angular.isDefined(attrs.uncheckable)) { + scope.$apply(function() { + ngModelCtrl.$setViewValue(isActive ? null : scope.$eval(attrs.btnRadio)); + ngModelCtrl.$render(); + }); + } + }); + } + }; +}).directive("btnCheckbox", [ "$document", function($document) { + return { + require: [ "btnCheckbox", "ngModel" ], + controller: "ButtonsController", + controllerAs: "button", + link: function(scope, element, attrs, ctrls) { + var buttonsCtrl = ctrls[0], ngModelCtrl = ctrls[1]; + element.find("input").css({ + display: "none" + }); + function getTrueValue() { + return getCheckboxValue(attrs.btnCheckboxTrue, true); + } + function getFalseValue() { + return getCheckboxValue(attrs.btnCheckboxFalse, false); + } + function getCheckboxValue(attributeValue, defaultValue) { + var val = scope.$eval(attributeValue); + return angular.isDefined(val) ? val : defaultValue; + } + ngModelCtrl.$render = function() { + element.toggleClass(buttonsCtrl.activeClass, angular.equals(ngModelCtrl.$modelValue, getTrueValue())); + }; + element.bind(buttonsCtrl.toggleEvent, function() { + if (attrs.disabled) { + return; + } + scope.$apply(function() { + ngModelCtrl.$setViewValue(element.hasClass(buttonsCtrl.activeClass) ? getFalseValue() : getTrueValue()); + ngModelCtrl.$render(); + }); + }); + element.on("keypress", function(e) { + if (attrs.disabled || e.which !== 32 || $document[0].activeElement !== element[0]) { + return; + } + scope.$apply(function() { + ngModelCtrl.$setViewValue(element.hasClass(buttonsCtrl.activeClass) ? getFalseValue() : getTrueValue()); + ngModelCtrl.$render(); + }); + }); + } + }; +} ]); + +angular.module("ui.bootstrap.carousel", []).controller("CarouselController", [ "$scope", "$element", "$interval", "$animate", function($scope, $element, $interval, $animate) { + var self = this, slides = self.slides = $scope.slides = [], NEW_ANIMATE = angular.version.minor >= 4, NO_TRANSITION = "uib-noTransition", SLIDE_DIRECTION = "uib-slideDirection", currentIndex = -1, currentInterval, isPlaying; + self.currentSlide = null; + var destroyed = false; + self.select = $scope.select = function(nextSlide, direction) { + var nextIndex = $scope.indexOfSlide(nextSlide); + if (direction === undefined) { + direction = nextIndex > self.getCurrentIndex() ? "next" : "prev"; + } + if (nextSlide && nextSlide !== self.currentSlide && !$scope.$currentTransition) { + goNext(nextSlide, nextIndex, direction); + } + }; + function goNext(slide, index, direction) { + if (destroyed) { + return; + } + angular.extend(slide, { + direction: direction, + active: true + }); + angular.extend(self.currentSlide || {}, { + direction: direction, + active: false + }); + if ($animate.enabled() && !$scope.noTransition && !$scope.$currentTransition && slide.$element && self.slides.length > 1) { + slide.$element.data(SLIDE_DIRECTION, slide.direction); + if (self.currentSlide && self.currentSlide.$element) { + self.currentSlide.$element.data(SLIDE_DIRECTION, slide.direction); + } + $scope.$currentTransition = true; + if (NEW_ANIMATE) { + $animate.on("addClass", slide.$element, function(element, phase) { + if (phase === "close") { + $scope.$currentTransition = null; + $animate.off("addClass", element); + } + }); + } else { + slide.$element.one("$animate:close", function closeFn() { + $scope.$currentTransition = null; + }); + } + } + self.currentSlide = slide; + currentIndex = index; + restartTimer(); + } + $scope.$on("$destroy", function() { + destroyed = true; + }); + function getSlideByIndex(index) { + if (angular.isUndefined(slides[index].index)) { + return slides[index]; + } + var i, len = slides.length; + for (i = 0; i < slides.length; ++i) { + if (slides[i].index == index) { + return slides[i]; + } + } + } + self.getCurrentIndex = function() { + if (self.currentSlide && angular.isDefined(self.currentSlide.index)) { + return +self.currentSlide.index; + } + return currentIndex; + }; + $scope.indexOfSlide = function(slide) { + return angular.isDefined(slide.index) ? +slide.index : slides.indexOf(slide); + }; + $scope.next = function() { + var newIndex = (self.getCurrentIndex() + 1) % slides.length; + if (newIndex === 0 && $scope.noWrap()) { + $scope.pause(); + return; + } + return self.select(getSlideByIndex(newIndex), "next"); + }; + $scope.prev = function() { + var newIndex = self.getCurrentIndex() - 1 < 0 ? slides.length - 1 : self.getCurrentIndex() - 1; + if ($scope.noWrap() && newIndex === slides.length - 1) { + $scope.pause(); + return; + } + return self.select(getSlideByIndex(newIndex), "prev"); + }; + $scope.isActive = function(slide) { + return self.currentSlide === slide; + }; + $scope.$watch("interval", restartTimer); + $scope.$on("$destroy", resetTimer); + function restartTimer() { + resetTimer(); + var interval = +$scope.interval; + if (!isNaN(interval) && interval > 0) { + currentInterval = $interval(timerFn, interval); + } + } + function resetTimer() { + if (currentInterval) { + $interval.cancel(currentInterval); + currentInterval = null; + } + } + function timerFn() { + var interval = +$scope.interval; + if (isPlaying && !isNaN(interval) && interval > 0 && slides.length) { + $scope.next(); + } else { + $scope.pause(); + } + } + $scope.play = function() { + if (!isPlaying) { + isPlaying = true; + restartTimer(); + } + }; + $scope.pause = function() { + if (!$scope.noPause) { + isPlaying = false; + resetTimer(); + } + }; + self.addSlide = function(slide, element) { + slide.$element = element; + slides.push(slide); + if (slides.length === 1 || slide.active) { + self.select(slides[slides.length - 1]); + if (slides.length == 1) { + $scope.play(); + } + } else { + slide.active = false; + } + }; + self.removeSlide = function(slide) { + if (angular.isDefined(slide.index)) { + slides.sort(function(a, b) { + return +a.index > +b.index; + }); + } + var index = slides.indexOf(slide); + slides.splice(index, 1); + if (slides.length > 0 && slide.active) { + if (index >= slides.length) { + self.select(slides[index - 1]); + } else { + self.select(slides[index]); + } + } else if (currentIndex > index) { + currentIndex--; + } + if (slides.length === 0) { + self.currentSlide = null; + } + }; + $scope.$watch("noTransition", function(noTransition) { + $element.data(NO_TRANSITION, noTransition); + }); +} ]).directive("carousel", [ function() { return { - link: function(scope, elem, attrs) { - var origScope = scope.$eval(attrs.tooltipTemplateTranscludeScope); - var changeCounter = 0, currentScope, previousElement, currentElement; - var cleanupLastIncludeContent = function() { - if (previousElement) { - previousElement.remove(); - previousElement = null; - } - if (currentScope) { - currentScope.$destroy(); - currentScope = null; + restrict: "EA", + transclude: true, + replace: true, + controller: "CarouselController", + controllerAs: "carousel", + require: "carousel", + templateUrl: function(element, attrs) { + return attrs.templateUrl || "template/carousel/carousel.html"; + }, + scope: { + interval: "=", + noTransition: "=", + noPause: "=", + noWrap: "&" + } + }; +} ]).directive("slide", function() { + return { + require: "^carousel", + restrict: "EA", + transclude: true, + replace: true, + templateUrl: function(element, attrs) { + return attrs.templateUrl || "template/carousel/slide.html"; + }, + scope: { + active: "=?", + actual: "=?", + index: "=?" + }, + link: function(scope, element, attrs, carouselCtrl) { + carouselCtrl.addSlide(scope, element); + scope.$on("$destroy", function() { + carouselCtrl.removeSlide(scope); + }); + scope.$watch("active", function(active) { + if (active) { + carouselCtrl.select(scope); } - if (currentElement) { - $animate.leave(currentElement).then(function() { - previousElement = null; + }); + } + }; +}).animation(".item", [ "$injector", "$animate", function($injector, $animate) { + var NO_TRANSITION = "uib-noTransition", SLIDE_DIRECTION = "uib-slideDirection", $animateCss = null; + if ($injector.has("$animateCss")) { + $animateCss = $injector.get("$animateCss"); + } + function removeClass(element, className, callback) { + element.removeClass(className); + if (callback) { + callback(); + } + } + return { + beforeAddClass: function(element, className, done) { + if (className == "active" && element.parent() && !element.parent().data(NO_TRANSITION)) { + var stopped = false; + var direction = element.data(SLIDE_DIRECTION); + var directionClass = direction == "next" ? "left" : "right"; + var removeClassFn = removeClass.bind(this, element, directionClass + " " + direction, done); + element.addClass(direction); + if ($animateCss) { + $animateCss(element, { + addClass: directionClass + }).start().done(removeClassFn); + } else { + $animate.addClass(element, directionClass).then(function() { + if (!stopped) { + removeClassFn(); + } + done(); }); - previousElement = currentElement; - currentElement = null; } - }; - scope.$watch($sce.parseAsResourceUrl(attrs.tooltipTemplateTransclude), function(src) { - var thisChangeId = ++changeCounter; - if (src) { - $templateRequest(src, true).then(function(response) { - if (thisChangeId !== changeCounter) { - return; - } - var newScope = origScope.$new(); - var template = response; - var clone = $compile(template)(newScope, function(clone) { - cleanupLastIncludeContent(); - $animate.enter(clone, elem); - }); - currentScope = newScope; - currentElement = clone; - currentScope.$emit("$includeContentLoaded", src); - }, function() { - if (thisChangeId === changeCounter) { - cleanupLastIncludeContent(); - scope.$emit("$includeContentError", src); + return function() { + stopped = true; + }; + } + done(); + }, + beforeRemoveClass: function(element, className, done) { + if (className === "active" && element.parent() && !element.parent().data(NO_TRANSITION)) { + var stopped = false; + var direction = element.data(SLIDE_DIRECTION); + var directionClass = direction == "next" ? "left" : "right"; + var removeClassFn = removeClass.bind(this, element, directionClass, done); + if ($animateCss) { + $animateCss(element, { + addClass: directionClass + }).start().done(removeClassFn); + } else { + $animate.addClass(element, directionClass).then(function() { + if (!stopped) { + removeClassFn(); } + done(); }); - scope.$emit("$includeContentRequested", src); - } else { - cleanupLastIncludeContent(); } - }); - scope.$on("$destroy", cleanupLastIncludeContent); + return function() { + stopped = true; + }; + } + done(); } }; -} ]).directive("tooltipClasses", function() { - return { - restrict: "A", - link: function(scope, element, attrs) { - if (scope.placement) { - element.addClass(scope.placement); +} ]); + +angular.module("ui.bootstrap.dateparser", []).service("dateParser", [ "$log", "$locale", "orderByFilter", function($log, $locale, orderByFilter) { + var SPECIAL_CHARACTERS_REGEXP = /[\\\^\$\*\+\?\|\[\]\(\)\.\{\}]/g; + this.parsers = {}; + var formatCodeToRegex = { + yyyy: { + regex: "\\d{4}", + apply: function(value) { + this.year = +value; } - if (scope.popupClass) { - element.addClass(scope.popupClass); + }, + yy: { + regex: "\\d{2}", + apply: function(value) { + this.year = +value + 2e3; } - if (scope.animation()) { - element.addClass(attrs.tooltipAnimationClass); + }, + y: { + regex: "\\d{1,4}", + apply: function(value) { + this.year = +value; } - } - }; -}).directive("tooltipPopup", function() { - return { - restrict: "EA", - replace: true, - scope: { - content: "@", - placement: "@", - popupClass: "@", - animation: "&", - isOpen: "&" }, - templateUrl: "template/tooltip/tooltip-popup.html" - }; -}).directive("tooltip", [ "$tooltip", function($tooltip) { - return $tooltip("tooltip", "tooltip", "mouseenter"); -} ]).directive("tooltipTemplatePopup", function() { - return { - restrict: "EA", - replace: true, - scope: { - contentExp: "&", - placement: "@", - popupClass: "@", - animation: "&", - isOpen: "&", - originScope: "&" + MMMM: { + regex: $locale.DATETIME_FORMATS.MONTH.join("|"), + apply: function(value) { + this.month = $locale.DATETIME_FORMATS.MONTH.indexOf(value); + } }, - templateUrl: "template/tooltip/tooltip-template-popup.html" - }; -}).directive("tooltipTemplate", [ "$tooltip", function($tooltip) { - return $tooltip("tooltipTemplate", "tooltip", "mouseenter", { - useContentExp: true - }); -} ]).directive("tooltipHtmlPopup", function() { - return { - restrict: "EA", - replace: true, - scope: { - contentExp: "&", - placement: "@", - popupClass: "@", - animation: "&", - isOpen: "&" + MMM: { + regex: $locale.DATETIME_FORMATS.SHORTMONTH.join("|"), + apply: function(value) { + this.month = $locale.DATETIME_FORMATS.SHORTMONTH.indexOf(value); + } }, - templateUrl: "template/tooltip/tooltip-html-popup.html" - }; -}).directive("tooltipHtml", [ "$tooltip", function($tooltip) { - return $tooltip("tooltipHtml", "tooltip", "mouseenter", { - useContentExp: true - }); -} ]).directive("tooltipHtmlUnsafePopup", function() { - return { - restrict: "EA", - replace: true, - scope: { - content: "@", - placement: "@", - popupClass: "@", - animation: "&", - isOpen: "&" + MM: { + regex: "0[1-9]|1[0-2]", + apply: function(value) { + this.month = value - 1; + } }, - templateUrl: "template/tooltip/tooltip-html-unsafe-popup.html" + M: { + regex: "[1-9]|1[0-2]", + apply: function(value) { + this.month = value - 1; + } + }, + dd: { + regex: "[0-2][0-9]{1}|3[0-1]{1}", + apply: function(value) { + this.date = +value; + } + }, + d: { + regex: "[1-2]?[0-9]{1}|3[0-1]{1}", + apply: function(value) { + this.date = +value; + } + }, + EEEE: { + regex: $locale.DATETIME_FORMATS.DAY.join("|") + }, + EEE: { + regex: $locale.DATETIME_FORMATS.SHORTDAY.join("|") + }, + HH: { + regex: "(?:0|1)[0-9]|2[0-3]", + apply: function(value) { + this.hours = +value; + } + }, + hh: { + regex: "0[0-9]|1[0-2]", + apply: function(value) { + this.hours = +value; + } + }, + H: { + regex: "1?[0-9]|2[0-3]", + apply: function(value) { + this.hours = +value; + } + }, + h: { + regex: "[0-9]|1[0-2]", + apply: function(value) { + this.hours = +value; + } + }, + mm: { + regex: "[0-5][0-9]", + apply: function(value) { + this.minutes = +value; + } + }, + m: { + regex: "[0-9]|[1-5][0-9]", + apply: function(value) { + this.minutes = +value; + } + }, + sss: { + regex: "[0-9][0-9][0-9]", + apply: function(value) { + this.milliseconds = +value; + } + }, + ss: { + regex: "[0-5][0-9]", + apply: function(value) { + this.seconds = +value; + } + }, + s: { + regex: "[0-9]|[1-5][0-9]", + apply: function(value) { + this.seconds = +value; + } + }, + a: { + regex: $locale.DATETIME_FORMATS.AMPMS.join("|"), + apply: function(value) { + if (this.hours === 12) { + this.hours = 0; + } + if (value === "PM") { + this.hours += 12; + } + } + } + }; + function createParser(format) { + var map = [], regex = format.split(""); + angular.forEach(formatCodeToRegex, function(data, code) { + var index = format.indexOf(code); + if (index > -1) { + format = format.split(""); + regex[index] = "(" + data.regex + ")"; + format[index] = "$"; + for (var i = index + 1, n = index + code.length; i < n; i++) { + regex[i] = ""; + format[i] = "$"; + } + format = format.join(""); + map.push({ + index: index, + apply: data.apply + }); + } + }); + return { + regex: new RegExp("^" + regex.join("") + "$"), + map: orderByFilter(map, "index") + }; + } + this.parse = function(input, format, baseDate) { + if (!angular.isString(input) || !format) { + return input; + } + format = $locale.DATETIME_FORMATS[format] || format; + format = format.replace(SPECIAL_CHARACTERS_REGEXP, "\\$&"); + if (!this.parsers[format]) { + this.parsers[format] = createParser(format); + } + var parser = this.parsers[format], regex = parser.regex, map = parser.map, results = input.match(regex); + if (results && results.length) { + var fields, dt; + if (angular.isDate(baseDate) && !isNaN(baseDate.getTime())) { + fields = { + year: baseDate.getFullYear(), + month: baseDate.getMonth(), + date: baseDate.getDate(), + hours: baseDate.getHours(), + minutes: baseDate.getMinutes(), + seconds: baseDate.getSeconds(), + milliseconds: baseDate.getMilliseconds() + }; + } else { + if (baseDate) { + $log.warn("dateparser:", "baseDate is not a valid date"); + } + fields = { + year: 1900, + month: 0, + date: 1, + hours: 0, + minutes: 0, + seconds: 0, + milliseconds: 0 + }; + } + for (var i = 1, n = results.length; i < n; i++) { + var mapper = map[i - 1]; + if (mapper.apply) { + mapper.apply.call(fields, results[i]); + } + } + if (isValid(fields.year, fields.month, fields.date)) { + dt = new Date(fields.year, fields.month, fields.date, fields.hours, fields.minutes, fields.seconds, fields.milliseconds || 0); + } + return dt; + } }; -}).value("tooltipHtmlUnsafeSuppressDeprecated", false).directive("tooltipHtmlUnsafe", [ "$tooltip", "tooltipHtmlUnsafeSuppressDeprecated", "$log", function($tooltip, tooltipHtmlUnsafeSuppressDeprecated, $log) { - if (!tooltipHtmlUnsafeSuppressDeprecated) { - $log.warn("tooltip-html-unsafe is now deprecated. Use tooltip-html or tooltip-template instead."); + function isValid(year, month, date) { + if (date < 1) { + return false; + } + if (month === 1 && date > 28) { + return date === 29 && (year % 4 === 0 && year % 100 !== 0 || year % 400 === 0); + } + if (month === 3 || month === 5 || month === 8 || month === 10) { + return date < 31; + } + return true; } - return $tooltip("tooltipHtmlUnsafe", "tooltip", "mouseenter"); } ]); -angular.module("ui.bootstrap.popover", [ "ui.bootstrap.tooltip" ]).directive("popoverTemplatePopup", function() { - return { - restrict: "EA", - replace: true, - scope: { - title: "@", - contentExp: "&", - placement: "@", - popupClass: "@", - animation: "&", - isOpen: "&", - originScope: "&" - }, - templateUrl: "template/popover/popover-template.html" +angular.module("ui.bootstrap.position", []).factory("$position", [ "$document", "$window", function($document, $window) { + function getStyle(el, cssprop) { + if (el.currentStyle) { + return el.currentStyle[cssprop]; + } else if ($window.getComputedStyle) { + return $window.getComputedStyle(el)[cssprop]; + } + return el.style[cssprop]; + } + function isStaticPositioned(element) { + return (getStyle(element, "position") || "static") === "static"; + } + var parentOffsetEl = function(element) { + var docDomEl = $document[0]; + var offsetParent = element.offsetParent || docDomEl; + while (offsetParent && offsetParent !== docDomEl && isStaticPositioned(offsetParent)) { + offsetParent = offsetParent.offsetParent; + } + return offsetParent || docDomEl; }; -}).directive("popoverTemplate", [ "$tooltip", function($tooltip) { - return $tooltip("popoverTemplate", "popover", "click", { - useContentExp: true - }); -} ]).directive("popoverHtmlPopup", function() { return { - restrict: "EA", - replace: true, - scope: { - contentExp: "&", - title: "@", - placement: "@", - popupClass: "@", - animation: "&", - isOpen: "&" + position: function(element) { + var elBCR = this.offset(element); + var offsetParentBCR = { + top: 0, + left: 0 + }; + var offsetParentEl = parentOffsetEl(element[0]); + if (offsetParentEl != $document[0]) { + offsetParentBCR = this.offset(angular.element(offsetParentEl)); + offsetParentBCR.top += offsetParentEl.clientTop - offsetParentEl.scrollTop; + offsetParentBCR.left += offsetParentEl.clientLeft - offsetParentEl.scrollLeft; + } + var boundingClientRect = element[0].getBoundingClientRect(); + return { + width: boundingClientRect.width || element.prop("offsetWidth"), + height: boundingClientRect.height || element.prop("offsetHeight"), + top: elBCR.top - offsetParentBCR.top, + left: elBCR.left - offsetParentBCR.left + }; }, - templateUrl: "template/popover/popover-html.html" - }; -}).directive("popoverHtml", [ "$tooltip", function($tooltip) { - return $tooltip("popoverHtml", "popover", "click", { - useContentExp: true - }); -} ]).directive("popoverPopup", function() { - return { - restrict: "EA", - replace: true, - scope: { - title: "@", - content: "@", - placement: "@", - popupClass: "@", - animation: "&", - isOpen: "&" + offset: function(element) { + var boundingClientRect = element[0].getBoundingClientRect(); + return { + width: boundingClientRect.width || element.prop("offsetWidth"), + height: boundingClientRect.height || element.prop("offsetHeight"), + top: boundingClientRect.top + ($window.pageYOffset || $document[0].documentElement.scrollTop), + left: boundingClientRect.left + ($window.pageXOffset || $document[0].documentElement.scrollLeft) + }; }, - templateUrl: "template/popover/popover.html" - }; -}).directive("popover", [ "$tooltip", function($tooltip) { - return $tooltip("popover", "popover", "click"); -} ]); + positionElements: function(hostEl, targetEl, positionStr, appendToBody) { + var positionStrParts = positionStr.split("-"); + var pos0 = positionStrParts[0], pos1 = positionStrParts[1] || "center"; + var hostElPos, targetElWidth, targetElHeight, targetElPos; + hostElPos = appendToBody ? this.offset(hostEl) : this.position(hostEl); + targetElWidth = targetEl.prop("offsetWidth"); + targetElHeight = targetEl.prop("offsetHeight"); + var shiftWidth = { + center: function() { + return hostElPos.left + hostElPos.width / 2 - targetElWidth / 2; + }, + left: function() { + return hostElPos.left; + }, + right: function() { + return hostElPos.left + hostElPos.width; + } + }; + var shiftHeight = { + center: function() { + return hostElPos.top + hostElPos.height / 2 - targetElHeight / 2; + }, + top: function() { + return hostElPos.top; + }, + bottom: function() { + return hostElPos.top + hostElPos.height; + } + }; + switch (pos0) { + case "right": + targetElPos = { + top: shiftHeight[pos1](), + left: shiftWidth[pos0]() + }; + break; -angular.module("ui.bootstrap.progressbar", []).constant("progressConfig", { - animate: true, - max: 100 -}).value("$progressSuppressWarning", false).controller("ProgressController", [ "$scope", "$attrs", "progressConfig", function($scope, $attrs, progressConfig) { - var self = this, animate = angular.isDefined($attrs.animate) ? $scope.$parent.$eval($attrs.animate) : progressConfig.animate; - this.bars = []; - $scope.max = angular.isDefined($scope.max) ? $scope.max : progressConfig.max; - this.addBar = function(bar, element) { - if (!animate) { - element.css({ - transition: "none" - }); - } - this.bars.push(bar); - bar.max = $scope.max; - bar.$watch("value", function(value) { - bar.recalculatePercentage(); - }); - bar.recalculatePercentage = function() { - bar.percent = +(100 * bar.value / bar.max).toFixed(2); - var totalPercentage = self.bars.reduce(function(total, bar) { - return total + bar.percent; - }, 0); - if (totalPercentage > 100) { - bar.percent -= totalPercentage - 100; + case "left": + targetElPos = { + top: shiftHeight[pos1](), + left: hostElPos.left - targetElWidth + }; + break; + + case "bottom": + targetElPos = { + top: shiftHeight[pos0](), + left: shiftWidth[pos1]() + }; + break; + + default: + targetElPos = { + top: hostElPos.top - targetElHeight, + left: shiftWidth[pos1]() + }; + break; } - }; - bar.$on("$destroy", function() { - element = null; - self.removeBar(bar); - }); - }; - this.removeBar = function(bar) { - this.bars.splice(this.bars.indexOf(bar), 1); + return targetElPos; + } }; - $scope.$watch("max", function(max) { - self.bars.forEach(function(bar) { - bar.max = $scope.max; - bar.recalculatePercentage(); - }); - }); -} ]).directive("uibProgress", function() { - return { - restrict: "EA", - replace: true, - transclude: true, - controller: "ProgressController", - require: "uibProgress", - scope: { - max: "=?" - }, - templateUrl: "template/progressbar/progress.html" +} ]); + +angular.module("ui.bootstrap.datepicker", [ "ui.bootstrap.dateparser", "ui.bootstrap.position" ]).value("$datepickerSuppressError", false).constant("datepickerConfig", { + formatDay: "dd", + formatMonth: "MMMM", + formatYear: "yyyy", + formatDayHeader: "EEE", + formatDayTitle: "MMMM yyyy", + formatMonthTitle: "yyyy", + datepickerMode: "day", + minMode: "day", + maxMode: "year", + showWeeks: true, + startingDay: 0, + yearRange: 20, + minDate: null, + maxDate: null, + shortcutPropagation: false +}).controller("DatepickerController", [ "$scope", "$attrs", "$parse", "$interpolate", "$log", "dateFilter", "datepickerConfig", "$datepickerSuppressError", function($scope, $attrs, $parse, $interpolate, $log, dateFilter, datepickerConfig, $datepickerSuppressError) { + var self = this, ngModelCtrl = { + $setViewValue: angular.noop }; -}).directive("progress", [ "$log", "$progressSuppressWarning", function($log, $progressSuppressWarning) { - return { - restrict: "EA", - replace: true, - transclude: true, - controller: "ProgressController", - require: "progress", - scope: { - max: "=?" - }, - templateUrl: "template/progressbar/progress.html", - link: function() { - if ($progressSuppressWarning) { - $log.warn("progress is now deprecated. Use uib-progress instead"); + this.modes = [ "day", "month", "year" ]; + angular.forEach([ "formatDay", "formatMonth", "formatYear", "formatDayHeader", "formatDayTitle", "formatMonthTitle", "showWeeks", "startingDay", "yearRange", "shortcutPropagation" ], function(key, index) { + self[key] = angular.isDefined($attrs[key]) ? index < 6 ? $interpolate($attrs[key])($scope.$parent) : $scope.$parent.$eval($attrs[key]) : datepickerConfig[key]; + }); + angular.forEach([ "minDate", "maxDate" ], function(key) { + if ($attrs[key]) { + $scope.$parent.$watch($parse($attrs[key]), function(value) { + self[key] = value ? new Date(value) : null; + self.refreshView(); + }); + } else { + self[key] = datepickerConfig[key] ? new Date(datepickerConfig[key]) : null; + } + }); + angular.forEach([ "minMode", "maxMode" ], function(key) { + if ($attrs[key]) { + $scope.$parent.$watch($parse($attrs[key]), function(value) { + self[key] = angular.isDefined(value) ? value : $attrs[key]; + $scope[key] = self[key]; + if (key == "minMode" && self.modes.indexOf($scope.datepickerMode) < self.modes.indexOf(self[key]) || key == "maxMode" && self.modes.indexOf($scope.datepickerMode) > self.modes.indexOf(self[key])) { + $scope.datepickerMode = self[key]; + } + }); + } else { + self[key] = datepickerConfig[key] || null; + $scope[key] = self[key]; + } + }); + $scope.datepickerMode = $scope.datepickerMode || datepickerConfig.datepickerMode; + $scope.uniqueId = "datepicker-" + $scope.$id + "-" + Math.floor(Math.random() * 1e4); + if (angular.isDefined($attrs.initDate)) { + this.activeDate = $scope.$parent.$eval($attrs.initDate) || new Date(); + $scope.$parent.$watch($attrs.initDate, function(initDate) { + if (initDate && (ngModelCtrl.$isEmpty(ngModelCtrl.$modelValue) || ngModelCtrl.$invalid)) { + self.activeDate = initDate; + self.refreshView(); } + }); + } else { + this.activeDate = new Date(); + } + $scope.isActive = function(dateObject) { + if (self.compare(dateObject.date, self.activeDate) === 0) { + $scope.activeDateId = dateObject.uid; + return true; } + return false; }; -} ]).directive("uibBar", function() { - return { - restrict: "EA", - replace: true, - transclude: true, - require: "^uibProgress", - scope: { - value: "=", - type: "@" - }, - templateUrl: "template/progressbar/bar.html", - link: function(scope, element, attrs, progressCtrl) { - progressCtrl.addBar(scope, element); - } + this.init = function(ngModelCtrl_) { + ngModelCtrl = ngModelCtrl_; + ngModelCtrl.$render = function() { + self.render(); + }; }; -}).directive("bar", [ "$log", "$progressSuppressWarning", function($log, $progressSuppressWarning) { - return { - restrict: "EA", - replace: true, - transclude: true, - require: "^progress", - scope: { - value: "=", - type: "@" - }, - templateUrl: "template/progressbar/bar.html", - link: function(scope, element, attrs, progressCtrl) { - if ($progressSuppressWarning) { - $log.warn("bar is now deprecated. Use uib-bar instead"); + this.render = function() { + if (ngModelCtrl.$viewValue) { + var date = new Date(ngModelCtrl.$viewValue), isValid = !isNaN(date); + if (isValid) { + this.activeDate = date; + } else if (!$datepickerSuppressError) { + $log.error('Datepicker directive: "ng-model" value must be a Date object, a number of milliseconds since 01.01.1970 or a string representing an RFC2822 or ISO 8601 date.'); } - progressCtrl.addBar(scope, element); } + this.refreshView(); }; -} ]).directive("progressbar", function() { - return { - restrict: "EA", - replace: true, - transclude: true, - controller: "ProgressController", - scope: { - value: "=", - max: "=?", - type: "@" - }, - templateUrl: "template/progressbar/progressbar.html", - link: function(scope, element, attrs, progressCtrl) { - progressCtrl.addBar(scope, angular.element(element.children()[0])); + this.refreshView = function() { + if (this.element) { + this._refreshView(); + var date = ngModelCtrl.$viewValue ? new Date(ngModelCtrl.$viewValue) : null; + ngModelCtrl.$setValidity("dateDisabled", !date || this.element && !this.isDisabled(date)); } }; -}); - -angular.module("ui.bootstrap.rating", []).constant("ratingConfig", { - max: 5, - stateOn: null, - stateOff: null, - titles: [ "one", "two", "three", "four", "five" ] -}).controller("RatingController", [ "$scope", "$attrs", "ratingConfig", function($scope, $attrs, ratingConfig) { - var ngModelCtrl = { - $setViewValue: angular.noop + this.createDateObject = function(date, format) { + var model = ngModelCtrl.$viewValue ? new Date(ngModelCtrl.$viewValue) : null; + return { + date: date, + label: dateFilter(date, format), + selected: model && this.compare(date, model) === 0, + disabled: this.isDisabled(date), + current: this.compare(date, new Date()) === 0, + customClass: this.customClass(date) + }; }; - this.init = function(ngModelCtrl_) { - ngModelCtrl = ngModelCtrl_; - ngModelCtrl.$render = this.render; - ngModelCtrl.$formatters.push(function(value) { - if (angular.isNumber(value) && value << 0 !== value) { - value = Math.round(value); - } - return value; + this.isDisabled = function(date) { + return this.minDate && this.compare(date, this.minDate) < 0 || this.maxDate && this.compare(date, this.maxDate) > 0 || $attrs.dateDisabled && $scope.dateDisabled({ + date: date, + mode: $scope.datepickerMode }); - this.stateOn = angular.isDefined($attrs.stateOn) ? $scope.$parent.$eval($attrs.stateOn) : ratingConfig.stateOn; - this.stateOff = angular.isDefined($attrs.stateOff) ? $scope.$parent.$eval($attrs.stateOff) : ratingConfig.stateOff; - var tmpTitles = angular.isDefined($attrs.titles) ? $scope.$parent.$eval($attrs.titles) : ratingConfig.titles; - this.titles = angular.isArray(tmpTitles) && tmpTitles.length > 0 ? tmpTitles : ratingConfig.titles; - var ratingStates = angular.isDefined($attrs.ratingStates) ? $scope.$parent.$eval($attrs.ratingStates) : new Array(angular.isDefined($attrs.max) ? $scope.$parent.$eval($attrs.max) : ratingConfig.max); - $scope.range = this.buildTemplateObjects(ratingStates); }; - this.buildTemplateObjects = function(states) { - for (var i = 0, n = states.length; i < n; i++) { - states[i] = angular.extend({ - index: i - }, { - stateOn: this.stateOn, - stateOff: this.stateOff, - title: this.getTitle(i) - }, states[i]); - } - return states; + this.customClass = function(date) { + return $scope.customClass({ + date: date, + mode: $scope.datepickerMode + }); }; - this.getTitle = function(index) { - if (index >= this.titles.length) { - return index + 1; - } else { - return this.titles[index]; + this.split = function(arr, size) { + var arrays = []; + while (arr.length > 0) { + arrays.push(arr.splice(0, size)); } + return arrays; }; - $scope.rate = function(value) { - if (!$scope.readonly && value >= 0 && value <= $scope.range.length) { - ngModelCtrl.$setViewValue(ngModelCtrl.$viewValue === value ? 0 : value); + this.fixTimeZone = function(date) { + var hours = date.getHours(); + date.setHours(hours === 23 ? hours + 2 : 0); + }; + $scope.select = function(date) { + if ($scope.datepickerMode === self.minMode) { + var dt = ngModelCtrl.$viewValue ? new Date(ngModelCtrl.$viewValue) : new Date(0, 0, 0, 0, 0, 0, 0); + dt.setFullYear(date.getFullYear(), date.getMonth(), date.getDate()); + ngModelCtrl.$setViewValue(dt); ngModelCtrl.$render(); + } else { + self.activeDate = date; + $scope.datepickerMode = self.modes[self.modes.indexOf($scope.datepickerMode) - 1]; } }; - $scope.enter = function(value) { - if (!$scope.readonly) { - $scope.value = value; + $scope.move = function(direction) { + var year = self.activeDate.getFullYear() + direction * (self.step.years || 0), month = self.activeDate.getMonth() + direction * (self.step.months || 0); + self.activeDate.setFullYear(year, month, 1); + self.refreshView(); + }; + $scope.toggleMode = function(direction) { + direction = direction || 1; + if ($scope.datepickerMode === self.maxMode && direction === 1 || $scope.datepickerMode === self.minMode && direction === -1) { + return; } - $scope.onHover({ - value: value - }); + $scope.datepickerMode = self.modes[self.modes.indexOf($scope.datepickerMode) + direction]; }; - $scope.reset = function() { - $scope.value = ngModelCtrl.$viewValue; - $scope.onLeave(); + $scope.keys = { + 13: "enter", + 32: "space", + 33: "pageup", + 34: "pagedown", + 35: "end", + 36: "home", + 37: "left", + 38: "up", + 39: "right", + 40: "down" }; - $scope.onKeydown = function(evt) { - if (/(37|38|39|40)/.test(evt.which)) { - evt.preventDefault(); + var focusElement = function() { + self.element[0].focus(); + }; + $scope.$on("datepicker.focus", focusElement); + $scope.keydown = function(evt) { + var key = $scope.keys[evt.which]; + if (!key || evt.shiftKey || evt.altKey) { + return; + } + evt.preventDefault(); + if (!self.shortcutPropagation) { evt.stopPropagation(); - $scope.rate($scope.value + (evt.which === 38 || evt.which === 39 ? 1 : -1)); + } + if (key === "enter" || key === "space") { + if (self.isDisabled(self.activeDate)) { + return; + } + $scope.select(self.activeDate); + focusElement(); + } else if (evt.ctrlKey && (key === "up" || key === "down")) { + $scope.toggleMode(key === "up" ? 1 : -1); + focusElement(); + } else { + self.handleKeyDown(key, evt); + self.refreshView(); } }; - this.render = function() { - $scope.value = ngModelCtrl.$viewValue; - }; -} ]).directive("rating", function() { +} ]).directive("datepicker", function() { return { restrict: "EA", - require: [ "rating", "ngModel" ], + replace: true, + templateUrl: function(element, attrs) { + return attrs.templateUrl || "template/datepicker/datepicker.html"; + }, scope: { - readonly: "=?", - onHover: "&", - onLeave: "&" + datepickerMode: "=?", + dateDisabled: "&", + customClass: "&", + shortcutPropagation: "&?" }, - controller: "RatingController", - templateUrl: "template/rating/rating.html", - replace: true, + require: [ "datepicker", "^ngModel" ], + controller: "DatepickerController", + controllerAs: "datepicker", link: function(scope, element, attrs, ctrls) { - var ratingCtrl = ctrls[0], ngModelCtrl = ctrls[1]; - ratingCtrl.init(ngModelCtrl); + var datepickerCtrl = ctrls[0], ngModelCtrl = ctrls[1]; + datepickerCtrl.init(ngModelCtrl); } }; -}); - -angular.module("ui.bootstrap.tabs", []).controller("TabsetController", [ "$scope", function TabsetCtrl($scope) { - var ctrl = this, tabs = ctrl.tabs = $scope.tabs = []; - ctrl.select = function(selectedTab) { - angular.forEach(tabs, function(tab) { - if (tab.active && tab !== selectedTab) { - tab.active = false; - tab.onDeselect(); - selectedTab.selectCalled = false; +}).directive("daypicker", [ "dateFilter", function(dateFilter) { + return { + restrict: "EA", + replace: true, + templateUrl: "template/datepicker/day.html", + require: "^datepicker", + link: function(scope, element, attrs, ctrl) { + scope.showWeeks = ctrl.showWeeks; + ctrl.step = { + months: 1 + }; + ctrl.element = element; + var DAYS_IN_MONTH = [ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 ]; + function getDaysInMonth(year, month) { + return month === 1 && year % 4 === 0 && (year % 100 !== 0 || year % 400 === 0) ? 29 : DAYS_IN_MONTH[month]; } - }); - selectedTab.active = true; - if (!selectedTab.selectCalled) { - selectedTab.onSelect(); - selectedTab.selectCalled = true; - } - }; - ctrl.addTab = function addTab(tab) { - tabs.push(tab); - if (tabs.length === 1 && tab.active !== false) { - tab.active = true; - } else if (tab.active) { - ctrl.select(tab); - } else { - tab.active = false; - } - }; - ctrl.removeTab = function removeTab(tab) { - var index = tabs.indexOf(tab); - if (tab.active && tabs.length > 1 && !destroyed) { - var newActiveIndex = index == tabs.length - 1 ? index - 1 : index + 1; - ctrl.select(tabs[newActiveIndex]); + function getDates(startDate, n) { + var dates = new Array(n), current = new Date(startDate), i = 0, date; + while (i < n) { + date = new Date(current); + ctrl.fixTimeZone(date); + dates[i++] = date; + current.setDate(current.getDate() + 1); + } + return dates; + } + ctrl._refreshView = function() { + var year = ctrl.activeDate.getFullYear(), month = ctrl.activeDate.getMonth(), firstDayOfMonth = new Date(year, month, 1), difference = ctrl.startingDay - firstDayOfMonth.getDay(), numDisplayedFromPreviousMonth = difference > 0 ? 7 - difference : -difference, firstDate = new Date(firstDayOfMonth); + if (numDisplayedFromPreviousMonth > 0) { + firstDate.setDate(-numDisplayedFromPreviousMonth + 1); + } + var days = getDates(firstDate, 42); + for (var i = 0; i < 42; i++) { + days[i] = angular.extend(ctrl.createDateObject(days[i], ctrl.formatDay), { + secondary: days[i].getMonth() !== month, + uid: scope.uniqueId + "-" + i + }); + } + scope.labels = new Array(7); + for (var j = 0; j < 7; j++) { + scope.labels[j] = { + abbr: dateFilter(days[j].date, ctrl.formatDayHeader), + full: dateFilter(days[j].date, "EEEE") + }; + } + scope.title = dateFilter(ctrl.activeDate, ctrl.formatDayTitle); + scope.rows = ctrl.split(days, 7); + if (scope.showWeeks) { + scope.weekNumbers = []; + var thursdayIndex = (4 + 7 - ctrl.startingDay) % 7, numWeeks = scope.rows.length; + for (var curWeek = 0; curWeek < numWeeks; curWeek++) { + scope.weekNumbers.push(getISO8601WeekNumber(scope.rows[curWeek][thursdayIndex].date)); + } + } + }; + ctrl.compare = function(date1, date2) { + return new Date(date1.getFullYear(), date1.getMonth(), date1.getDate()) - new Date(date2.getFullYear(), date2.getMonth(), date2.getDate()); + }; + function getISO8601WeekNumber(date) { + var checkDate = new Date(date); + checkDate.setDate(checkDate.getDate() + 4 - (checkDate.getDay() || 7)); + var time = checkDate.getTime(); + checkDate.setMonth(0); + checkDate.setDate(1); + return Math.floor(Math.round((time - checkDate) / 864e5) / 7) + 1; + } + ctrl.handleKeyDown = function(key, evt) { + var date = ctrl.activeDate.getDate(); + if (key === "left") { + date = date - 1; + } else if (key === "up") { + date = date - 7; + } else if (key === "right") { + date = date + 1; + } else if (key === "down") { + date = date + 7; + } else if (key === "pageup" || key === "pagedown") { + var month = ctrl.activeDate.getMonth() + (key === "pageup" ? -1 : 1); + ctrl.activeDate.setMonth(month, 1); + date = Math.min(getDaysInMonth(ctrl.activeDate.getFullYear(), ctrl.activeDate.getMonth()), date); + } else if (key === "home") { + date = 1; + } else if (key === "end") { + date = getDaysInMonth(ctrl.activeDate.getFullYear(), ctrl.activeDate.getMonth()); + } + ctrl.activeDate.setDate(date); + }; + ctrl.refreshView(); } - tabs.splice(index, 1); }; - var destroyed; - $scope.$on("$destroy", function() { - destroyed = true; - }); -} ]).directive("tabset", function() { +} ]).directive("monthpicker", [ "dateFilter", function(dateFilter) { return { restrict: "EA", - transclude: true, replace: true, - scope: { - type: "@" - }, - controller: "TabsetController", - templateUrl: "template/tabs/tabset.html", - link: function(scope, element, attrs) { - scope.vertical = angular.isDefined(attrs.vertical) ? scope.$parent.$eval(attrs.vertical) : false; - scope.justified = angular.isDefined(attrs.justified) ? scope.$parent.$eval(attrs.justified) : false; + templateUrl: "template/datepicker/month.html", + require: "^datepicker", + link: function(scope, element, attrs, ctrl) { + ctrl.step = { + years: 1 + }; + ctrl.element = element; + ctrl._refreshView = function() { + var months = new Array(12), year = ctrl.activeDate.getFullYear(), date; + for (var i = 0; i < 12; i++) { + date = new Date(year, i, 1); + ctrl.fixTimeZone(date); + months[i] = angular.extend(ctrl.createDateObject(date, ctrl.formatMonth), { + uid: scope.uniqueId + "-" + i + }); + } + scope.title = dateFilter(ctrl.activeDate, ctrl.formatMonthTitle); + scope.rows = ctrl.split(months, 3); + }; + ctrl.compare = function(date1, date2) { + return new Date(date1.getFullYear(), date1.getMonth()) - new Date(date2.getFullYear(), date2.getMonth()); + }; + ctrl.handleKeyDown = function(key, evt) { + var date = ctrl.activeDate.getMonth(); + if (key === "left") { + date = date - 1; + } else if (key === "up") { + date = date - 3; + } else if (key === "right") { + date = date + 1; + } else if (key === "down") { + date = date + 3; + } else if (key === "pageup" || key === "pagedown") { + var year = ctrl.activeDate.getFullYear() + (key === "pageup" ? -1 : 1); + ctrl.activeDate.setFullYear(year); + } else if (key === "home") { + date = 0; + } else if (key === "end") { + date = 11; + } + ctrl.activeDate.setMonth(date); + }; + ctrl.refreshView(); } }; -}).directive("tab", [ "$parse", "$log", function($parse, $log) { +} ]).directive("yearpicker", [ "dateFilter", function(dateFilter) { return { - require: "^tabset", restrict: "EA", replace: true, - templateUrl: "template/tabs/tab.html", - transclude: true, - scope: { - active: "=?", - heading: "@", - onSelect: "&select", - onDeselect: "&deselect" - }, - controller: function() {}, - link: function(scope, elm, attrs, tabsetCtrl, transclude) { - scope.$watch("active", function(active) { - if (active) { - tabsetCtrl.select(scope); - } - }); - scope.disabled = false; - if (attrs.disable) { - scope.$parent.$watch($parse(attrs.disable), function(value) { - scope.disabled = !!value; - }); - } - if (attrs.disabled) { - $log.warn('Use of "disabled" attribute has been deprecated, please use "disable"'); - scope.$parent.$watch($parse(attrs.disabled), function(value) { - scope.disabled = !!value; - }); + templateUrl: "template/datepicker/year.html", + require: "^datepicker", + link: function(scope, element, attrs, ctrl) { + var range = ctrl.yearRange; + ctrl.step = { + years: range + }; + ctrl.element = element; + function getStartingYear(year) { + return parseInt((year - 1) / range, 10) * range + 1; } - scope.select = function() { - if (!scope.disabled) { - scope.active = true; + ctrl._refreshView = function() { + var years = new Array(range), date; + for (var i = 0, start = getStartingYear(ctrl.activeDate.getFullYear()); i < range; i++) { + date = new Date(start + i, 0, 1); + ctrl.fixTimeZone(date); + years[i] = angular.extend(ctrl.createDateObject(date, ctrl.formatYear), { + uid: scope.uniqueId + "-" + i + }); } + scope.title = [ years[0].label, years[range - 1].label ].join(" - "); + scope.rows = ctrl.split(years, 5); }; - tabsetCtrl.addTab(scope); - scope.$on("$destroy", function() { - tabsetCtrl.removeTab(scope); - }); - scope.$transcludeFn = transclude; - } - }; -} ]).directive("tabHeadingTransclude", function() { - return { - restrict: "A", - require: "^tab", - link: function(scope, elm, attrs, tabCtrl) { - scope.$watch("headingElement", function updateHeadingElement(heading) { - if (heading) { - elm.html(""); - elm.append(heading); + ctrl.compare = function(date1, date2) { + return date1.getFullYear() - date2.getFullYear(); + }; + ctrl.handleKeyDown = function(key, evt) { + var date = ctrl.activeDate.getFullYear(); + if (key === "left") { + date = date - 1; + } else if (key === "up") { + date = date - 5; + } else if (key === "right") { + date = date + 1; + } else if (key === "down") { + date = date + 5; + } else if (key === "pageup" || key === "pagedown") { + date += (key === "pageup" ? -1 : 1) * ctrl.step.years; + } else if (key === "home") { + date = getStartingYear(ctrl.activeDate.getFullYear()); + } else if (key === "end") { + date = getStartingYear(ctrl.activeDate.getFullYear()) + range - 1; } - }); + ctrl.activeDate.setFullYear(date); + }; + ctrl.refreshView(); } }; -}).directive("tabContentTransclude", function() { +} ]).constant("datepickerPopupConfig", { + datepickerPopup: "yyyy-MM-dd", + datepickerPopupTemplateUrl: "template/datepicker/popup.html", + datepickerTemplateUrl: "template/datepicker/datepicker.html", + html5Types: { + date: "yyyy-MM-dd", + "datetime-local": "yyyy-MM-ddTHH:mm:ss.sss", + month: "yyyy-MM" + }, + currentText: "Today", + clearText: "Clear", + closeText: "Done", + closeOnDateSelection: true, + appendToBody: false, + showButtonBar: true, + onOpenFocus: true +}).directive("datepickerPopup", [ "$compile", "$parse", "$document", "$rootScope", "$position", "dateFilter", "dateParser", "datepickerPopupConfig", "$timeout", function($compile, $parse, $document, $rootScope, $position, dateFilter, dateParser, datepickerPopupConfig, $timeout) { return { - restrict: "A", - require: "^tabset", - link: function(scope, elm, attrs) { - var tab = scope.$eval(attrs.tabContentTransclude); - tab.$transcludeFn(tab.$parent, function(contents) { - angular.forEach(contents, function(node) { - if (isTabHeading(node)) { - tab.headingElement = node; - } else { - elm.append(node); - } - }); - }); - } - }; - function isTabHeading(node) { - return node.tagName && (node.hasAttribute("tab-heading") || node.hasAttribute("data-tab-heading") || node.hasAttribute("x-tab-heading") || node.tagName.toLowerCase() === "tab-heading" || node.tagName.toLowerCase() === "data-tab-heading" || node.tagName.toLowerCase() === "x-tab-heading"); - } -}); - -angular.module("ui.bootstrap.timepicker", []).constant("timepickerConfig", { - hourStep: 1, - minuteStep: 1, - showMeridian: true, - meridians: null, - readonlyInput: false, - mousewheel: true, - arrowkeys: true, - showSpinners: true -}).controller("TimepickerController", [ "$scope", "$attrs", "$parse", "$log", "$locale", "timepickerConfig", function($scope, $attrs, $parse, $log, $locale, timepickerConfig) { - var selected = new Date(), ngModelCtrl = { - $setViewValue: angular.noop - }, meridians = angular.isDefined($attrs.meridians) ? $scope.$parent.$eval($attrs.meridians) : timepickerConfig.meridians || $locale.DATETIME_FORMATS.AMPMS; - this.init = function(ngModelCtrl_, inputs) { - ngModelCtrl = ngModelCtrl_; - ngModelCtrl.$render = this.render; - ngModelCtrl.$formatters.unshift(function(modelValue) { - return modelValue ? new Date(modelValue) : null; - }); - var hoursInputEl = inputs.eq(0), minutesInputEl = inputs.eq(1); - var mousewheel = angular.isDefined($attrs.mousewheel) ? $scope.$parent.$eval($attrs.mousewheel) : timepickerConfig.mousewheel; - if (mousewheel) { - this.setupMousewheelEvents(hoursInputEl, minutesInputEl); - } - var arrowkeys = angular.isDefined($attrs.arrowkeys) ? $scope.$parent.$eval($attrs.arrowkeys) : timepickerConfig.arrowkeys; - if (arrowkeys) { - this.setupArrowkeyEvents(hoursInputEl, minutesInputEl); - } - $scope.readonlyInput = angular.isDefined($attrs.readonlyInput) ? $scope.$parent.$eval($attrs.readonlyInput) : timepickerConfig.readonlyInput; - this.setupInputEvents(hoursInputEl, minutesInputEl); - }; - var hourStep = timepickerConfig.hourStep; - if ($attrs.hourStep) { - $scope.$parent.$watch($parse($attrs.hourStep), function(value) { - hourStep = parseInt(value, 10); - }); - } - var minuteStep = timepickerConfig.minuteStep; - if ($attrs.minuteStep) { - $scope.$parent.$watch($parse($attrs.minuteStep), function(value) { - minuteStep = parseInt(value, 10); - }); - } - var min; - $scope.$parent.$watch($parse($attrs.min), function(value) { - var dt = new Date(value); - min = isNaN(dt) ? undefined : dt; - }); - var max; - $scope.$parent.$watch($parse($attrs.max), function(value) { - var dt = new Date(value); - max = isNaN(dt) ? undefined : dt; - }); - $scope.noIncrementHours = function() { - var incrementedSelected = addMinutes(selected, hourStep * 60); - return incrementedSelected > max || incrementedSelected < selected && incrementedSelected < min; - }; - $scope.noDecrementHours = function() { - var decrementedSelected = addMinutes(selected, -hourStep * 60); - return decrementedSelected < min || decrementedSelected > selected && decrementedSelected > max; - }; - $scope.noIncrementMinutes = function() { - var incrementedSelected = addMinutes(selected, minuteStep); - return incrementedSelected > max || incrementedSelected < selected && incrementedSelected < min; - }; - $scope.noDecrementMinutes = function() { - var decrementedSelected = addMinutes(selected, -minuteStep); - return decrementedSelected < min || decrementedSelected > selected && decrementedSelected > max; - }; - $scope.noToggleMeridian = function() { - if (selected.getHours() < 13) { - return addMinutes(selected, 12 * 60) > max; - } else { - return addMinutes(selected, -12 * 60) < min; - } - }; - $scope.showMeridian = timepickerConfig.showMeridian; - if ($attrs.showMeridian) { - $scope.$parent.$watch($parse($attrs.showMeridian), function(value) { - $scope.showMeridian = !!value; - if (ngModelCtrl.$error.time) { - var hours = getHoursFromTemplate(), minutes = getMinutesFromTemplate(); - if (angular.isDefined(hours) && angular.isDefined(minutes)) { - selected.setHours(hours); - refresh(); + restrict: "EA", + require: "ngModel", + scope: { + isOpen: "=?", + currentText: "@", + clearText: "@", + closeText: "@", + dateDisabled: "&", + customClass: "&" + }, + link: function(scope, element, attrs, ngModel) { + var dateFormat, closeOnDateSelection = angular.isDefined(attrs.closeOnDateSelection) ? scope.$parent.$eval(attrs.closeOnDateSelection) : datepickerPopupConfig.closeOnDateSelection, appendToBody = angular.isDefined(attrs.datepickerAppendToBody) ? scope.$parent.$eval(attrs.datepickerAppendToBody) : datepickerPopupConfig.appendToBody, onOpenFocus = angular.isDefined(attrs.onOpenFocus) ? scope.$parent.$eval(attrs.onOpenFocus) : datepickerPopupConfig.onOpenFocus, datepickerPopupTemplateUrl = angular.isDefined(attrs.datepickerPopupTemplateUrl) ? attrs.datepickerPopupTemplateUrl : datepickerPopupConfig.datepickerPopupTemplateUrl, datepickerTemplateUrl = angular.isDefined(attrs.datepickerTemplateUrl) ? attrs.datepickerTemplateUrl : datepickerPopupConfig.datepickerTemplateUrl, cache = {}; + scope.showButtonBar = angular.isDefined(attrs.showButtonBar) ? scope.$parent.$eval(attrs.showButtonBar) : datepickerPopupConfig.showButtonBar; + scope.getText = function(key) { + return scope[key + "Text"] || datepickerPopupConfig[key + "Text"]; + }; + scope.isDisabled = function(date) { + if (date === "today") { + date = new Date(); } + return scope.watchData.minDate && scope.compare(date, cache.minDate) < 0 || scope.watchData.maxDate && scope.compare(date, cache.maxDate) > 0; + }; + scope.compare = function(date1, date2) { + return new Date(date1.getFullYear(), date1.getMonth(), date1.getDate()) - new Date(date2.getFullYear(), date2.getMonth(), date2.getDate()); + }; + var isHtml5DateInput = false; + if (datepickerPopupConfig.html5Types[attrs.type]) { + dateFormat = datepickerPopupConfig.html5Types[attrs.type]; + isHtml5DateInput = true; } else { - updateTemplate(); + dateFormat = attrs.datepickerPopup || datepickerPopupConfig.datepickerPopup; + attrs.$observe("datepickerPopup", function(value, oldValue) { + var newDateFormat = value || datepickerPopupConfig.datepickerPopup; + if (newDateFormat !== dateFormat) { + dateFormat = newDateFormat; + ngModel.$modelValue = null; + if (!dateFormat) { + throw new Error("datepickerPopup must have a date format specified."); + } + } + }); } - }); - } - function getHoursFromTemplate() { - var hours = parseInt($scope.hours, 10); - var valid = $scope.showMeridian ? hours > 0 && hours < 13 : hours >= 0 && hours < 24; - if (!valid) { - return undefined; - } - if ($scope.showMeridian) { - if (hours === 12) { - hours = 0; + if (!dateFormat) { + throw new Error("datepickerPopup must have a date format specified."); } - if ($scope.meridian === meridians[1]) { - hours = hours + 12; + if (isHtml5DateInput && attrs.datepickerPopup) { + throw new Error("HTML5 date input types do not support custom formats."); } - } - return hours; - } - function getMinutesFromTemplate() { - var minutes = parseInt($scope.minutes, 10); - return minutes >= 0 && minutes < 60 ? minutes : undefined; - } - function pad(value) { - return angular.isDefined(value) && value.toString().length < 2 ? "0" + value : value.toString(); - } - this.setupMousewheelEvents = function(hoursInputEl, minutesInputEl) { - var isScrollingUp = function(e) { - if (e.originalEvent) { - e = e.originalEvent; + var popupEl = angular.element("
        "); + popupEl.attr({ + "ng-model": "date", + "ng-change": "dateSelection(date)", + "template-url": datepickerPopupTemplateUrl + }); + function cameltoDash(string) { + return string.replace(/([A-Z])/g, function($1) { + return "-" + $1.toLowerCase(); + }); + } + var datepickerEl = angular.element(popupEl.children()[0]); + datepickerEl.attr("template-url", datepickerTemplateUrl); + if (isHtml5DateInput) { + if (attrs.type === "month") { + datepickerEl.attr("datepicker-mode", '"month"'); + datepickerEl.attr("min-mode", "month"); + } } - var delta = e.wheelDelta ? e.wheelDelta : -e.deltaY; - return e.detail || delta > 0; - }; - hoursInputEl.bind("mousewheel wheel", function(e) { - $scope.$apply(isScrollingUp(e) ? $scope.incrementHours() : $scope.decrementHours()); - e.preventDefault(); - }); - minutesInputEl.bind("mousewheel wheel", function(e) { - $scope.$apply(isScrollingUp(e) ? $scope.incrementMinutes() : $scope.decrementMinutes()); - e.preventDefault(); - }); - }; - this.setupArrowkeyEvents = function(hoursInputEl, minutesInputEl) { - hoursInputEl.bind("keydown", function(e) { - if (e.which === 38) { - e.preventDefault(); - $scope.incrementHours(); - $scope.$apply(); - } else if (e.which === 40) { - e.preventDefault(); - $scope.decrementHours(); - $scope.$apply(); + if (attrs.datepickerOptions) { + var options = scope.$parent.$eval(attrs.datepickerOptions); + if (options && options.initDate) { + scope.initDate = options.initDate; + datepickerEl.attr("init-date", "initDate"); + delete options.initDate; + } + angular.forEach(options, function(value, option) { + datepickerEl.attr(cameltoDash(option), value); + }); } - }); - minutesInputEl.bind("keydown", function(e) { - if (e.which === 38) { - e.preventDefault(); - $scope.incrementMinutes(); - $scope.$apply(); - } else if (e.which === 40) { - e.preventDefault(); - $scope.decrementMinutes(); - $scope.$apply(); + scope.watchData = {}; + angular.forEach([ "minMode", "maxMode", "minDate", "maxDate", "datepickerMode", "initDate", "shortcutPropagation" ], function(key) { + if (attrs[key]) { + var getAttribute = $parse(attrs[key]); + scope.$parent.$watch(getAttribute, function(value) { + scope.watchData[key] = value; + if (key === "minDate" || key === "maxDate") { + cache[key] = new Date(value); + } + }); + datepickerEl.attr(cameltoDash(key), "watchData." + key); + if (key === "datepickerMode") { + var setAttribute = getAttribute.assign; + scope.$watch("watchData." + key, function(value, oldvalue) { + if (angular.isFunction(setAttribute) && value !== oldvalue) { + setAttribute(scope.$parent, value); + } + }); + } + } + }); + if (attrs.dateDisabled) { + datepickerEl.attr("date-disabled", "dateDisabled({ date: date, mode: mode })"); } - }); - }; - this.setupInputEvents = function(hoursInputEl, minutesInputEl) { - if ($scope.readonlyInput) { - $scope.updateHours = angular.noop; - $scope.updateMinutes = angular.noop; - return; - } - var invalidate = function(invalidHours, invalidMinutes) { - ngModelCtrl.$setViewValue(null); - ngModelCtrl.$setValidity("time", false); - if (angular.isDefined(invalidHours)) { - $scope.invalidHours = invalidHours; + if (attrs.showWeeks) { + datepickerEl.attr("show-weeks", attrs.showWeeks); } - if (angular.isDefined(invalidMinutes)) { - $scope.invalidMinutes = invalidMinutes; + if (attrs.customClass) { + datepickerEl.attr("custom-class", "customClass({ date: date, mode: mode })"); } - }; - $scope.updateHours = function() { - var hours = getHoursFromTemplate(), minutes = getMinutesFromTemplate(); - if (angular.isDefined(hours) && angular.isDefined(minutes)) { - selected.setHours(hours); - if (selected < min || selected > max) { - invalidate(true); + function parseDate(viewValue) { + if (angular.isNumber(viewValue)) { + viewValue = new Date(viewValue); + } + if (!viewValue) { + return null; + } else if (angular.isDate(viewValue) && !isNaN(viewValue)) { + return viewValue; + } else if (angular.isString(viewValue)) { + var date = dateParser.parse(viewValue, dateFormat, scope.date); + if (isNaN(date)) { + return undefined; + } else { + return date; + } } else { - refresh("h"); + return undefined; } - } else { - invalidate(true); - } - }; - hoursInputEl.bind("blur", function(e) { - if (!$scope.invalidHours && $scope.hours < 10) { - $scope.$apply(function() { - $scope.hours = pad($scope.hours); - }); } - }); - $scope.updateMinutes = function() { - var minutes = getMinutesFromTemplate(), hours = getHoursFromTemplate(); - if (angular.isDefined(minutes) && angular.isDefined(hours)) { - selected.setMinutes(minutes); - if (selected < min || selected > max) { - invalidate(undefined, true); + function validator(modelValue, viewValue) { + var value = modelValue || viewValue; + if (!attrs.ngRequired && !value) { + return true; + } + if (angular.isNumber(value)) { + value = new Date(value); + } + if (!value) { + return true; + } else if (angular.isDate(value) && !isNaN(value)) { + return true; + } else if (angular.isString(value)) { + var date = dateParser.parse(value, dateFormat); + return !isNaN(date); } else { - refresh("m"); + return false; } - } else { - invalidate(undefined, true); } - }; - minutesInputEl.bind("blur", function(e) { - if (!$scope.invalidMinutes && $scope.minutes < 10) { - $scope.$apply(function() { - $scope.minutes = pad($scope.minutes); + if (!isHtml5DateInput) { + ngModel.$$parserName = "date"; + ngModel.$validators.date = validator; + ngModel.$parsers.unshift(parseDate); + ngModel.$formatters.push(function(value) { + scope.date = value; + return ngModel.$isEmpty(value) ? value : dateFilter(value, dateFormat); + }); + } else { + ngModel.$formatters.push(function(value) { + scope.date = value; + return value; }); } - }); - }; - this.render = function() { - var date = ngModelCtrl.$viewValue; - if (isNaN(date)) { - ngModelCtrl.$setValidity("time", false); - $log.error('Timepicker directive: "ng-model" value must be a Date object, a number of milliseconds since 01.01.1970 or a string representing an RFC2822 or ISO 8601 date.'); - } else { - if (date) { - selected = date; - } - if (selected < min || selected > max) { - ngModelCtrl.$setValidity("time", false); - $scope.invalidHours = true; - $scope.invalidMinutes = true; + scope.dateSelection = function(dt) { + if (angular.isDefined(dt)) { + scope.date = dt; + } + var date = scope.date ? dateFilter(scope.date, dateFormat) : null; + element.val(date); + ngModel.$setViewValue(date); + if (closeOnDateSelection) { + scope.isOpen = false; + element[0].focus(); + } + }; + ngModel.$viewChangeListeners.push(function() { + scope.date = dateParser.parse(ngModel.$viewValue, dateFormat, scope.date); + }); + var documentClickBind = function(event) { + if (scope.isOpen && !(element[0].contains(event.target) || popupEl[0].contains(event.target))) { + scope.$apply(function() { + scope.isOpen = false; + }); + } + }; + var inputKeydownBind = function(evt) { + if (evt.which === 27 && scope.isOpen) { + evt.preventDefault(); + evt.stopPropagation(); + scope.$apply(function() { + scope.isOpen = false; + }); + element[0].focus(); + } else if (evt.which === 40 && !scope.isOpen) { + evt.preventDefault(); + evt.stopPropagation(); + scope.$apply(function() { + scope.isOpen = true; + }); + } + }; + element.bind("keydown", inputKeydownBind); + scope.keydown = function(evt) { + if (evt.which === 27) { + scope.isOpen = false; + element[0].focus(); + } + }; + scope.$watch("isOpen", function(value) { + if (value) { + scope.position = appendToBody ? $position.offset(element) : $position.position(element); + scope.position.top = scope.position.top + element.prop("offsetHeight"); + $timeout(function() { + if (onOpenFocus) { + scope.$broadcast("datepicker.focus"); + } + $document.bind("click", documentClickBind); + }, 0, false); + } else { + $document.unbind("click", documentClickBind); + } + }); + scope.select = function(date) { + if (date === "today") { + var today = new Date(); + if (angular.isDate(scope.date)) { + date = new Date(scope.date); + date.setFullYear(today.getFullYear(), today.getMonth(), today.getDate()); + } else { + date = new Date(today.setHours(0, 0, 0, 0)); + } + } + scope.dateSelection(date); + }; + scope.close = function() { + scope.isOpen = false; + element[0].focus(); + }; + var $popup = $compile(popupEl)(scope); + popupEl.remove(); + if (appendToBody) { + $document.find("body").append($popup); } else { - makeValid(); + element.after($popup); } - updateTemplate(); + scope.$on("$destroy", function() { + if (scope.isOpen === true) { + if (!$rootScope.$$phase) { + scope.$apply(function() { + scope.isOpen = false; + }); + } + } + $popup.remove(); + element.unbind("keydown", inputKeydownBind); + $document.unbind("click", documentClickBind); + }); } }; - function refresh(keyboardChange) { - makeValid(); - ngModelCtrl.$setViewValue(new Date(selected)); - updateTemplate(keyboardChange); - } - function makeValid() { - ngModelCtrl.$setValidity("time", true); - $scope.invalidHours = false; - $scope.invalidMinutes = false; - } - function updateTemplate(keyboardChange) { - var hours = selected.getHours(), minutes = selected.getMinutes(); - if ($scope.showMeridian) { - hours = hours === 0 || hours === 12 ? 12 : hours % 12; +} ]).directive("datepickerPopupWrap", function() { + return { + restrict: "EA", + replace: true, + transclude: true, + templateUrl: function(element, attrs) { + return attrs.templateUrl || "template/datepicker/popup.html"; } - $scope.hours = keyboardChange === "h" ? hours : pad(hours); - if (keyboardChange !== "m") { - $scope.minutes = pad(minutes); + }; +}); + +angular.module("ui.bootstrap.dropdown", [ "ui.bootstrap.position" ]).constant("dropdownConfig", { + openClass: "open" +}).service("dropdownService", [ "$document", "$rootScope", function($document, $rootScope) { + var openScope = null; + this.open = function(dropdownScope) { + if (!openScope) { + $document.bind("click", closeDropdown); + $document.bind("keydown", keybindFilter); } - $scope.meridian = selected.getHours() < 12 ? meridians[0] : meridians[1]; - } - function addMinutes(date, minutes) { - var dt = new Date(date.getTime() + minutes * 6e4); - var newDate = new Date(date); - newDate.setHours(dt.getHours(), dt.getMinutes()); - return newDate; - } - function addMinutesToSelected(minutes) { - selected = addMinutes(selected, minutes); - refresh(); - } - $scope.showSpinners = angular.isDefined($attrs.showSpinners) ? $scope.$parent.$eval($attrs.showSpinners) : timepickerConfig.showSpinners; - $scope.incrementHours = function() { - if (!$scope.noIncrementHours()) { - addMinutesToSelected(hourStep * 60); + if (openScope && openScope !== dropdownScope) { + openScope.isOpen = false; } + openScope = dropdownScope; }; - $scope.decrementHours = function() { - if (!$scope.noDecrementHours()) { - addMinutesToSelected(-hourStep * 60); + this.close = function(dropdownScope) { + if (openScope === dropdownScope) { + openScope = null; + $document.unbind("click", closeDropdown); + $document.unbind("keydown", keybindFilter); } }; - $scope.incrementMinutes = function() { - if (!$scope.noIncrementMinutes()) { - addMinutesToSelected(minuteStep); + var closeDropdown = function(evt) { + if (!openScope) { + return; } - }; - $scope.decrementMinutes = function() { - if (!$scope.noDecrementMinutes()) { - addMinutesToSelected(-minuteStep); + if (evt && openScope.getAutoClose() === "disabled") { + return; } - }; - $scope.toggleMeridian = function() { - if (!$scope.noToggleMeridian()) { - addMinutesToSelected(12 * 60 * (selected.getHours() < 12 ? 1 : -1)); + var toggleElement = openScope.getToggleElement(); + if (evt && toggleElement && toggleElement[0].contains(evt.target)) { + return; + } + var dropdownElement = openScope.getDropdownElement(); + if (evt && openScope.getAutoClose() === "outsideClick" && dropdownElement && dropdownElement[0].contains(evt.target)) { + return; + } + openScope.isOpen = false; + if (!$rootScope.$$phase) { + openScope.$apply(); } }; -} ]).directive("timepicker", function() { - return { - restrict: "EA", - require: [ "timepicker", "?^ngModel" ], - controller: "TimepickerController", - controllerAs: "timepicker", - replace: true, - scope: {}, - templateUrl: function(element, attrs) { - return attrs.templateUrl || "template/timepicker/timepicker.html"; - }, - link: function(scope, element, attrs, ctrls) { - var timepickerCtrl = ctrls[0], ngModelCtrl = ctrls[1]; - if (ngModelCtrl) { - timepickerCtrl.init(ngModelCtrl, element.find("input")); - } + var keybindFilter = function(evt) { + if (evt.which === 27) { + openScope.focusToggleElement(); + closeDropdown(); + } else if (openScope.isKeynavEnabled() && /(38|40)/.test(evt.which) && openScope.isOpen) { + evt.preventDefault(); + evt.stopPropagation(); + openScope.focusDropdownEntry(evt.which); } }; -}); - -angular.module("ui.bootstrap.transition", []).value("$transitionSuppressDeprecated", false).factory("$transition", [ "$q", "$timeout", "$rootScope", "$log", "$transitionSuppressDeprecated", function($q, $timeout, $rootScope, $log, $transitionSuppressDeprecated) { - if (!$transitionSuppressDeprecated) { - $log.warn("$transition is now deprecated. Use $animate from ngAnimate instead."); - } - var $transition = function(element, trigger, options) { - options = options || {}; - var deferred = $q.defer(); - var endEventName = $transition[options.animation ? "animationEndEventName" : "transitionEndEventName"]; - var transitionEndHandler = function(event) { - $rootScope.$apply(function() { - element.unbind(endEventName, transitionEndHandler); - deferred.resolve(element); +} ]).controller("DropdownController", [ "$scope", "$attrs", "$parse", "dropdownConfig", "dropdownService", "$animate", "$position", "$document", "$compile", "$templateRequest", function($scope, $attrs, $parse, dropdownConfig, dropdownService, $animate, $position, $document, $compile, $templateRequest) { + var self = this, scope = $scope.$new(), templateScope, openClass = dropdownConfig.openClass, getIsOpen, setIsOpen = angular.noop, toggleInvoker = $attrs.onToggle ? $parse($attrs.onToggle) : angular.noop, appendToBody = false, keynavEnabled = false, selectedOption = null, body = $document.find("body"); + this.init = function(element) { + self.$element = element; + if ($attrs.isOpen) { + getIsOpen = $parse($attrs.isOpen); + setIsOpen = getIsOpen.assign; + $scope.$watch(getIsOpen, function(value) { + scope.isOpen = !!value; + }); + } + appendToBody = angular.isDefined($attrs.dropdownAppendToBody); + keynavEnabled = angular.isDefined($attrs.keyboardNav); + if (appendToBody && self.dropdownMenu) { + body.append(self.dropdownMenu); + body.addClass("dropdown"); + element.on("$destroy", function handleDestroyEvent() { + self.dropdownMenu.remove(); }); - }; - if (endEventName) { - element.bind(endEventName, transitionEndHandler); } - $timeout(function() { - if (angular.isString(trigger)) { - element.addClass(trigger); - } else if (angular.isFunction(trigger)) { - trigger(element); - } else if (angular.isObject(trigger)) { - element.css(trigger); - } - if (!endEventName) { - deferred.resolve(element); - } - }); - deferred.promise.cancel = function() { - if (endEventName) { - element.unbind(endEventName, transitionEndHandler); - } - deferred.reject("Transition cancelled"); - }; - return deferred.promise; }; - var transElement = document.createElement("trans"); - var transitionEndEventNames = { - WebkitTransition: "webkitTransitionEnd", - MozTransition: "transitionend", - OTransition: "oTransitionEnd", - transition: "transitionend" + this.toggle = function(open) { + return scope.isOpen = arguments.length ? !!open : !scope.isOpen; }; - var animationEndEventNames = { - WebkitTransition: "webkitAnimationEnd", - MozTransition: "animationend", - OTransition: "oAnimationEnd", - transition: "animationend" + this.isOpen = function() { + return scope.isOpen; }; - function findEndEventName(endEventNames) { - for (var name in endEventNames) { - if (transElement.style[name] !== undefined) { - return endEventNames[name]; - } - } - } - $transition.transitionEndEventName = findEndEventName(transitionEndEventNames); - $transition.animationEndEventName = findEndEventName(animationEndEventNames); - return $transition; -} ]); - -angular.module("ui.bootstrap.typeahead", [ "ui.bootstrap.position" ]).factory("typeaheadParser", [ "$parse", function($parse) { - var TYPEAHEAD_REGEXP = /^\s*([\s\S]+?)(?:\s+as\s+([\s\S]+?))?\s+for\s+(?:([\$\w][\$\w\d]*))\s+in\s+([\s\S]+?)$/; - return { - parse: function(input) { - var match = input.match(TYPEAHEAD_REGEXP); - if (!match) { - throw new Error('Expected typeahead specification in form of "_modelValue_ (as _label_)? for _item_ in _collection_"' + ' but got "' + input + '".'); - } - return { - itemName: match[3], - source: $parse(match[4]), - viewMapper: $parse(match[2] || match[1]), - modelMapper: $parse(match[1]) - }; - } + scope.getToggleElement = function() { + return self.toggleElement; }; -} ]).directive("typeahead", [ "$compile", "$parse", "$q", "$timeout", "$document", "$window", "$rootScope", "$position", "typeaheadParser", function($compile, $parse, $q, $timeout, $document, $window, $rootScope, $position, typeaheadParser) { - var HOT_KEYS = [ 9, 13, 27, 38, 40 ]; - var eventDebounceTime = 200; - return { - require: [ "ngModel", "^?ngModelOptions" ], - link: function(originalScope, element, attrs, ctrls) { - var modelCtrl = ctrls[0]; - var ngModelOptions = ctrls[1]; - var minLength = originalScope.$eval(attrs.typeaheadMinLength); - if (!minLength && minLength !== 0) { - minLength = 1; - } - var waitTime = originalScope.$eval(attrs.typeaheadWaitMs) || 0; - var isEditable = originalScope.$eval(attrs.typeaheadEditable) !== false; - var isLoadingSetter = $parse(attrs.typeaheadLoading).assign || angular.noop; - var onSelectCallback = $parse(attrs.typeaheadOnSelect); - var isSelectOnBlur = angular.isDefined(attrs.typeaheadSelectOnBlur) ? originalScope.$eval(attrs.typeaheadSelectOnBlur) : false; - var isNoResultsSetter = $parse(attrs.typeaheadNoResults).assign || angular.noop; - var inputFormatter = attrs.typeaheadInputFormatter ? $parse(attrs.typeaheadInputFormatter) : undefined; - var appendToBody = attrs.typeaheadAppendToBody ? originalScope.$eval(attrs.typeaheadAppendToBody) : false; - var focusFirst = originalScope.$eval(attrs.typeaheadFocusFirst) !== false; - var selectOnExact = attrs.typeaheadSelectOnExact ? originalScope.$eval(attrs.typeaheadSelectOnExact) : false; - var parsedModel = $parse(attrs.ngModel); - var invokeModelSetter = $parse(attrs.ngModel + "($$$p)"); - var $setModelValue = function(scope, newValue) { - if (angular.isFunction(parsedModel(originalScope)) && ngModelOptions && ngModelOptions.$options && ngModelOptions.$options.getterSetter) { - return invokeModelSetter(scope, { - $$$p: newValue - }); + scope.getAutoClose = function() { + return $attrs.autoClose || "always"; + }; + scope.getElement = function() { + return self.$element; + }; + scope.isKeynavEnabled = function() { + return keynavEnabled; + }; + scope.focusDropdownEntry = function(keyCode) { + var elems = self.dropdownMenu ? angular.element(self.dropdownMenu).find("a") : angular.element(self.$element).find("ul").eq(0).find("a"); + switch (keyCode) { + case 40: + { + if (!angular.isNumber(self.selectedOption)) { + self.selectedOption = 0; } else { - return parsedModel.assign(scope, newValue); + self.selectedOption = self.selectedOption === elems.length - 1 ? self.selectedOption : self.selectedOption + 1; } - }; - var parserResult = typeaheadParser.parse(attrs.typeahead); - var hasFocus; - var selected; - var scope = originalScope.$new(); - var offDestroy = originalScope.$on("$destroy", function() { - scope.$destroy(); - }); - scope.$on("$destroy", offDestroy); - var popupId = "typeahead-" + scope.$id + "-" + Math.floor(Math.random() * 1e4); - element.attr({ - "aria-autocomplete": "list", - "aria-expanded": false, - "aria-owns": popupId - }); - var popUpEl = angular.element("
        "); - popUpEl.attr({ - id: popupId, - matches: "matches", - active: "activeIdx", - select: "select(activeIdx)", - "move-in-progress": "moveInProgress", - query: "query", - position: "position" - }); - if (angular.isDefined(attrs.typeaheadTemplateUrl)) { - popUpEl.attr("template-url", attrs.typeaheadTemplateUrl); - } - if (angular.isDefined(attrs.typeaheadPopupTemplateUrl)) { - popUpEl.attr("popup-template-url", attrs.typeaheadPopupTemplateUrl); + break; } - var resetMatches = function() { - scope.matches = []; - scope.activeIdx = -1; - element.attr("aria-expanded", false); - }; - var getMatchId = function(index) { - return popupId + "-option-" + index; - }; - scope.$watch("activeIdx", function(index) { - if (index < 0) { - element.removeAttr("aria-activedescendant"); + + case 38: + { + if (!angular.isNumber(self.selectedOption)) { + self.selectedOption = elems.length - 1; } else { - element.attr("aria-activedescendant", getMatchId(index)); - } - }); - var inputIsExactMatch = function(inputValue, index) { - if (scope.matches.length > index && inputValue) { - return inputValue.toUpperCase() === scope.matches[index].label.toUpperCase(); + self.selectedOption = self.selectedOption === 0 ? 0 : self.selectedOption - 1; } - return false; + break; + } + } + elems[self.selectedOption].focus(); + }; + scope.getDropdownElement = function() { + return self.dropdownMenu; + }; + scope.focusToggleElement = function() { + if (self.toggleElement) { + self.toggleElement[0].focus(); + } + }; + scope.$watch("isOpen", function(isOpen, wasOpen) { + if (appendToBody && self.dropdownMenu) { + var pos = $position.positionElements(self.$element, self.dropdownMenu, "bottom-left", true); + var css = { + top: pos.top + "px", + display: isOpen ? "block" : "none" }; - var getMatchesAsync = function(inputValue) { - var locals = { - $viewValue: inputValue - }; - isLoadingSetter(originalScope, true); - isNoResultsSetter(originalScope, false); - $q.when(parserResult.source(originalScope, locals)).then(function(matches) { - var onCurrentRequest = inputValue === modelCtrl.$viewValue; - if (onCurrentRequest && hasFocus) { - if (matches && matches.length > 0) { - scope.activeIdx = focusFirst ? 0 : -1; - isNoResultsSetter(originalScope, false); - scope.matches.length = 0; - for (var i = 0; i < matches.length; i++) { - locals[parserResult.itemName] = matches[i]; - scope.matches.push({ - id: getMatchId(i), - label: parserResult.viewMapper(scope, locals), - model: matches[i] - }); - } - scope.query = inputValue; - recalculatePosition(); - element.attr("aria-expanded", true); - if (selectOnExact && scope.matches.length === 1 && inputIsExactMatch(inputValue, 0)) { - scope.select(0); - } - } else { - resetMatches(); - isNoResultsSetter(originalScope, true); - } - } - if (onCurrentRequest) { - isLoadingSetter(originalScope, false); - } - }, function() { - resetMatches(); - isLoadingSetter(originalScope, false); - isNoResultsSetter(originalScope, true); + var rightalign = self.dropdownMenu.hasClass("dropdown-menu-right"); + if (!rightalign) { + css.left = pos.left + "px"; + css.right = "auto"; + } else { + css.left = "auto"; + css.right = window.innerWidth - (pos.left + self.$element.prop("offsetWidth")) + "px"; + } + self.dropdownMenu.css(css); + } + var openContainer = appendToBody ? body : self.$element; + $animate[isOpen ? "addClass" : "removeClass"](openContainer, openClass).then(function() { + if (angular.isDefined(isOpen) && isOpen !== wasOpen) { + toggleInvoker($scope, { + open: !!isOpen }); - }; - if (appendToBody) { - angular.element($window).bind("resize", fireRecalculating); - $document.find("body").bind("scroll", fireRecalculating); } - var timeoutEventPromise; - scope.moveInProgress = false; - function fireRecalculating() { - if (!scope.moveInProgress) { - scope.moveInProgress = true; - scope.$digest(); - } - if (timeoutEventPromise) { - $timeout.cancel(timeoutEventPromise); + }); + if (isOpen) { + if (self.dropdownMenuTemplateUrl) { + $templateRequest(self.dropdownMenuTemplateUrl).then(function(tplContent) { + templateScope = scope.$new(); + $compile(tplContent.trim())(templateScope, function(dropdownElement) { + var newEl = dropdownElement; + self.dropdownMenu.replaceWith(newEl); + self.dropdownMenu = newEl; + }); + }); + } + scope.focusToggleElement(); + dropdownService.open(scope); + } else { + if (self.dropdownMenuTemplateUrl) { + if (templateScope) { + templateScope.$destroy(); } - timeoutEventPromise = $timeout(function() { - if (scope.matches.length) { - recalculatePosition(); - } - scope.moveInProgress = false; - scope.$digest(); - }, eventDebounceTime); + var newEl = angular.element(''); + self.dropdownMenu.replaceWith(newEl); + self.dropdownMenu = newEl; } - function recalculatePosition() { - scope.position = appendToBody ? $position.offset(element) : $position.position(element); - scope.position.top += element.prop("offsetHeight"); + dropdownService.close(scope); + self.selectedOption = null; + } + if (angular.isFunction(setIsOpen)) { + setIsOpen($scope, isOpen); + } + }); + $scope.$on("$locationChangeSuccess", function() { + if (scope.getAutoClose() !== "disabled") { + scope.isOpen = false; + } + }); + var offDestroy = $scope.$on("$destroy", function() { + scope.$destroy(); + }); + scope.$on("$destroy", offDestroy); +} ]).directive("dropdown", function() { + return { + controller: "DropdownController", + link: function(scope, element, attrs, dropdownCtrl) { + dropdownCtrl.init(element); + element.addClass("dropdown"); + } + }; +}).directive("dropdownMenu", function() { + return { + restrict: "AC", + require: "?^dropdown", + link: function(scope, element, attrs, dropdownCtrl) { + if (!dropdownCtrl) { + return; } - resetMatches(); - scope.query = undefined; - var timeoutPromise; - var scheduleSearchWithTimeout = function(inputValue) { - timeoutPromise = $timeout(function() { - getMatchesAsync(inputValue); - }, waitTime); - }; - var cancelPreviousTimeout = function() { - if (timeoutPromise) { - $timeout.cancel(timeoutPromise); - } - }; - modelCtrl.$parsers.unshift(function(inputValue) { - hasFocus = true; - if (minLength === 0 || inputValue && inputValue.length >= minLength) { - if (waitTime > 0) { - cancelPreviousTimeout(); - scheduleSearchWithTimeout(inputValue); - } else { - getMatchesAsync(inputValue); - } - } else { - isLoadingSetter(originalScope, false); - cancelPreviousTimeout(); - resetMatches(); - } - if (isEditable) { - return inputValue; - } else { - if (!inputValue) { - modelCtrl.$setValidity("editable", true); - return null; - } else { - modelCtrl.$setValidity("editable", false); - return undefined; + var tplUrl = attrs.templateUrl; + if (tplUrl) { + dropdownCtrl.dropdownMenuTemplateUrl = tplUrl; + } + if (!dropdownCtrl.dropdownMenu) { + dropdownCtrl.dropdownMenu = element; + } + } + }; +}).directive("keyboardNav", function() { + return { + restrict: "A", + require: "?^dropdown", + link: function(scope, element, attrs, dropdownCtrl) { + element.bind("keydown", function(e) { + if ([ 38, 40 ].indexOf(e.which) !== -1) { + e.preventDefault(); + e.stopPropagation(); + var elems = dropdownCtrl.dropdownMenu.find("a"); + switch (e.which) { + case 40: + { + if (!angular.isNumber(dropdownCtrl.selectedOption)) { + dropdownCtrl.selectedOption = 0; + } else { + dropdownCtrl.selectedOption = dropdownCtrl.selectedOption === elems.length - 1 ? dropdownCtrl.selectedOption : dropdownCtrl.selectedOption + 1; + } + break; + } + + case 38: + { + if (!angular.isNumber(dropdownCtrl.selectedOption)) { + dropdownCtrl.selectedOption = elems.length - 1; + } else { + dropdownCtrl.selectedOption = dropdownCtrl.selectedOption === 0 ? 0 : dropdownCtrl.selectedOption - 1; + } + break; + } } + elems[dropdownCtrl.selectedOption].focus(); } }); - modelCtrl.$formatters.push(function(modelValue) { - var candidateViewValue, emptyViewValue; - var locals = {}; - if (!isEditable) { - modelCtrl.$setValidity("editable", true); - } - if (inputFormatter) { - locals.$model = modelValue; - return inputFormatter(originalScope, locals); - } else { - locals[parserResult.itemName] = modelValue; - candidateViewValue = parserResult.viewMapper(originalScope, locals); - locals[parserResult.itemName] = undefined; - emptyViewValue = parserResult.viewMapper(originalScope, locals); - return candidateViewValue !== emptyViewValue ? candidateViewValue : modelValue; - } - }); - scope.select = function(activeIdx) { - var locals = {}; - var model, item; - selected = true; - locals[parserResult.itemName] = item = scope.matches[activeIdx].model; - model = parserResult.modelMapper(originalScope, locals); - $setModelValue(originalScope, model); - modelCtrl.$setValidity("editable", true); - modelCtrl.$setValidity("parse", true); - onSelectCallback(originalScope, { - $item: item, - $model: model, - $label: parserResult.viewMapper(originalScope, locals) - }); - resetMatches(); - if (scope.$eval(attrs.typeaheadFocusOnSelect) !== false) { - $timeout(function() { - element[0].focus(); - }, 0, false); - } - }; - element.bind("keydown", function(evt) { - if (scope.matches.length === 0 || HOT_KEYS.indexOf(evt.which) === -1) { - return; - } - if (scope.activeIdx === -1 && (evt.which === 9 || evt.which === 13)) { - resetMatches(); - scope.$digest(); - return; - } - evt.preventDefault(); - if (evt.which === 40) { - scope.activeIdx = (scope.activeIdx + 1) % scope.matches.length; - scope.$digest(); - } else if (evt.which === 38) { - scope.activeIdx = (scope.activeIdx > 0 ? scope.activeIdx : scope.matches.length) - 1; - scope.$digest(); - } else if (evt.which === 13 || evt.which === 9) { + } + }; +}).directive("dropdownToggle", function() { + return { + require: "?^dropdown", + link: function(scope, element, attrs, dropdownCtrl) { + if (!dropdownCtrl) { + return; + } + element.addClass("dropdown-toggle"); + dropdownCtrl.toggleElement = element; + var toggleDropdown = function(event) { + event.preventDefault(); + if (!element.hasClass("disabled") && !attrs.disabled) { scope.$apply(function() { - scope.select(scope.activeIdx); + dropdownCtrl.toggle(); }); - } else if (evt.which === 27) { - evt.stopPropagation(); - resetMatches(); - scope.$digest(); } + }; + element.bind("click", toggleDropdown); + element.attr({ + "aria-haspopup": true, + "aria-expanded": false }); - element.bind("blur", function() { - if (isSelectOnBlur && scope.matches.length && scope.activeIdx !== -1 && !selected) { - selected = true; - scope.$apply(function() { - scope.select(scope.activeIdx); - }); - } - hasFocus = false; - selected = false; + scope.$watch(dropdownCtrl.isOpen, function(isOpen) { + element.attr("aria-expanded", !!isOpen); }); - var dismissClickHandler = function(evt) { - if (element[0] !== evt.target && evt.which !== 3 && scope.matches.length !== 0) { - resetMatches(); - if (!$rootScope.$$phase) { - scope.$digest(); + scope.$on("$destroy", function() { + element.unbind("click", toggleDropdown); + }); + } + }; +}); + +angular.module("ui.bootstrap.modal", []).factory("$$stackedMap", function() { + return { + createNew: function() { + var stack = []; + return { + add: function(key, value) { + stack.push({ + key: key, + value: value + }); + }, + get: function(key) { + for (var i = 0; i < stack.length; i++) { + if (key == stack[i].key) { + return stack[i]; + } + } + }, + keys: function() { + var keys = []; + for (var i = 0; i < stack.length; i++) { + keys.push(stack[i].key); + } + return keys; + }, + top: function() { + return stack[stack.length - 1]; + }, + remove: function(key) { + var idx = -1; + for (var i = 0; i < stack.length; i++) { + if (key == stack[i].key) { + idx = i; + break; + } } + return stack.splice(idx, 1)[0]; + }, + removeTop: function() { + return stack.splice(stack.length - 1, 1)[0]; + }, + length: function() { + return stack.length; } }; - $document.bind("click", dismissClickHandler); - originalScope.$on("$destroy", function() { - $document.unbind("click", dismissClickHandler); - if (appendToBody) { - $popup.remove(); - } - popUpEl.remove(); - }); - var $popup = $compile(popUpEl)(scope); - if (appendToBody) { - $document.find("body").append($popup); - } else { - element.after($popup); - } } }; -} ]).directive("typeaheadPopup", function() { +}).factory("$$multiMap", function() { return { - restrict: "EA", - scope: { - matches: "=", - query: "=", - active: "=", - position: "&", - moveInProgress: "=", - select: "&" - }, - replace: true, - templateUrl: function(element, attrs) { - return attrs.popupTemplateUrl || "template/typeahead/typeahead-popup.html"; - }, - link: function(scope, element, attrs) { - scope.templateUrl = attrs.templateUrl; - scope.isOpen = function() { - return scope.matches.length > 0; - }; - scope.isActive = function(matchIdx) { - return scope.active == matchIdx; - }; - scope.selectActive = function(matchIdx) { - scope.active = matchIdx; - }; - scope.selectMatch = function(activeIdx) { - scope.select({ - activeIdx: activeIdx - }); + createNew: function() { + var map = {}; + return { + entries: function() { + return Object.keys(map).map(function(key) { + return { + key: key, + value: map[key] + }; + }); + }, + get: function(key) { + return map[key]; + }, + hasKey: function(key) { + return !!map[key]; + }, + keys: function() { + return Object.keys(map); + }, + put: function(key, value) { + if (!map[key]) { + map[key] = []; + } + map[key].push(value); + }, + remove: function(key, value) { + var values = map[key]; + if (!values) { + return; + } + var idx = values.indexOf(value); + if (idx !== -1) { + values.splice(idx, 1); + } + if (!values.length) { + delete map[key]; + } + } }; } }; -}).directive("typeaheadMatch", [ "$templateRequest", "$compile", "$parse", function($templateRequest, $compile, $parse) { +}).directive("modalBackdrop", [ "$animate", "$injector", "$modalStack", function($animate, $injector, $modalStack) { + var $animateCss = null; + if ($injector.has("$animateCss")) { + $animateCss = $injector.get("$animateCss"); + } return { restrict: "EA", - scope: { - index: "=", - match: "=", - query: "=" - }, - link: function(scope, element, attrs) { - var tplUrl = $parse(attrs.templateUrl)(scope.$parent) || "template/typeahead/typeahead-match.html"; - $templateRequest(tplUrl).then(function(tplContent) { - $compile(tplContent.trim())(scope, function(clonedElement) { - element.replaceWith(clonedElement); - }); - }); - } - }; -} ]).filter("typeaheadHighlight", [ "$sce", "$injector", "$log", function($sce, $injector, $log) { - var isSanitizePresent; - isSanitizePresent = $injector.has("$sanitize"); - function escapeRegexp(queryToEscape) { - return queryToEscape.replace(/([.?*+^$[\]\\(){}|-])/g, "\\$1"); - } - function containsHtml(matchItem) { - return /<.*>/g.test(matchItem); - } - return function(matchItem, query) { - if (!isSanitizePresent && containsHtml(matchItem)) { - $log.warn("Unsafe use of typeahead please use ngSanitize"); - } - matchItem = query ? ("" + matchItem).replace(new RegExp(escapeRegexp(query), "gi"), "$&") : matchItem; - if (!isSanitizePresent) { - matchItem = $sce.trustAsHtml(matchItem); + replace: true, + templateUrl: "template/modal/backdrop.html", + compile: function(tElement, tAttrs) { + tElement.addClass(tAttrs.backdropClass); + return linkFn; } - return matchItem; }; -} ]); - -angular.module("template/accordion/accordion-group.html", []).run([ "$templateCache", function($templateCache) { - $templateCache.put("template/accordion/accordion-group.html", "
        \n" + '
        \n' + '

        \n' + ' {{heading}}\n' + "

        \n" + "
        \n" + '
        \n' + '
        \n' + "
        \n" + "
        \n" + ""); -} ]); - -angular.module("template/accordion/accordion.html", []).run([ "$templateCache", function($templateCache) { - $templateCache.put("template/accordion/accordion.html", '
        '); -} ]); - -angular.module("template/alert/alert.html", []).run([ "$templateCache", function($templateCache) { - $templateCache.put("template/alert/alert.html", "
        \n" + ' \n" + "
        \n" + "
        \n" + ""); -} ]); - -angular.module("template/carousel/carousel.html", []).run([ "$templateCache", function($templateCache) { - $templateCache.put("template/carousel/carousel.html", '\n" + ""); -} ]); - -angular.module("template/carousel/slide.html", []).run([ "$templateCache", function($templateCache) { - $templateCache.put("template/carousel/slide.html", '
        \n' + ""); -} ]); - -angular.module("template/datepicker/datepicker.html", []).run([ "$templateCache", function($templateCache) { - $templateCache.put("template/datepicker/datepicker.html", '
        \n' + ' \n' + ' \n' + ' \n' + "
        "); -} ]); - -angular.module("template/datepicker/day.html", []).run([ "$templateCache", function($templateCache) { - $templateCache.put("template/datepicker/day.html", '\n' + " \n" + " \n" + ' \n' + ' \n' + ' \n' + " \n" + " \n" + ' \n' + ' \n' + " \n" + " \n" + " \n" + ' \n' + ' \n' + ' \n" + " \n" + " \n" + "
        {{::label.abbr}}
        {{ weekNumbers[$index] }}\n' + ' \n' + "
        \n" + ""); -} ]); - -angular.module("template/datepicker/month.html", []).run([ "$templateCache", function($templateCache) { - $templateCache.put("template/datepicker/month.html", '\n' + " \n" + " \n" + ' \n' + ' \n' + ' \n' + " \n" + " \n" + " \n" + ' \n' + ' \n" + " \n" + " \n" + "
        \n' + ' \n' + "
        \n" + ""); -} ]); - -angular.module("template/datepicker/popup.html", []).run([ "$templateCache", function($templateCache) { - $templateCache.put("template/datepicker/popup.html", '\n" + ""); -} ]); - -angular.module("template/datepicker/year.html", []).run([ "$templateCache", function($templateCache) { - $templateCache.put("template/datepicker/year.html", '\n' + " \n" + " \n" + ' \n' + ' \n' + ' \n' + " \n" + " \n" + " \n" + ' \n' + ' \n" + " \n" + " \n" + "
        \n' + ' \n' + "
        \n" + ""); -} ]); - -angular.module("template/modal/backdrop.html", []).run([ "$templateCache", function($templateCache) { - $templateCache.put("template/modal/backdrop.html", '\n" + ""); -} ]); - -angular.module("template/modal/window.html", []).run([ "$templateCache", function($templateCache) { - $templateCache.put("template/modal/window.html", '\n" + ""); -} ]); - -angular.module("template/pagination/pager.html", []).run([ "$templateCache", function($templateCache) { - $templateCache.put("template/pagination/pager.html", '\n" + ""); -} ]); - -angular.module("template/pagination/pagination.html", []).run([ "$templateCache", function($templateCache) { - $templateCache.put("template/pagination/pagination.html", '\n" + ""); -} ]); - -angular.module("template/tooltip/tooltip-html-popup.html", []).run([ "$templateCache", function($templateCache) { - $templateCache.put("template/tooltip/tooltip-html-popup.html", '
        \n' + '
        \n' + '
        \n' + "
        \n" + ""); -} ]); - -angular.module("template/tooltip/tooltip-html-unsafe-popup.html", []).run([ "$templateCache", function($templateCache) { - $templateCache.put("template/tooltip/tooltip-html-unsafe-popup.html", '
        \n' + '
        \n' + '
        \n' + "
        \n" + ""); -} ]); - -angular.module("template/tooltip/tooltip-popup.html", []).run([ "$templateCache", function($templateCache) { - $templateCache.put("template/tooltip/tooltip-popup.html", '
        \n' + '
        \n' + '
        \n' + "
        \n" + ""); -} ]); - -angular.module("template/tooltip/tooltip-template-popup.html", []).run([ "$templateCache", function($templateCache) { - $templateCache.put("template/tooltip/tooltip-template-popup.html", '
        \n' + '
        \n' + '
        \n' + "
        \n" + ""); -} ]); - -angular.module("template/popover/popover-html.html", []).run([ "$templateCache", function($templateCache) { - $templateCache.put("template/popover/popover-html.html", '
        \n' + '
        \n' + "\n" + '
        \n' + '

        \n' + '
        \n' + "
        \n" + "
        \n" + ""); -} ]); - -angular.module("template/popover/popover-template.html", []).run([ "$templateCache", function($templateCache) { - $templateCache.put("template/popover/popover-template.html", '
        \n' + '
        \n' + "\n" + '
        \n' + '

        \n' + '
        \n' + "
        \n" + "
        \n" + ""); -} ]); - -angular.module("template/popover/popover.html", []).run([ "$templateCache", function($templateCache) { - $templateCache.put("template/popover/popover.html", '
        \n' + '
        \n' + "\n" + '
        \n' + '

        \n' + '
        \n' + "
        \n" + "
        \n" + ""); -} ]); - -angular.module("template/progressbar/bar.html", []).run([ "$templateCache", function($templateCache) { - $templateCache.put("template/progressbar/bar.html", '
        \n' + ""); -} ]); - -angular.module("template/progressbar/progress.html", []).run([ "$templateCache", function($templateCache) { - $templateCache.put("template/progressbar/progress.html", '
        '); -} ]); - -angular.module("template/progressbar/progressbar.html", []).run([ "$templateCache", function($templateCache) { - $templateCache.put("template/progressbar/progressbar.html", '
        \n' + '
        \n' + "
        \n" + ""); -} ]); - -angular.module("template/rating/rating.html", []).run([ "$templateCache", function($templateCache) { - $templateCache.put("template/rating/rating.html", '\n' + " ({{ $index < value ? '*' : ' ' }})\n" + ' \n' + "\n" + ""); -} ]); - -angular.module("template/tabs/tab.html", []).run([ "$templateCache", function($templateCache) { - $templateCache.put("template/tabs/tab.html", '
      • \n' + ' {{heading}}\n' + "
      • \n" + ""); -} ]); - -angular.module("template/tabs/tabset.html", []).run([ "$templateCache", function($templateCache) { - $templateCache.put("template/tabs/tabset.html", "
        \n" + "
          \n" + '
          \n' + '
          \n' + "
          \n" + "
          \n" + "
          \n" + ""); -} ]); - -angular.module("template/timepicker/timepicker.html", []).run([ "$templateCache", function($templateCache) { - $templateCache.put("template/timepicker/timepicker.html", "\n" + " \n" + ' \n' + ' \n' + " \n" + ' \n' + ' \n' + " \n" + " \n" + ' \n" + " \n" + ' \n" + ' \n' + " \n" + ' \n' + ' \n' + " \n" + ' \n' + ' \n' + " \n" + " \n" + "
           
          \n' + ' \n' + " :\n' + ' \n' + "
           
          \n" + ""); -} ]); - -angular.module("template/typeahead/typeahead-match.html", []).run([ "$templateCache", function($templateCache) { - $templateCache.put("template/typeahead/typeahead-match.html", '\n' + ""); -} ]); - -angular.module("template/typeahead/typeahead-popup.html", []).run([ "$templateCache", function($templateCache) { - $templateCache.put("template/typeahead/typeahead-popup.html", '\n" + ""); -} ]); - -!angular.$$csp() && angular.element(document).find("head").prepend(''); - -"use strict"; - -var WaveSurfer = { - defaultParams: { - height: 128, - waveColor: "#999", - progressColor: "#555", - cursorColor: "#333", - cursorWidth: 1, - skipLength: 2, - minPxPerSec: 20, - pixelRatio: window.devicePixelRatio, - fillParent: !0, - scrollParent: !1, - hideScrollbar: !1, - normalize: !1, - audioContext: null, - container: null, - dragSelection: !0, - loopSelection: !0, - audioRate: 1, - interact: !0, - splitChannels: !1, - renderer: "Canvas", - backend: "WebAudio", - mediaType: "audio" - }, - init: function(a) { - if (this.params = WaveSurfer.util.extend({}, this.defaultParams, a), this.container = "string" == typeof a.container ? document.querySelector(this.params.container) : this.params.container, - !this.container) throw new Error("Container element not found"); - if ("undefined" == typeof this.params.mediaContainer ? this.mediaContainer = this.container : "string" == typeof this.params.mediaContainer ? this.mediaContainer = document.querySelector(this.params.mediaContainer) : this.mediaContainer = this.params.mediaContainer, - !this.mediaContainer) throw new Error("Media Container element not found"); - this.savedVolume = 0, this.isMuted = !1, this.tmpEvents = [], this.createDrawer(), - this.createBackend(); - }, - createDrawer: function() { - var a = this; - this.drawer = Object.create(WaveSurfer.Drawer[this.params.renderer]), this.drawer.init(this.container, this.params), - this.drawer.on("redraw", function() { - a.drawBuffer(), a.drawer.progress(a.backend.getPlayedPercents()); - }), this.drawer.on("click", function(b, c) { - setTimeout(function() { - a.seekTo(c); - }, 0); - }), this.drawer.on("scroll", function(b) { - a.fireEvent("scroll", b); - }); - }, - createBackend: function() { - var a = this; - this.backend && this.backend.destroy(), "AudioElement" == this.params.backend && (this.params.backend = "MediaElement"), - "WebAudio" != this.params.backend || WaveSurfer.WebAudio.supportsWebAudio() || (this.params.backend = "MediaElement"), - this.backend = Object.create(WaveSurfer[this.params.backend]), this.backend.init(this.params), - this.backend.on("finish", function() { - a.fireEvent("finish"); - }), this.backend.on("play", function() { - a.fireEvent("play"); - }), this.backend.on("pause", function() { - a.fireEvent("pause"); - }), this.backend.on("audioprocess", function(b) { - a.drawer.progress(a.backend.getPlayedPercents()), a.fireEvent("audioprocess", b); + function linkFn(scope, element, attrs) { + if (attrs.modalInClass) { + if ($animateCss) { + $animateCss(element, { + addClass: attrs.modalInClass + }).start(); + } else { + $animate.addClass(element, attrs.modalInClass); + } + scope.$on($modalStack.NOW_CLOSING_EVENT, function(e, setIsAsync) { + var done = setIsAsync(); + if ($animateCss) { + $animateCss(element, { + removeClass: attrs.modalInClass + }).start().then(done); + } else { + $animate.removeClass(element, attrs.modalInClass).then(done); + } + }); + } + } +} ]).directive("modalWindow", [ "$modalStack", "$q", "$animate", "$injector", function($modalStack, $q, $animate, $injector) { + var $animateCss = null; + if ($injector.has("$animateCss")) { + $animateCss = $injector.get("$animateCss"); + } + return { + restrict: "EA", + scope: { + index: "@" + }, + replace: true, + transclude: true, + templateUrl: function(tElement, tAttrs) { + return tAttrs.templateUrl || "template/modal/window.html"; + }, + link: function(scope, element, attrs) { + element.addClass(attrs.windowClass || ""); + scope.size = attrs.size; + scope.close = function(evt) { + var modal = $modalStack.getTop(); + if (modal && modal.value.backdrop && modal.value.backdrop !== "static" && evt.target === evt.currentTarget) { + evt.preventDefault(); + evt.stopPropagation(); + $modalStack.dismiss(modal.key, "backdrop click"); + } + }; + scope.$isRendered = true; + var modalRenderDeferObj = $q.defer(); + attrs.$observe("modalRender", function(value) { + if (value == "true") { + modalRenderDeferObj.resolve(); + } + }); + modalRenderDeferObj.promise.then(function() { + var animationPromise = null; + if (attrs.modalInClass) { + if ($animateCss) { + animationPromise = $animateCss(element, { + addClass: attrs.modalInClass + }).start(); + } else { + animationPromise = $animate.addClass(element, attrs.modalInClass); + } + scope.$on($modalStack.NOW_CLOSING_EVENT, function(e, setIsAsync) { + var done = setIsAsync(); + if ($animateCss) { + $animateCss(element, { + removeClass: attrs.modalInClass + }).start().then(done); + } else { + $animate.removeClass(element, attrs.modalInClass).then(done); + } + }); + } + $q.when(animationPromise).then(function() { + var inputsWithAutofocus = element[0].querySelectorAll("[autofocus]"); + if (inputsWithAutofocus.length) { + inputsWithAutofocus[0].focus(); + } else { + element[0].focus(); + } + }); + var modal = $modalStack.getTop(); + if (modal) { + $modalStack.modalRendered(modal.key); + } + }); + } + }; +} ]).directive("modalAnimationClass", [ function() { + return { + compile: function(tElement, tAttrs) { + if (tAttrs.modalAnimation) { + tElement.addClass(tAttrs.modalAnimationClass); + } + } + }; +} ]).directive("modalTransclude", function() { + return { + link: function($scope, $element, $attrs, controller, $transclude) { + $transclude($scope.$parent, function(clone) { + $element.empty(); + $element.append(clone); + }); + } + }; +}).factory("$modalStack", [ "$animate", "$timeout", "$document", "$compile", "$rootScope", "$q", "$injector", "$$multiMap", "$$stackedMap", function($animate, $timeout, $document, $compile, $rootScope, $q, $injector, $$multiMap, $$stackedMap) { + var $animateCss = null; + if ($injector.has("$animateCss")) { + $animateCss = $injector.get("$animateCss"); + } + var OPENED_MODAL_CLASS = "modal-open"; + var backdropDomEl, backdropScope; + var openedWindows = $$stackedMap.createNew(); + var openedClasses = $$multiMap.createNew(); + var $modalStack = { + NOW_CLOSING_EVENT: "modal.stack.now-closing" + }; + var focusableElementList; + var focusIndex = 0; + var tababbleSelector = "a[href], area[href], input:not([disabled]), " + "button:not([disabled]),select:not([disabled]), textarea:not([disabled]), " + "iframe, object, embed, *[tabindex], *[contenteditable=true]"; + function backdropIndex() { + var topBackdropIndex = -1; + var opened = openedWindows.keys(); + for (var i = 0; i < opened.length; i++) { + if (openedWindows.get(opened[i]).value.backdrop) { + topBackdropIndex = i; + } + } + return topBackdropIndex; + } + $rootScope.$watch(backdropIndex, function(newBackdropIndex) { + if (backdropScope) { + backdropScope.index = newBackdropIndex; + } + }); + function removeModalWindow(modalInstance, elementToReceiveFocus) { + var body = $document.find("body").eq(0); + var modalWindow = openedWindows.get(modalInstance).value; + openedWindows.remove(modalInstance); + removeAfterAnimate(modalWindow.modalDomEl, modalWindow.modalScope, function() { + var modalBodyClass = modalWindow.openedClass || OPENED_MODAL_CLASS; + openedClasses.remove(modalBodyClass, modalInstance); + body.toggleClass(modalBodyClass, openedClasses.hasKey(modalBodyClass)); }); - }, - getDuration: function() { - return this.backend.getDuration(); - }, - getCurrentTime: function() { - return this.backend.getCurrentTime(); - }, - play: function(a, b) { - this.backend.play(a, b); - }, - pause: function() { - this.backend.pause(); - }, - playPause: function() { - this.backend.isPaused() ? this.play() : this.pause(); - }, - isPlaying: function() { - return !this.backend.isPaused(); - }, - skipBackward: function(a) { - this.skip(-a || -this.params.skipLength); - }, - skipForward: function(a) { - this.skip(a || this.params.skipLength); - }, - skip: function(a) { - var b = this.getCurrentTime() || 0, c = this.getDuration() || 1; - b = Math.max(0, Math.min(c, b + (a || 0))), this.seekAndCenter(b / c); - }, - seekAndCenter: function(a) { - this.seekTo(a), this.drawer.recenter(a); - }, - seekTo: function(a) { - var b = this.backend.isPaused(), c = this.params.scrollParent; - b && (this.params.scrollParent = !1), this.backend.seekTo(a * this.getDuration()), - this.drawer.progress(this.backend.getPlayedPercents()), b || (this.backend.pause(), - this.backend.play()), this.params.scrollParent = c, this.fireEvent("seek", a); - }, - stop: function() { - this.pause(), this.seekTo(0), this.drawer.progress(0); - }, - setVolume: function(a) { - this.backend.setVolume(a); - }, - setPlaybackRate: function(a) { - this.backend.setPlaybackRate(a); - }, - toggleMute: function() { - this.isMuted ? (this.backend.setVolume(this.savedVolume), this.isMuted = !1) : (this.savedVolume = this.backend.getVolume(), - this.backend.setVolume(0), this.isMuted = !0); - }, - toggleScroll: function() { - this.params.scrollParent = !this.params.scrollParent, this.drawBuffer(); - }, - toggleInteraction: function() { - this.params.interact = !this.params.interact; - }, - drawBuffer: function() { - var a = Math.round(this.getDuration() * this.params.minPxPerSec * this.params.pixelRatio), b = this.drawer.getWidth(), c = a; - this.params.fillParent && (!this.params.scrollParent || b > a) && (c = b); - var d = this.backend.getPeaks(c); - this.drawer.drawPeaks(d, c), this.fireEvent("redraw", d, c); - }, - zoom: function(a) { - this.params.minPxPerSec = a, this.params.scrollParent = !0, this.drawBuffer(), this.seekAndCenter(this.getCurrentTime() / this.getDuration()); - }, - loadArrayBuffer: function(a) { - this.decodeArrayBuffer(a, function(a) { - this.loadDecodedBuffer(a); - }.bind(this)); - }, - loadDecodedBuffer: function(a) { - this.backend.load(a), this.drawBuffer(), this.fireEvent("ready"); - }, - loadBlob: function(a) { - var b = this, c = new FileReader(); - c.addEventListener("progress", function(a) { - b.onProgress(a); - }), c.addEventListener("load", function(a) { - b.loadArrayBuffer(a.target.result); - }), c.addEventListener("error", function() { - b.fireEvent("error", "Error reading file"); - }), c.readAsArrayBuffer(a), this.empty(); - }, - load: function(a, b) { - switch (this.params.backend) { - case "WebAudio": - return this.loadBuffer(a); + checkRemoveBackdrop(); + if (elementToReceiveFocus && elementToReceiveFocus.focus) { + elementToReceiveFocus.focus(); + } else { + body.focus(); + } + } + function checkRemoveBackdrop() { + if (backdropDomEl && backdropIndex() == -1) { + var backdropScopeRef = backdropScope; + removeAfterAnimate(backdropDomEl, backdropScope, function() { + backdropScopeRef = null; + }); + backdropDomEl = undefined; + backdropScope = undefined; + } + } + function removeAfterAnimate(domEl, scope, done) { + var asyncDeferred; + var asyncPromise = null; + var setIsAsync = function() { + if (!asyncDeferred) { + asyncDeferred = $q.defer(); + asyncPromise = asyncDeferred.promise; + } + return function asyncDone() { + asyncDeferred.resolve(); + }; + }; + scope.$broadcast($modalStack.NOW_CLOSING_EVENT, setIsAsync); + return $q.when(asyncPromise).then(afterAnimating); + function afterAnimating() { + if (afterAnimating.done) { + return; + } + afterAnimating.done = true; + if ($animateCss) { + $animateCss(domEl, { + event: "leave" + }).start().then(function() { + domEl.remove(); + }); + } else { + $animate.leave(domEl); + } + scope.$destroy(); + if (done) { + done(); + } + } + } + $document.bind("keydown", function(evt) { + if (evt.isDefaultPrevented()) { + return evt; + } + var modal = openedWindows.top(); + if (modal && modal.value.keyboard) { + switch (evt.which) { + case 27: + { + evt.preventDefault(); + $rootScope.$apply(function() { + $modalStack.dismiss(modal.key, "escape key press"); + }); + break; + } + + case 9: + { + $modalStack.loadFocusElementList(modal); + var focusChanged = false; + if (evt.shiftKey) { + if ($modalStack.isFocusInFirstItem(evt)) { + focusChanged = $modalStack.focusLastFocusableElement(); + } + } else { + if ($modalStack.isFocusInLastItem(evt)) { + focusChanged = $modalStack.focusFirstFocusableElement(); + } + } + if (focusChanged) { + evt.preventDefault(); + evt.stopPropagation(); + } + break; + } + } + } + }); + $modalStack.open = function(modalInstance, modal) { + var modalOpener = $document[0].activeElement, modalBodyClass = modal.openedClass || OPENED_MODAL_CLASS; + openedWindows.add(modalInstance, { + deferred: modal.deferred, + renderDeferred: modal.renderDeferred, + modalScope: modal.scope, + backdrop: modal.backdrop, + keyboard: modal.keyboard, + openedClass: modal.openedClass + }); + openedClasses.put(modalBodyClass, modalInstance); + var body = $document.find("body").eq(0), currBackdropIndex = backdropIndex(); + if (currBackdropIndex >= 0 && !backdropDomEl) { + backdropScope = $rootScope.$new(true); + backdropScope.index = currBackdropIndex; + var angularBackgroundDomEl = angular.element('
          '); + angularBackgroundDomEl.attr("backdrop-class", modal.backdropClass); + if (modal.animation) { + angularBackgroundDomEl.attr("modal-animation", "true"); + } + backdropDomEl = $compile(angularBackgroundDomEl)(backdropScope); + body.append(backdropDomEl); + } + var angularDomEl = angular.element('
          '); + angularDomEl.attr({ + "template-url": modal.windowTemplateUrl, + "window-class": modal.windowClass, + size: modal.size, + index: openedWindows.length() - 1, + animate: "animate" + }).html(modal.content); + if (modal.animation) { + angularDomEl.attr("modal-animation", "true"); + } + var modalDomEl = $compile(angularDomEl)(modal.scope); + openedWindows.top().value.modalDomEl = modalDomEl; + openedWindows.top().value.modalOpener = modalOpener; + body.append(modalDomEl); + body.addClass(modalBodyClass); + $modalStack.clearFocusListCache(); + }; + function broadcastClosing(modalWindow, resultOrReason, closing) { + return !modalWindow.value.modalScope.$broadcast("modal.closing", resultOrReason, closing).defaultPrevented; + } + $modalStack.close = function(modalInstance, result) { + var modalWindow = openedWindows.get(modalInstance); + if (modalWindow && broadcastClosing(modalWindow, result, true)) { + modalWindow.value.modalScope.$$uibDestructionScheduled = true; + modalWindow.value.deferred.resolve(result); + removeModalWindow(modalInstance, modalWindow.value.modalOpener); + return true; + } + return !modalWindow; + }; + $modalStack.dismiss = function(modalInstance, reason) { + var modalWindow = openedWindows.get(modalInstance); + if (modalWindow && broadcastClosing(modalWindow, reason, false)) { + modalWindow.value.modalScope.$$uibDestructionScheduled = true; + modalWindow.value.deferred.reject(reason); + removeModalWindow(modalInstance, modalWindow.value.modalOpener); + return true; + } + return !modalWindow; + }; + $modalStack.dismissAll = function(reason) { + var topModal = this.getTop(); + while (topModal && this.dismiss(topModal.key, reason)) { + topModal = this.getTop(); + } + }; + $modalStack.getTop = function() { + return openedWindows.top(); + }; + $modalStack.modalRendered = function(modalInstance) { + var modalWindow = openedWindows.get(modalInstance); + if (modalWindow) { + modalWindow.value.renderDeferred.resolve(); + } + }; + $modalStack.focusFirstFocusableElement = function() { + if (focusableElementList.length > 0) { + focusableElementList[0].focus(); + return true; + } + return false; + }; + $modalStack.focusLastFocusableElement = function() { + if (focusableElementList.length > 0) { + focusableElementList[focusableElementList.length - 1].focus(); + return true; + } + return false; + }; + $modalStack.isFocusInFirstItem = function(evt) { + if (focusableElementList.length > 0) { + return (evt.target || evt.srcElement) == focusableElementList[0]; + } + return false; + }; + $modalStack.isFocusInLastItem = function(evt) { + if (focusableElementList.length > 0) { + return (evt.target || evt.srcElement) == focusableElementList[focusableElementList.length - 1]; + } + return false; + }; + $modalStack.clearFocusListCache = function() { + focusableElementList = []; + focusIndex = 0; + }; + $modalStack.loadFocusElementList = function(modalWindow) { + if (focusableElementList === undefined || !focusableElementList.length0) { + if (modalWindow) { + var modalDomE1 = modalWindow.value.modalDomEl; + if (modalDomE1 && modalDomE1.length) { + focusableElementList = modalDomE1[0].querySelectorAll(tababbleSelector); + } + } + } + }; + return $modalStack; +} ]).provider("$modal", function() { + var $modalProvider = { + options: { + animation: true, + backdrop: true, + keyboard: true + }, + $get: [ "$injector", "$rootScope", "$q", "$templateRequest", "$controller", "$modalStack", function($injector, $rootScope, $q, $templateRequest, $controller, $modalStack) { + var $modal = {}; + function getTemplatePromise(options) { + return options.template ? $q.when(options.template) : $templateRequest(angular.isFunction(options.templateUrl) ? options.templateUrl() : options.templateUrl); + } + function getResolvePromises(resolves) { + var promisesArr = []; + angular.forEach(resolves, function(value) { + if (angular.isFunction(value) || angular.isArray(value)) { + promisesArr.push($q.when($injector.invoke(value))); + } else if (angular.isString(value)) { + promisesArr.push($q.when($injector.get(value))); + } else { + promisesArr.push($q.when(value)); + } + }); + return promisesArr; + } + var promiseChain = null; + $modal.getPromiseChain = function() { + return promiseChain; + }; + $modal.open = function(modalOptions) { + var modalResultDeferred = $q.defer(); + var modalOpenedDeferred = $q.defer(); + var modalRenderDeferred = $q.defer(); + var modalInstance = { + result: modalResultDeferred.promise, + opened: modalOpenedDeferred.promise, + rendered: modalRenderDeferred.promise, + close: function(result) { + return $modalStack.close(modalInstance, result); + }, + dismiss: function(reason) { + return $modalStack.dismiss(modalInstance, reason); + } + }; + modalOptions = angular.extend({}, $modalProvider.options, modalOptions); + modalOptions.resolve = modalOptions.resolve || {}; + if (!modalOptions.template && !modalOptions.templateUrl) { + throw new Error("One of template or templateUrl options is required."); + } + var templateAndResolvePromise = $q.all([ getTemplatePromise(modalOptions) ].concat(getResolvePromises(modalOptions.resolve))); + var samePromise; + samePromise = promiseChain = $q.all([ promiseChain ]).then(function() { + return templateAndResolvePromise; + }, function() { + return templateAndResolvePromise; + }).then(function resolveSuccess(tplAndVars) { + var modalScope = (modalOptions.scope || $rootScope).$new(); + modalScope.$close = modalInstance.close; + modalScope.$dismiss = modalInstance.dismiss; + modalScope.$on("$destroy", function() { + if (!modalScope.$$uibDestructionScheduled) { + modalScope.$dismiss("$uibUnscheduledDestruction"); + } + }); + var ctrlInstance, ctrlLocals = {}; + var resolveIter = 1; + if (modalOptions.controller) { + ctrlLocals.$scope = modalScope; + ctrlLocals.$modalInstance = modalInstance; + angular.forEach(modalOptions.resolve, function(value, key) { + ctrlLocals[key] = tplAndVars[resolveIter++]; + }); + ctrlInstance = $controller(modalOptions.controller, ctrlLocals); + if (modalOptions.controllerAs) { + if (modalOptions.bindToController) { + angular.extend(ctrlInstance, modalScope); + } + modalScope[modalOptions.controllerAs] = ctrlInstance; + } + } + $modalStack.open(modalInstance, { + scope: modalScope, + deferred: modalResultDeferred, + renderDeferred: modalRenderDeferred, + content: tplAndVars[0], + animation: modalOptions.animation, + backdrop: modalOptions.backdrop, + keyboard: modalOptions.keyboard, + backdropClass: modalOptions.backdropClass, + windowClass: modalOptions.windowClass, + windowTemplateUrl: modalOptions.windowTemplateUrl, + size: modalOptions.size, + openedClass: modalOptions.openedClass + }); + modalOpenedDeferred.resolve(true); + }, function resolveError(reason) { + modalOpenedDeferred.reject(reason); + modalResultDeferred.reject(reason); + }).finally(function() { + if (promiseChain === samePromise) { + promiseChain = null; + } + }); + return modalInstance; + }; + return $modal; + } ] + }; + return $modalProvider; +}); - case "MediaElement": - return this.loadMediaElement(a, b); +angular.module("ui.bootstrap.pagination", []).controller("PaginationController", [ "$scope", "$attrs", "$parse", function($scope, $attrs, $parse) { + var self = this, ngModelCtrl = { + $setViewValue: angular.noop + }, setNumPages = $attrs.numPages ? $parse($attrs.numPages).assign : angular.noop; + this.init = function(ngModelCtrl_, config) { + ngModelCtrl = ngModelCtrl_; + this.config = config; + ngModelCtrl.$render = function() { + self.render(); + }; + if ($attrs.itemsPerPage) { + $scope.$parent.$watch($parse($attrs.itemsPerPage), function(value) { + self.itemsPerPage = parseInt(value, 10); + $scope.totalPages = self.calculateTotalPages(); + }); + } else { + this.itemsPerPage = config.itemsPerPage; } - }, - loadBuffer: function(a) { - return this.empty(), this.getArrayBuffer(a, this.loadArrayBuffer.bind(this)); - }, - loadMediaElement: function(a, b) { - this.empty(), this.backend.load(a, this.mediaContainer, b), this.tmpEvents.push(this.backend.once("canplay", function() { - this.drawBuffer(), this.fireEvent("ready"); - }.bind(this)), this.backend.once("error", function(a) { - this.fireEvent("error", a); - }.bind(this))), !b && this.backend.supportsWebAudio() && this.getArrayBuffer(a, function(a) { - this.decodeArrayBuffer(a, function(a) { - this.backend.buffer = a, this.drawBuffer(); - }.bind(this)); - }.bind(this)); - }, - decodeArrayBuffer: function(a, b) { - this.backend.decodeArrayBuffer(a, this.fireEvent.bind(this, "decoded"), this.fireEvent.bind(this, "error", "Error decoding audiobuffer")), - this.tmpEvents.push(this.once("decoded", b)); - }, - getArrayBuffer: function(a, b) { - var c = this, d = WaveSurfer.util.ajax({ - url: a, - responseType: "arraybuffer" + $scope.$watch("totalItems", function() { + $scope.totalPages = self.calculateTotalPages(); }); - return this.tmpEvents.push(d.on("progress", function(a) { - c.onProgress(a); - }), d.on("success", b), d.on("error", function(a) { - c.fireEvent("error", "XHR error: " + a.target.statusText); - })), d; - }, - onProgress: function(a) { - if (a.lengthComputable) var b = a.loaded / a.total; else b = a.loaded / (a.loaded + 1e6); - this.fireEvent("loading", Math.round(100 * b), a.target); - }, - exportPCM: function(a, b, c) { - a = a || 1024, b = b || 1e4, c = c || !1; - var d = this.backend.getPeaks(a, b), e = [].map.call(d, function(a) { - return Math.round(a * b) / b; - }), f = JSON.stringify(e); - return c || window.open("data:application/json;charset=utf-8," + encodeURIComponent(f)), - f; - }, - clearTmpEvents: function() { - this.tmpEvents.forEach(function(a) { - a.un(); + $scope.$watch("totalPages", function(value) { + setNumPages($scope.$parent, value); + if ($scope.page > value) { + $scope.selectPage(value); + } else { + ngModelCtrl.$render(); + } }); - }, - empty: function() { - this.backend.isPaused() || (this.stop(), this.backend.disconnectSource()), this.clearTmpEvents(), - this.drawer.progress(0), this.drawer.setWidth(0), this.drawer.drawPeaks({ - length: this.drawer.getWidth() - }, 0); - }, - destroy: function() { - this.fireEvent("destroy"), this.clearTmpEvents(), this.unAll(), this.backend.destroy(), - this.drawer.destroy(); - } -}; - -WaveSurfer.create = function(a) { - var b = Object.create(WaveSurfer); - return b.init(a), b; -}, WaveSurfer.util = { - extend: function(a) { - var b = Array.prototype.slice.call(arguments, 1); - return b.forEach(function(b) { - Object.keys(b).forEach(function(c) { - a[c] = b[c]; - }); - }), a; - }, - getId: function() { - return "wavesurfer_" + Math.random().toString(32).substring(2); - }, - ajax: function(a) { - var b = Object.create(WaveSurfer.Observer), c = new XMLHttpRequest(), d = !1; - return c.open(a.method || "GET", a.url, !0), c.responseType = a.responseType || "json", - c.addEventListener("progress", function(a) { - b.fireEvent("progress", a), a.lengthComputable && a.loaded == a.total && (d = !0); - }), c.addEventListener("load", function(a) { - d || b.fireEvent("progress", a), b.fireEvent("load", a), 200 == c.status || 206 == c.status ? b.fireEvent("success", c.response, a) : b.fireEvent("error", a); - }), c.addEventListener("error", function(a) { - b.fireEvent("error", a); - }), c.send(), b.xhr = c, b; - } -}, WaveSurfer.Observer = { - on: function(a, b) { - this.handlers || (this.handlers = {}); - var c = this.handlers[a]; - return c || (c = this.handlers[a] = []), c.push(b), { - name: a, - callback: b, - un: this.un.bind(this, a, b) - }; - }, - un: function(a, b) { - if (this.handlers) { - var c = this.handlers[a]; - if (c) if (b) for (var d = c.length - 1; d >= 0; d--) c[d] == b && c.splice(d, 1); else c.length = 0; + }; + this.calculateTotalPages = function() { + var totalPages = this.itemsPerPage < 1 ? 1 : Math.ceil($scope.totalItems / this.itemsPerPage); + return Math.max(totalPages || 0, 1); + }; + this.render = function() { + $scope.page = parseInt(ngModelCtrl.$viewValue, 10) || 1; + }; + $scope.selectPage = function(page, evt) { + if (evt) { + evt.preventDefault(); } - }, - unAll: function() { - this.handlers = null; - }, - once: function(a, b) { - var c = this, d = function() { - b.apply(this, arguments), setTimeout(function() { - c.un(a, d); - }, 0); - }; - return this.on(a, d); - }, - fireEvent: function(a) { - if (this.handlers) { - var b = this.handlers[a], c = Array.prototype.slice.call(arguments, 1); - b && b.forEach(function(a) { - a.apply(null, c); - }); + var clickAllowed = !$scope.ngDisabled || !evt; + if (clickAllowed && $scope.page !== page && page > 0 && page <= $scope.totalPages) { + if (evt && evt.target) { + evt.target.blur(); + } + ngModelCtrl.$setViewValue(page); + ngModelCtrl.$render(); + } + }; + $scope.getText = function(key) { + return $scope[key + "Text"] || self.config[key + "Text"]; + }; + $scope.noPrevious = function() { + return $scope.page === 1; + }; + $scope.noNext = function() { + return $scope.page === $scope.totalPages; + }; +} ]).constant("paginationConfig", { + itemsPerPage: 10, + boundaryLinks: false, + directionLinks: true, + firstText: "First", + previousText: "Previous", + nextText: "Next", + lastText: "Last", + rotate: true +}).directive("pagination", [ "$parse", "paginationConfig", function($parse, paginationConfig) { + return { + restrict: "EA", + scope: { + totalItems: "=", + firstText: "@", + previousText: "@", + nextText: "@", + lastText: "@", + ngDisabled: "=" + }, + require: [ "pagination", "?ngModel" ], + controller: "PaginationController", + controllerAs: "pagination", + templateUrl: function(element, attrs) { + return attrs.templateUrl || "template/pagination/pagination.html"; + }, + replace: true, + link: function(scope, element, attrs, ctrls) { + var paginationCtrl = ctrls[0], ngModelCtrl = ctrls[1]; + if (!ngModelCtrl) { + return; + } + var maxSize = angular.isDefined(attrs.maxSize) ? scope.$parent.$eval(attrs.maxSize) : paginationConfig.maxSize, rotate = angular.isDefined(attrs.rotate) ? scope.$parent.$eval(attrs.rotate) : paginationConfig.rotate; + scope.boundaryLinks = angular.isDefined(attrs.boundaryLinks) ? scope.$parent.$eval(attrs.boundaryLinks) : paginationConfig.boundaryLinks; + scope.directionLinks = angular.isDefined(attrs.directionLinks) ? scope.$parent.$eval(attrs.directionLinks) : paginationConfig.directionLinks; + paginationCtrl.init(ngModelCtrl, paginationConfig); + if (attrs.maxSize) { + scope.$parent.$watch($parse(attrs.maxSize), function(value) { + maxSize = parseInt(value, 10); + paginationCtrl.render(); + }); + } + function makePage(number, text, isActive) { + return { + number: number, + text: text, + active: isActive + }; + } + function getPages(currentPage, totalPages) { + var pages = []; + var startPage = 1, endPage = totalPages; + var isMaxSized = angular.isDefined(maxSize) && maxSize < totalPages; + if (isMaxSized) { + if (rotate) { + startPage = Math.max(currentPage - Math.floor(maxSize / 2), 1); + endPage = startPage + maxSize - 1; + if (endPage > totalPages) { + endPage = totalPages; + startPage = endPage - maxSize + 1; + } + } else { + startPage = (Math.ceil(currentPage / maxSize) - 1) * maxSize + 1; + endPage = Math.min(startPage + maxSize - 1, totalPages); + } + } + for (var number = startPage; number <= endPage; number++) { + var page = makePage(number, number, number === currentPage); + pages.push(page); + } + if (isMaxSized && !rotate) { + if (startPage > 1) { + var previousPageSet = makePage(startPage - 1, "...", false); + pages.unshift(previousPageSet); + } + if (endPage < totalPages) { + var nextPageSet = makePage(endPage + 1, "...", false); + pages.push(nextPageSet); + } + } + return pages; + } + var originalRender = paginationCtrl.render; + paginationCtrl.render = function() { + originalRender(); + if (scope.page > 0 && scope.page <= scope.totalPages) { + scope.pages = getPages(scope.page, scope.totalPages); + } + }; } - } -}, WaveSurfer.util.extend(WaveSurfer, WaveSurfer.Observer), WaveSurfer.WebAudio = { - scriptBufferSize: 256, - PLAYING_STATE: 0, - PAUSED_STATE: 1, - FINISHED_STATE: 2, - supportsWebAudio: function() { - return !(!window.AudioContext && !window.webkitAudioContext); - }, - getAudioContext: function() { - return WaveSurfer.WebAudio.audioContext || (WaveSurfer.WebAudio.audioContext = new (window.AudioContext || window.webkitAudioContext)()), - WaveSurfer.WebAudio.audioContext; - }, - getOfflineAudioContext: function(a) { - return WaveSurfer.WebAudio.offlineAudioContext || (WaveSurfer.WebAudio.offlineAudioContext = new (window.OfflineAudioContext || window.webkitOfflineAudioContext)(1, 2, a)), - WaveSurfer.WebAudio.offlineAudioContext; - }, - init: function(a) { - this.params = a, this.ac = a.audioContext || this.getAudioContext(), this.lastPlay = this.ac.currentTime, - this.startPosition = 0, this.scheduledPause = null, this.states = [ Object.create(WaveSurfer.WebAudio.state.playing), Object.create(WaveSurfer.WebAudio.state.paused), Object.create(WaveSurfer.WebAudio.state.finished) ], - this.createVolumeNode(), this.createScriptNode(), this.createAnalyserNode(), this.setState(this.PAUSED_STATE), - this.setPlaybackRate(this.params.audioRate); - }, - disconnectFilters: function() { - this.filters && (this.filters.forEach(function(a) { - a && a.disconnect(); - }), this.filters = null, this.analyser.connect(this.gainNode)); - }, - setState: function(a) { - this.state !== this.states[a] && (this.state = this.states[a], this.state.init.call(this)); - }, - setFilter: function() { - this.setFilters([].slice.call(arguments)); - }, - setFilters: function(a) { - this.disconnectFilters(), a && a.length && (this.filters = a, this.analyser.disconnect(), - a.reduce(function(a, b) { - return a.connect(b), b; - }, this.analyser).connect(this.gainNode)); - }, - createScriptNode: function() { - this.ac.createScriptProcessor ? this.scriptNode = this.ac.createScriptProcessor(this.scriptBufferSize) : this.scriptNode = this.ac.createJavaScriptNode(this.scriptBufferSize), - this.scriptNode.connect(this.ac.destination); - }, - addOnAudioProcess: function() { - var a = this; - this.scriptNode.onaudioprocess = function() { - var b = a.getCurrentTime(); - b >= a.getDuration() ? (a.setState(a.FINISHED_STATE), a.fireEvent("pause")) : b >= a.scheduledPause ? (a.setState(a.PAUSED_STATE), - a.fireEvent("pause")) : a.state === a.states[a.PLAYING_STATE] && a.fireEvent("audioprocess", b); - }; - }, - removeOnAudioProcess: function() { - this.scriptNode.onaudioprocess = null; - }, - createAnalyserNode: function() { - this.analyser = this.ac.createAnalyser(), this.analyser.connect(this.gainNode); - }, - createVolumeNode: function() { - this.ac.createGain ? this.gainNode = this.ac.createGain() : this.gainNode = this.ac.createGainNode(), - this.gainNode.connect(this.ac.destination); - }, - setVolume: function(a) { - this.gainNode.gain.value = a; - }, - getVolume: function() { - return this.gainNode.gain.value; - }, - decodeArrayBuffer: function(a, b, c) { - this.offlineAc || (this.offlineAc = this.getOfflineAudioContext(this.ac ? this.ac.sampleRate : 44100)), - this.offlineAc.decodeAudioData(a, function(a) { - b(a); - }.bind(this), c); - }, - getPeaks: function(a) { - for (var b = this.buffer.length / a, c = ~~(b / 10) || 1, d = this.buffer.numberOfChannels, e = [], f = [], g = 0; d > g; g++) for (var h = e[g] = [], i = this.buffer.getChannelData(g), j = 0; a > j; j++) { - for (var k = ~~(j * b), l = ~~(k + b), m = i[0], n = i[0], o = k; l > o; o += c) { - var p = i[o]; - p > n && (n = p), m > p && (m = p); + }; +} ]).constant("pagerConfig", { + itemsPerPage: 10, + previousText: "« Previous", + nextText: "Next »", + align: true +}).directive("pager", [ "pagerConfig", function(pagerConfig) { + return { + restrict: "EA", + scope: { + totalItems: "=", + previousText: "@", + nextText: "@", + ngDisabled: "=" + }, + require: [ "pager", "?ngModel" ], + controller: "PaginationController", + controllerAs: "pagination", + templateUrl: function(element, attrs) { + return attrs.templateUrl || "template/pagination/pager.html"; + }, + replace: true, + link: function(scope, element, attrs, ctrls) { + var paginationCtrl = ctrls[0], ngModelCtrl = ctrls[1]; + if (!ngModelCtrl) { + return; } - h[2 * j] = n, h[2 * j + 1] = m, (0 == g || n > f[2 * j]) && (f[2 * j] = n), (0 == g || m < f[2 * j + 1]) && (f[2 * j + 1] = m); + scope.align = angular.isDefined(attrs.align) ? scope.$parent.$eval(attrs.align) : pagerConfig.align; + paginationCtrl.init(ngModelCtrl, pagerConfig); } - return this.params.splitChannels ? e : f; - }, - getPlayedPercents: function() { - return this.state.getPlayedPercents.call(this); - }, - disconnectSource: function() { - this.source && this.source.disconnect(); - }, - destroy: function() { - this.isPaused() || this.pause(), this.unAll(), this.buffer = null, this.disconnectFilters(), - this.disconnectSource(), this.gainNode.disconnect(), this.scriptNode.disconnect(), - this.analyser.disconnect(); - }, - load: function(a) { - this.startPosition = 0, this.lastPlay = this.ac.currentTime, this.buffer = a, this.createSource(); - }, - createSource: function() { - this.disconnectSource(), this.source = this.ac.createBufferSource(), this.source.start = this.source.start || this.source.noteGrainOn, - this.source.stop = this.source.stop || this.source.noteOff, this.source.playbackRate.value = this.playbackRate, - this.source.buffer = this.buffer, this.source.connect(this.analyser); - }, - isPaused: function() { - return this.state !== this.states[this.PLAYING_STATE]; - }, - getDuration: function() { - return this.buffer ? this.buffer.duration : 0; - }, - seekTo: function(a, b) { - return this.scheduledPause = null, null == a && (a = this.getCurrentTime(), a >= this.getDuration() && (a = 0)), - null == b && (b = this.getDuration()), this.startPosition = a, this.lastPlay = this.ac.currentTime, - this.state === this.states[this.FINISHED_STATE] && this.setState(this.PAUSED_STATE), - { - start: a, - end: b - }; - }, - getPlayedTime: function() { - return (this.ac.currentTime - this.lastPlay) * this.playbackRate; - }, - play: function(a, b) { - this.createSource(); - var c = this.seekTo(a, b); - a = c.start, b = c.end, this.scheduledPause = b, this.source.start(0, a, b - a), - this.setState(this.PLAYING_STATE), this.fireEvent("play"); - }, - pause: function() { - this.scheduledPause = null, this.startPosition += this.getPlayedTime(), this.source && this.source.stop(0), - this.setState(this.PAUSED_STATE), this.fireEvent("pause"); - }, - getCurrentTime: function() { - return this.state.getCurrentTime.call(this); - }, - setPlaybackRate: function(a) { - a = a || 1, this.isPaused() ? this.playbackRate = a : (this.pause(), this.playbackRate = a, - this.play()); - } -}, WaveSurfer.WebAudio.state = {}, WaveSurfer.WebAudio.state.playing = { - init: function() { - this.addOnAudioProcess(); - }, - getPlayedPercents: function() { - var a = this.getDuration(); - return this.getCurrentTime() / a || 0; - }, - getCurrentTime: function() { - return this.startPosition + this.getPlayedTime(); - } -}, WaveSurfer.WebAudio.state.paused = { - init: function() { - this.removeOnAudioProcess(); - }, - getPlayedPercents: function() { - var a = this.getDuration(); - return this.getCurrentTime() / a || 0; - }, - getCurrentTime: function() { - return this.startPosition; - } -}, WaveSurfer.WebAudio.state.finished = { - init: function() { - this.removeOnAudioProcess(), this.fireEvent("finish"); - }, - getPlayedPercents: function() { - return 1; - }, - getCurrentTime: function() { - return this.getDuration(); - } -}, WaveSurfer.util.extend(WaveSurfer.WebAudio, WaveSurfer.Observer), WaveSurfer.MediaElement = Object.create(WaveSurfer.WebAudio), -WaveSurfer.util.extend(WaveSurfer.MediaElement, { - init: function(a) { - this.params = a, this.media = { - currentTime: 0, - duration: 0, - paused: !0, - playbackRate: 1, - play: function() {}, - pause: function() {} - }, this.mediaType = a.mediaType.toLowerCase(), this.elementPosition = a.elementPosition; - }, - load: function(a, b, c) { - var d = this, e = document.createElement(this.mediaType); - e.controls = !1, e.autoplay = !1, e.preload = "auto", e.src = a, e.addEventListener("error", function() { - d.fireEvent("error", "Error loading media element"); - }), e.addEventListener("canplay", function() { - d.fireEvent("canplay"); - }), e.addEventListener("ended", function() { - d.fireEvent("finish"); - }), e.addEventListener("timeupdate", function() { - d.fireEvent("audioprocess", d.getCurrentTime()); + }; +} ]); + +angular.module("ui.bootstrap.tooltip", [ "ui.bootstrap.position", "ui.bootstrap.bindHtml" ]).provider("$tooltip", function() { + var defaultOptions = { + placement: "top", + animation: true, + popupDelay: 0, + useContentExp: false + }; + var triggerMap = { + mouseenter: "mouseleave", + click: "click", + focus: "blur", + none: "" + }; + var globalOptions = {}; + this.options = function(value) { + angular.extend(globalOptions, value); + }; + this.setTriggers = function setTriggers(triggers) { + angular.extend(triggerMap, triggers); + }; + function snake_case(name) { + var regexp = /[A-Z]/g; + var separator = "-"; + return name.replace(regexp, function(letter, pos) { + return (pos ? separator : "") + letter.toLowerCase(); }); - var f = b.querySelector(this.mediaType); - f && b.removeChild(f), b.appendChild(e), this.media = e, this.peaks = c, this.onPlayEnd = null, - this.buffer = null, this.setPlaybackRate(this.playbackRate); - }, - isPaused: function() { - return !this.media || this.media.paused; - }, - getDuration: function() { - var a = this.media.duration; - return a >= 1 / 0 && (a = this.media.seekable.end()), a; - }, - getCurrentTime: function() { - return this.media && this.media.currentTime; - }, - getPlayedPercents: function() { - return this.getCurrentTime() / this.getDuration() || 0; - }, - setPlaybackRate: function(a) { - this.playbackRate = a || 1, this.media.playbackRate = this.playbackRate; - }, - seekTo: function(a) { - null != a && (this.media.currentTime = a), this.clearPlayEnd(); - }, - play: function(a, b) { - this.seekTo(a), this.media.play(), b && this.setPlayEnd(b), this.fireEvent("play"); - }, - pause: function() { - this.media && this.media.pause(), this.clearPlayEnd(), this.fireEvent("pause"); - }, - setPlayEnd: function(a) { - var b = this; - this.onPlayEnd = function(c) { - c >= a && (b.pause(), b.seekTo(a)); - }, this.on("audioprocess", this.onPlayEnd); - }, - clearPlayEnd: function() { - this.onPlayEnd && (this.un("audioprocess", this.onPlayEnd), this.onPlayEnd = null); - }, - getPeaks: function(a) { - return this.buffer ? WaveSurfer.WebAudio.getPeaks.call(this, a) : this.peaks || []; - }, - getVolume: function() { - return this.media.volume; - }, - setVolume: function(a) { - this.media.volume = a; - }, - destroy: function() { - this.pause(), this.unAll(), this.media && this.media.parentNode && this.media.parentNode.removeChild(this.media), - this.media = null; } -}), WaveSurfer.AudioElement = WaveSurfer.MediaElement, WaveSurfer.Drawer = { - init: function(a, b) { - this.container = a, this.params = b, this.width = 0, this.height = b.height * this.params.pixelRatio, - this.lastPos = 0, this.createWrapper(), this.createElements(); - }, - createWrapper: function() { - this.wrapper = this.container.appendChild(document.createElement("wave")), this.style(this.wrapper, { - display: "block", - position: "relative", - userSelect: "none", - webkitUserSelect: "none", - height: this.params.height + "px" - }), (this.params.fillParent || this.params.scrollParent) && this.style(this.wrapper, { - width: "100%", - overflowX: this.params.hideScrollbar ? "hidden" : "auto", - overflowY: "hidden" - }), this.setupWrapperEvents(); - }, - handleEvent: function(a) { - a.preventDefault(); - var b = this.wrapper.getBoundingClientRect(); - return (a.clientX - b.left + this.wrapper.scrollLeft) / this.wrapper.scrollWidth || 0; - }, - setupWrapperEvents: function() { - var a = this; - this.wrapper.addEventListener("click", function(b) { - var c = a.wrapper.offsetHeight - a.wrapper.clientHeight; - if (0 != c) { - var d = a.wrapper.getBoundingClientRect(); - if (b.clientY >= d.bottom - c) return; + this.$get = [ "$window", "$compile", "$timeout", "$document", "$position", "$interpolate", "$rootScope", "$parse", function($window, $compile, $timeout, $document, $position, $interpolate, $rootScope, $parse) { + return function $tooltip(type, prefix, defaultTriggerShow, options) { + options = angular.extend({}, defaultOptions, globalOptions, options); + function getTriggers(trigger) { + var show = (trigger || options.trigger || defaultTriggerShow).split(" "); + var hide = show.map(function(trigger) { + return triggerMap[trigger] || trigger; + }); + return { + show: show, + hide: hide + }; + } + var directiveName = snake_case(type); + var startSym = $interpolate.startSymbol(); + var endSym = $interpolate.endSymbol(); + var template = "
          " + "
          "; + return { + restrict: "EA", + compile: function(tElem, tAttrs) { + var tooltipLinker = $compile(template); + return function link(scope, element, attrs, tooltipCtrl) { + var tooltip; + var tooltipLinkedScope; + var transitionTimeout; + var popupTimeout; + var positionTimeout; + var appendToBody = angular.isDefined(options.appendToBody) ? options.appendToBody : false; + var triggers = getTriggers(undefined); + var hasEnableExp = angular.isDefined(attrs[prefix + "Enable"]); + var ttScope = scope.$new(true); + var repositionScheduled = false; + var isOpenExp = angular.isDefined(attrs[prefix + "IsOpen"]) ? $parse(attrs[prefix + "IsOpen"]) : false; + var positionTooltip = function() { + if (!tooltip) { + return; + } + if (!positionTimeout) { + positionTimeout = $timeout(function() { + tooltip.css({ + top: 0, + left: 0, + width: "auto", + height: "auto" + }); + var ttBox = $position.position(tooltip); + var ttCss = $position.positionElements(element, tooltip, ttScope.placement, appendToBody); + ttCss.top += "px"; + ttCss.left += "px"; + ttCss.width = ttBox.width + "px"; + ttCss.height = ttBox.height + "px"; + tooltip.css(ttCss); + positionTimeout = null; + }, 0, false); + } + }; + ttScope.origScope = scope; + ttScope.isOpen = false; + function toggleTooltipBind() { + if (!ttScope.isOpen) { + showTooltipBind(); + } else { + hideTooltipBind(); + } + } + function showTooltipBind() { + if (hasEnableExp && !scope.$eval(attrs[prefix + "Enable"])) { + return; + } + prepareTooltip(); + if (ttScope.popupDelay) { + if (!popupTimeout) { + popupTimeout = $timeout(show, ttScope.popupDelay, false); + } + } else { + show(); + } + } + function hideTooltipBind() { + hide(); + if (!$rootScope.$$phase) { + $rootScope.$digest(); + } + } + function show() { + popupTimeout = null; + if (transitionTimeout) { + $timeout.cancel(transitionTimeout); + transitionTimeout = null; + } + if (!(options.useContentExp ? ttScope.contentExp() : ttScope.content)) { + return angular.noop; + } + createTooltip(); + ttScope.isOpen = true; + if (isOpenExp) { + isOpenExp.assign(ttScope.origScope, ttScope.isOpen); + } + if (!$rootScope.$$phase) { + ttScope.$apply(); + } + tooltip.css({ + display: "block" + }); + positionTooltip(); + } + function hide() { + ttScope.isOpen = false; + if (isOpenExp) { + isOpenExp.assign(ttScope.origScope, ttScope.isOpen); + } + $timeout.cancel(popupTimeout); + popupTimeout = null; + $timeout.cancel(positionTimeout); + positionTimeout = null; + if (ttScope.animation) { + if (!transitionTimeout) { + transitionTimeout = $timeout(removeTooltip, 500); + } + } else { + removeTooltip(); + } + } + function createTooltip() { + if (tooltip) { + removeTooltip(); + } + tooltipLinkedScope = ttScope.$new(); + tooltip = tooltipLinker(tooltipLinkedScope, function(tooltip) { + if (appendToBody) { + $document.find("body").append(tooltip); + } else { + element.after(tooltip); + } + }); + if (options.useContentExp) { + tooltipLinkedScope.$watch("contentExp()", function(val) { + if (!val && ttScope.isOpen) { + hide(); + } + }); + tooltipLinkedScope.$watch(function() { + if (!repositionScheduled) { + repositionScheduled = true; + tooltipLinkedScope.$$postDigest(function() { + repositionScheduled = false; + if (ttScope.isOpen) { + positionTooltip(); + } + }); + } + }); + } + } + function removeTooltip() { + transitionTimeout = null; + if (tooltip) { + tooltip.remove(); + tooltip = null; + } + if (tooltipLinkedScope) { + tooltipLinkedScope.$destroy(); + tooltipLinkedScope = null; + } + } + function prepareTooltip() { + prepPopupClass(); + prepPlacement(); + prepPopupDelay(); + } + ttScope.contentExp = function() { + return scope.$eval(attrs[type]); + }; + if (!options.useContentExp) { + attrs.$observe(type, function(val) { + ttScope.content = val; + if (!val && ttScope.isOpen) { + hide(); + } else { + positionTooltip(); + } + }); + } + attrs.$observe("disabled", function(val) { + if (popupTimeout && val) { + $timeout.cancel(popupTimeout); + popupTimeout = null; + } + if (val && ttScope.isOpen) { + hide(); + } + }); + attrs.$observe(prefix + "Title", function(val) { + ttScope.title = val; + positionTooltip(); + }); + attrs.$observe(prefix + "Placement", function() { + if (ttScope.isOpen) { + prepPlacement(); + positionTooltip(); + } + }); + if (isOpenExp) { + scope.$watch(isOpenExp, function(val) { + if (val !== ttScope.isOpen) { + toggleTooltipBind(); + } + }); + } + function prepPopupClass() { + ttScope.popupClass = attrs[prefix + "Class"]; + } + function prepPlacement() { + var val = attrs[prefix + "Placement"]; + ttScope.placement = angular.isDefined(val) ? val : options.placement; + } + function prepPopupDelay() { + var val = attrs[prefix + "PopupDelay"]; + var delay = parseInt(val, 10); + ttScope.popupDelay = !isNaN(delay) ? delay : options.popupDelay; + } + var unregisterTriggers = function() { + triggers.show.forEach(function(trigger) { + element.unbind(trigger, showTooltipBind); + }); + triggers.hide.forEach(function(trigger) { + element.unbind(trigger, hideTooltipBind); + }); + }; + function prepTriggers() { + var val = attrs[prefix + "Trigger"]; + unregisterTriggers(); + triggers = getTriggers(val); + if (triggers.show !== "none") { + triggers.show.forEach(function(trigger, idx) { + if (trigger === triggers.hide[idx]) { + element[0].addEventListener(trigger, toggleTooltipBind); + } else if (trigger) { + element[0].addEventListener(trigger, showTooltipBind); + element[0].addEventListener(triggers.hide[idx], hideTooltipBind); + } + }); + } + } + prepTriggers(); + var animation = scope.$eval(attrs[prefix + "Animation"]); + ttScope.animation = angular.isDefined(animation) ? !!animation : options.animation; + var appendToBodyVal = scope.$eval(attrs[prefix + "AppendToBody"]); + appendToBody = angular.isDefined(appendToBodyVal) ? appendToBodyVal : appendToBody; + if (appendToBody) { + scope.$on("$locationChangeSuccess", function closeTooltipOnLocationChangeSuccess() { + if (ttScope.isOpen) { + hide(); + } + }); + } + scope.$on("$destroy", function onDestroyTooltip() { + $timeout.cancel(transitionTimeout); + $timeout.cancel(popupTimeout); + $timeout.cancel(positionTimeout); + unregisterTriggers(); + removeTooltip(); + ttScope = null; + }); + }; + } + }; + }; + } ]; +}).directive("tooltipTemplateTransclude", [ "$animate", "$sce", "$compile", "$templateRequest", function($animate, $sce, $compile, $templateRequest) { + return { + link: function(scope, elem, attrs) { + var origScope = scope.$eval(attrs.tooltipTemplateTranscludeScope); + var changeCounter = 0, currentScope, previousElement, currentElement; + var cleanupLastIncludeContent = function() { + if (previousElement) { + previousElement.remove(); + previousElement = null; + } + if (currentScope) { + currentScope.$destroy(); + currentScope = null; + } + if (currentElement) { + $animate.leave(currentElement).then(function() { + previousElement = null; + }); + previousElement = currentElement; + currentElement = null; + } + }; + scope.$watch($sce.parseAsResourceUrl(attrs.tooltipTemplateTransclude), function(src) { + var thisChangeId = ++changeCounter; + if (src) { + $templateRequest(src, true).then(function(response) { + if (thisChangeId !== changeCounter) { + return; + } + var newScope = origScope.$new(); + var template = response; + var clone = $compile(template)(newScope, function(clone) { + cleanupLastIncludeContent(); + $animate.enter(clone, elem); + }); + currentScope = newScope; + currentElement = clone; + currentScope.$emit("$includeContentLoaded", src); + }, function() { + if (thisChangeId === changeCounter) { + cleanupLastIncludeContent(); + scope.$emit("$includeContentError", src); + } + }); + scope.$emit("$includeContentRequested", src); + } else { + cleanupLastIncludeContent(); + } + }); + scope.$on("$destroy", cleanupLastIncludeContent); + } + }; +} ]).directive("tooltipClasses", function() { + return { + restrict: "A", + link: function(scope, element, attrs) { + if (scope.placement) { + element.addClass(scope.placement); } - a.params.interact && a.fireEvent("click", b, a.handleEvent(b)); - }), this.wrapper.addEventListener("scroll", function(b) { - a.fireEvent("scroll", b); + if (scope.popupClass) { + element.addClass(scope.popupClass); + } + if (scope.animation()) { + element.addClass(attrs.tooltipAnimationClass); + } + } + }; +}).directive("tooltipPopup", function() { + return { + restrict: "EA", + replace: true, + scope: { + content: "@", + placement: "@", + popupClass: "@", + animation: "&", + isOpen: "&" + }, + templateUrl: "template/tooltip/tooltip-popup.html" + }; +}).directive("tooltip", [ "$tooltip", function($tooltip) { + return $tooltip("tooltip", "tooltip", "mouseenter"); +} ]).directive("tooltipTemplatePopup", function() { + return { + restrict: "EA", + replace: true, + scope: { + contentExp: "&", + placement: "@", + popupClass: "@", + animation: "&", + isOpen: "&", + originScope: "&" + }, + templateUrl: "template/tooltip/tooltip-template-popup.html" + }; +}).directive("tooltipTemplate", [ "$tooltip", function($tooltip) { + return $tooltip("tooltipTemplate", "tooltip", "mouseenter", { + useContentExp: true + }); +} ]).directive("tooltipHtmlPopup", function() { + return { + restrict: "EA", + replace: true, + scope: { + contentExp: "&", + placement: "@", + popupClass: "@", + animation: "&", + isOpen: "&" + }, + templateUrl: "template/tooltip/tooltip-html-popup.html" + }; +}).directive("tooltipHtml", [ "$tooltip", function($tooltip) { + return $tooltip("tooltipHtml", "tooltip", "mouseenter", { + useContentExp: true + }); +} ]).directive("tooltipHtmlUnsafePopup", function() { + return { + restrict: "EA", + replace: true, + scope: { + content: "@", + placement: "@", + popupClass: "@", + animation: "&", + isOpen: "&" + }, + templateUrl: "template/tooltip/tooltip-html-unsafe-popup.html" + }; +}).value("tooltipHtmlUnsafeSuppressDeprecated", false).directive("tooltipHtmlUnsafe", [ "$tooltip", "tooltipHtmlUnsafeSuppressDeprecated", "$log", function($tooltip, tooltipHtmlUnsafeSuppressDeprecated, $log) { + if (!tooltipHtmlUnsafeSuppressDeprecated) { + $log.warn("tooltip-html-unsafe is now deprecated. Use tooltip-html or tooltip-template instead."); + } + return $tooltip("tooltipHtmlUnsafe", "tooltip", "mouseenter"); +} ]); + +angular.module("ui.bootstrap.popover", [ "ui.bootstrap.tooltip" ]).directive("popoverTemplatePopup", function() { + return { + restrict: "EA", + replace: true, + scope: { + title: "@", + contentExp: "&", + placement: "@", + popupClass: "@", + animation: "&", + isOpen: "&", + originScope: "&" + }, + templateUrl: "template/popover/popover-template.html" + }; +}).directive("popoverTemplate", [ "$tooltip", function($tooltip) { + return $tooltip("popoverTemplate", "popover", "click", { + useContentExp: true + }); +} ]).directive("popoverHtmlPopup", function() { + return { + restrict: "EA", + replace: true, + scope: { + contentExp: "&", + title: "@", + placement: "@", + popupClass: "@", + animation: "&", + isOpen: "&" + }, + templateUrl: "template/popover/popover-html.html" + }; +}).directive("popoverHtml", [ "$tooltip", function($tooltip) { + return $tooltip("popoverHtml", "popover", "click", { + useContentExp: true + }); +} ]).directive("popoverPopup", function() { + return { + restrict: "EA", + replace: true, + scope: { + title: "@", + content: "@", + placement: "@", + popupClass: "@", + animation: "&", + isOpen: "&" + }, + templateUrl: "template/popover/popover.html" + }; +}).directive("popover", [ "$tooltip", function($tooltip) { + return $tooltip("popover", "popover", "click"); +} ]); + +angular.module("ui.bootstrap.progressbar", []).constant("progressConfig", { + animate: true, + max: 100 +}).value("$progressSuppressWarning", false).controller("ProgressController", [ "$scope", "$attrs", "progressConfig", function($scope, $attrs, progressConfig) { + var self = this, animate = angular.isDefined($attrs.animate) ? $scope.$parent.$eval($attrs.animate) : progressConfig.animate; + this.bars = []; + $scope.max = angular.isDefined($scope.max) ? $scope.max : progressConfig.max; + this.addBar = function(bar, element) { + if (!animate) { + element.css({ + transition: "none" + }); + } + this.bars.push(bar); + bar.max = $scope.max; + bar.$watch("value", function(value) { + bar.recalculatePercentage(); }); - }, - drawPeaks: function(a, b) { - this.resetScroll(), this.setWidth(b), this.params.barWidth ? this.drawBars(a) : this.drawWave(a); - }, - style: function(a, b) { - return Object.keys(b).forEach(function(c) { - a.style[c] !== b[c] && (a.style[c] = b[c]); - }), a; - }, - resetScroll: function() { - null !== this.wrapper && (this.wrapper.scrollLeft = 0); - }, - recenter: function(a) { - var b = this.wrapper.scrollWidth * a; - this.recenterOnPosition(b, !0); - }, - recenterOnPosition: function(a, b) { - var c = this.wrapper.scrollLeft, d = ~~(this.wrapper.clientWidth / 2), e = a - d, f = e - c, g = this.wrapper.scrollWidth - this.wrapper.clientWidth; - if (0 != g) { - if (!b && f >= -d && d > f) { - var h = 5; - f = Math.max(-h, Math.min(h, f)), e = c + f; + bar.recalculatePercentage = function() { + bar.percent = +(100 * bar.value / bar.max).toFixed(2); + var totalPercentage = self.bars.reduce(function(total, bar) { + return total + bar.percent; + }, 0); + if (totalPercentage > 100) { + bar.percent -= totalPercentage - 100; } - e = Math.max(0, Math.min(g, e)), e != c && (this.wrapper.scrollLeft = e); - } - }, - getWidth: function() { - return Math.round(this.container.clientWidth * this.params.pixelRatio); - }, - setWidth: function(a) { - a != this.width && (this.width = a, this.params.fillParent || this.params.scrollParent ? this.style(this.wrapper, { - width: "" - }) : this.style(this.wrapper, { - width: ~~(this.width / this.params.pixelRatio) + "px" - }), this.updateSize()); - }, - setHeight: function(a) { - a != this.height && (this.height = a, this.style(this.wrapper, { - height: ~~(this.height / this.params.pixelRatio) + "px" - }), this.updateSize()); - }, - progress: function(a) { - var b = 1 / this.params.pixelRatio, c = Math.round(a * this.width) * b; - if (c < this.lastPos || c - this.lastPos >= b) { - if (this.lastPos = c, this.params.scrollParent) { - var d = ~~(this.wrapper.scrollWidth * a); - this.recenterOnPosition(d); + }; + bar.$on("$destroy", function() { + element = null; + self.removeBar(bar); + }); + }; + this.removeBar = function(bar) { + this.bars.splice(this.bars.indexOf(bar), 1); + }; + $scope.$watch("max", function(max) { + self.bars.forEach(function(bar) { + bar.max = $scope.max; + bar.recalculatePercentage(); + }); + }); +} ]).directive("uibProgress", function() { + return { + restrict: "EA", + replace: true, + transclude: true, + controller: "ProgressController", + require: "uibProgress", + scope: { + max: "=?" + }, + templateUrl: "template/progressbar/progress.html" + }; +}).directive("progress", [ "$log", "$progressSuppressWarning", function($log, $progressSuppressWarning) { + return { + restrict: "EA", + replace: true, + transclude: true, + controller: "ProgressController", + require: "progress", + scope: { + max: "=?" + }, + templateUrl: "template/progressbar/progress.html", + link: function() { + if ($progressSuppressWarning) { + $log.warn("progress is now deprecated. Use uib-progress instead"); } - this.updateProgress(a); - } - }, - destroy: function() { - this.unAll(), this.wrapper && (this.container.removeChild(this.wrapper), this.wrapper = null); - }, - createElements: function() {}, - updateSize: function() {}, - drawWave: function(a, b) {}, - clearWave: function() {}, - updateProgress: function(a) {} -}, WaveSurfer.util.extend(WaveSurfer.Drawer, WaveSurfer.Observer), WaveSurfer.Drawer.Canvas = Object.create(WaveSurfer.Drawer), -WaveSurfer.util.extend(WaveSurfer.Drawer.Canvas, { - createElements: function() { - var a = this.wrapper.appendChild(this.style(document.createElement("canvas"), { - position: "absolute", - zIndex: 1, - left: 0, - top: 0, - bottom: 0 - })); - if (this.waveCc = a.getContext("2d"), this.progressWave = this.wrapper.appendChild(this.style(document.createElement("wave"), { - position: "absolute", - zIndex: 2, - left: 0, - top: 0, - bottom: 0, - overflow: "hidden", - width: "0", - display: "none", - boxSizing: "border-box", - borderRightStyle: "solid", - borderRightWidth: this.params.cursorWidth + "px", - borderRightColor: this.params.cursorColor - })), this.params.waveColor != this.params.progressColor) { - var b = this.progressWave.appendChild(document.createElement("canvas")); - this.progressCc = b.getContext("2d"); - } - }, - updateSize: function() { - var a = Math.round(this.width / this.params.pixelRatio); - this.waveCc.canvas.width = this.width, this.waveCc.canvas.height = this.height, - this.style(this.waveCc.canvas, { - width: a + "px" - }), this.style(this.progressWave, { - display: "block" - }), this.progressCc && (this.progressCc.canvas.width = this.width, this.progressCc.canvas.height = this.height, - this.style(this.progressCc.canvas, { - width: a + "px" - })), this.clearWave(); - }, - clearWave: function() { - this.waveCc.clearRect(0, 0, this.width, this.height), this.progressCc && this.progressCc.clearRect(0, 0, this.width, this.height); - }, - drawBars: function(a, b) { - if (a[0] instanceof Array) { - var c = a; - if (this.params.splitChannels) return this.setHeight(c.length * this.params.height * this.params.pixelRatio), - void c.forEach(this.drawBars, this); - a = c[0]; } - var d = .5 / this.params.pixelRatio, e = this.width, f = this.params.height * this.params.pixelRatio, g = f * b || 0, h = f / 2, i = ~~(a.length / 2), j = this.params.barWidth * this.params.pixelRatio, k = Math.max(this.params.pixelRatio, ~~(j / 2)), l = j + k, m = 1; - if (this.params.normalize) { - var n, o; - o = Math.max.apply(Math, a), n = Math.min.apply(Math, a), m = o, -n > m && (m = -n); + }; +} ]).directive("uibBar", function() { + return { + restrict: "EA", + replace: true, + transclude: true, + require: "^uibProgress", + scope: { + value: "=", + type: "@" + }, + templateUrl: "template/progressbar/bar.html", + link: function(scope, element, attrs, progressCtrl) { + progressCtrl.addBar(scope, element); } - var p = i / e; - this.waveCc.fillStyle = this.params.waveColor, this.progressCc && (this.progressCc.fillStyle = this.params.progressColor), - [ this.waveCc, this.progressCc ].forEach(function(b) { - if (b) if (this.params.reflection) for (var c = 0; e > c; c += l) { - var f = Math.round(a[2 * c * p] / m * h); - b.fillRect(c + d, h - f + g, j + d, 2 * f); - } else { - for (var c = 0; e > c; c += l) { - var f = Math.round(a[2 * c * p] / m * h); - b.fillRect(c + d, h - f + g, j + d, f); - } - for (var c = 0; e > c; c += l) { - var f = Math.round(a[2 * c * p + 1] / m * h); - b.fillRect(c + d, h - f + g, j + d, f); - } + }; +}).directive("bar", [ "$log", "$progressSuppressWarning", function($log, $progressSuppressWarning) { + return { + restrict: "EA", + replace: true, + transclude: true, + require: "^progress", + scope: { + value: "=", + type: "@" + }, + templateUrl: "template/progressbar/bar.html", + link: function(scope, element, attrs, progressCtrl) { + if ($progressSuppressWarning) { + $log.warn("bar is now deprecated. Use uib-bar instead"); } - }, this); - }, - drawWave: function(a, b) { - if (a[0] instanceof Array) { - var c = a; - if (this.params.splitChannels) return this.setHeight(c.length * this.params.height * this.params.pixelRatio), - void c.forEach(this.drawWave, this); - a = c[0]; + progressCtrl.addBar(scope, element); } - var d = .5 / this.params.pixelRatio, e = this.params.height * this.params.pixelRatio, f = e * b || 0, g = e / 2, h = ~~(a.length / 2), i = 1; - this.params.fillParent && this.width != h && (i = this.width / h); - var j = 1; - if (this.params.normalize) { - var k, l; - l = Math.max.apply(Math, a), k = Math.min.apply(Math, a), j = l, -k > j && (j = -k); + }; +} ]).directive("progressbar", function() { + return { + restrict: "EA", + replace: true, + transclude: true, + controller: "ProgressController", + scope: { + value: "=", + max: "=?", + type: "@" + }, + templateUrl: "template/progressbar/progressbar.html", + link: function(scope, element, attrs, progressCtrl) { + progressCtrl.addBar(scope, angular.element(element.children()[0])); } - this.waveCc.fillStyle = this.params.waveColor, this.progressCc && (this.progressCc.fillStyle = this.params.progressColor), - [ this.waveCc, this.progressCc ].forEach(function(b) { - if (b) { - b.beginPath(), b.moveTo(d, g + f); - for (var c = 0; h > c; c++) { - var e = Math.round(a[2 * c] / j * g); - b.lineTo(c * i + d, g - e + f); - } - for (var c = h - 1; c >= 0; c--) { - var e = Math.round(a[2 * c + 1] / j * g); - b.lineTo(c * i + d, g - e + f); - } - b.closePath(), b.fill(), b.fillRect(0, g + f - d, this.width, d); - } - }, this); - }, - updateProgress: function(a) { - var b = Math.round(this.width * a) / this.params.pixelRatio; - this.style(this.progressWave, { - width: b + "px" - }); - } + }; }); -+function($) { - "use strict"; - var Validator = function(element, options) { - this.$element = $(element); - this.options = options; - options.errors = $.extend({}, Validator.DEFAULTS.errors, options.errors); - for (var custom in options.custom) { - if (!options.errors[custom]) throw new Error("Missing default error message for custom validator: " + custom); - } - $.extend(Validator.VALIDATORS, options.custom); - this.$element.attr("novalidate", true); - this.toggleSubmit(); - this.$element.on("input.bs.validator change.bs.validator focusout.bs.validator", $.proxy(this.validateInput, this)); - this.$element.on("submit.bs.validator", $.proxy(this.onSubmit, this)); - this.$element.find("[data-match]").each(function() { - var $this = $(this); - var target = $this.data("match"); - $(target).on("input.bs.validator", function(e) { - $this.val() && $this.trigger("input.bs.validator"); - }); - }); +angular.module("ui.bootstrap.rating", []).constant("ratingConfig", { + max: 5, + stateOn: null, + stateOff: null, + titles: [ "one", "two", "three", "four", "five" ] +}).controller("RatingController", [ "$scope", "$attrs", "ratingConfig", function($scope, $attrs, ratingConfig) { + var ngModelCtrl = { + $setViewValue: angular.noop }; - Validator.INPUT_SELECTOR = ':input:not([type="submit"], button):enabled:visible'; - Validator.DEFAULTS = { - delay: 500, - html: false, - disable: true, - custom: {}, - errors: { - match: "Does not match", - minlength: "Not long enough" - }, - feedback: { - success: "glyphicon-ok", - error: "glyphicon-remove" - } - }; - Validator.VALIDATORS = { - "native": function($el) { - var el = $el[0]; - return el.checkValidity ? el.checkValidity() : true; - }, - match: function($el) { - var target = $el.data("match"); - return !$el.val() || $el.val() === $(target).val(); - }, - minlength: function($el) { - var minlength = $el.data("minlength"); - return !$el.val() || $el.val().length >= minlength; - } - }; - Validator.prototype.validateInput = function(e) { - var $el = $(e.target); - var prevErrors = $el.data("bs.validator.errors"); - var errors; - if ($el.is('[type="radio"]')) $el = this.$element.find('input[name="' + $el.attr("name") + '"]'); - this.$element.trigger(e = $.Event("validate.bs.validator", { - relatedTarget: $el[0] - })); - if (e.isDefaultPrevented()) return; - var self = this; - this.runValidators($el).done(function(errors) { - $el.data("bs.validator.errors", errors); - errors.length ? self.showErrors($el) : self.clearErrors($el); - if (!prevErrors || errors.toString() !== prevErrors.toString()) { - e = errors.length ? $.Event("invalid.bs.validator", { - relatedTarget: $el[0], - detail: errors - }) : $.Event("valid.bs.validator", { - relatedTarget: $el[0], - detail: prevErrors - }); - self.$element.trigger(e); + this.init = function(ngModelCtrl_) { + ngModelCtrl = ngModelCtrl_; + ngModelCtrl.$render = this.render; + ngModelCtrl.$formatters.push(function(value) { + if (angular.isNumber(value) && value << 0 !== value) { + value = Math.round(value); } - self.toggleSubmit(); - self.$element.trigger($.Event("validated.bs.validator", { - relatedTarget: $el[0] - })); + return value; }); + this.stateOn = angular.isDefined($attrs.stateOn) ? $scope.$parent.$eval($attrs.stateOn) : ratingConfig.stateOn; + this.stateOff = angular.isDefined($attrs.stateOff) ? $scope.$parent.$eval($attrs.stateOff) : ratingConfig.stateOff; + var tmpTitles = angular.isDefined($attrs.titles) ? $scope.$parent.$eval($attrs.titles) : ratingConfig.titles; + this.titles = angular.isArray(tmpTitles) && tmpTitles.length > 0 ? tmpTitles : ratingConfig.titles; + var ratingStates = angular.isDefined($attrs.ratingStates) ? $scope.$parent.$eval($attrs.ratingStates) : new Array(angular.isDefined($attrs.max) ? $scope.$parent.$eval($attrs.max) : ratingConfig.max); + $scope.range = this.buildTemplateObjects(ratingStates); }; - Validator.prototype.runValidators = function($el) { - var errors = []; - var deferred = $.Deferred(); - var options = this.options; - $el.data("bs.validator.deferred") && $el.data("bs.validator.deferred").reject(); - $el.data("bs.validator.deferred", deferred); - function getErrorMessage(key) { - return $el.data(key + "-error") || $el.data("error") || key == "native" && $el[0].validationMessage || options.errors[key]; + this.buildTemplateObjects = function(states) { + for (var i = 0, n = states.length; i < n; i++) { + states[i] = angular.extend({ + index: i + }, { + stateOn: this.stateOn, + stateOff: this.stateOff, + title: this.getTitle(i) + }, states[i]); } - $.each(Validator.VALIDATORS, $.proxy(function(key, validator) { - if (($el.data(key) || key == "native") && !validator.call(this, $el)) { - var error = getErrorMessage(key); - !~errors.indexOf(error) && errors.push(error); - } - }, this)); - if (!errors.length && $el.val() && $el.data("remote")) { - this.defer($el, function() { - var data = {}; - data[$el.attr("name")] = $el.val(); - $.get($el.data("remote"), data).fail(function(jqXHR, textStatus, error) { - errors.push(getErrorMessage("remote") || error); - }).always(function() { - deferred.resolve(errors); - }); - }); - } else deferred.resolve(errors); - return deferred.promise(); + return states; }; - Validator.prototype.validate = function() { - var delay = this.options.delay; - this.options.delay = 0; - this.$element.find(Validator.INPUT_SELECTOR).trigger("input.bs.validator"); - this.options.delay = delay; - return this; + this.getTitle = function(index) { + if (index >= this.titles.length) { + return index + 1; + } else { + return this.titles[index]; + } }; - Validator.prototype.showErrors = function($el) { - var method = this.options.html ? "html" : "text"; - this.defer($el, function() { - var $group = $el.closest(".form-group"); - var $block = $group.find(".help-block.with-errors"); - var $feedback = $group.find(".form-control-feedback"); - var errors = $el.data("bs.validator.errors"); - if (!errors.length) return; - errors = $("
            ").addClass("list-unstyled").append($.map(errors, function(error) { - return $("
          • ")[method](error); - })); - $block.data("bs.validator.originalContent") === undefined && $block.data("bs.validator.originalContent", $block.html()); - $block.empty().append(errors); - $group.addClass("has-error"); - $feedback.length && $feedback.removeClass(this.options.feedback.success) && $feedback.addClass(this.options.feedback.error) && $group.removeClass("has-success"); - }); - }; - Validator.prototype.clearErrors = function($el) { - var $group = $el.closest(".form-group"); - var $block = $group.find(".help-block.with-errors"); - var $feedback = $group.find(".form-control-feedback"); - $block.html($block.data("bs.validator.originalContent")); - $group.removeClass("has-error"); - $feedback.length && $feedback.removeClass(this.options.feedback.error) && $feedback.addClass(this.options.feedback.success) && $group.addClass("has-success"); - }; - Validator.prototype.hasErrors = function() { - function fieldErrors() { - return !!($(this).data("bs.validator.errors") || []).length; - } - return !!this.$element.find(Validator.INPUT_SELECTOR).filter(fieldErrors).length; - }; - Validator.prototype.isIncomplete = function() { - function fieldIncomplete() { - return this.type === "checkbox" ? !this.checked : this.type === "radio" ? !$('[name="' + this.name + '"]:checked').length : $.trim(this.value) === ""; - } - return !!this.$element.find(Validator.INPUT_SELECTOR).filter("[required]").filter(fieldIncomplete).length; - }; - Validator.prototype.onSubmit = function(e) { - this.validate(); - if (this.isIncomplete() || this.hasErrors()) e.preventDefault(); - }; - Validator.prototype.toggleSubmit = function() { - if (!this.options.disable) return; - var $btn = $('button[type="submit"], input[type="submit"]').filter('[form="' + this.$element.attr("id") + '"]').add(this.$element.find('input[type="submit"], button[type="submit"]')); - $btn.toggleClass("disabled", this.isIncomplete() || this.hasErrors()); - }; - Validator.prototype.defer = function($el, callback) { - callback = $.proxy(callback, this); - if (!this.options.delay) return callback(); - window.clearTimeout($el.data("bs.validator.timeout")); - $el.data("bs.validator.timeout", window.setTimeout(callback, this.options.delay)); - }; - Validator.prototype.destroy = function() { - this.$element.removeAttr("novalidate").removeData("bs.validator").off(".bs.validator"); - this.$element.find(Validator.INPUT_SELECTOR).off(".bs.validator").removeData([ "bs.validator.errors", "bs.validator.deferred" ]).each(function() { - var $this = $(this); - var timeout = $this.data("bs.validator.timeout"); - window.clearTimeout(timeout) && $this.removeData("bs.validator.timeout"); - }); - this.$element.find(".help-block.with-errors").each(function() { - var $this = $(this); - var originalContent = $this.data("bs.validator.originalContent"); - $this.removeData("bs.validator.originalContent").html(originalContent); - }); - this.$element.find('input[type="submit"], button[type="submit"]').removeClass("disabled"); - this.$element.find(".has-error").removeClass("has-error"); - return this; + $scope.rate = function(value) { + if (!$scope.readonly && value >= 0 && value <= $scope.range.length) { + ngModelCtrl.$setViewValue(ngModelCtrl.$viewValue === value ? 0 : value); + ngModelCtrl.$render(); + } }; - function Plugin(option) { - return this.each(function() { - var $this = $(this); - var options = $.extend({}, Validator.DEFAULTS, $this.data(), typeof option == "object" && option); - var data = $this.data("bs.validator"); - if (!data && option == "destroy") return; - if (!data) $this.data("bs.validator", data = new Validator(this, options)); - if (typeof option == "string") data[option](); + $scope.enter = function(value) { + if (!$scope.readonly) { + $scope.value = value; + } + $scope.onHover({ + value: value }); - } - var old = $.fn.validator; - $.fn.validator = Plugin; - $.fn.validator.Constructor = Validator; - $.fn.validator.noConflict = function() { - $.fn.validator = old; - return this; }; - $(window).on("load", function() { - $('form[data-toggle="validator"]').each(function() { - var $form = $(this); - Plugin.call($form, $form.data()); - }); - }); -}(jQuery); - -(function(window, angular, undefined) { - "use strict"; - var ngRouteModule = angular.module("ngRoute", [ "ng" ]).provider("$route", $RouteProvider), $routeMinErr = angular.$$minErr("ngRoute"); - function $RouteProvider() { - function inherit(parent, extra) { - return angular.extend(Object.create(parent), extra); - } - var routes = {}; - this.when = function(path, route) { - var routeCopy = angular.copy(route); - if (angular.isUndefined(routeCopy.reloadOnSearch)) { - routeCopy.reloadOnSearch = true; - } - if (angular.isUndefined(routeCopy.caseInsensitiveMatch)) { - routeCopy.caseInsensitiveMatch = this.caseInsensitiveMatch; - } - routes[path] = angular.extend(routeCopy, path && pathRegExp(path, routeCopy)); - if (path) { - var redirectPath = path[path.length - 1] == "/" ? path.substr(0, path.length - 1) : path + "/"; - routes[redirectPath] = angular.extend({ - redirectTo: path - }, pathRegExp(redirectPath, routeCopy)); - } - return this; - }; - this.caseInsensitiveMatch = false; - function pathRegExp(path, opts) { - var insensitive = opts.caseInsensitiveMatch, ret = { - originalPath: path, - regexp: path - }, keys = ret.keys = []; - path = path.replace(/([().])/g, "\\$1").replace(/(\/)?:(\w+)([\?\*])?/g, function(_, slash, key, option) { - var optional = option === "?" ? option : null; - var star = option === "*" ? option : null; - keys.push({ - name: key, - optional: !!optional - }); - slash = slash || ""; - return "" + (optional ? "" : slash) + "(?:" + (optional ? slash : "") + (star && "(.+?)" || "([^/]+)") + (optional || "") + ")" + (optional || ""); - }).replace(/([\/$\*])/g, "\\$1"); - ret.regexp = new RegExp("^" + path + "$", insensitive ? "i" : ""); - return ret; + $scope.reset = function() { + $scope.value = ngModelCtrl.$viewValue; + $scope.onLeave(); + }; + $scope.onKeydown = function(evt) { + if (/(37|38|39|40)/.test(evt.which)) { + evt.preventDefault(); + evt.stopPropagation(); + $scope.rate($scope.value + (evt.which === 38 || evt.which === 39 ? 1 : -1)); } - this.otherwise = function(params) { - if (typeof params === "string") { - params = { - redirectTo: params - }; - } - this.when(null, params); - return this; - }; - this.$get = [ "$rootScope", "$location", "$routeParams", "$q", "$injector", "$templateRequest", "$sce", function($rootScope, $location, $routeParams, $q, $injector, $templateRequest, $sce) { - var forceReload = false, preparedRoute, preparedRouteIsUpdateOnly, $route = { - routes: routes, - reload: function() { - forceReload = true; - $rootScope.$evalAsync(function() { - prepareRoute(); - commitRoute(); - }); - }, - updateParams: function(newParams) { - if (this.current && this.current.$$route) { - newParams = angular.extend({}, this.current.params, newParams); - $location.path(interpolate(this.current.$$route.originalPath, newParams)); - $location.search(newParams); - } else { - throw $routeMinErr("norout", "Tried updating route when with no current route"); - } - } - }; - $rootScope.$on("$locationChangeStart", prepareRoute); - $rootScope.$on("$locationChangeSuccess", commitRoute); - return $route; - function switchRouteMatcher(on, route) { - var keys = route.keys, params = {}; - if (!route.regexp) return null; - var m = route.regexp.exec(on); - if (!m) return null; - for (var i = 1, len = m.length; i < len; ++i) { - var key = keys[i - 1]; - var val = m[i]; - if (key && val) { - params[key.name] = val; - } - } - return params; - } - function prepareRoute($locationEvent) { - var lastRoute = $route.current; - preparedRoute = parseRoute(); - preparedRouteIsUpdateOnly = preparedRoute && lastRoute && preparedRoute.$$route === lastRoute.$$route && angular.equals(preparedRoute.pathParams, lastRoute.pathParams) && !preparedRoute.reloadOnSearch && !forceReload; - if (!preparedRouteIsUpdateOnly && (lastRoute || preparedRoute)) { - if ($rootScope.$broadcast("$routeChangeStart", preparedRoute, lastRoute).defaultPrevented) { - if ($locationEvent) { - $locationEvent.preventDefault(); - } - } - } - } - function commitRoute() { - var lastRoute = $route.current; - var nextRoute = preparedRoute; - if (preparedRouteIsUpdateOnly) { - lastRoute.params = nextRoute.params; - angular.copy(lastRoute.params, $routeParams); - $rootScope.$broadcast("$routeUpdate", lastRoute); - } else if (nextRoute || lastRoute) { - forceReload = false; - $route.current = nextRoute; - if (nextRoute) { - if (nextRoute.redirectTo) { - if (angular.isString(nextRoute.redirectTo)) { - $location.path(interpolate(nextRoute.redirectTo, nextRoute.params)).search(nextRoute.params).replace(); - } else { - $location.url(nextRoute.redirectTo(nextRoute.pathParams, $location.path(), $location.search())).replace(); - } - } - } - $q.when(nextRoute).then(function() { - if (nextRoute) { - var locals = angular.extend({}, nextRoute.resolve), template, templateUrl; - angular.forEach(locals, function(value, key) { - locals[key] = angular.isString(value) ? $injector.get(value) : $injector.invoke(value, null, null, key); - }); - if (angular.isDefined(template = nextRoute.template)) { - if (angular.isFunction(template)) { - template = template(nextRoute.params); - } - } else if (angular.isDefined(templateUrl = nextRoute.templateUrl)) { - if (angular.isFunction(templateUrl)) { - templateUrl = templateUrl(nextRoute.params); - } - if (angular.isDefined(templateUrl)) { - nextRoute.loadedTemplateUrl = $sce.valueOf(templateUrl); - template = $templateRequest(templateUrl); - } - } - if (angular.isDefined(template)) { - locals["$template"] = template; - } - return $q.all(locals); - } - }).then(function(locals) { - if (nextRoute == $route.current) { - if (nextRoute) { - nextRoute.locals = locals; - angular.copy(nextRoute.params, $routeParams); - } - $rootScope.$broadcast("$routeChangeSuccess", nextRoute, lastRoute); - } - }, function(error) { - if (nextRoute == $route.current) { - $rootScope.$broadcast("$routeChangeError", nextRoute, lastRoute, error); - } - }); - } - } - function parseRoute() { - var params, match; - angular.forEach(routes, function(route, path) { - if (!match && (params = switchRouteMatcher($location.path(), route))) { - match = inherit(route, { - params: angular.extend({}, $location.search(), params), - pathParams: params - }); - match.$$route = route; - } - }); - return match || routes[null] && inherit(routes[null], { - params: {}, - pathParams: {} - }); - } - function interpolate(string, params) { - var result = []; - angular.forEach((string || "").split(":"), function(segment, i) { - if (i === 0) { - result.push(segment); - } else { - var segmentMatch = segment.match(/(\w+)(?:[?*])?(.*)/); - var key = segmentMatch[1]; - result.push(params[key]); - result.push(segmentMatch[2] || ""); - delete params[key]; - } - }); - return result.join(""); - } - } ]; - } - ngRouteModule.provider("$routeParams", $RouteParamsProvider); - function $RouteParamsProvider() { - this.$get = function() { - return {}; - }; - } - ngRouteModule.directive("ngView", ngViewFactory); - ngRouteModule.directive("ngView", ngViewFillContentFactory); - ngViewFactory.$inject = [ "$route", "$anchorScroll", "$animate" ]; - function ngViewFactory($route, $anchorScroll, $animate) { - return { - restrict: "ECA", - terminal: true, - priority: 400, - transclude: "element", - link: function(scope, $element, attr, ctrl, $transclude) { - var currentScope, currentElement, previousLeaveAnimation, autoScrollExp = attr.autoscroll, onloadExp = attr.onload || ""; - scope.$on("$routeChangeSuccess", update); - update(); - function cleanupLastView() { - if (previousLeaveAnimation) { - $animate.cancel(previousLeaveAnimation); - previousLeaveAnimation = null; - } - if (currentScope) { - currentScope.$destroy(); - currentScope = null; - } - if (currentElement) { - previousLeaveAnimation = $animate.leave(currentElement); - previousLeaveAnimation.then(function() { - previousLeaveAnimation = null; - }); - currentElement = null; - } - } - function update() { - var locals = $route.current && $route.current.locals, template = locals && locals.$template; - if (angular.isDefined(template)) { - var newScope = scope.$new(); - var current = $route.current; - var clone = $transclude(newScope, function(clone) { - $animate.enter(clone, null, currentElement || $element).then(function onNgViewEnter() { - if (angular.isDefined(autoScrollExp) && (!autoScrollExp || scope.$eval(autoScrollExp))) { - $anchorScroll(); - } - }); - cleanupLastView(); - }); - currentElement = clone; - currentScope = current.scope = newScope; - currentScope.$emit("$viewContentLoaded"); - currentScope.$eval(onloadExp); - } else { - cleanupLastView(); - } - } - } - }; - } - ngViewFillContentFactory.$inject = [ "$compile", "$controller", "$route" ]; - function ngViewFillContentFactory($compile, $controller, $route) { - return { - restrict: "ECA", - priority: -400, - link: function(scope, $element) { - var current = $route.current, locals = current.locals; - $element.html(locals.$template); - var link = $compile($element.contents()); - if (current.controller) { - locals.$scope = scope; - var controller = $controller(current.controller, locals); - if (current.controllerAs) { - scope[current.controllerAs] = controller; - } - $element.data("$ngControllerController", controller); - $element.children().data("$ngControllerController", controller); - } - link(scope); - } - }; - } -})(window, window.angular); - -if (typeof module !== "undefined" && typeof exports !== "undefined" && module.exports === exports) { - module.exports = "ui.router"; -} - -(function(window, angular, undefined) { - "use strict"; - var isDefined = angular.isDefined, isFunction = angular.isFunction, isString = angular.isString, isObject = angular.isObject, isArray = angular.isArray, forEach = angular.forEach, extend = angular.extend, copy = angular.copy; - function inherit(parent, extra) { - return extend(new (extend(function() {}, { - prototype: parent - }))(), extra); - } - function merge(dst) { - forEach(arguments, function(obj) { - if (obj !== dst) { - forEach(obj, function(value, key) { - if (!dst.hasOwnProperty(key)) dst[key] = value; - }); + }; + this.render = function() { + $scope.value = ngModelCtrl.$viewValue; + }; +} ]).directive("rating", function() { + return { + restrict: "EA", + require: [ "rating", "ngModel" ], + scope: { + readonly: "=?", + onHover: "&", + onLeave: "&" + }, + controller: "RatingController", + templateUrl: "template/rating/rating.html", + replace: true, + link: function(scope, element, attrs, ctrls) { + var ratingCtrl = ctrls[0], ngModelCtrl = ctrls[1]; + ratingCtrl.init(ngModelCtrl); + } + }; +}); + +angular.module("ui.bootstrap.tabs", []).controller("TabsetController", [ "$scope", function TabsetCtrl($scope) { + var ctrl = this, tabs = ctrl.tabs = $scope.tabs = []; + ctrl.select = function(selectedTab) { + angular.forEach(tabs, function(tab) { + if (tab.active && tab !== selectedTab) { + tab.active = false; + tab.onDeselect(); + selectedTab.selectCalled = false; } }); - return dst; - } - function ancestors(first, second) { - var path = []; - for (var n in first.path) { - if (first.path[n] !== second.path[n]) break; - path.push(first.path[n]); + selectedTab.active = true; + if (!selectedTab.selectCalled) { + selectedTab.onSelect(); + selectedTab.selectCalled = true; } - return path; - } - function objectKeys(object) { - if (Object.keys) { - return Object.keys(object); + }; + ctrl.addTab = function addTab(tab) { + tabs.push(tab); + if (tabs.length === 1 && tab.active !== false) { + tab.active = true; + } else if (tab.active) { + ctrl.select(tab); + } else { + tab.active = false; } - var result = []; - forEach(object, function(val, key) { - result.push(key); - }); - return result; - } - function indexOf(array, value) { - if (Array.prototype.indexOf) { - return array.indexOf(value, Number(arguments[2]) || 0); + }; + ctrl.removeTab = function removeTab(tab) { + var index = tabs.indexOf(tab); + if (tab.active && tabs.length > 1 && !destroyed) { + var newActiveIndex = index == tabs.length - 1 ? index - 1 : index + 1; + ctrl.select(tabs[newActiveIndex]); } - var len = array.length >>> 0, from = Number(arguments[2]) || 0; - from = from < 0 ? Math.ceil(from) : Math.floor(from); - if (from < 0) from += len; - for (;from < len; from++) { - if (from in array && array[from] === value) return from; + tabs.splice(index, 1); + }; + var destroyed; + $scope.$on("$destroy", function() { + destroyed = true; + }); +} ]).directive("tabset", function() { + return { + restrict: "EA", + transclude: true, + replace: true, + scope: { + type: "@" + }, + controller: "TabsetController", + templateUrl: "template/tabs/tabset.html", + link: function(scope, element, attrs) { + scope.vertical = angular.isDefined(attrs.vertical) ? scope.$parent.$eval(attrs.vertical) : false; + scope.justified = angular.isDefined(attrs.justified) ? scope.$parent.$eval(attrs.justified) : false; } - return -1; - } - function inheritParams(currentParams, newParams, $current, $to) { - var parents = ancestors($current, $to), parentParams, inherited = {}, inheritList = []; - for (var i in parents) { - if (!parents[i].params) continue; - parentParams = objectKeys(parents[i].params); - if (!parentParams.length) continue; - for (var j in parentParams) { - if (indexOf(inheritList, parentParams[j]) >= 0) continue; - inheritList.push(parentParams[j]); - inherited[parentParams[j]] = currentParams[parentParams[j]]; + }; +}).directive("tab", [ "$parse", "$log", function($parse, $log) { + return { + require: "^tabset", + restrict: "EA", + replace: true, + templateUrl: "template/tabs/tab.html", + transclude: true, + scope: { + active: "=?", + heading: "@", + onSelect: "&select", + onDeselect: "&deselect" + }, + controller: function() {}, + link: function(scope, elm, attrs, tabsetCtrl, transclude) { + scope.$watch("active", function(active) { + if (active) { + tabsetCtrl.select(scope); + } + }); + scope.disabled = false; + if (attrs.disable) { + scope.$parent.$watch($parse(attrs.disable), function(value) { + scope.disabled = !!value; + }); + } + if (attrs.disabled) { + $log.warn('Use of "disabled" attribute has been deprecated, please use "disable"'); + scope.$parent.$watch($parse(attrs.disabled), function(value) { + scope.disabled = !!value; + }); } + scope.select = function() { + if (!scope.disabled) { + scope.active = true; + } + }; + tabsetCtrl.addTab(scope); + scope.$on("$destroy", function() { + tabsetCtrl.removeTab(scope); + }); + scope.$transcludeFn = transclude; } - return extend({}, inherited, newParams); - } - function equalForKeys(a, b, keys) { - if (!keys) { - keys = []; - for (var n in a) keys.push(n); + }; +} ]).directive("tabHeadingTransclude", function() { + return { + restrict: "A", + require: "^tab", + link: function(scope, elm, attrs, tabCtrl) { + scope.$watch("headingElement", function updateHeadingElement(heading) { + if (heading) { + elm.html(""); + elm.append(heading); + } + }); } - for (var i = 0; i < keys.length; i++) { - var k = keys[i]; - if (a[k] != b[k]) return false; + }; +}).directive("tabContentTransclude", function() { + return { + restrict: "A", + require: "^tabset", + link: function(scope, elm, attrs) { + var tab = scope.$eval(attrs.tabContentTransclude); + tab.$transcludeFn(tab.$parent, function(contents) { + angular.forEach(contents, function(node) { + if (isTabHeading(node)) { + tab.headingElement = node; + } else { + elm.append(node); + } + }); + }); } - return true; - } - function filterByKeys(keys, values) { - var filtered = {}; - forEach(keys, function(name) { - filtered[name] = values[name]; - }); - return filtered; - } - function indexBy(array, propName) { - var result = {}; - forEach(array, function(item) { - result[item[propName]] = item; - }); - return result; + }; + function isTabHeading(node) { + return node.tagName && (node.hasAttribute("tab-heading") || node.hasAttribute("data-tab-heading") || node.hasAttribute("x-tab-heading") || node.tagName.toLowerCase() === "tab-heading" || node.tagName.toLowerCase() === "data-tab-heading" || node.tagName.toLowerCase() === "x-tab-heading"); } - function pick(obj) { - var copy = {}; - var keys = Array.prototype.concat.apply(Array.prototype, Array.prototype.slice.call(arguments, 1)); - forEach(keys, function(key) { - if (key in obj) copy[key] = obj[key]; +}); + +angular.module("ui.bootstrap.timepicker", []).constant("timepickerConfig", { + hourStep: 1, + minuteStep: 1, + showMeridian: true, + meridians: null, + readonlyInput: false, + mousewheel: true, + arrowkeys: true, + showSpinners: true +}).controller("TimepickerController", [ "$scope", "$attrs", "$parse", "$log", "$locale", "timepickerConfig", function($scope, $attrs, $parse, $log, $locale, timepickerConfig) { + var selected = new Date(), ngModelCtrl = { + $setViewValue: angular.noop + }, meridians = angular.isDefined($attrs.meridians) ? $scope.$parent.$eval($attrs.meridians) : timepickerConfig.meridians || $locale.DATETIME_FORMATS.AMPMS; + this.init = function(ngModelCtrl_, inputs) { + ngModelCtrl = ngModelCtrl_; + ngModelCtrl.$render = this.render; + ngModelCtrl.$formatters.unshift(function(modelValue) { + return modelValue ? new Date(modelValue) : null; }); - return copy; - } - function omit(obj) { - var copy = {}; - var keys = Array.prototype.concat.apply(Array.prototype, Array.prototype.slice.call(arguments, 1)); - for (var key in obj) { - if (indexOf(keys, key) == -1) copy[key] = obj[key]; + var hoursInputEl = inputs.eq(0), minutesInputEl = inputs.eq(1); + var mousewheel = angular.isDefined($attrs.mousewheel) ? $scope.$parent.$eval($attrs.mousewheel) : timepickerConfig.mousewheel; + if (mousewheel) { + this.setupMousewheelEvents(hoursInputEl, minutesInputEl); } - return copy; - } - function pluck(collection, key) { - var result = isArray(collection) ? [] : {}; - forEach(collection, function(val, i) { - result[i] = isFunction(key) ? key(val) : val[key]; - }); - return result; - } - function filter(collection, callback) { - var array = isArray(collection); - var result = array ? [] : {}; - forEach(collection, function(val, i) { - if (callback(val, i)) { - result[array ? result.length : i] = val; - } + var arrowkeys = angular.isDefined($attrs.arrowkeys) ? $scope.$parent.$eval($attrs.arrowkeys) : timepickerConfig.arrowkeys; + if (arrowkeys) { + this.setupArrowkeyEvents(hoursInputEl, minutesInputEl); + } + $scope.readonlyInput = angular.isDefined($attrs.readonlyInput) ? $scope.$parent.$eval($attrs.readonlyInput) : timepickerConfig.readonlyInput; + this.setupInputEvents(hoursInputEl, minutesInputEl); + }; + var hourStep = timepickerConfig.hourStep; + if ($attrs.hourStep) { + $scope.$parent.$watch($parse($attrs.hourStep), function(value) { + hourStep = parseInt(value, 10); }); - return result; } - function map(collection, callback) { - var result = isArray(collection) ? [] : {}; - forEach(collection, function(val, i) { - result[i] = callback(val, i); + var minuteStep = timepickerConfig.minuteStep; + if ($attrs.minuteStep) { + $scope.$parent.$watch($parse($attrs.minuteStep), function(value) { + minuteStep = parseInt(value, 10); }); - return result; - } - angular.module("ui.router.util", [ "ng" ]); - angular.module("ui.router.router", [ "ui.router.util" ]); - angular.module("ui.router.state", [ "ui.router.router", "ui.router.util" ]); - angular.module("ui.router", [ "ui.router.state" ]); - angular.module("ui.router.compat", [ "ui.router" ]); - $Resolve.$inject = [ "$q", "$injector" ]; - function $Resolve($q, $injector) { - var VISIT_IN_PROGRESS = 1, VISIT_DONE = 2, NOTHING = {}, NO_DEPENDENCIES = [], NO_LOCALS = NOTHING, NO_PARENT = extend($q.when(NOTHING), { - $$promises: NOTHING, - $$values: NOTHING - }); - this.study = function(invocables) { - if (!isObject(invocables)) throw new Error("'invocables' must be an object"); - var invocableKeys = objectKeys(invocables || {}); - var plan = [], cycle = [], visited = {}; - function visit(value, key) { - if (visited[key] === VISIT_DONE) return; - cycle.push(key); - if (visited[key] === VISIT_IN_PROGRESS) { - cycle.splice(0, indexOf(cycle, key)); - throw new Error("Cyclic dependency: " + cycle.join(" -> ")); - } - visited[key] = VISIT_IN_PROGRESS; - if (isString(value)) { - plan.push(key, [ function() { - return $injector.get(value); - } ], NO_DEPENDENCIES); - } else { - var params = $injector.annotate(value); - forEach(params, function(param) { - if (param !== key && invocables.hasOwnProperty(param)) visit(invocables[param], param); - }); - plan.push(key, value, params); - } - cycle.pop(); - visited[key] = VISIT_DONE; - } - forEach(invocables, visit); - invocables = cycle = visited = null; - function isResolve(value) { - return isObject(value) && value.then && value.$$promises; - } - return function(locals, parent, self) { - if (isResolve(locals) && self === undefined) { - self = parent; - parent = locals; - locals = null; - } - if (!locals) locals = NO_LOCALS; else if (!isObject(locals)) { - throw new Error("'locals' must be an object"); - } - if (!parent) parent = NO_PARENT; else if (!isResolve(parent)) { - throw new Error("'parent' must be a promise returned by $resolve.resolve()"); - } - var resolution = $q.defer(), result = resolution.promise, promises = result.$$promises = {}, values = extend({}, locals), wait = 1 + plan.length / 3, merged = false; - function done() { - if (!--wait) { - if (!merged) merge(values, parent.$$values); - result.$$values = values; - result.$$promises = result.$$promises || true; - delete result.$$inheritedValues; - resolution.resolve(values); - } - } - function fail(reason) { - result.$$failure = reason; - resolution.reject(reason); - } - if (isDefined(parent.$$failure)) { - fail(parent.$$failure); - return result; - } - if (parent.$$inheritedValues) { - merge(values, omit(parent.$$inheritedValues, invocableKeys)); - } - extend(promises, parent.$$promises); - if (parent.$$values) { - merged = merge(values, omit(parent.$$values, invocableKeys)); - result.$$inheritedValues = omit(parent.$$values, invocableKeys); - done(); - } else { - if (parent.$$inheritedValues) { - result.$$inheritedValues = omit(parent.$$inheritedValues, invocableKeys); - } - parent.then(done, fail); - } - for (var i = 0, ii = plan.length; i < ii; i += 3) { - if (locals.hasOwnProperty(plan[i])) done(); else invoke(plan[i], plan[i + 1], plan[i + 2]); - } - function invoke(key, invocable, params) { - var invocation = $q.defer(), waitParams = 0; - function onfailure(reason) { - invocation.reject(reason); - fail(reason); - } - forEach(params, function(dep) { - if (promises.hasOwnProperty(dep) && !locals.hasOwnProperty(dep)) { - waitParams++; - promises[dep].then(function(result) { - values[dep] = result; - if (!--waitParams) proceed(); - }, onfailure); - } - }); - if (!waitParams) proceed(); - function proceed() { - if (isDefined(result.$$failure)) return; - try { - invocation.resolve($injector.invoke(invocable, self, values)); - invocation.promise.then(function(result) { - values[key] = result; - done(); - }, onfailure); - } catch (e) { - onfailure(e); - } - } - promises[key] = invocation.promise; - } - return result; - }; - }; - this.resolve = function(invocables, locals, parent, self) { - return this.study(invocables)(locals, parent, self); - }; } - angular.module("ui.router.util").service("$resolve", $Resolve); - $TemplateFactory.$inject = [ "$http", "$templateCache", "$injector" ]; - function $TemplateFactory($http, $templateCache, $injector) { - this.fromConfig = function(config, params, locals) { - return isDefined(config.template) ? this.fromString(config.template, params) : isDefined(config.templateUrl) ? this.fromUrl(config.templateUrl, params) : isDefined(config.templateProvider) ? this.fromProvider(config.templateProvider, params, locals) : null; - }; - this.fromString = function(template, params) { - return isFunction(template) ? template(params) : template; - }; - this.fromUrl = function(url, params) { - if (isFunction(url)) url = url(params); - if (url == null) return null; else return $http.get(url, { - cache: $templateCache, - headers: { - Accept: "text/html" - } - }).then(function(response) { - return response.data; - }); - }; - this.fromProvider = function(provider, params, locals) { - return $injector.invoke(provider, null, locals || { - params: params - }); - }; - } - angular.module("ui.router.util").service("$templateFactory", $TemplateFactory); - var $$UMFP; - function UrlMatcher(pattern, config, parentMatcher) { - config = extend({ - params: {} - }, isObject(config) ? config : {}); - var placeholder = /([:*])([\w\[\]]+)|\{([\w\[\]]+)(?:\:((?:[^{}\\]+|\\.|\{(?:[^{}\\]+|\\.)*\})+))?\}/g, searchPlaceholder = /([:]?)([\w\[\]-]+)|\{([\w\[\]-]+)(?:\:((?:[^{}\\]+|\\.|\{(?:[^{}\\]+|\\.)*\})+))?\}/g, compiled = "^", last = 0, m, segments = this.segments = [], parentParams = parentMatcher ? parentMatcher.params : {}, params = this.params = parentMatcher ? parentMatcher.params.$$new() : new $$UMFP.ParamSet(), paramNames = []; - function addParameter(id, type, config, location) { - paramNames.push(id); - if (parentParams[id]) return parentParams[id]; - if (!/^\w+(-+\w+)*(?:\[\])?$/.test(id)) throw new Error("Invalid parameter name '" + id + "' in pattern '" + pattern + "'"); - if (params[id]) throw new Error("Duplicate parameter name '" + id + "' in pattern '" + pattern + "'"); - params[id] = new $$UMFP.Param(id, type, config, location); - return params[id]; - } - function quoteRegExp(string, pattern, squash, optional) { - var surroundPattern = [ "", "" ], result = string.replace(/[\\\[\]\^$*+?.()|{}]/g, "\\$&"); - if (!pattern) return result; - switch (squash) { - case false: - surroundPattern = [ "(", ")" + (optional ? "?" : "") ]; - break; - - case true: - surroundPattern = [ "?(", ")?" ]; - break; - - default: - surroundPattern = [ "(" + squash + "|", ")?" ]; - break; - } - return result + surroundPattern[0] + pattern + surroundPattern[1]; - } - this.source = pattern; - function matchDetails(m, isSearch) { - var id, regexp, segment, type, cfg, arrayMode; - id = m[2] || m[3]; - cfg = config.params[id]; - segment = pattern.substring(last, m.index); - regexp = isSearch ? m[4] : m[4] || (m[1] == "*" ? ".*" : null); - type = $$UMFP.type(regexp || "string") || inherit($$UMFP.type("string"), { - pattern: new RegExp(regexp, config.caseInsensitive ? "i" : undefined) - }); - return { - id: id, - regexp: regexp, - segment: segment, - type: type, - cfg: cfg - }; - } - var p, param, segment; - while (m = placeholder.exec(pattern)) { - p = matchDetails(m, false); - if (p.segment.indexOf("?") >= 0) break; - param = addParameter(p.id, p.type, p.cfg, "path"); - compiled += quoteRegExp(p.segment, param.type.pattern.source, param.squash, param.isOptional); - segments.push(p.segment); - last = placeholder.lastIndex; - } - segment = pattern.substring(last); - var i = segment.indexOf("?"); - if (i >= 0) { - var search = this.sourceSearch = segment.substring(i); - segment = segment.substring(0, i); - this.sourcePath = pattern.substring(0, last + i); - if (search.length > 0) { - last = 0; - while (m = searchPlaceholder.exec(search)) { - p = matchDetails(m, true); - param = addParameter(p.id, p.type, p.cfg, "search"); - last = placeholder.lastIndex; - } - } + var min; + $scope.$parent.$watch($parse($attrs.min), function(value) { + var dt = new Date(value); + min = isNaN(dt) ? undefined : dt; + }); + var max; + $scope.$parent.$watch($parse($attrs.max), function(value) { + var dt = new Date(value); + max = isNaN(dt) ? undefined : dt; + }); + $scope.noIncrementHours = function() { + var incrementedSelected = addMinutes(selected, hourStep * 60); + return incrementedSelected > max || incrementedSelected < selected && incrementedSelected < min; + }; + $scope.noDecrementHours = function() { + var decrementedSelected = addMinutes(selected, -hourStep * 60); + return decrementedSelected < min || decrementedSelected > selected && decrementedSelected > max; + }; + $scope.noIncrementMinutes = function() { + var incrementedSelected = addMinutes(selected, minuteStep); + return incrementedSelected > max || incrementedSelected < selected && incrementedSelected < min; + }; + $scope.noDecrementMinutes = function() { + var decrementedSelected = addMinutes(selected, -minuteStep); + return decrementedSelected < min || decrementedSelected > selected && decrementedSelected > max; + }; + $scope.noToggleMeridian = function() { + if (selected.getHours() < 13) { + return addMinutes(selected, 12 * 60) > max; } else { - this.sourcePath = pattern; - this.sourceSearch = ""; - } - compiled += quoteRegExp(segment) + (config.strict === false ? "/?" : "") + "$"; - segments.push(segment); - this.regexp = new RegExp(compiled, config.caseInsensitive ? "i" : undefined); - this.prefix = segments[0]; - this.$$paramNames = paramNames; - } - UrlMatcher.prototype.concat = function(pattern, config) { - var defaultConfig = { - caseInsensitive: $$UMFP.caseInsensitive(), - strict: $$UMFP.strictMode(), - squash: $$UMFP.defaultSquashPolicy() - }; - return new UrlMatcher(this.sourcePath + pattern + this.sourceSearch, extend(defaultConfig, config), this); - }; - UrlMatcher.prototype.toString = function() { - return this.source; - }; - UrlMatcher.prototype.exec = function(path, searchParams) { - var m = this.regexp.exec(path); - if (!m) return null; - searchParams = searchParams || {}; - var paramNames = this.parameters(), nTotal = paramNames.length, nPath = this.segments.length - 1, values = {}, i, j, cfg, paramName; - if (nPath !== m.length - 1) throw new Error("Unbalanced capture group in route '" + this.source + "'"); - function decodePathArray(string) { - function reverseString(str) { - return str.split("").reverse().join(""); - } - function unquoteDashes(str) { - return str.replace(/\\-/g, "-"); - } - var split = reverseString(string).split(/-(?!\\)/); - var allReversed = map(split, reverseString); - return map(allReversed, unquoteDashes).reverse(); - } - for (i = 0; i < nPath; i++) { - paramName = paramNames[i]; - var param = this.params[paramName]; - var paramVal = m[i + 1]; - for (j = 0; j < param.replace; j++) { - if (param.replace[j].from === paramVal) paramVal = param.replace[j].to; - } - if (paramVal && param.array === true) paramVal = decodePathArray(paramVal); - values[paramName] = param.value(paramVal); - } - for (;i < nTotal; i++) { - paramName = paramNames[i]; - values[paramName] = this.params[paramName].value(searchParams[paramName]); + return addMinutes(selected, -12 * 60) < min; } - return values; }; - UrlMatcher.prototype.parameters = function(param) { - if (!isDefined(param)) return this.$$paramNames; - return this.params[param] || null; - }; - UrlMatcher.prototype.validates = function(params) { - return this.params.$$validates(params); - }; - UrlMatcher.prototype.format = function(values) { - values = values || {}; - var segments = this.segments, params = this.parameters(), paramset = this.params; - if (!this.validates(values)) return null; - var i, search = false, nPath = segments.length - 1, nTotal = params.length, result = segments[0]; - function encodeDashes(str) { - return encodeURIComponent(str).replace(/-/g, function(c) { - return "%5C%" + c.charCodeAt(0).toString(16).toUpperCase(); - }); - } - for (i = 0; i < nTotal; i++) { - var isPathParam = i < nPath; - var name = params[i], param = paramset[name], value = param.value(values[name]); - var isDefaultValue = param.isOptional && param.type.equals(param.value(), value); - var squash = isDefaultValue ? param.squash : false; - var encoded = param.type.encode(value); - if (isPathParam) { - var nextSegment = segments[i + 1]; - if (squash === false) { - if (encoded != null) { - if (isArray(encoded)) { - result += map(encoded, encodeDashes).join("-"); - } else { - result += encodeURIComponent(encoded); - } - } - result += nextSegment; - } else if (squash === true) { - var capture = result.match(/\/$/) ? /\/?(.*)/ : /(.*)/; - result += nextSegment.match(capture)[1]; - } else if (isString(squash)) { - result += squash + nextSegment; + $scope.showMeridian = timepickerConfig.showMeridian; + if ($attrs.showMeridian) { + $scope.$parent.$watch($parse($attrs.showMeridian), function(value) { + $scope.showMeridian = !!value; + if (ngModelCtrl.$error.time) { + var hours = getHoursFromTemplate(), minutes = getMinutesFromTemplate(); + if (angular.isDefined(hours) && angular.isDefined(minutes)) { + selected.setHours(hours); + refresh(); } } else { - if (encoded == null || isDefaultValue && squash !== false) continue; - if (!isArray(encoded)) encoded = [ encoded ]; - encoded = map(encoded, encodeURIComponent).join("&" + name + "="); - result += (search ? "&" : "?") + (name + "=" + encoded); - search = true; + updateTemplate(); } - } - return result; - }; - function Type(config) { - extend(this, config); + }); } - Type.prototype.is = function(val, key) { - return true; - }; - Type.prototype.encode = function(val, key) { - return val; - }; - Type.prototype.decode = function(val, key) { - return val; - }; - Type.prototype.equals = function(a, b) { - return a == b; - }; - Type.prototype.$subPattern = function() { - var sub = this.pattern.toString(); - return sub.substr(1, sub.length - 2); - }; - Type.prototype.pattern = /.*/; - Type.prototype.toString = function() { - return "{Type:" + this.name + "}"; - }; - Type.prototype.$normalize = function(val) { - return this.is(val) ? val : this.decode(val); - }; - Type.prototype.$asArray = function(mode, isSearch) { - if (!mode) return this; - if (mode === "auto" && !isSearch) throw new Error("'auto' array mode is for query parameters only"); - function ArrayType(type, mode) { - function bindTo(type, callbackName) { - return function() { - return type[callbackName].apply(type, arguments); - }; + function getHoursFromTemplate() { + var hours = parseInt($scope.hours, 10); + var valid = $scope.showMeridian ? hours > 0 && hours < 13 : hours >= 0 && hours < 24; + if (!valid) { + return undefined; + } + if ($scope.showMeridian) { + if (hours === 12) { + hours = 0; } - function arrayWrap(val) { - return isArray(val) ? val : isDefined(val) ? [ val ] : []; + if ($scope.meridian === meridians[1]) { + hours = hours + 12; } - function arrayUnwrap(val) { - switch (val.length) { - case 0: - return undefined; - - case 1: - return mode === "auto" ? val[0] : val; - - default: - return val; - } + } + return hours; + } + function getMinutesFromTemplate() { + var minutes = parseInt($scope.minutes, 10); + return minutes >= 0 && minutes < 60 ? minutes : undefined; + } + function pad(value) { + return angular.isDefined(value) && value.toString().length < 2 ? "0" + value : value.toString(); + } + this.setupMousewheelEvents = function(hoursInputEl, minutesInputEl) { + var isScrollingUp = function(e) { + if (e.originalEvent) { + e = e.originalEvent; } - function falsey(val) { - return !val; + var delta = e.wheelDelta ? e.wheelDelta : -e.deltaY; + return e.detail || delta > 0; + }; + hoursInputEl.bind("mousewheel wheel", function(e) { + $scope.$apply(isScrollingUp(e) ? $scope.incrementHours() : $scope.decrementHours()); + e.preventDefault(); + }); + minutesInputEl.bind("mousewheel wheel", function(e) { + $scope.$apply(isScrollingUp(e) ? $scope.incrementMinutes() : $scope.decrementMinutes()); + e.preventDefault(); + }); + }; + this.setupArrowkeyEvents = function(hoursInputEl, minutesInputEl) { + hoursInputEl.bind("keydown", function(e) { + if (e.which === 38) { + e.preventDefault(); + $scope.incrementHours(); + $scope.$apply(); + } else if (e.which === 40) { + e.preventDefault(); + $scope.decrementHours(); + $scope.$apply(); } - function arrayHandler(callback, allTruthyMode) { - return function handleArray(val) { - val = arrayWrap(val); - var result = map(val, callback); - if (allTruthyMode === true) return filter(result, falsey).length === 0; - return arrayUnwrap(result); - }; + }); + minutesInputEl.bind("keydown", function(e) { + if (e.which === 38) { + e.preventDefault(); + $scope.incrementMinutes(); + $scope.$apply(); + } else if (e.which === 40) { + e.preventDefault(); + $scope.decrementMinutes(); + $scope.$apply(); } - function arrayEqualsHandler(callback) { - return function handleArray(val1, val2) { - var left = arrayWrap(val1), right = arrayWrap(val2); - if (left.length !== right.length) return false; - for (var i = 0; i < left.length; i++) { - if (!callback(left[i], right[i])) return false; - } - return true; - }; + }); + }; + this.setupInputEvents = function(hoursInputEl, minutesInputEl) { + if ($scope.readonlyInput) { + $scope.updateHours = angular.noop; + $scope.updateMinutes = angular.noop; + return; + } + var invalidate = function(invalidHours, invalidMinutes) { + ngModelCtrl.$setViewValue(null); + ngModelCtrl.$setValidity("time", false); + if (angular.isDefined(invalidHours)) { + $scope.invalidHours = invalidHours; } - this.encode = arrayHandler(bindTo(type, "encode")); - this.decode = arrayHandler(bindTo(type, "decode")); - this.is = arrayHandler(bindTo(type, "is"), true); - this.equals = arrayEqualsHandler(bindTo(type, "equals")); - this.pattern = type.pattern; - this.$normalize = arrayHandler(bindTo(type, "$normalize")); - this.name = type.name; - this.$arrayMode = mode; - } - return new ArrayType(this, mode); - }; - function $UrlMatcherFactory() { - $$UMFP = this; - var isCaseInsensitive = false, isStrictMode = true, defaultSquashPolicy = false; - function valToString(val) { - return val != null ? val.toString().replace(/\//g, "%2F") : val; - } - function valFromString(val) { - return val != null ? val.toString().replace(/%2F/g, "/") : val; - } - var $types = {}, enqueue = true, typeQueue = [], injector, defaultTypes = { - string: { - encode: valToString, - decode: valFromString, - is: function(val) { - return val == null || !isDefined(val) || typeof val === "string"; - }, - pattern: /[^/]*/ - }, - "int": { - encode: valToString, - decode: function(val) { - return parseInt(val, 10); - }, - is: function(val) { - return isDefined(val) && this.decode(val.toString()) === val; - }, - pattern: /\d+/ - }, - bool: { - encode: function(val) { - return val ? 1 : 0; - }, - decode: function(val) { - return parseInt(val, 10) !== 0; - }, - is: function(val) { - return val === true || val === false; - }, - pattern: /0|1/ - }, - date: { - encode: function(val) { - if (!this.is(val)) return undefined; - return [ val.getFullYear(), ("0" + (val.getMonth() + 1)).slice(-2), ("0" + val.getDate()).slice(-2) ].join("-"); - }, - decode: function(val) { - if (this.is(val)) return val; - var match = this.capture.exec(val); - return match ? new Date(match[1], match[2] - 1, match[3]) : undefined; - }, - is: function(val) { - return val instanceof Date && !isNaN(val.valueOf()); - }, - equals: function(a, b) { - return this.is(a) && this.is(b) && a.toISOString() === b.toISOString(); - }, - pattern: /[0-9]{4}-(?:0[1-9]|1[0-2])-(?:0[1-9]|[1-2][0-9]|3[0-1])/, - capture: /([0-9]{4})-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1])/ - }, - json: { - encode: angular.toJson, - decode: angular.fromJson, - is: angular.isObject, - equals: angular.equals, - pattern: /[^/]*/ - }, - any: { - encode: angular.identity, - decode: angular.identity, - equals: angular.equals, - pattern: /.*/ + if (angular.isDefined(invalidMinutes)) { + $scope.invalidMinutes = invalidMinutes; } }; - function getDefaultConfig() { - return { - strict: isStrictMode, - caseInsensitive: isCaseInsensitive - }; - } - function isInjectable(value) { - return isFunction(value) || isArray(value) && isFunction(value[value.length - 1]); - } - $UrlMatcherFactory.$$getDefaultValue = function(config) { - if (!isInjectable(config.value)) return config.value; - if (!injector) throw new Error("Injectable functions cannot be called at configuration time"); - return injector.invoke(config.value); - }; - this.caseInsensitive = function(value) { - if (isDefined(value)) isCaseInsensitive = value; - return isCaseInsensitive; - }; - this.strictMode = function(value) { - if (isDefined(value)) isStrictMode = value; - return isStrictMode; - }; - this.defaultSquashPolicy = function(value) { - if (!isDefined(value)) return defaultSquashPolicy; - if (value !== true && value !== false && !isString(value)) throw new Error("Invalid squash policy: " + value + ". Valid policies: false, true, arbitrary-string"); - defaultSquashPolicy = value; - return value; - }; - this.compile = function(pattern, config) { - return new UrlMatcher(pattern, extend(getDefaultConfig(), config)); - }; - this.isMatcher = function(o) { - if (!isObject(o)) return false; - var result = true; - forEach(UrlMatcher.prototype, function(val, name) { - if (isFunction(val)) { - result = result && (isDefined(o[name]) && isFunction(o[name])); + $scope.updateHours = function() { + var hours = getHoursFromTemplate(), minutes = getMinutesFromTemplate(); + if (angular.isDefined(hours) && angular.isDefined(minutes)) { + selected.setHours(hours); + if (selected < min || selected > max) { + invalidate(true); + } else { + refresh("h"); } - }); - return result; - }; - this.type = function(name, definition, definitionFn) { - if (!isDefined(definition)) return $types[name]; - if ($types.hasOwnProperty(name)) throw new Error("A type named '" + name + "' has already been defined."); - $types[name] = new Type(extend({ - name: name - }, definition)); - if (definitionFn) { - typeQueue.push({ - name: name, - def: definitionFn - }); - if (!enqueue) flushTypeQueue(); + } else { + invalidate(true); } - return this; }; - function flushTypeQueue() { - while (typeQueue.length) { - var type = typeQueue.shift(); - if (type.pattern) throw new Error("You cannot override a type's .pattern at runtime."); - angular.extend($types[type.name], injector.invoke(type.def)); + hoursInputEl.bind("blur", function(e) { + if (!$scope.invalidHours && $scope.hours < 10) { + $scope.$apply(function() { + $scope.hours = pad($scope.hours); + }); } - } - forEach(defaultTypes, function(type, name) { - $types[name] = new Type(extend({ - name: name - }, type)); }); - $types = inherit($types, {}); - this.$get = [ "$injector", function($injector) { - injector = $injector; - enqueue = false; - flushTypeQueue(); - forEach(defaultTypes, function(type, name) { - if (!$types[name]) $types[name] = new Type(type); - }); - return this; - } ]; - this.Param = function Param(id, type, config, location) { - var self = this; - config = unwrapShorthand(config); - type = getType(config, type, location); - var arrayMode = getArrayMode(); - type = arrayMode ? type.$asArray(arrayMode, location === "search") : type; - if (type.name === "string" && !arrayMode && location === "path" && config.value === undefined) config.value = ""; - var isOptional = config.value !== undefined; - var squash = getSquashPolicy(config, isOptional); - var replace = getReplace(config, arrayMode, isOptional, squash); - function unwrapShorthand(config) { - var keys = isObject(config) ? objectKeys(config) : []; - var isShorthand = indexOf(keys, "value") === -1 && indexOf(keys, "type") === -1 && indexOf(keys, "squash") === -1 && indexOf(keys, "array") === -1; - if (isShorthand) config = { - value: config - }; - config.$$fn = isInjectable(config.value) ? config.value : function() { - return config.value; - }; - return config; - } - function getType(config, urlType, location) { - if (config.type && urlType) throw new Error("Param '" + id + "' has two type configurations."); - if (urlType) return urlType; - if (!config.type) return location === "config" ? $types.any : $types.string; - return config.type instanceof Type ? config.type : new Type(config.type); + $scope.updateMinutes = function() { + var minutes = getMinutesFromTemplate(), hours = getHoursFromTemplate(); + if (angular.isDefined(minutes) && angular.isDefined(hours)) { + selected.setMinutes(minutes); + if (selected < min || selected > max) { + invalidate(undefined, true); + } else { + refresh("m"); + } + } else { + invalidate(undefined, true); } - function getArrayMode() { - var arrayDefaults = { - array: location === "search" ? "auto" : false - }; - var arrayParamNomenclature = id.match(/\[\]$/) ? { - array: true - } : {}; - return extend(arrayDefaults, arrayParamNomenclature, config).array; - } - function getSquashPolicy(config, isOptional) { - var squash = config.squash; - if (!isOptional || squash === false) return false; - if (!isDefined(squash) || squash == null) return defaultSquashPolicy; - if (squash === true || isString(squash)) return squash; - throw new Error("Invalid squash policy: '" + squash + "'. Valid policies: false, true, or arbitrary string"); - } - function getReplace(config, arrayMode, isOptional, squash) { - var replace, configuredKeys, defaultPolicy = [ { - from: "", - to: isOptional || arrayMode ? undefined : "" - }, { - from: null, - to: isOptional || arrayMode ? undefined : "" - } ]; - replace = isArray(config.replace) ? config.replace : []; - if (isString(squash)) replace.push({ - from: squash, - to: undefined - }); - configuredKeys = map(replace, function(item) { - return item.from; + }; + minutesInputEl.bind("blur", function(e) { + if (!$scope.invalidMinutes && $scope.minutes < 10) { + $scope.$apply(function() { + $scope.minutes = pad($scope.minutes); }); - return filter(defaultPolicy, function(item) { - return indexOf(configuredKeys, item.from) === -1; - }).concat(replace); - } - function $$getDefaultValue() { - if (!injector) throw new Error("Injectable functions cannot be called at configuration time"); - var defaultValue = injector.invoke(config.$$fn); - if (defaultValue !== null && defaultValue !== undefined && !self.type.is(defaultValue)) throw new Error("Default value (" + defaultValue + ") for parameter '" + self.id + "' is not an instance of Type (" + self.type.name + ")"); - return defaultValue; - } - function $value(value) { - function hasReplaceVal(val) { - return function(obj) { - return obj.from === val; - }; - } - function $replace(value) { - var replacement = map(filter(self.replace, hasReplaceVal(value)), function(obj) { - return obj.to; - }); - return replacement.length ? replacement[0] : value; - } - value = $replace(value); - return !isDefined(value) ? $$getDefaultValue() : self.type.$normalize(value); } - function toString() { - return "{Param:" + id + " " + type + " squash: '" + squash + "' optional: " + isOptional + "}"; + }); + }; + this.render = function() { + var date = ngModelCtrl.$viewValue; + if (isNaN(date)) { + ngModelCtrl.$setValidity("time", false); + $log.error('Timepicker directive: "ng-model" value must be a Date object, a number of milliseconds since 01.01.1970 or a string representing an RFC2822 or ISO 8601 date.'); + } else { + if (date) { + selected = date; } - extend(this, { - id: id, - type: type, - location: location, - array: arrayMode, - squash: squash, - replace: replace, - isOptional: isOptional, - value: $value, - dynamic: undefined, - config: config, - toString: toString - }); - }; - function ParamSet(params) { - extend(this, params || {}); - } - ParamSet.prototype = { - $$new: function() { - return inherit(this, extend(new ParamSet(), { - $$parent: this - })); - }, - $$keys: function() { - var keys = [], chain = [], parent = this, ignore = objectKeys(ParamSet.prototype); - while (parent) { - chain.push(parent); - parent = parent.$$parent; - } - chain.reverse(); - forEach(chain, function(paramset) { - forEach(objectKeys(paramset), function(key) { - if (indexOf(keys, key) === -1 && indexOf(ignore, key) === -1) keys.push(key); - }); - }); - return keys; - }, - $$values: function(paramValues) { - var values = {}, self = this; - forEach(self.$$keys(), function(key) { - values[key] = self[key].value(paramValues && paramValues[key]); - }); - return values; - }, - $$equals: function(paramValues1, paramValues2) { - var equal = true, self = this; - forEach(self.$$keys(), function(key) { - var left = paramValues1 && paramValues1[key], right = paramValues2 && paramValues2[key]; - if (!self[key].type.equals(left, right)) equal = false; - }); - return equal; - }, - $$validates: function $$validate(paramValues) { - var keys = this.$$keys(), i, param, rawVal, normalized, encoded; - for (i = 0; i < keys.length; i++) { - param = this[keys[i]]; - rawVal = paramValues[keys[i]]; - if ((rawVal === undefined || rawVal === null) && param.isOptional) break; - normalized = param.type.$normalize(rawVal); - if (!param.type.is(normalized)) return false; - encoded = param.type.encode(normalized); - if (angular.isString(encoded) && !param.type.pattern.exec(encoded)) return false; - } - return true; - }, - $$parent: undefined - }; - this.ParamSet = ParamSet; + if (selected < min || selected > max) { + ngModelCtrl.$setValidity("time", false); + $scope.invalidHours = true; + $scope.invalidMinutes = true; + } else { + makeValid(); + } + updateTemplate(); + } + }; + function refresh(keyboardChange) { + makeValid(); + ngModelCtrl.$setViewValue(new Date(selected)); + updateTemplate(keyboardChange); + } + function makeValid() { + ngModelCtrl.$setValidity("time", true); + $scope.invalidHours = false; + $scope.invalidMinutes = false; + } + function updateTemplate(keyboardChange) { + var hours = selected.getHours(), minutes = selected.getMinutes(); + if ($scope.showMeridian) { + hours = hours === 0 || hours === 12 ? 12 : hours % 12; + } + $scope.hours = keyboardChange === "h" ? hours : pad(hours); + if (keyboardChange !== "m") { + $scope.minutes = pad(minutes); + } + $scope.meridian = selected.getHours() < 12 ? meridians[0] : meridians[1]; + } + function addMinutes(date, minutes) { + var dt = new Date(date.getTime() + minutes * 6e4); + var newDate = new Date(date); + newDate.setHours(dt.getHours(), dt.getMinutes()); + return newDate; } - angular.module("ui.router.util").provider("$urlMatcherFactory", $UrlMatcherFactory); - angular.module("ui.router.util").run([ "$urlMatcherFactory", function($urlMatcherFactory) {} ]); - $UrlRouterProvider.$inject = [ "$locationProvider", "$urlMatcherFactoryProvider" ]; - function $UrlRouterProvider($locationProvider, $urlMatcherFactory) { - var rules = [], otherwise = null, interceptDeferred = false, listener; - function regExpPrefix(re) { - var prefix = /^\^((?:\\[^a-zA-Z0-9]|[^\\\[\]\^$*+?.()|{}]+)*)/.exec(re.source); - return prefix != null ? prefix[1].replace(/\\(.)/g, "$1") : ""; + function addMinutesToSelected(minutes) { + selected = addMinutes(selected, minutes); + refresh(); + } + $scope.showSpinners = angular.isDefined($attrs.showSpinners) ? $scope.$parent.$eval($attrs.showSpinners) : timepickerConfig.showSpinners; + $scope.incrementHours = function() { + if (!$scope.noIncrementHours()) { + addMinutesToSelected(hourStep * 60); } - function interpolate(pattern, match) { - return pattern.replace(/\$(\$|\d{1,2})/, function(m, what) { - return match[what === "$" ? 0 : Number(what)]; - }); + }; + $scope.decrementHours = function() { + if (!$scope.noDecrementHours()) { + addMinutesToSelected(-hourStep * 60); } - this.rule = function(rule) { - if (!isFunction(rule)) throw new Error("'rule' must be a function"); - rules.push(rule); - return this; - }; - this.otherwise = function(rule) { - if (isString(rule)) { - var redirect = rule; - rule = function() { - return redirect; - }; - } else if (!isFunction(rule)) throw new Error("'rule' must be a function"); - otherwise = rule; - return this; - }; - function handleIfMatch($injector, handler, match) { - if (!match) return false; - var result = $injector.invoke(handler, handler, { - $match: match - }); - return isDefined(result) ? result : true; - } - this.when = function(what, handler) { - var redirect, handlerIsString = isString(handler); - if (isString(what)) what = $urlMatcherFactory.compile(what); - if (!handlerIsString && !isFunction(handler) && !isArray(handler)) throw new Error("invalid 'handler' in when()"); - var strategies = { - matcher: function(what, handler) { - if (handlerIsString) { - redirect = $urlMatcherFactory.compile(handler); - handler = [ "$match", function($match) { - return redirect.format($match); - } ]; - } - return extend(function($injector, $location) { - return handleIfMatch($injector, handler, what.exec($location.path(), $location.search())); - }, { - prefix: isString(what.prefix) ? what.prefix : "" - }); - }, - regex: function(what, handler) { - if (what.global || what.sticky) throw new Error("when() RegExp must not be global or sticky"); - if (handlerIsString) { - redirect = handler; - handler = [ "$match", function($match) { - return interpolate(redirect, $match); - } ]; - } - return extend(function($injector, $location) { - return handleIfMatch($injector, handler, what.exec($location.path())); - }, { - prefix: regExpPrefix(what) - }); - } - }; - var check = { - matcher: $urlMatcherFactory.isMatcher(what), - regex: what instanceof RegExp - }; - for (var n in check) { - if (check[n]) return this.rule(strategies[n](what, handler)); - } - throw new Error("invalid 'what' in when()"); - }; - this.deferIntercept = function(defer) { - if (defer === undefined) defer = true; - interceptDeferred = defer; - }; - this.$get = $get; - $get.$inject = [ "$location", "$rootScope", "$injector", "$browser" ]; - function $get($location, $rootScope, $injector, $browser) { - var baseHref = $browser.baseHref(), location = $location.url(), lastPushedUrl; - function appendBasePath(url, isHtml5, absolute) { - if (baseHref === "/") return url; - if (isHtml5) return baseHref.slice(0, -1) + url; - if (absolute) return baseHref.slice(1) + url; - return url; - } - function update(evt) { - if (evt && evt.defaultPrevented) return; - var ignoreUpdate = lastPushedUrl && $location.url() === lastPushedUrl; - lastPushedUrl = undefined; - function check(rule) { - var handled = rule($injector, $location); - if (!handled) return false; - if (isString(handled)) $location.replace().url(handled); - return true; - } - var n = rules.length, i; - for (i = 0; i < n; i++) { - if (check(rules[i])) return; - } - if (otherwise) check(otherwise); - } - function listen() { - listener = listener || $rootScope.$on("$locationChangeSuccess", update); - return listener; - } - if (!interceptDeferred) listen(); - return { - sync: function() { - update(); - }, - listen: function() { - return listen(); - }, - update: function(read) { - if (read) { - location = $location.url(); - return; - } - if ($location.url() === location) return; - $location.url(location); - $location.replace(); - }, - push: function(urlMatcher, params, options) { - var url = urlMatcher.format(params || {}); - if (url !== null && params && params["#"]) { - url += "#" + params["#"]; - } - $location.url(url); - lastPushedUrl = options && options.$$avoidResync ? $location.url() : undefined; - if (options && options.replace) $location.replace(); - }, - href: function(urlMatcher, params, options) { - if (!urlMatcher.validates(params)) return null; - var isHtml5 = $locationProvider.html5Mode(); - if (angular.isObject(isHtml5)) { - isHtml5 = isHtml5.enabled; - } - var url = urlMatcher.format(params); - options = options || {}; - if (!isHtml5 && url !== null) { - url = "#" + $locationProvider.hashPrefix() + url; - } - if (url !== null && params && params["#"]) { - url += "#" + params["#"]; - } - url = appendBasePath(url, isHtml5, options.absolute); - if (!options.absolute || !url) { - return url; - } - var slash = !isHtml5 && url ? "/" : "", port = $location.port(); - port = port === 80 || port === 443 ? "" : ":" + port; - return [ $location.protocol(), "://", $location.host(), port, slash, url ].join(""); - } - }; + }; + $scope.incrementMinutes = function() { + if (!$scope.noIncrementMinutes()) { + addMinutesToSelected(minuteStep); } - } - angular.module("ui.router.router").provider("$urlRouter", $UrlRouterProvider); - $StateProvider.$inject = [ "$urlRouterProvider", "$urlMatcherFactoryProvider" ]; - function $StateProvider($urlRouterProvider, $urlMatcherFactory) { - var root, states = {}, $state, queue = {}, abstractKey = "abstract"; - var stateBuilder = { - parent: function(state) { - if (isDefined(state.parent) && state.parent) return findState(state.parent); - var compositeName = /^(.+)\.[^.]+$/.exec(state.name); - return compositeName ? findState(compositeName[1]) : root; - }, - data: function(state) { - if (state.parent && state.parent.data) { - state.data = state.self.data = extend({}, state.parent.data, state.data); - } - return state.data; - }, - url: function(state) { - var url = state.url, config = { - params: state.params || {} - }; - if (isString(url)) { - if (url.charAt(0) == "^") return $urlMatcherFactory.compile(url.substring(1), config); - return (state.parent.navigable || root).url.concat(url, config); - } - if (!url || $urlMatcherFactory.isMatcher(url)) return url; - throw new Error("Invalid url '" + url + "' in state '" + state + "'"); - }, - navigable: function(state) { - return state.url ? state : state.parent ? state.parent.navigable : null; - }, - ownParams: function(state) { - var params = state.url && state.url.params || new $$UMFP.ParamSet(); - forEach(state.params || {}, function(config, id) { - if (!params[id]) params[id] = new $$UMFP.Param(id, null, config, "config"); - }); - return params; - }, - params: function(state) { - return state.parent && state.parent.params ? extend(state.parent.params.$$new(), state.ownParams) : new $$UMFP.ParamSet(); - }, - views: function(state) { - var views = {}; - forEach(isDefined(state.views) ? state.views : { - "": state - }, function(view, name) { - if (name.indexOf("@") < 0) name += "@" + state.parent.name; - views[name] = view; - }); - return views; - }, - path: function(state) { - return state.parent ? state.parent.path.concat(state) : []; - }, - includes: function(state) { - var includes = state.parent ? extend({}, state.parent.includes) : {}; - includes[state.name] = true; - return includes; - }, - $delegates: {} - }; - function isRelative(stateName) { - return stateName.indexOf(".") === 0 || stateName.indexOf("^") === 0; - } - function findState(stateOrName, base) { - if (!stateOrName) return undefined; - var isStr = isString(stateOrName), name = isStr ? stateOrName : stateOrName.name, path = isRelative(name); - if (path) { - if (!base) throw new Error("No reference point given for path '" + name + "'"); - base = findState(base); - var rel = name.split("."), i = 0, pathLength = rel.length, current = base; - for (;i < pathLength; i++) { - if (rel[i] === "" && i === 0) { - current = base; - continue; - } - if (rel[i] === "^") { - if (!current.parent) throw new Error("Path '" + name + "' not valid for state '" + base.name + "'"); - current = current.parent; - continue; - } - break; - } - rel = rel.slice(i).join("."); - name = current.name + (current.name && rel ? "." : "") + rel; - } - var state = states[name]; - if (state && (isStr || !isStr && (state === stateOrName || state.self === stateOrName))) { - return state; - } - return undefined; + }; + $scope.decrementMinutes = function() { + if (!$scope.noDecrementMinutes()) { + addMinutesToSelected(-minuteStep); } - function queueState(parentName, state) { - if (!queue[parentName]) { - queue[parentName] = []; - } - queue[parentName].push(state); + }; + $scope.toggleMeridian = function() { + if (!$scope.noToggleMeridian()) { + addMinutesToSelected(12 * 60 * (selected.getHours() < 12 ? 1 : -1)); } - function flushQueuedChildren(parentName) { - var queued = queue[parentName] || []; - while (queued.length) { - registerState(queued.shift()); + }; +} ]).directive("timepicker", function() { + return { + restrict: "EA", + require: [ "timepicker", "?^ngModel" ], + controller: "TimepickerController", + controllerAs: "timepicker", + replace: true, + scope: {}, + templateUrl: function(element, attrs) { + return attrs.templateUrl || "template/timepicker/timepicker.html"; + }, + link: function(scope, element, attrs, ctrls) { + var timepickerCtrl = ctrls[0], ngModelCtrl = ctrls[1]; + if (ngModelCtrl) { + timepickerCtrl.init(ngModelCtrl, element.find("input")); } } - function registerState(state) { - state = inherit(state, { - self: state, - resolve: state.resolve || {}, - toString: function() { - return this.name; - } + }; +}); + +angular.module("ui.bootstrap.transition", []).value("$transitionSuppressDeprecated", false).factory("$transition", [ "$q", "$timeout", "$rootScope", "$log", "$transitionSuppressDeprecated", function($q, $timeout, $rootScope, $log, $transitionSuppressDeprecated) { + if (!$transitionSuppressDeprecated) { + $log.warn("$transition is now deprecated. Use $animate from ngAnimate instead."); + } + var $transition = function(element, trigger, options) { + options = options || {}; + var deferred = $q.defer(); + var endEventName = $transition[options.animation ? "animationEndEventName" : "transitionEndEventName"]; + var transitionEndHandler = function(event) { + $rootScope.$apply(function() { + element.unbind(endEventName, transitionEndHandler); + deferred.resolve(element); }); - var name = state.name; - if (!isString(name) || name.indexOf("@") >= 0) throw new Error("State must have a valid name"); - if (states.hasOwnProperty(name)) throw new Error("State '" + name + "'' is already defined"); - var parentName = name.indexOf(".") !== -1 ? name.substring(0, name.lastIndexOf(".")) : isString(state.parent) ? state.parent : isObject(state.parent) && isString(state.parent.name) ? state.parent.name : ""; - if (parentName && !states[parentName]) { - return queueState(parentName, state.self); - } - for (var key in stateBuilder) { - if (isFunction(stateBuilder[key])) state[key] = stateBuilder[key](state, stateBuilder.$delegates[key]); - } - states[name] = state; - if (!state[abstractKey] && state.url) { - $urlRouterProvider.when(state.url, [ "$match", "$stateParams", function($match, $stateParams) { - if ($state.$current.navigable != state || !equalForKeys($match, $stateParams)) { - $state.transitionTo(state, $match, { - inherit: true, - location: false - }); - } - } ]); - } - flushQueuedChildren(name); - return state; - } - function isGlob(text) { - return text.indexOf("*") > -1; + }; + if (endEventName) { + element.bind(endEventName, transitionEndHandler); } - function doesStateMatchGlob(glob) { - var globSegments = glob.split("."), segments = $state.$current.name.split("."); - for (var i = 0, l = globSegments.length; i < l; i++) { - if (globSegments[i] === "*") { - segments[i] = "*"; - } + $timeout(function() { + if (angular.isString(trigger)) { + element.addClass(trigger); + } else if (angular.isFunction(trigger)) { + trigger(element); + } else if (angular.isObject(trigger)) { + element.css(trigger); } - if (globSegments[0] === "**") { - segments = segments.slice(indexOf(segments, globSegments[1])); - segments.unshift("**"); + if (!endEventName) { + deferred.resolve(element); } - if (globSegments[globSegments.length - 1] === "**") { - segments.splice(indexOf(segments, globSegments[globSegments.length - 2]) + 1, Number.MAX_VALUE); - segments.push("**"); + }); + deferred.promise.cancel = function() { + if (endEventName) { + element.unbind(endEventName, transitionEndHandler); } - if (globSegments.length != segments.length) { - return false; + deferred.reject("Transition cancelled"); + }; + return deferred.promise; + }; + var transElement = document.createElement("trans"); + var transitionEndEventNames = { + WebkitTransition: "webkitTransitionEnd", + MozTransition: "transitionend", + OTransition: "oTransitionEnd", + transition: "transitionend" + }; + var animationEndEventNames = { + WebkitTransition: "webkitAnimationEnd", + MozTransition: "animationend", + OTransition: "oAnimationEnd", + transition: "animationend" + }; + function findEndEventName(endEventNames) { + for (var name in endEventNames) { + if (transElement.style[name] !== undefined) { + return endEventNames[name]; } - return segments.join("") === globSegments.join(""); } - root = registerState({ - name: "", - url: "^", - views: null, - "abstract": true - }); - root.navigable = null; - this.decorator = decorator; - function decorator(name, func) { - if (isString(name) && !isDefined(func)) { - return stateBuilder[name]; + } + $transition.transitionEndEventName = findEndEventName(transitionEndEventNames); + $transition.animationEndEventName = findEndEventName(animationEndEventNames); + return $transition; +} ]); + +angular.module("ui.bootstrap.typeahead", [ "ui.bootstrap.position" ]).factory("typeaheadParser", [ "$parse", function($parse) { + var TYPEAHEAD_REGEXP = /^\s*([\s\S]+?)(?:\s+as\s+([\s\S]+?))?\s+for\s+(?:([\$\w][\$\w\d]*))\s+in\s+([\s\S]+?)$/; + return { + parse: function(input) { + var match = input.match(TYPEAHEAD_REGEXP); + if (!match) { + throw new Error('Expected typeahead specification in form of "_modelValue_ (as _label_)? for _item_ in _collection_"' + ' but got "' + input + '".'); } - if (!isFunction(func) || !isString(name)) { - return this; + return { + itemName: match[3], + source: $parse(match[4]), + viewMapper: $parse(match[2] || match[1]), + modelMapper: $parse(match[1]) + }; + } + }; +} ]).directive("typeahead", [ "$compile", "$parse", "$q", "$timeout", "$document", "$window", "$rootScope", "$position", "typeaheadParser", function($compile, $parse, $q, $timeout, $document, $window, $rootScope, $position, typeaheadParser) { + var HOT_KEYS = [ 9, 13, 27, 38, 40 ]; + var eventDebounceTime = 200; + return { + require: [ "ngModel", "^?ngModelOptions" ], + link: function(originalScope, element, attrs, ctrls) { + var modelCtrl = ctrls[0]; + var ngModelOptions = ctrls[1]; + var minLength = originalScope.$eval(attrs.typeaheadMinLength); + if (!minLength && minLength !== 0) { + minLength = 1; + } + var waitTime = originalScope.$eval(attrs.typeaheadWaitMs) || 0; + var isEditable = originalScope.$eval(attrs.typeaheadEditable) !== false; + var isLoadingSetter = $parse(attrs.typeaheadLoading).assign || angular.noop; + var onSelectCallback = $parse(attrs.typeaheadOnSelect); + var isSelectOnBlur = angular.isDefined(attrs.typeaheadSelectOnBlur) ? originalScope.$eval(attrs.typeaheadSelectOnBlur) : false; + var isNoResultsSetter = $parse(attrs.typeaheadNoResults).assign || angular.noop; + var inputFormatter = attrs.typeaheadInputFormatter ? $parse(attrs.typeaheadInputFormatter) : undefined; + var appendToBody = attrs.typeaheadAppendToBody ? originalScope.$eval(attrs.typeaheadAppendToBody) : false; + var focusFirst = originalScope.$eval(attrs.typeaheadFocusFirst) !== false; + var selectOnExact = attrs.typeaheadSelectOnExact ? originalScope.$eval(attrs.typeaheadSelectOnExact) : false; + var parsedModel = $parse(attrs.ngModel); + var invokeModelSetter = $parse(attrs.ngModel + "($$$p)"); + var $setModelValue = function(scope, newValue) { + if (angular.isFunction(parsedModel(originalScope)) && ngModelOptions && ngModelOptions.$options && ngModelOptions.$options.getterSetter) { + return invokeModelSetter(scope, { + $$$p: newValue + }); + } else { + return parsedModel.assign(scope, newValue); + } + }; + var parserResult = typeaheadParser.parse(attrs.typeahead); + var hasFocus; + var selected; + var scope = originalScope.$new(); + var offDestroy = originalScope.$on("$destroy", function() { + scope.$destroy(); + }); + scope.$on("$destroy", offDestroy); + var popupId = "typeahead-" + scope.$id + "-" + Math.floor(Math.random() * 1e4); + element.attr({ + "aria-autocomplete": "list", + "aria-expanded": false, + "aria-owns": popupId + }); + var popUpEl = angular.element("
            "); + popUpEl.attr({ + id: popupId, + matches: "matches", + active: "activeIdx", + select: "select(activeIdx)", + "move-in-progress": "moveInProgress", + query: "query", + position: "position" + }); + if (angular.isDefined(attrs.typeaheadTemplateUrl)) { + popUpEl.attr("template-url", attrs.typeaheadTemplateUrl); } - if (stateBuilder[name] && !stateBuilder.$delegates[name]) { - stateBuilder.$delegates[name] = stateBuilder[name]; + if (angular.isDefined(attrs.typeaheadPopupTemplateUrl)) { + popUpEl.attr("popup-template-url", attrs.typeaheadPopupTemplateUrl); } - stateBuilder[name] = func; - return this; - } - this.state = state; - function state(name, definition) { - if (isObject(name)) definition = name; else definition.name = name; - registerState(definition); - return this; - } - this.$get = $get; - $get.$inject = [ "$rootScope", "$q", "$view", "$injector", "$resolve", "$stateParams", "$urlRouter", "$location", "$urlMatcherFactory" ]; - function $get($rootScope, $q, $view, $injector, $resolve, $stateParams, $urlRouter, $location, $urlMatcherFactory) { - var TransitionSuperseded = $q.reject(new Error("transition superseded")); - var TransitionPrevented = $q.reject(new Error("transition prevented")); - var TransitionAborted = $q.reject(new Error("transition aborted")); - var TransitionFailed = $q.reject(new Error("transition failed")); - function handleRedirect(redirect, state, params, options) { - var evt = $rootScope.$broadcast("$stateNotFound", redirect, state, params); - if (evt.defaultPrevented) { - $urlRouter.update(); - return TransitionAborted; - } - if (!evt.retry) { - return null; - } - if (options.$retry) { - $urlRouter.update(); - return TransitionFailed; - } - var retryTransition = $state.transition = $q.when(evt.retry); - retryTransition.then(function() { - if (retryTransition !== $state.transition) return TransitionSuperseded; - redirect.options.$retry = true; - return $state.transitionTo(redirect.to, redirect.toParams, redirect.options); - }, function() { - return TransitionAborted; - }); - $urlRouter.update(); - return retryTransition; - } - root.locals = { - resolve: null, - globals: { - $stateParams: {} - } - }; - $state = { - params: {}, - current: root.self, - $current: root, - transition: null - }; - $state.reload = function reload(state) { - return $state.transitionTo($state.current, $stateParams, { - reload: state || true, - inherit: false, - notify: true - }); + var resetMatches = function() { + scope.matches = []; + scope.activeIdx = -1; + element.attr("aria-expanded", false); }; - $state.go = function go(to, params, options) { - return $state.transitionTo(to, params, extend({ - inherit: true, - relative: $state.$current - }, options)); - }; - $state.transitionTo = function transitionTo(to, toParams, options) { - toParams = toParams || {}; - options = extend({ - location: true, - inherit: false, - relative: null, - notify: true, - reload: false, - $retry: false - }, options || {}); - var from = $state.$current, fromParams = $state.params, fromPath = from.path; - var evt, toState = findState(to, options.relative); - var hash = toParams["#"]; - if (!isDefined(toState)) { - var redirect = { - to: to, - toParams: toParams, - options: options - }; - var redirectResult = handleRedirect(redirect, from.self, fromParams, options); - if (redirectResult) { - return redirectResult; - } - to = redirect.to; - toParams = redirect.toParams; - options = redirect.options; - toState = findState(to, options.relative); - if (!isDefined(toState)) { - if (!options.relative) throw new Error("No such state '" + to + "'"); - throw new Error("Could not resolve '" + to + "' from state '" + options.relative + "'"); - } - } - if (toState[abstractKey]) throw new Error("Cannot transition to abstract state '" + to + "'"); - if (options.inherit) toParams = inheritParams($stateParams, toParams || {}, $state.$current, toState); - if (!toState.params.$$validates(toParams)) return TransitionFailed; - toParams = toState.params.$$values(toParams); - to = toState; - var toPath = to.path; - var keep = 0, state = toPath[keep], locals = root.locals, toLocals = []; - if (!options.reload) { - while (state && state === fromPath[keep] && state.ownParams.$$equals(toParams, fromParams)) { - locals = toLocals[keep] = state.locals; - keep++; - state = toPath[keep]; - } - } else if (isString(options.reload) || isObject(options.reload)) { - if (isObject(options.reload) && !options.reload.name) { - throw new Error("Invalid reload state object"); - } - var reloadState = options.reload === true ? fromPath[0] : findState(options.reload); - if (options.reload && !reloadState) { - throw new Error("No such reload state '" + (isString(options.reload) ? options.reload : options.reload.name) + "'"); - } - while (state && state === fromPath[keep] && state !== reloadState) { - locals = toLocals[keep] = state.locals; - keep++; - state = toPath[keep]; - } - } - if (shouldSkipReload(to, toParams, from, fromParams, locals, options)) { - if (hash) toParams["#"] = hash; - $state.params = toParams; - copy($state.params, $stateParams); - if (options.location && to.navigable && to.navigable.url) { - $urlRouter.push(to.navigable.url, toParams, { - $$avoidResync: true, - replace: options.location === "replace" - }); - $urlRouter.update(true); - } - $state.transition = null; - return $q.when($state.current); - } - toParams = filterByKeys(to.params.$$keys(), toParams || {}); - if (options.notify) { - if ($rootScope.$broadcast("$stateChangeStart", to.self, toParams, from.self, fromParams).defaultPrevented) { - $rootScope.$broadcast("$stateChangeCancel", to.self, toParams, from.self, fromParams); - $urlRouter.update(); - return TransitionPrevented; - } - } - var resolved = $q.when(locals); - for (var l = keep; l < toPath.length; l++, state = toPath[l]) { - locals = toLocals[l] = inherit(locals); - resolved = resolveState(state, toParams, state === to, resolved, locals, options); - } - var transition = $state.transition = resolved.then(function() { - var l, entering, exiting; - if ($state.transition !== transition) return TransitionSuperseded; - for (l = fromPath.length - 1; l >= keep; l--) { - exiting = fromPath[l]; - if (exiting.self.onExit) { - $injector.invoke(exiting.self.onExit, exiting.self, exiting.locals.globals); - } - exiting.locals = null; - } - for (l = keep; l < toPath.length; l++) { - entering = toPath[l]; - entering.locals = toLocals[l]; - if (entering.self.onEnter) { - $injector.invoke(entering.self.onEnter, entering.self, entering.locals.globals); - } - } - if (hash) toParams["#"] = hash; - if ($state.transition !== transition) return TransitionSuperseded; - $state.$current = to; - $state.current = to.self; - $state.params = toParams; - copy($state.params, $stateParams); - $state.transition = null; - if (options.location && to.navigable) { - $urlRouter.push(to.navigable.url, to.navigable.locals.globals.$stateParams, { - $$avoidResync: true, - replace: options.location === "replace" - }); - } - if (options.notify) { - $rootScope.$broadcast("$stateChangeSuccess", to.self, toParams, from.self, fromParams); - } - $urlRouter.update(true); - return $state.current; - }, function(error) { - if ($state.transition !== transition) return TransitionSuperseded; - $state.transition = null; - evt = $rootScope.$broadcast("$stateChangeError", to.self, toParams, from.self, fromParams, error); - if (!evt.defaultPrevented) { - $urlRouter.update(); - } - return $q.reject(error); - }); - return transition; - }; - $state.is = function is(stateOrName, params, options) { - options = extend({ - relative: $state.$current - }, options || {}); - var state = findState(stateOrName, options.relative); - if (!isDefined(state)) { - return undefined; - } - if ($state.$current !== state) { - return false; - } - return params ? equalForKeys(state.params.$$values(params), $stateParams) : true; + var getMatchId = function(index) { + return popupId + "-option-" + index; }; - $state.includes = function includes(stateOrName, params, options) { - options = extend({ - relative: $state.$current - }, options || {}); - if (isString(stateOrName) && isGlob(stateOrName)) { - if (!doesStateMatchGlob(stateOrName)) { - return false; - } - stateOrName = $state.$current.name; - } - var state = findState(stateOrName, options.relative); - if (!isDefined(state)) { - return undefined; - } - if (!isDefined($state.$current.includes[state.name])) { - return false; + scope.$watch("activeIdx", function(index) { + if (index < 0) { + element.removeAttr("aria-activedescendant"); + } else { + element.attr("aria-activedescendant", getMatchId(index)); } - return params ? equalForKeys(state.params.$$values(params), $stateParams, objectKeys(params)) : true; - }; - $state.href = function href(stateOrName, params, options) { - options = extend({ - lossy: true, - inherit: true, - absolute: false, - relative: $state.$current - }, options || {}); - var state = findState(stateOrName, options.relative); - if (!isDefined(state)) return null; - if (options.inherit) params = inheritParams($stateParams, params || {}, $state.$current, state); - var nav = state && options.lossy ? state.navigable : state; - if (!nav || nav.url === undefined || nav.url === null) { - return null; + }); + var inputIsExactMatch = function(inputValue, index) { + if (scope.matches.length > index && inputValue) { + return inputValue.toUpperCase() === scope.matches[index].label.toUpperCase(); } - return $urlRouter.href(nav.url, filterByKeys(state.params.$$keys().concat("#"), params || {}), { - absolute: options.absolute - }); - }; - $state.get = function(stateOrName, context) { - if (arguments.length === 0) return map(objectKeys(states), function(name) { - return states[name].self; - }); - var state = findState(stateOrName, context || $state.$current); - return state && state.self ? state.self : null; + return false; }; - function resolveState(state, params, paramsAreFiltered, inherited, dst, options) { - var $stateParams = paramsAreFiltered ? params : filterByKeys(state.params.$$keys(), params); + var getMatchesAsync = function(inputValue) { var locals = { - $stateParams: $stateParams + $viewValue: inputValue }; - dst.resolve = $resolve.resolve(state.resolve, locals, dst.resolve, state); - var promises = [ dst.resolve.then(function(globals) { - dst.globals = globals; - }) ]; - if (inherited) promises.push(inherited); - function resolveViews() { - var viewsPromises = []; - forEach(state.views, function(view, name) { - var injectables = view.resolve && view.resolve !== state.resolve ? view.resolve : {}; - injectables.$template = [ function() { - return $view.load(name, { - view: view, - locals: dst.globals, - params: $stateParams, - notify: options.notify - }) || ""; - } ]; - viewsPromises.push($resolve.resolve(injectables, dst.globals, dst.resolve, state).then(function(result) { - if (isFunction(view.controllerProvider) || isArray(view.controllerProvider)) { - var injectLocals = angular.extend({}, injectables, dst.globals); - result.$$controller = $injector.invoke(view.controllerProvider, null, injectLocals); - } else { - result.$$controller = view.controller; + isLoadingSetter(originalScope, true); + isNoResultsSetter(originalScope, false); + $q.when(parserResult.source(originalScope, locals)).then(function(matches) { + var onCurrentRequest = inputValue === modelCtrl.$viewValue; + if (onCurrentRequest && hasFocus) { + if (matches && matches.length > 0) { + scope.activeIdx = focusFirst ? 0 : -1; + isNoResultsSetter(originalScope, false); + scope.matches.length = 0; + for (var i = 0; i < matches.length; i++) { + locals[parserResult.itemName] = matches[i]; + scope.matches.push({ + id: getMatchId(i), + label: parserResult.viewMapper(scope, locals), + model: matches[i] + }); } - result.$$state = state; - result.$$controllerAs = view.controllerAs; - dst[name] = result; - })); - }); - return $q.all(viewsPromises).then(function() { - return dst.globals; - }); - } - return $q.all(promises).then(resolveViews).then(function(values) { - return dst; - }); - } - return $state; - } - function shouldSkipReload(to, toParams, from, fromParams, locals, options) { - function nonSearchParamsEqual(fromAndToState, fromParams, toParams) { - function notSearchParam(key) { - return fromAndToState.params[key].location != "search"; - } - var nonQueryParamKeys = fromAndToState.params.$$keys().filter(notSearchParam); - var nonQueryParams = pick.apply({}, [ fromAndToState.params ].concat(nonQueryParamKeys)); - var nonQueryParamSet = new $$UMFP.ParamSet(nonQueryParams); - return nonQueryParamSet.$$equals(fromParams, toParams); - } - if (!options.reload && to === from && (locals === from.locals || to.self.reloadOnSearch === false && nonSearchParamsEqual(from, fromParams, toParams))) { - return true; - } - } - } - angular.module("ui.router.state").value("$stateParams", {}).provider("$state", $StateProvider); - $ViewProvider.$inject = []; - function $ViewProvider() { - this.$get = $get; - $get.$inject = [ "$rootScope", "$templateFactory" ]; - function $get($rootScope, $templateFactory) { - return { - load: function load(name, options) { - var result, defaults = { - template: null, - controller: null, - view: null, - locals: null, - notify: true, - async: true, - params: {} - }; - options = extend(defaults, options); - if (options.view) { - result = $templateFactory.fromConfig(options.view, options.params, options.locals); + scope.query = inputValue; + recalculatePosition(); + element.attr("aria-expanded", true); + if (selectOnExact && scope.matches.length === 1 && inputIsExactMatch(inputValue, 0)) { + scope.select(0); + } + } else { + resetMatches(); + isNoResultsSetter(originalScope, true); + } } - if (result && options.notify) { - $rootScope.$broadcast("$viewContentLoading", options); + if (onCurrentRequest) { + isLoadingSetter(originalScope, false); } - return result; - } + }, function() { + resetMatches(); + isLoadingSetter(originalScope, false); + isNoResultsSetter(originalScope, true); + }); }; - } - } - angular.module("ui.router.state").provider("$view", $ViewProvider); - function $ViewScrollProvider() { - var useAnchorScroll = false; - this.useAnchorScroll = function() { - useAnchorScroll = true; - }; - this.$get = [ "$anchorScroll", "$timeout", function($anchorScroll, $timeout) { - if (useAnchorScroll) { - return $anchorScroll; + if (appendToBody) { + angular.element($window).bind("resize", fireRecalculating); + $document.find("body").bind("scroll", fireRecalculating); } - return function($element) { - return $timeout(function() { - $element[0].scrollIntoView(); - }, 0, false); - }; - } ]; - } - angular.module("ui.router.state").provider("$uiViewScroll", $ViewScrollProvider); - $ViewDirective.$inject = [ "$state", "$injector", "$uiViewScroll", "$interpolate" ]; - function $ViewDirective($state, $injector, $uiViewScroll, $interpolate) { - function getService() { - return $injector.has ? function(service) { - return $injector.has(service) ? $injector.get(service) : null; - } : function(service) { - try { - return $injector.get(service); - } catch (e) { - return null; + var timeoutEventPromise; + scope.moveInProgress = false; + function fireRecalculating() { + if (!scope.moveInProgress) { + scope.moveInProgress = true; + scope.$digest(); } - }; - } - var service = getService(), $animator = service("$animator"), $animate = service("$animate"); - function getRenderer(attrs, scope) { - var statics = function() { - return { - enter: function(element, target, cb) { - target.after(element); - cb(); - }, - leave: function(element, cb) { - element.remove(); - cb(); - } - }; - }; - if ($animate) { - return { - enter: function(element, target, cb) { - var promise = $animate.enter(element, null, target, cb); - if (promise && promise.then) promise.then(cb); - }, - leave: function(element, cb) { - var promise = $animate.leave(element, cb); - if (promise && promise.then) promise.then(cb); - } - }; - } - if ($animator) { - var animate = $animator && $animator(scope, attrs); - return { - enter: function(element, target, cb) { - animate.enter(element, null, target); - cb(); - }, - leave: function(element, cb) { - animate.leave(element); - cb(); - } - }; - } - return statics(); - } - var directive = { - restrict: "ECA", - terminal: true, - priority: 400, - transclude: "element", - compile: function(tElement, tAttrs, $transclude) { - return function(scope, $element, attrs) { - var previousEl, currentEl, currentScope, latestLocals, onloadExp = attrs.onload || "", autoScrollExp = attrs.autoscroll, renderer = getRenderer(attrs, scope); - scope.$on("$stateChangeSuccess", function() { - updateView(false); - }); - scope.$on("$viewContentLoading", function() { - updateView(false); - }); - updateView(true); - function cleanupLastView() { - if (previousEl) { - previousEl.remove(); - previousEl = null; - } - if (currentScope) { - currentScope.$destroy(); - currentScope = null; - } - if (currentEl) { - renderer.leave(currentEl, function() { - previousEl = null; - }); - previousEl = currentEl; - currentEl = null; - } - } - function updateView(firstTime) { - var newScope, name = getUiViewName(scope, attrs, $element, $interpolate), previousLocals = name && $state.$current && $state.$current.locals[name]; - if (!firstTime && previousLocals === latestLocals) return; - newScope = scope.$new(); - latestLocals = $state.$current.locals[name]; - var clone = $transclude(newScope, function(clone) { - renderer.enter(clone, $element, function onUiViewEnter() { - if (currentScope) { - currentScope.$emit("$viewContentAnimationEnded"); - } - if (angular.isDefined(autoScrollExp) && !autoScrollExp || scope.$eval(autoScrollExp)) { - $uiViewScroll(clone); - } - }); - cleanupLastView(); - }); - currentEl = clone; - currentScope = newScope; - currentScope.$emit("$viewContentLoaded"); - currentScope.$eval(onloadExp); + if (timeoutEventPromise) { + $timeout.cancel(timeoutEventPromise); + } + timeoutEventPromise = $timeout(function() { + if (scope.matches.length) { + recalculatePosition(); } - }; + scope.moveInProgress = false; + scope.$digest(); + }, eventDebounceTime); } - }; - return directive; - } - $ViewDirectiveFill.$inject = [ "$compile", "$controller", "$state", "$interpolate" ]; - function $ViewDirectiveFill($compile, $controller, $state, $interpolate) { - return { - restrict: "ECA", - priority: -400, - compile: function(tElement) { - var initial = tElement.html(); - return function(scope, $element, attrs) { - var current = $state.$current, name = getUiViewName(scope, attrs, $element, $interpolate), locals = current && current.locals[name]; - if (!locals) { - return; - } - $element.data("$uiView", { - name: name, - state: locals.$$state - }); - $element.html(locals.$template ? locals.$template : initial); - var link = $compile($element.contents()); - if (locals.$$controller) { - locals.$scope = scope; - locals.$element = $element; - var controller = $controller(locals.$$controller, locals); - if (locals.$$controllerAs) { - scope[locals.$$controllerAs] = controller; - } - $element.data("$ngControllerController", controller); - $element.children().data("$ngControllerController", controller); - } - link(scope); - }; + function recalculatePosition() { + scope.position = appendToBody ? $position.offset(element) : $position.position(element); + scope.position.top += element.prop("offsetHeight"); } - }; - } - function getUiViewName(scope, attrs, element, $interpolate) { - var name = $interpolate(attrs.uiView || attrs.name || "")(scope); - var inherited = element.inheritedData("$uiView"); - return name.indexOf("@") >= 0 ? name : name + "@" + (inherited ? inherited.state.name : ""); - } - angular.module("ui.router.state").directive("uiView", $ViewDirective); - angular.module("ui.router.state").directive("uiView", $ViewDirectiveFill); - function parseStateRef(ref, current) { - var preparsed = ref.match(/^\s*({[^}]*})\s*$/), parsed; - if (preparsed) ref = current + "(" + preparsed[1] + ")"; - parsed = ref.replace(/\n/g, " ").match(/^([^(]+?)\s*(\((.*)\))?$/); - if (!parsed || parsed.length !== 4) throw new Error("Invalid state ref '" + ref + "'"); - return { - state: parsed[1], - paramExpr: parsed[3] || null - }; - } - function stateContext(el) { - var stateData = el.parent().inheritedData("$uiView"); - if (stateData && stateData.state && stateData.state.name) { - return stateData.state; - } - } - $StateRefDirective.$inject = [ "$state", "$timeout" ]; - function $StateRefDirective($state, $timeout) { - var allowedOptions = [ "location", "inherit", "reload", "absolute" ]; - return { - restrict: "A", - require: [ "?^uiSrefActive", "?^uiSrefActiveEq" ], - link: function(scope, element, attrs, uiSrefActive) { - var ref = parseStateRef(attrs.uiSref, $state.current.name); - var params = null, url = null, base = stateContext(element) || $state.$current; - var hrefKind = Object.prototype.toString.call(element.prop("href")) === "[object SVGAnimatedString]" ? "xlink:href" : "href"; - var newHref = null, isAnchor = element.prop("tagName").toUpperCase() === "A"; - var isForm = element[0].nodeName === "FORM"; - var attr = isForm ? "action" : hrefKind, nav = true; - var options = { - relative: base, - inherit: true - }; - var optionsOverride = scope.$eval(attrs.uiSrefOpts) || {}; - angular.forEach(allowedOptions, function(option) { - if (option in optionsOverride) { - options[option] = optionsOverride[option]; - } - }); - var update = function(newVal) { - if (newVal) params = angular.copy(newVal); - if (!nav) return; - newHref = $state.href(ref.state, params, options); - var activeDirective = uiSrefActive[1] || uiSrefActive[0]; - if (activeDirective) { - activeDirective.$$addStateInfo(ref.state, params); - } - if (newHref === null) { - nav = false; - return false; + resetMatches(); + scope.query = undefined; + var timeoutPromise; + var scheduleSearchWithTimeout = function(inputValue) { + timeoutPromise = $timeout(function() { + getMatchesAsync(inputValue); + }, waitTime); + }; + var cancelPreviousTimeout = function() { + if (timeoutPromise) { + $timeout.cancel(timeoutPromise); + } + }; + modelCtrl.$parsers.unshift(function(inputValue) { + hasFocus = true; + if (minLength === 0 || inputValue && inputValue.length >= minLength) { + if (waitTime > 0) { + cancelPreviousTimeout(); + scheduleSearchWithTimeout(inputValue); + } else { + getMatchesAsync(inputValue); } - attrs.$set(attr, newHref); - }; - if (ref.paramExpr) { - scope.$watch(ref.paramExpr, function(newVal, oldVal) { - if (newVal !== params) update(newVal); - }, true); - params = angular.copy(scope.$eval(ref.paramExpr)); - } - update(); - if (isForm) return; - element.bind("click", function(e) { - var button = e.which || e.button; - if (!(button > 1 || e.ctrlKey || e.metaKey || e.shiftKey || element.attr("target"))) { - var transition = $timeout(function() { - $state.go(ref.state, params, options); - }); - e.preventDefault(); - var ignorePreventDefaultCount = isAnchor && !newHref ? 1 : 0; - e.preventDefault = function() { - if (ignorePreventDefaultCount-- <= 0) $timeout.cancel(transition); - }; + } else { + isLoadingSetter(originalScope, false); + cancelPreviousTimeout(); + resetMatches(); + } + if (isEditable) { + return inputValue; + } else { + if (!inputValue) { + modelCtrl.$setValidity("editable", true); + return null; + } else { + modelCtrl.$setValidity("editable", false); + return undefined; } + } + }); + modelCtrl.$formatters.push(function(modelValue) { + var candidateViewValue, emptyViewValue; + var locals = {}; + if (!isEditable) { + modelCtrl.$setValidity("editable", true); + } + if (inputFormatter) { + locals.$model = modelValue; + return inputFormatter(originalScope, locals); + } else { + locals[parserResult.itemName] = modelValue; + candidateViewValue = parserResult.viewMapper(originalScope, locals); + locals[parserResult.itemName] = undefined; + emptyViewValue = parserResult.viewMapper(originalScope, locals); + return candidateViewValue !== emptyViewValue ? candidateViewValue : modelValue; + } + }); + scope.select = function(activeIdx) { + var locals = {}; + var model, item; + selected = true; + locals[parserResult.itemName] = item = scope.matches[activeIdx].model; + model = parserResult.modelMapper(originalScope, locals); + $setModelValue(originalScope, model); + modelCtrl.$setValidity("editable", true); + modelCtrl.$setValidity("parse", true); + onSelectCallback(originalScope, { + $item: item, + $model: model, + $label: parserResult.viewMapper(originalScope, locals) }); - } - }; - } - $StateRefActiveDirective.$inject = [ "$state", "$stateParams", "$interpolate" ]; - function $StateRefActiveDirective($state, $stateParams, $interpolate) { - return { - restrict: "A", - controller: [ "$scope", "$element", "$attrs", function($scope, $element, $attrs) { - var states = [], activeClass; - activeClass = $interpolate($attrs.uiSrefActiveEq || $attrs.uiSrefActive || "", false)($scope); - this.$$addStateInfo = function(newState, newParams) { - var state = $state.get(newState, stateContext($element)); - states.push({ - state: state || { - name: newState - }, - params: newParams + resetMatches(); + if (scope.$eval(attrs.typeaheadFocusOnSelect) !== false) { + $timeout(function() { + element[0].focus(); + }, 0, false); + } + }; + element.bind("keydown", function(evt) { + if (scope.matches.length === 0 || HOT_KEYS.indexOf(evt.which) === -1) { + return; + } + if (scope.activeIdx === -1 && (evt.which === 9 || evt.which === 13)) { + resetMatches(); + scope.$digest(); + return; + } + evt.preventDefault(); + if (evt.which === 40) { + scope.activeIdx = (scope.activeIdx + 1) % scope.matches.length; + scope.$digest(); + } else if (evt.which === 38) { + scope.activeIdx = (scope.activeIdx > 0 ? scope.activeIdx : scope.matches.length) - 1; + scope.$digest(); + } else if (evt.which === 13 || evt.which === 9) { + scope.$apply(function() { + scope.select(scope.activeIdx); }); - update(); - }; - $scope.$on("$stateChangeSuccess", update); - function update() { - if (anyMatch()) { - $element.addClass(activeClass); - } else { - $element.removeClass(activeClass); - } + } else if (evt.which === 27) { + evt.stopPropagation(); + resetMatches(); + scope.$digest(); } - function anyMatch() { - for (var i = 0; i < states.length; i++) { - if (isMatch(states[i].state, states[i].params)) { - return true; - } - } - return false; + }); + element.bind("blur", function() { + if (isSelectOnBlur && scope.matches.length && scope.activeIdx !== -1 && !selected) { + selected = true; + scope.$apply(function() { + scope.select(scope.activeIdx); + }); } - function isMatch(state, params) { - if (typeof $attrs.uiSrefActiveEq !== "undefined") { - return $state.is(state.name, params); - } else { - return $state.includes(state.name, params); + hasFocus = false; + selected = false; + }); + var dismissClickHandler = function(evt) { + if (element[0] !== evt.target && evt.which !== 3 && scope.matches.length !== 0) { + resetMatches(); + if (!$rootScope.$$phase) { + scope.$digest(); } } - } ] - }; - } - angular.module("ui.router.state").directive("uiSref", $StateRefDirective).directive("uiSrefActive", $StateRefActiveDirective).directive("uiSrefActiveEq", $StateRefActiveDirective); - $IsStateFilter.$inject = [ "$state" ]; - function $IsStateFilter($state) { - var isFilter = function(state) { - return $state.is(state); - }; - isFilter.$stateful = true; - return isFilter; + }; + $document.bind("click", dismissClickHandler); + originalScope.$on("$destroy", function() { + $document.unbind("click", dismissClickHandler); + if (appendToBody) { + $popup.remove(); + } + popUpEl.remove(); + }); + var $popup = $compile(popUpEl)(scope); + if (appendToBody) { + $document.find("body").append($popup); + } else { + element.after($popup); + } + } + }; +} ]).directive("typeaheadPopup", function() { + return { + restrict: "EA", + scope: { + matches: "=", + query: "=", + active: "=", + position: "&", + moveInProgress: "=", + select: "&" + }, + replace: true, + templateUrl: function(element, attrs) { + return attrs.popupTemplateUrl || "template/typeahead/typeahead-popup.html"; + }, + link: function(scope, element, attrs) { + scope.templateUrl = attrs.templateUrl; + scope.isOpen = function() { + return scope.matches.length > 0; + }; + scope.isActive = function(matchIdx) { + return scope.active == matchIdx; + }; + scope.selectActive = function(matchIdx) { + scope.active = matchIdx; + }; + scope.selectMatch = function(activeIdx) { + scope.select({ + activeIdx: activeIdx + }); + }; + } + }; +}).directive("typeaheadMatch", [ "$templateRequest", "$compile", "$parse", function($templateRequest, $compile, $parse) { + return { + restrict: "EA", + scope: { + index: "=", + match: "=", + query: "=" + }, + link: function(scope, element, attrs) { + var tplUrl = $parse(attrs.templateUrl)(scope.$parent) || "template/typeahead/typeahead-match.html"; + $templateRequest(tplUrl).then(function(tplContent) { + $compile(tplContent.trim())(scope, function(clonedElement) { + element.replaceWith(clonedElement); + }); + }); + } + }; +} ]).filter("typeaheadHighlight", [ "$sce", "$injector", "$log", function($sce, $injector, $log) { + var isSanitizePresent; + isSanitizePresent = $injector.has("$sanitize"); + function escapeRegexp(queryToEscape) { + return queryToEscape.replace(/([.?*+^$[\]\\(){}|-])/g, "\\$1"); } - $IncludedByStateFilter.$inject = [ "$state" ]; - function $IncludedByStateFilter($state) { - var includesFilter = function(state) { - return $state.includes(state); - }; - includesFilter.$stateful = true; - return includesFilter; + function containsHtml(matchItem) { + return /<.*>/g.test(matchItem); } - angular.module("ui.router.state").filter("isState", $IsStateFilter).filter("includedByState", $IncludedByStateFilter); -})(window, window.angular); + return function(matchItem, query) { + if (!isSanitizePresent && containsHtml(matchItem)) { + $log.warn("Unsafe use of typeahead please use ngSanitize"); + } + matchItem = query ? ("" + matchItem).replace(new RegExp(escapeRegexp(query), "gi"), "$&") : matchItem; + if (!isSanitizePresent) { + matchItem = $sce.trustAsHtml(matchItem); + } + return matchItem; + }; +} ]); + +angular.module("template/accordion/accordion-group.html", []).run([ "$templateCache", function($templateCache) { + $templateCache.put("template/accordion/accordion-group.html", "
            \n" + '
            \n' + '

            \n' + ' {{heading}}\n' + "

            \n" + "
            \n" + '
            \n' + '
            \n' + "
            \n" + "
            \n" + ""); +} ]); + +angular.module("template/accordion/accordion.html", []).run([ "$templateCache", function($templateCache) { + $templateCache.put("template/accordion/accordion.html", '
            '); +} ]); + +angular.module("template/alert/alert.html", []).run([ "$templateCache", function($templateCache) { + $templateCache.put("template/alert/alert.html", "
            \n" + ' \n" + "
            \n" + "
            \n" + ""); +} ]); + +angular.module("template/carousel/carousel.html", []).run([ "$templateCache", function($templateCache) { + $templateCache.put("template/carousel/carousel.html", '\n" + ""); +} ]); + +angular.module("template/carousel/slide.html", []).run([ "$templateCache", function($templateCache) { + $templateCache.put("template/carousel/slide.html", '
            \n' + ""); +} ]); + +angular.module("template/datepicker/datepicker.html", []).run([ "$templateCache", function($templateCache) { + $templateCache.put("template/datepicker/datepicker.html", '
            \n' + ' \n' + ' \n' + ' \n' + "
            "); +} ]); + +angular.module("template/datepicker/day.html", []).run([ "$templateCache", function($templateCache) { + $templateCache.put("template/datepicker/day.html", '\n' + " \n" + " \n" + ' \n' + ' \n' + ' \n' + " \n" + " \n" + ' \n' + ' \n' + " \n" + " \n" + " \n" + ' \n' + ' \n' + ' \n" + " \n" + " \n" + "
            {{::label.abbr}}
            {{ weekNumbers[$index] }}\n' + ' \n' + "
            \n" + ""); +} ]); + +angular.module("template/datepicker/month.html", []).run([ "$templateCache", function($templateCache) { + $templateCache.put("template/datepicker/month.html", '\n' + " \n" + " \n" + ' \n' + ' \n' + ' \n' + " \n" + " \n" + " \n" + ' \n' + ' \n" + " \n" + " \n" + "
            \n' + ' \n' + "
            \n" + ""); +} ]); + +angular.module("template/datepicker/popup.html", []).run([ "$templateCache", function($templateCache) { + $templateCache.put("template/datepicker/popup.html", '\n" + ""); +} ]); + +angular.module("template/datepicker/year.html", []).run([ "$templateCache", function($templateCache) { + $templateCache.put("template/datepicker/year.html", '\n' + " \n" + " \n" + ' \n' + ' \n' + ' \n' + " \n" + " \n" + " \n" + ' \n' + ' \n" + " \n" + " \n" + "
            \n' + ' \n' + "
            \n" + ""); +} ]); + +angular.module("template/modal/backdrop.html", []).run([ "$templateCache", function($templateCache) { + $templateCache.put("template/modal/backdrop.html", '\n" + ""); +} ]); + +angular.module("template/modal/window.html", []).run([ "$templateCache", function($templateCache) { + $templateCache.put("template/modal/window.html", '\n" + ""); +} ]); + +angular.module("template/pagination/pager.html", []).run([ "$templateCache", function($templateCache) { + $templateCache.put("template/pagination/pager.html", '\n" + ""); +} ]); + +angular.module("template/pagination/pagination.html", []).run([ "$templateCache", function($templateCache) { + $templateCache.put("template/pagination/pagination.html", '\n" + ""); +} ]); + +angular.module("template/tooltip/tooltip-html-popup.html", []).run([ "$templateCache", function($templateCache) { + $templateCache.put("template/tooltip/tooltip-html-popup.html", '
            \n' + '
            \n' + '
            \n' + "
            \n" + ""); +} ]); + +angular.module("template/tooltip/tooltip-html-unsafe-popup.html", []).run([ "$templateCache", function($templateCache) { + $templateCache.put("template/tooltip/tooltip-html-unsafe-popup.html", '
            \n' + '
            \n' + '
            \n' + "
            \n" + ""); +} ]); + +angular.module("template/tooltip/tooltip-popup.html", []).run([ "$templateCache", function($templateCache) { + $templateCache.put("template/tooltip/tooltip-popup.html", '
            \n' + '
            \n' + '
            \n' + "
            \n" + ""); +} ]); + +angular.module("template/tooltip/tooltip-template-popup.html", []).run([ "$templateCache", function($templateCache) { + $templateCache.put("template/tooltip/tooltip-template-popup.html", '
            \n' + '
            \n' + '
            \n' + "
            \n" + ""); +} ]); + +angular.module("template/popover/popover-html.html", []).run([ "$templateCache", function($templateCache) { + $templateCache.put("template/popover/popover-html.html", '
            \n' + '
            \n' + "\n" + '
            \n' + '

            \n' + '
            \n' + "
            \n" + "
            \n" + ""); +} ]); + +angular.module("template/popover/popover-template.html", []).run([ "$templateCache", function($templateCache) { + $templateCache.put("template/popover/popover-template.html", '
            \n' + '
            \n' + "\n" + '
            \n' + '

            \n' + '
            \n' + "
            \n" + "
            \n" + ""); +} ]); + +angular.module("template/popover/popover.html", []).run([ "$templateCache", function($templateCache) { + $templateCache.put("template/popover/popover.html", '
            \n' + '
            \n' + "\n" + '
            \n' + '

            \n' + '
            \n' + "
            \n" + "
            \n" + ""); +} ]); + +angular.module("template/progressbar/bar.html", []).run([ "$templateCache", function($templateCache) { + $templateCache.put("template/progressbar/bar.html", '
            \n' + ""); +} ]); + +angular.module("template/progressbar/progress.html", []).run([ "$templateCache", function($templateCache) { + $templateCache.put("template/progressbar/progress.html", '
            '); +} ]); + +angular.module("template/progressbar/progressbar.html", []).run([ "$templateCache", function($templateCache) { + $templateCache.put("template/progressbar/progressbar.html", '
            \n' + '
            \n' + "
            \n" + ""); +} ]); + +angular.module("template/rating/rating.html", []).run([ "$templateCache", function($templateCache) { + $templateCache.put("template/rating/rating.html", '\n' + " ({{ $index < value ? '*' : ' ' }})\n" + ' \n' + "\n" + ""); +} ]); + +angular.module("template/tabs/tab.html", []).run([ "$templateCache", function($templateCache) { + $templateCache.put("template/tabs/tab.html", '
          • \n' + ' {{heading}}\n' + "
          • \n" + ""); +} ]); + +angular.module("template/tabs/tabset.html", []).run([ "$templateCache", function($templateCache) { + $templateCache.put("template/tabs/tabset.html", "
            \n" + "
              \n" + '
              \n' + '
              \n' + "
              \n" + "
              \n" + "
              \n" + ""); +} ]); + +angular.module("template/timepicker/timepicker.html", []).run([ "$templateCache", function($templateCache) { + $templateCache.put("template/timepicker/timepicker.html", "\n" + " \n" + ' \n' + ' \n' + " \n" + ' \n' + ' \n' + " \n" + " \n" + ' \n" + " \n" + ' \n" + ' \n' + " \n" + ' \n' + ' \n' + " \n" + ' \n' + ' \n' + " \n" + " \n" + "
               
              \n' + ' \n' + " :\n' + ' \n' + "
               
              \n" + ""); +} ]); + +angular.module("template/typeahead/typeahead-match.html", []).run([ "$templateCache", function($templateCache) { + $templateCache.put("template/typeahead/typeahead-match.html", '\n' + ""); +} ]); + +angular.module("template/typeahead/typeahead-popup.html", []).run([ "$templateCache", function($templateCache) { + $templateCache.put("template/typeahead/typeahead-popup.html", '\n" + ""); +} ]); + +!angular.$$csp() && angular.element(document).find("head").prepend(''); (function(window, angular, undefined) { "use strict"; @@ -29568,11 +30496,6 @@ if (typeof module !== "undefined" && typeof exports !== "undefined" && module.ex if (!b) return a; return a + " " + b; } - function $$BodyProvider() { - this.$get = [ "$document", function($document) { - return jqLite($document[0].body); - } ]; - } var $$rAFSchedulerFactory = [ "$$rAF", function($$rAF) { var queue, cancelFn; function scheduler(tasks) { @@ -29710,6 +30633,11 @@ if (typeof module !== "undefined" && typeof exports !== "undefined" && module.ex } }; } + function registerRestorableStyles(backup, node, properties) { + forEach(properties, function(prop) { + backup[prop] = isDefined(backup[prop]) ? backup[prop] : node.style.getPropertyValue(prop); + }); + } var $AnimateCssProvider = [ "$animateProvider", function($animateProvider) { var gcsLookup = createLocalCacheLookup(); var gcsStaggerLookup = createLocalCacheLookup(); @@ -29772,6 +30700,7 @@ if (typeof module !== "undefined" && typeof exports !== "undefined" && module.ex return timings; } return function init(element, options) { + var restoreStyles = {}; var node = getDomNode(element); if (!node || !node.parentNode || !$animate.enabled()) { return closeAndReturnNoopAnimator(); @@ -29907,7 +30836,12 @@ if (typeof module !== "undefined" && typeof exports !== "undefined" && module.ex flags.blockTransition = timings.transitionDuration > 0; flags.blockKeyframeAnimation = timings.animationDuration > 0 && stagger.animationDelay > 0 && stagger.animationDuration === 0; } - applyAnimationFromStyles(element, options); + if (options.from) { + if (options.cleanupStyles) { + registerRestorableStyles(restoreStyles, node, Object.keys(options.from)); + } + applyAnimationFromStyles(element, options); + } if (flags.blockTransition || flags.blockKeyframeAnimation) { applyBlocking(maxDuration); } else if (!options.skipBlocking) { @@ -29950,6 +30884,11 @@ if (typeof module !== "undefined" && typeof exports !== "undefined" && module.ex }); applyAnimationClasses(element, options); applyAnimationStyles(element, options); + if (Object.keys(restoreStyles).length) { + forEach(restoreStyles, function(value, prop) { + value ? node.style.setProperty(prop, value) : node.style.removeProperty(prop); + }); + } if (options.onDone) { options.onDone(); } @@ -30088,7 +31027,12 @@ if (typeof module !== "undefined" && typeof exports !== "undefined" && module.ex element.data(ANIMATE_TIMER_KEY, animationsData); } element.on(events.join(" "), onAnimationProgress); - applyAnimationToStyles(element, options); + if (options.to) { + if (options.cleanupStyles) { + registerRestorableStyles(restoreStyles, node, Object.keys(options.to)); + } + applyAnimationToStyles(element, options); + } } function onAnimationExpired() { var animationsData = element.data(ANIMATE_TIMER_KEY); @@ -30119,11 +31063,14 @@ if (typeof module !== "undefined" && typeof exports !== "undefined" && module.ex var NG_ANIMATE_ANCHOR_CLASS_NAME = "ng-anchor"; var NG_OUT_ANCHOR_CLASS_NAME = "ng-anchor-out"; var NG_IN_ANCHOR_CLASS_NAME = "ng-anchor-in"; - this.$get = [ "$animateCss", "$rootScope", "$$AnimateRunner", "$rootElement", "$$body", "$sniffer", "$$jqLite", function($animateCss, $rootScope, $$AnimateRunner, $rootElement, $$body, $sniffer, $$jqLite) { + function isDocumentFragment(node) { + return node.parentNode && node.parentNode.nodeType === 11; + } + this.$get = [ "$animateCss", "$rootScope", "$$AnimateRunner", "$rootElement", "$sniffer", "$$jqLite", "$document", function($animateCss, $rootScope, $$AnimateRunner, $rootElement, $sniffer, $$jqLite, $document) { if (!$sniffer.animations && !$sniffer.transitions) return noop; - var bodyNode = getDomNode($$body); + var bodyNode = $document[0].body; var rootNode = getDomNode($rootElement); - var rootBodyElement = jqLite(bodyNode.parentNode === rootNode ? bodyNode : rootNode); + var rootBodyElement = jqLite(isDocumentFragment(rootNode) || bodyNode.contains(rootNode) ? rootNode : bodyNode); var applyAnimationClasses = applyAnimationClassesFactory($$jqLite); return function initDriverFn(animationDetails) { return animationDetails.from && animationDetails.to ? prepareFromToAnchorAnimation(animationDetails.from, animationDetails.to, animationDetails.classes, animationDetails.anchors) : prepareRegularAnimation(animationDetails); @@ -30592,10 +31539,23 @@ if (typeof module !== "undefined" && typeof exports !== "undefined" && module.ex var cO = currentAnimation.options; return nO.addClass && nO.addClass === cO.removeClass || nO.removeClass && nO.removeClass === cO.addClass; }); - this.$get = [ "$$rAF", "$rootScope", "$rootElement", "$document", "$$body", "$$HashMap", "$$animation", "$$AnimateRunner", "$templateRequest", "$$jqLite", "$$forceReflow", function($$rAF, $rootScope, $rootElement, $document, $$body, $$HashMap, $$animation, $$AnimateRunner, $templateRequest, $$jqLite, $$forceReflow) { + this.$get = [ "$$rAF", "$rootScope", "$rootElement", "$document", "$$HashMap", "$$animation", "$$AnimateRunner", "$templateRequest", "$$jqLite", "$$forceReflow", function($$rAF, $rootScope, $rootElement, $document, $$HashMap, $$animation, $$AnimateRunner, $templateRequest, $$jqLite, $$forceReflow) { var activeAnimationsLookup = new $$HashMap(); var disabledElementsLookup = new $$HashMap(); var animationsEnabled = null; + function postDigestTaskFactory() { + var postDigestCalled = false; + return function(fn) { + if (postDigestCalled) { + fn(); + } else { + $rootScope.$$postDigest(function() { + postDigestCalled = true; + fn(); + }); + } + }; + } var deregisterWatch = $rootScope.$watch(function() { return $templateRequest.totalPendingRequests === 0; }, function(isEmpty) { @@ -30633,13 +31593,6 @@ if (typeof module !== "undefined" && typeof exports !== "undefined" && module.ex } return matches; } - function triggerCallback(event, element, phase, data) { - $$rAF(function() { - forEach(findCallbacks(element, event), function(callback) { - callback(element, phase, data); - }); - }); - } return { on: function(event, container, callback) { var node = extractElementNode(container); @@ -30706,6 +31659,7 @@ if (typeof module !== "undefined" && typeof exports !== "undefined" && module.ex } options = prepareAnimationOptions(options); var runner = new $$AnimateRunner(); + var runInNextPostDigestOrNow = postDigestTaskFactory(); if (isArray(options.addClass)) { options.addClass = options.addClass.join(" "); } @@ -30840,7 +31794,16 @@ if (typeof module !== "undefined" && typeof exports !== "undefined" && module.ex }); return runner; function notifyProgress(runner, event, phase, data) { - triggerCallback(event, element, phase, data); + runInNextPostDigestOrNow(function() { + var callbacks = findCallbacks(element, event); + if (callbacks.length) { + $$rAF(function() { + forEach(callbacks, function(callback) { + callback(element, phase, data); + }); + }); + } + }); runner.progress(event, phase, data); } function close(reject) { @@ -30878,7 +31841,8 @@ if (typeof module !== "undefined" && typeof exports !== "undefined" && module.ex return getDomNode(nodeOrElmA) === getDomNode(nodeOrElmB); } function areAnimationsAllowed(element, parentElement, event) { - var bodyElementDetected = isMatchingElement(element, $$body) || element[0].nodeName === "HTML"; + var bodyElement = jqLite($document[0].body); + var bodyElementDetected = isMatchingElement(element, bodyElement) || element[0].nodeName === "HTML"; var rootElementDetected = isMatchingElement(element, $rootElement); var parentAnimationDetected = false; var animateChildren; @@ -30914,896 +31878,3387 @@ if (typeof module !== "undefined" && typeof exports !== "undefined" && module.ex } } } - if (!bodyElementDetected) { - bodyElementDetected = isMatchingElement(parentElement, $$body); + if (!bodyElementDetected) { + bodyElementDetected = isMatchingElement(parentElement, bodyElement); + } + parentElement = parentElement.parent(); + } + var allowAnimation = !parentAnimationDetected || animateChildren; + return allowAnimation && rootElementDetected && bodyElementDetected; + } + function markElementAnimationState(element, state, details) { + details = details || {}; + details.state = state; + var node = getDomNode(element); + node.setAttribute(NG_ANIMATE_ATTR_NAME, state); + var oldValue = activeAnimationsLookup.get(node); + var newValue = oldValue ? extend(oldValue, details) : details; + activeAnimationsLookup.put(node, newValue); + } + } ]; + } ]; + var $$AnimateAsyncRunFactory = [ "$$rAF", function($$rAF) { + var waitQueue = []; + function waitForTick(fn) { + waitQueue.push(fn); + if (waitQueue.length > 1) return; + $$rAF(function() { + for (var i = 0; i < waitQueue.length; i++) { + waitQueue[i](); + } + waitQueue = []; + }); + } + return function() { + var passed = false; + waitForTick(function() { + passed = true; + }); + return function(callback) { + passed ? callback() : waitForTick(callback); + }; + }; + } ]; + var $$AnimateRunnerFactory = [ "$q", "$sniffer", "$$animateAsyncRun", function($q, $sniffer, $$animateAsyncRun) { + var INITIAL_STATE = 0; + var DONE_PENDING_STATE = 1; + var DONE_COMPLETE_STATE = 2; + AnimateRunner.chain = function(chain, callback) { + var index = 0; + next(); + function next() { + if (index === chain.length) { + callback(true); + return; + } + chain[index](function(response) { + if (response === false) { + callback(false); + return; + } + index++; + next(); + }); + } + }; + AnimateRunner.all = function(runners, callback) { + var count = 0; + var status = true; + forEach(runners, function(runner) { + runner.done(onProgress); + }); + function onProgress(response) { + status = status && response; + if (++count === runners.length) { + callback(status); + } + } + }; + function AnimateRunner(host) { + this.setHost(host); + this._doneCallbacks = []; + this._runInAnimationFrame = $$animateAsyncRun(); + this._state = 0; + } + AnimateRunner.prototype = { + setHost: function(host) { + this.host = host || {}; + }, + done: function(fn) { + if (this._state === DONE_COMPLETE_STATE) { + fn(); + } else { + this._doneCallbacks.push(fn); + } + }, + progress: noop, + getPromise: function() { + if (!this.promise) { + var self = this; + this.promise = $q(function(resolve, reject) { + self.done(function(status) { + status === false ? reject() : resolve(); + }); + }); + } + return this.promise; + }, + then: function(resolveHandler, rejectHandler) { + return this.getPromise().then(resolveHandler, rejectHandler); + }, + "catch": function(handler) { + return this.getPromise()["catch"](handler); + }, + "finally": function(handler) { + return this.getPromise()["finally"](handler); + }, + pause: function() { + if (this.host.pause) { + this.host.pause(); + } + }, + resume: function() { + if (this.host.resume) { + this.host.resume(); + } + }, + end: function() { + if (this.host.end) { + this.host.end(); + } + this._resolve(true); + }, + cancel: function() { + if (this.host.cancel) { + this.host.cancel(); + } + this._resolve(false); + }, + complete: function(response) { + var self = this; + if (self._state === INITIAL_STATE) { + self._state = DONE_PENDING_STATE; + self._runInAnimationFrame(function() { + self._resolve(response); + }); + } + }, + _resolve: function(response) { + if (this._state !== DONE_COMPLETE_STATE) { + forEach(this._doneCallbacks, function(fn) { + fn(response); + }); + this._doneCallbacks.length = 0; + this._state = DONE_COMPLETE_STATE; + } + } + }; + return AnimateRunner; + } ]; + var $$AnimationProvider = [ "$animateProvider", function($animateProvider) { + var NG_ANIMATE_REF_ATTR = "ng-animate-ref"; + var drivers = this.drivers = []; + var RUNNER_STORAGE_KEY = "$$animationRunner"; + function setRunner(element, runner) { + element.data(RUNNER_STORAGE_KEY, runner); + } + function removeRunner(element) { + element.removeData(RUNNER_STORAGE_KEY); + } + function getRunner(element) { + return element.data(RUNNER_STORAGE_KEY); + } + this.$get = [ "$$jqLite", "$rootScope", "$injector", "$$AnimateRunner", "$$HashMap", "$$rAFScheduler", function($$jqLite, $rootScope, $injector, $$AnimateRunner, $$HashMap, $$rAFScheduler) { + var animationQueue = []; + var applyAnimationClasses = applyAnimationClassesFactory($$jqLite); + function sortAnimations(animations) { + var tree = { + children: [] + }; + var i, lookup = new $$HashMap(); + for (i = 0; i < animations.length; i++) { + var animation = animations[i]; + lookup.put(animation.domNode, animations[i] = { + domNode: animation.domNode, + fn: animation.fn, + children: [] + }); + } + for (i = 0; i < animations.length; i++) { + processNode(animations[i]); + } + return flatten(tree); + function processNode(entry) { + if (entry.processed) return entry; + entry.processed = true; + var elementNode = entry.domNode; + var parentNode = elementNode.parentNode; + lookup.put(elementNode, entry); + var parentEntry; + while (parentNode) { + parentEntry = lookup.get(parentNode); + if (parentEntry) { + if (!parentEntry.processed) { + parentEntry = processNode(parentEntry); + } + break; + } + parentNode = parentNode.parentNode; + } + (parentEntry || tree).children.push(entry); + return entry; + } + function flatten(tree) { + var result = []; + var queue = []; + var i; + for (i = 0; i < tree.children.length; i++) { + queue.push(tree.children[i]); } - parentElement = parentElement.parent(); + var remainingLevelEntries = queue.length; + var nextLevelEntries = 0; + var row = []; + for (i = 0; i < queue.length; i++) { + var entry = queue[i]; + if (remainingLevelEntries <= 0) { + remainingLevelEntries = nextLevelEntries; + nextLevelEntries = 0; + result.push(row); + row = []; + } + row.push(entry.fn); + entry.children.forEach(function(childEntry) { + nextLevelEntries++; + queue.push(childEntry); + }); + remainingLevelEntries--; + } + if (row.length) { + result.push(row); + } + return result; } - var allowAnimation = !parentAnimationDetected || animateChildren; - return allowAnimation && rootElementDetected && bodyElementDetected; - } - function markElementAnimationState(element, state, details) { - details = details || {}; - details.state = state; - var node = getDomNode(element); - node.setAttribute(NG_ANIMATE_ATTR_NAME, state); - var oldValue = activeAnimationsLookup.get(node); - var newValue = oldValue ? extend(oldValue, details) : details; - activeAnimationsLookup.put(node, newValue); } - } ]; - } ]; - var $$AnimateAsyncRunFactory = [ "$$rAF", function($$rAF) { - var waitQueue = []; - function waitForTick(fn) { - waitQueue.push(fn); - if (waitQueue.length > 1) return; - $$rAF(function() { - for (var i = 0; i < waitQueue.length; i++) { - waitQueue[i](); - } - waitQueue = []; - }); - } - return function() { - var passed = false; - waitForTick(function() { - passed = true; - }); - return function(callback) { - passed ? callback() : waitForTick(callback); - }; - }; - } ]; - var $$AnimateRunnerFactory = [ "$q", "$sniffer", "$$animateAsyncRun", function($q, $sniffer, $$animateAsyncRun) { - var INITIAL_STATE = 0; - var DONE_PENDING_STATE = 1; - var DONE_COMPLETE_STATE = 2; - AnimateRunner.chain = function(chain, callback) { - var index = 0; - next(); - function next() { - if (index === chain.length) { - callback(true); - return; - } - chain[index](function(response) { - if (response === false) { - callback(false); - return; + return function(element, event, options) { + options = prepareAnimationOptions(options); + var isStructural = [ "enter", "move", "leave" ].indexOf(event) >= 0; + var runner = new $$AnimateRunner({ + end: function() { + close(); + }, + cancel: function() { + close(true); } - index++; - next(); }); - } - }; - AnimateRunner.all = function(runners, callback) { - var count = 0; - var status = true; - forEach(runners, function(runner) { - runner.done(onProgress); - }); - function onProgress(response) { - status = status && response; - if (++count === runners.length) { - callback(status); + if (!drivers.length) { + close(); + return runner; } - } - }; - function AnimateRunner(host) { - this.setHost(host); - this._doneCallbacks = []; - this._runInAnimationFrame = $$animateAsyncRun(); - this._state = 0; - } - AnimateRunner.prototype = { - setHost: function(host) { - this.host = host || {}; - }, - done: function(fn) { - if (this._state === DONE_COMPLETE_STATE) { - fn(); - } else { - this._doneCallbacks.push(fn); + setRunner(element, runner); + var classes = mergeClasses(element.attr("class"), mergeClasses(options.addClass, options.removeClass)); + var tempClasses = options.tempClasses; + if (tempClasses) { + classes += " " + tempClasses; + options.tempClasses = null; } - }, - progress: noop, - getPromise: function() { - if (!this.promise) { - var self = this; - this.promise = $q(function(resolve, reject) { - self.done(function(status) { - status === false ? reject() : resolve(); + animationQueue.push({ + element: element, + classes: classes, + event: event, + structural: isStructural, + options: options, + beforeStart: beforeStart, + close: close + }); + element.on("$destroy", handleDestroyedElement); + if (animationQueue.length > 1) return runner; + $rootScope.$$postDigest(function() { + var animations = []; + forEach(animationQueue, function(entry) { + if (getRunner(entry.element)) { + animations.push(entry); + } else { + entry.close(); + } + }); + animationQueue.length = 0; + var groupedAnimations = groupAnimations(animations); + var toBeSortedAnimations = []; + forEach(groupedAnimations, function(animationEntry) { + toBeSortedAnimations.push({ + domNode: getDomNode(animationEntry.from ? animationEntry.from.element : animationEntry.element), + fn: function triggerAnimationStart() { + animationEntry.beforeStart(); + var startAnimationFn, closeFn = animationEntry.close; + var targetElement = animationEntry.anchors ? animationEntry.from.element || animationEntry.to.element : animationEntry.element; + if (getRunner(targetElement)) { + var operation = invokeFirstDriver(animationEntry); + if (operation) { + startAnimationFn = operation.start; + } + } + if (!startAnimationFn) { + closeFn(); + } else { + var animationRunner = startAnimationFn(); + animationRunner.done(function(status) { + closeFn(!status); + }); + updateAnimationRunners(animationEntry, animationRunner); + } + } + }); + }); + $$rAFScheduler(sortAnimations(toBeSortedAnimations)); + }); + return runner; + function getAnchorNodes(node) { + var SELECTOR = "[" + NG_ANIMATE_REF_ATTR + "]"; + var items = node.hasAttribute(NG_ANIMATE_REF_ATTR) ? [ node ] : node.querySelectorAll(SELECTOR); + var anchors = []; + forEach(items, function(node) { + var attr = node.getAttribute(NG_ANIMATE_REF_ATTR); + if (attr && attr.length) { + anchors.push(node); + } + }); + return anchors; + } + function groupAnimations(animations) { + var preparedAnimations = []; + var refLookup = {}; + forEach(animations, function(animation, index) { + var element = animation.element; + var node = getDomNode(element); + var event = animation.event; + var enterOrMove = [ "enter", "move" ].indexOf(event) >= 0; + var anchorNodes = animation.structural ? getAnchorNodes(node) : []; + if (anchorNodes.length) { + var direction = enterOrMove ? "to" : "from"; + forEach(anchorNodes, function(anchor) { + var key = anchor.getAttribute(NG_ANIMATE_REF_ATTR); + refLookup[key] = refLookup[key] || {}; + refLookup[key][direction] = { + animationID: index, + element: jqLite(anchor) + }; + }); + } else { + preparedAnimations.push(animation); + } + }); + var usedIndicesLookup = {}; + var anchorGroups = {}; + forEach(refLookup, function(operations, key) { + var from = operations.from; + var to = operations.to; + if (!from || !to) { + var index = from ? from.animationID : to.animationID; + var indexKey = index.toString(); + if (!usedIndicesLookup[indexKey]) { + usedIndicesLookup[indexKey] = true; + preparedAnimations.push(animations[index]); + } + return; + } + var fromAnimation = animations[from.animationID]; + var toAnimation = animations[to.animationID]; + var lookupKey = from.animationID.toString(); + if (!anchorGroups[lookupKey]) { + var group = anchorGroups[lookupKey] = { + structural: true, + beforeStart: function() { + fromAnimation.beforeStart(); + toAnimation.beforeStart(); + }, + close: function() { + fromAnimation.close(); + toAnimation.close(); + }, + classes: cssClassesIntersection(fromAnimation.classes, toAnimation.classes), + from: fromAnimation, + to: toAnimation, + anchors: [] + }; + if (group.classes.length) { + preparedAnimations.push(group); + } else { + preparedAnimations.push(fromAnimation); + preparedAnimations.push(toAnimation); + } + } + anchorGroups[lookupKey].anchors.push({ + out: from.element, + "in": to.element }); }); + return preparedAnimations; } - return this.promise; - }, - then: function(resolveHandler, rejectHandler) { - return this.getPromise().then(resolveHandler, rejectHandler); - }, - "catch": function(handler) { - return this.getPromise()["catch"](handler); - }, - "finally": function(handler) { - return this.getPromise()["finally"](handler); - }, - pause: function() { - if (this.host.pause) { - this.host.pause(); + function cssClassesIntersection(a, b) { + a = a.split(" "); + b = b.split(" "); + var matches = []; + for (var i = 0; i < a.length; i++) { + var aa = a[i]; + if (aa.substring(0, 3) === "ng-") continue; + for (var j = 0; j < b.length; j++) { + if (aa === b[j]) { + matches.push(aa); + break; + } + } + } + return matches.join(" "); } - }, - resume: function() { - if (this.host.resume) { - this.host.resume(); + function invokeFirstDriver(animationDetails) { + for (var i = drivers.length - 1; i >= 0; i--) { + var driverName = drivers[i]; + if (!$injector.has(driverName)) continue; + var factory = $injector.get(driverName); + var driver = factory(animationDetails); + if (driver) { + return driver; + } + } } - }, - end: function() { - if (this.host.end) { - this.host.end(); + function beforeStart() { + element.addClass(NG_ANIMATE_CLASSNAME); + if (tempClasses) { + $$jqLite.addClass(element, tempClasses); + } } - this._resolve(true); - }, - cancel: function() { - if (this.host.cancel) { - this.host.cancel(); + function updateAnimationRunners(animation, newRunner) { + if (animation.from && animation.to) { + update(animation.from.element); + update(animation.to.element); + } else { + update(animation.element); + } + function update(element) { + getRunner(element).setHost(newRunner); + } } - this._resolve(false); - }, - complete: function(response) { - var self = this; - if (self._state === INITIAL_STATE) { - self._state = DONE_PENDING_STATE; - self._runInAnimationFrame(function() { - self._resolve(response); + function handleDestroyedElement() { + var runner = getRunner(element); + if (runner && (event !== "leave" || !options.$$domOperationFired)) { + runner.end(); + } + } + function close(rejected) { + element.off("$destroy", handleDestroyedElement); + removeRunner(element); + applyAnimationClasses(element, options); + applyAnimationStyles(element, options); + options.domOperation(); + if (tempClasses) { + $$jqLite.removeClass(element, tempClasses); + } + element.removeClass(NG_ANIMATE_CLASSNAME); + runner.complete(!rejected); + } + }; + } ]; + } ]; + angular.module("ngAnimate", []).directive("ngAnimateChildren", $$AnimateChildrenDirective).factory("$$rAFScheduler", $$rAFSchedulerFactory).factory("$$AnimateRunner", $$AnimateRunnerFactory).factory("$$animateAsyncRun", $$AnimateAsyncRunFactory).provider("$$animateQueue", $$AnimateQueueProvider).provider("$$animation", $$AnimationProvider).provider("$animateCss", $AnimateCssProvider).provider("$$animateCssDriver", $$AnimateCssDriverProvider).provider("$$animateJs", $$AnimateJsProvider).provider("$$animateJsDriver", $$AnimateJsDriverProvider); +})(window, window.angular); + +angular.module("ngMap", []); + +(function() { + "use strict"; + var Attr2MapOptions; + var __MapController = function($scope, $element, $attrs, $parse, _Attr2MapOptions_, NgMap) { + Attr2MapOptions = _Attr2MapOptions_; + var vm = this; + vm.mapOptions; + vm.mapEvents; + vm.ngMapDiv; + vm.addObject = function(groupName, obj) { + if (vm.map) { + vm.map[groupName] = vm.map[groupName] || {}; + var len = Object.keys(vm.map[groupName]).length; + vm.map[groupName][obj.id || len] = obj; + if (groupName != "infoWindows" && obj.setMap) { + obj.setMap && obj.setMap(vm.map); + } + if (obj.centered && obj.position) { + vm.map.setCenter(obj.position); + } + groupName == "markers" && vm.objectChanged("markers"); + groupName == "customMarkers" && vm.objectChanged("customMarkers"); + } + }; + vm.deleteObject = function(groupName, obj) { + if (obj.map) { + var objs = obj.map[groupName]; + for (var name in objs) { + objs[name] === obj && delete objs[name]; + } + obj.map && obj.setMap && obj.setMap(null); + groupName == "markers" && vm.objectChanged("markers"); + groupName == "customMarkers" && vm.objectChanged("customMarkers"); + } + }; + vm.observeAttrSetObj = function(orgAttrs, attrs, obj) { + if (attrs.noWatcher) { + return false; + } + var attrsToObserve = Attr2MapOptions.getAttrsToObserve(orgAttrs); + for (var i = 0; i < attrsToObserve.length; i++) { + var attrName = attrsToObserve[i]; + attrs.$observe(attrName, NgMap.observeAndSet(attrName, obj)); + } + }; + vm.zoomToIncludeMarkers = function() { + var bounds = new google.maps.LatLngBounds(); + for (var k1 in vm.map.markers) { + bounds.extend(vm.map.markers[k1].getPosition()); + } + for (var k2 in vm.map.customMarkers) { + bounds.extend(vm.map.customMarkers[k2].getPosition()); + } + vm.map.fitBounds(bounds); + }; + vm.objectChanged = function(group) { + if ((group == "markers" || group == "customMarkers") && vm.map.zoomToIncludeMarkers == "auto") { + vm.zoomToIncludeMarkers(); + } + }; + vm.initializeMap = function() { + var mapOptions = vm.mapOptions, mapEvents = vm.mapEvents, ngMapDiv = vm.ngMapDiv; + vm.map = new google.maps.Map(ngMapDiv, {}); + mapOptions.zoom = mapOptions.zoom || 15; + var center = mapOptions.center; + if (!mapOptions.center || typeof center === "string" && center.match(/\{\{.*\}\}/)) { + mapOptions.center = new google.maps.LatLng(0, 0); + } else if (!(center instanceof google.maps.LatLng)) { + var geoCenter = mapOptions.center; + delete mapOptions.center; + NgMap.getGeoLocation(geoCenter, mapOptions.geoLocationOptions).then(function(latlng) { + vm.map.setCenter(latlng); + var geoCallback = mapOptions.geoCallback; + geoCallback && $parse(geoCallback)($scope); + }, function() { + if (mapOptions.geoFallbackCenter) { + vm.map.setCenter(mapOptions.geoFallbackCenter); + } + }); + } + vm.map.setOptions(mapOptions); + for (var eventName in mapEvents) { + google.maps.event.addListener(vm.map, eventName, mapEvents[eventName]); + } + vm.observeAttrSetObj(orgAttrs, $attrs, vm.map); + vm.singleInfoWindow = mapOptions.singleInfoWindow; + google.maps.event.addListenerOnce(vm.map, "idle", function() { + NgMap.addMap(vm); + if (mapOptions.zoomToIncludeMarkers) { + vm.zoomToIncludeMarkers(); + } + $scope.map = vm.map; + $scope.$emit("mapInitialized", vm.map); + if ($attrs.mapInitialized) { + $parse($attrs.mapInitialized)($scope, { + map: vm.map }); } - }, - _resolve: function(response) { - if (this._state !== DONE_COMPLETE_STATE) { - forEach(this._doneCallbacks, function(fn) { - fn(response); + }); + }; + $scope.google = google; + var orgAttrs = Attr2MapOptions.orgAttributes($element); + var filtered = Attr2MapOptions.filter($attrs); + var options = Attr2MapOptions.getOptions(filtered); + var controlOptions = Attr2MapOptions.getControlOptions(filtered); + var mapOptions = angular.extend(options, controlOptions); + var mapEvents = Attr2MapOptions.getEvents($scope, filtered); + void 0; + vm.mapOptions = mapOptions; + vm.mapEvents = mapEvents; + vm.ngMapDiv = NgMap.getNgMapDiv($element[0]); + $element.append(vm.ngMapDiv); + if (options.lazyInit) { + vm.map = { + id: $attrs.id + }; + NgMap.addMap(vm); + } else { + vm.initializeMap(); + } + $element.bind("$destroy", function() { + NgMap.deleteMap(vm); + }); + }; + __MapController.$inject = [ "$scope", "$element", "$attrs", "$parse", "Attr2MapOptions", "NgMap" ]; + angular.module("ngMap").controller("__MapController", __MapController); +})(); + +(function() { + "use strict"; + var parser; + var linkFunc = function(scope, element, attrs, mapController) { + mapController = mapController[0] || mapController[1]; + var orgAttrs = parser.orgAttributes(element); + var filtered = parser.filter(attrs); + var options = parser.getOptions(filtered); + var events = parser.getEvents(scope, filtered); + void 0; + var layer = getLayer(options, events); + mapController.addObject("bicyclingLayers", layer); + mapController.observeAttrSetObj(orgAttrs, attrs, layer); + element.bind("$destroy", function() { + mapController.deleteObject("bicyclingLayers", layer); + }); + }; + var getLayer = function(options, events) { + var layer = new google.maps.BicyclingLayer(options); + for (var eventName in events) { + google.maps.event.addListener(layer, eventName, events[eventName]); + } + return layer; + }; + var bicyclingLayer = function(Attr2MapOptions) { + parser = Attr2MapOptions; + return { + restrict: "E", + require: [ "?^map", "?^ngMap" ], + link: linkFunc + }; + }; + bicyclingLayer.$inject = [ "Attr2MapOptions" ]; + angular.module("ngMap").directive("bicyclingLayer", bicyclingLayer); +})(); + +(function() { + "use strict"; + var parser, $compile, NgMap; + var linkFunc = function(scope, element, attrs, mapController) { + mapController = mapController[0] || mapController[1]; + var filtered = parser.filter(attrs); + var options = parser.getOptions(filtered); + var events = parser.getEvents(scope, filtered); + void 0; + var customControlEl = element[0].parentElement.removeChild(element[0]); + $compile(customControlEl.innerHTML.trim())(scope); + for (var eventName in events) { + google.maps.event.addDomListener(customControlEl, eventName, events[eventName]); + } + mapController.addObject("customControls", customControlEl); + NgMap.getMap().then(function(map) { + var position = options.position; + map.controls[google.maps.ControlPosition[position]].push(customControlEl); + }); + }; + var customControl = function(Attr2MapOptions, _$compile_, _NgMap_) { + parser = Attr2MapOptions, $compile = _$compile_, NgMap = _NgMap_; + return { + restrict: "E", + require: [ "?^map", "?^ngMap" ], + link: linkFunc + }; + }; + customControl.$inject = [ "Attr2MapOptions", "$compile", "NgMap" ]; + angular.module("ngMap").directive("customControl", customControl); +})(); + +(function() { + "use strict"; + var parser, $timeout, $compile, NgMap; + var CustomMarker = function(options) { + options = options || {}; + this.el = document.createElement("div"); + this.el.style.display = "inline-block"; + this.visible = true; + for (var key in options) { + this[key] = options[key]; + } + }; + var setCustomMarker = function() { + CustomMarker.prototype = new google.maps.OverlayView(); + CustomMarker.prototype.setContent = function(html, scope) { + this.el.innerHTML = html; + this.el.style.position = "absolute"; + if (scope) { + $compile(angular.element(this.el).contents())(scope); + } + }; + CustomMarker.prototype.getDraggable = function() { + return this.draggable; + }; + CustomMarker.prototype.setDraggable = function(draggable) { + this.draggable = draggable; + }; + CustomMarker.prototype.getPosition = function() { + return this.position; + }; + CustomMarker.prototype.setPosition = function(position) { + position && (this.position = position); + if (this.getProjection() && typeof this.position.lng == "function") { + var posPixel = this.getProjection().fromLatLngToDivPixel(this.position); + var x = Math.round(posPixel.x - this.el.offsetWidth / 2); + var y = Math.round(posPixel.y - this.el.offsetHeight - 10); + this.el.style.left = x + "px"; + this.el.style.top = y + "px"; + } + }; + CustomMarker.prototype.setZIndex = function(zIndex) { + zIndex && (this.zIndex = zIndex); + this.el.style.zIndex = this.zIndex; + }; + CustomMarker.prototype.setVisible = function(visible) { + this.el.style.display = visible ? "inline-block" : "none"; + this.visible = visible; + }; + CustomMarker.prototype.addClass = function(className) { + var classNames = this.el.className.trim().split(" "); + classNames.indexOf(className) == -1 && classNames.push(className); + this.el.className = classNames.join(" "); + }; + CustomMarker.prototype.removeClass = function(className) { + var classNames = this.el.className.split(" "); + var index = classNames.indexOf(className); + index > -1 && classNames.splice(index, 1); + this.el.className = classNames.join(" "); + }; + CustomMarker.prototype.onAdd = function() { + this.getPanes().overlayMouseTarget.appendChild(this.el); + }; + CustomMarker.prototype.draw = function() { + this.setPosition(); + this.setZIndex(this.zIndex); + this.setVisible(this.visible); + }; + CustomMarker.prototype.onRemove = function() { + this.el.parentNode.removeChild(this.el); + }; + }; + var linkFunc = function(orgHtml, varsToWatch) { + return function(scope, element, attrs, mapController) { + mapController = mapController[0] || mapController[1]; + var orgAttrs = parser.orgAttributes(element); + var filtered = parser.filter(attrs); + var options = parser.getOptions(filtered, scope); + var events = parser.getEvents(scope, filtered); + var removedEl = element[0].parentElement.removeChild(element[0]); + void 0; + var customMarker = new CustomMarker(options); + $timeout(function() { + scope.$watch("[" + varsToWatch.join(",") + "]", function() { + customMarker.setContent(orgHtml, scope); + }); + customMarker.setContent(removedEl.innerHTML, scope); + var classNames = removedEl.firstElementChild.className; + customMarker.addClass("custom-marker"); + customMarker.addClass(classNames); + void 0; + if (!(options.position instanceof google.maps.LatLng)) { + NgMap.getGeoLocation(options.position).then(function(latlng) { + customMarker.setPosition(latlng); }); - this._doneCallbacks.length = 0; - this._state = DONE_COMPLETE_STATE; } + }); + void 0; + for (var eventName in events) { + google.maps.event.addDomListener(customMarker.el, eventName, events[eventName]); } + mapController.addObject("customMarkers", customMarker); + mapController.observeAttrSetObj(orgAttrs, attrs, customMarker); + element.bind("$destroy", function() { + mapController.deleteObject("customMarkers", customMarker); + }); }; - return AnimateRunner; - } ]; - var $$AnimationProvider = [ "$animateProvider", function($animateProvider) { - var NG_ANIMATE_REF_ATTR = "ng-animate-ref"; - var drivers = this.drivers = []; - var RUNNER_STORAGE_KEY = "$$animationRunner"; - function setRunner(element, runner) { - element.data(RUNNER_STORAGE_KEY, runner); + }; + var customMarkerDirective = function(_$timeout_, _$compile_, Attr2MapOptions, _NgMap_) { + parser = Attr2MapOptions; + $timeout = _$timeout_; + $compile = _$compile_; + NgMap = _NgMap_; + return { + restrict: "E", + require: [ "?^map", "?^ngMap" ], + compile: function(element) { + setCustomMarker(); + element[0].style.display = "none"; + var orgHtml = element.html(); + var matches = orgHtml.match(/{{([^}]+)}}/g); + var varsToWatch = []; + (matches || []).forEach(function(match) { + var toWatch = match.replace("{{", "").replace("}}", ""); + if (match.indexOf("::") == -1 && match.indexOf("this.") == -1 && varsToWatch.indexOf(toWatch) == -1) { + varsToWatch.push(match.replace("{{", "").replace("}}", "")); + } + }); + return linkFunc(orgHtml, varsToWatch); + } + }; + }; + customMarkerDirective.$inject = [ "$timeout", "$compile", "Attr2MapOptions", "NgMap" ]; + angular.module("ngMap").directive("customMarker", customMarkerDirective); +})(); + +(function() { + "use strict"; + var NgMap, $timeout, NavigatorGeolocation; + var getDirectionsRenderer = function(options, events) { + if (options.panel) { + options.panel = document.getElementById(options.panel) || document.querySelector(options.panel); } - function removeRunner(element) { - element.removeData(RUNNER_STORAGE_KEY); + var renderer = new google.maps.DirectionsRenderer(options); + for (var eventName in events) { + google.maps.event.addListener(renderer, eventName, events[eventName]); } - function getRunner(element) { - return element.data(RUNNER_STORAGE_KEY); + return renderer; + }; + var updateRoute = function(renderer, options) { + var directionsService = new google.maps.DirectionsService(); + var request = options; + request.travelMode = request.travelMode || "DRIVING"; + var validKeys = [ "origin", "destination", "travelMode", "transitOptions", "unitSystem", "durationInTraffic", "waypoints", "optimizeWaypoints", "provideRouteAlternatives", "avoidHighways", "avoidTolls", "region" ]; + for (var key in request) { + validKeys.indexOf(key) === -1 && delete request[key]; } - this.$get = [ "$$jqLite", "$rootScope", "$injector", "$$AnimateRunner", "$$HashMap", "$$rAFScheduler", function($$jqLite, $rootScope, $injector, $$AnimateRunner, $$HashMap, $$rAFScheduler) { - var animationQueue = []; - var applyAnimationClasses = applyAnimationClassesFactory($$jqLite); - function sortAnimations(animations) { - var tree = { - children: [] - }; - var i, lookup = new $$HashMap(); - for (i = 0; i < animations.length; i++) { - var animation = animations[i]; - lookup.put(animation.domNode, animations[i] = { - domNode: animation.domNode, - fn: animation.fn, - children: [] + if (request.waypoints) { + if (request.waypoints == "[]" || request.waypoints === "") { + delete request.waypoints; + } + } + var showDirections = function(request) { + directionsService.route(request, function(response, status) { + if (status == google.maps.DirectionsStatus.OK) { + $timeout(function() { + renderer.setDirections(response); }); } - for (i = 0; i < animations.length; i++) { - processNode(animations[i]); - } - return flatten(tree); - function processNode(entry) { - if (entry.processed) return entry; - entry.processed = true; - var elementNode = entry.domNode; - var parentNode = elementNode.parentNode; - lookup.put(elementNode, entry); - var parentEntry; - while (parentNode) { - parentEntry = lookup.get(parentNode); - if (parentEntry) { - if (!parentEntry.processed) { - parentEntry = processNode(parentEntry); - } - break; + }); + }; + if (request.origin && request.destination) { + if (request.origin == "current-location") { + NavigatorGeolocation.getCurrentPosition().then(function(ll) { + request.origin = new google.maps.LatLng(ll.coords.latitude, ll.coords.longitude); + showDirections(request); + }); + } else if (request.destination == "current-location") { + NavigatorGeolocation.getCurrentPosition().then(function(ll) { + request.destination = new google.maps.LatLng(ll.coords.latitude, ll.coords.longitude); + showDirections(request); + }); + } else { + showDirections(request); + } + } + }; + var directions = function(Attr2MapOptions, _$timeout_, _NavigatorGeolocation_, _NgMap_) { + var parser = Attr2MapOptions; + NgMap = _NgMap_; + $timeout = _$timeout_; + NavigatorGeolocation = _NavigatorGeolocation_; + var linkFunc = function(scope, element, attrs, mapController) { + mapController = mapController[0] || mapController[1]; + var orgAttrs = parser.orgAttributes(element); + var filtered = parser.filter(attrs); + var options = parser.getOptions(filtered); + var events = parser.getEvents(scope, filtered); + var attrsToObserve = parser.getAttrsToObserve(orgAttrs); + var renderer = getDirectionsRenderer(options, events); + mapController.addObject("directionsRenderers", renderer); + attrsToObserve.forEach(function(attrName) { + (function(attrName) { + attrs.$observe(attrName, function(val) { + if (attrName == "panel") { + $timeout(function() { + var panel = document.getElementById(val) || document.querySelector(val); + void 0; + panel && renderer.setPanel(panel); + }); + } else if (options[attrName] !== val) { + var optionValue = parser.toOptionValue(val, { + key: attrName + }); + void 0; + options[attrName] = optionValue; + updateRoute(renderer, options); } - parentNode = parentNode.parentNode; - } - (parentEntry || tree).children.push(entry); - return entry; + }); + })(attrName); + }); + NgMap.getMap().then(function() { + updateRoute(renderer, options); + }); + element.bind("$destroy", function() { + mapController.deleteObject("directionsRenderers", renderer); + }); + }; + return { + restrict: "E", + require: [ "?^map", "?^ngMap" ], + link: linkFunc + }; + }; + directions.$inject = [ "Attr2MapOptions", "$timeout", "NavigatorGeolocation", "NgMap" ]; + angular.module("ngMap").directive("directions", directions); +})(); + +(function() { + "use strict"; + angular.module("ngMap").directive("drawingManager", [ "Attr2MapOptions", function(Attr2MapOptions) { + var parser = Attr2MapOptions; + return { + restrict: "E", + require: [ "?^map", "?^ngMap" ], + link: function(scope, element, attrs, mapController) { + mapController = mapController[0] || mapController[1]; + var filtered = parser.filter(attrs); + var options = parser.getOptions(filtered); + var controlOptions = parser.getControlOptions(filtered); + var events = parser.getEvents(scope, filtered); + void 0; + var drawingManager = new google.maps.drawing.DrawingManager({ + drawingMode: options.drawingmode, + drawingControl: options.drawingcontrol, + drawingControlOptions: controlOptions.drawingControlOptions, + circleOptions: options.circleoptions, + markerOptions: options.markeroptions, + polygonOptions: options.polygonoptions, + polylineOptions: options.polylineoptions, + rectangleOptions: options.rectangleoptions + }); + for (var eventName in events) { + google.maps.event.addListener(drawingManager, eventName, events[eventName]); + } + mapController.addObject("mapDrawingManager", drawingManager); + } + }; + } ]); +})(); + +(function() { + "use strict"; + angular.module("ngMap").directive("dynamicMapsEngineLayer", [ "Attr2MapOptions", function(Attr2MapOptions) { + var parser = Attr2MapOptions; + var getDynamicMapsEngineLayer = function(options, events) { + var layer = new google.maps.visualization.DynamicMapsEngineLayer(options); + for (var eventName in events) { + google.maps.event.addListener(layer, eventName, events[eventName]); + } + return layer; + }; + return { + restrict: "E", + require: [ "?^map", "?^ngMap" ], + link: function(scope, element, attrs, mapController) { + mapController = mapController[0] || mapController[1]; + var filtered = parser.filter(attrs); + var options = parser.getOptions(filtered); + var events = parser.getEvents(scope, filtered, events); + void 0; + var layer = getDynamicMapsEngineLayer(options, events); + mapController.addObject("mapsEngineLayers", layer); + } + }; + } ]); +})(); + +(function() { + "use strict"; + angular.module("ngMap").directive("fusionTablesLayer", [ "Attr2MapOptions", function(Attr2MapOptions) { + var parser = Attr2MapOptions; + var getLayer = function(options, events) { + var layer = new google.maps.FusionTablesLayer(options); + for (var eventName in events) { + google.maps.event.addListener(layer, eventName, events[eventName]); + } + return layer; + }; + return { + restrict: "E", + require: [ "?^map", "?^ngMap" ], + link: function(scope, element, attrs, mapController) { + mapController = mapController[0] || mapController[1]; + var filtered = parser.filter(attrs); + var options = parser.getOptions(filtered); + var events = parser.getEvents(scope, filtered, events); + void 0; + var layer = getLayer(options, events); + mapController.addObject("fusionTablesLayers", layer); + } + }; + } ]); +})(); + +(function() { + "use strict"; + angular.module("ngMap").directive("heatmapLayer", [ "Attr2MapOptions", "$window", function(Attr2MapOptions, $window) { + var parser = Attr2MapOptions; + return { + restrict: "E", + require: [ "?^map", "?^ngMap" ], + link: function(scope, element, attrs, mapController) { + mapController = mapController[0] || mapController[1]; + var filtered = parser.filter(attrs); + var options = parser.getOptions(filtered); + options.data = $window[attrs.data] || scope[attrs.data]; + if (options.data instanceof Array) { + options.data = new google.maps.MVCArray(options.data); + } else { + throw "invalid heatmap data"; } - function flatten(tree) { - var result = []; - var queue = []; - var i; - for (i = 0; i < tree.children.length; i++) { - queue.push(tree.children[i]); + var layer = new google.maps.visualization.HeatmapLayer(options); + var events = parser.getEvents(scope, filtered); + void 0; + mapController.addObject("heatmapLayers", layer); + } + }; + } ]); +})(); + +(function() { + "use strict"; + var infoWindow = function(Attr2MapOptions, $compile, $timeout, $parse, NgMap) { + var parser = Attr2MapOptions; + var getInfoWindow = function(options, events, element) { + var infoWindow; + if (options.position && !(options.position instanceof google.maps.LatLng)) { + delete options.position; + } + infoWindow = new google.maps.InfoWindow(options); + if (Object.keys(events).length > 0) { + void 0; + } + for (var eventName in events) { + if (eventName) { + google.maps.event.addListener(infoWindow, eventName, events[eventName]); + } + } + var template = element.html().trim(); + if (angular.element(template).length != 1) { + throw "info-window working as a template must have a container"; + } + infoWindow.__template = template.replace(/\s?ng-non-bindable[='"]+/, ""); + infoWindow.__open = function(map, scope, anchor) { + $timeout(function() { + anchor && (scope.anchor = anchor); + var el = $compile(infoWindow.__template)(scope); + infoWindow.setContent(el[0]); + scope.$apply(); + if (anchor && anchor.getPosition) { + infoWindow.open(map, anchor); + } else if (anchor && anchor instanceof google.maps.LatLng) { + infoWindow.open(map); + infoWindow.setPosition(anchor); + } else { + infoWindow.open(map); } - var remainingLevelEntries = queue.length; - var nextLevelEntries = 0; - var row = []; - for (i = 0; i < queue.length; i++) { - var entry = queue[i]; - if (remainingLevelEntries <= 0) { - remainingLevelEntries = nextLevelEntries; - nextLevelEntries = 0; - result.push(row); - row = []; + }); + }; + return infoWindow; + }; + var linkFunc = function(scope, element, attrs, mapController) { + mapController = mapController[0] || mapController[1]; + element.css("display", "none"); + var orgAttrs = parser.orgAttributes(element); + var filtered = parser.filter(attrs); + var options = parser.getOptions(filtered); + var events = parser.getEvents(scope, filtered); + void 0; + var address; + if (options.position && !(options.position instanceof google.maps.LatLng)) { + address = options.position; + } + var infoWindow = getInfoWindow(options, events, element); + if (address) { + NgMap.getGeoLocation(address).then(function(latlng) { + infoWindow.setPosition(latlng); + infoWindow.__open(mapController.map, scope, latlng); + var geoCallback = attrs.geoCallback; + geoCallback && $parse(geoCallback)(scope); + }); + } + mapController.addObject("infoWindows", infoWindow); + mapController.observeAttrSetObj(orgAttrs, attrs, infoWindow); + NgMap.getMap().then(function(map) { + infoWindow.visible && infoWindow.__open(map, scope); + if (infoWindow.visibleOnMarker) { + var markerId = infoWindow.visibleOnMarker; + infoWindow.__open(map, scope, map.markers[markerId]); + } + map.showInfoWindow = map.showInfoWindow || function(p1, p2, p3) { + var id = typeof p1 == "string" ? p1 : p2; + var marker = typeof p1 == "string" ? p2 : p3; + var infoWindow = mapController.map.infoWindows[id]; + var anchor = marker ? marker : this.getPosition ? this : null; + infoWindow.__open(mapController.map, scope, anchor); + if (mapController.singleInfoWindow) { + if (mapController.lastInfoWindow) { + scope.hideInfoWindow(mapController.lastInfoWindow); + } + mapController.lastInfoWindow = id; + } + }; + map.hideInfoWindow = scope.hideInfoWindow || function(p1, p2) { + var id = typeof p1 == "string" ? p1 : p2; + var infoWindow = mapController.map.infoWindows[id]; + infoWindow.close(); + }; + scope.showInfoWindow = map.showInfoWindow; + scope.hideInfoWindow = map.hideInfoWindow; + }); + }; + return { + restrict: "E", + require: [ "?^map", "?^ngMap" ], + link: linkFunc + }; + }; + infoWindow.$inject = [ "Attr2MapOptions", "$compile", "$timeout", "$parse", "NgMap" ]; + angular.module("ngMap").directive("infoWindow", infoWindow); +})(); + +(function() { + "use strict"; + angular.module("ngMap").directive("kmlLayer", [ "Attr2MapOptions", function(Attr2MapOptions) { + var parser = Attr2MapOptions; + var getKmlLayer = function(options, events) { + var kmlLayer = new google.maps.KmlLayer(options); + for (var eventName in events) { + google.maps.event.addListener(kmlLayer, eventName, events[eventName]); + } + return kmlLayer; + }; + return { + restrict: "E", + require: [ "?^map", "?^ngMap" ], + link: function(scope, element, attrs, mapController) { + mapController = mapController[0] || mapController[1]; + var orgAttrs = parser.orgAttributes(element); + var filtered = parser.filter(attrs); + var options = parser.getOptions(filtered); + var events = parser.getEvents(scope, filtered); + void 0; + var kmlLayer = getKmlLayer(options, events); + mapController.addObject("kmlLayers", kmlLayer); + mapController.observeAttrSetObj(orgAttrs, attrs, kmlLayer); + element.bind("$destroy", function() { + mapController.deleteObject("kmlLayers", kmlLayer); + }); + } + }; + } ]); +})(); + +(function() { + "use strict"; + angular.module("ngMap").directive("mapData", [ "Attr2MapOptions", "NgMap", function(Attr2MapOptions, NgMap) { + var parser = Attr2MapOptions; + return { + restrict: "E", + require: [ "?^map", "?^ngMap" ], + link: function(scope, element, attrs) { + var filtered = parser.filter(attrs); + var options = parser.getOptions(filtered); + var events = parser.getEvents(scope, filtered, events); + void 0; + NgMap.getMap().then(function(map) { + for (var key in options) { + var val = options[key]; + if (typeof scope[val] === "function") { + map.data[key](scope[val]); + } else { + map.data[key](val); } - row.push(entry.fn); - entry.children.forEach(function(childEntry) { - nextLevelEntries++; - queue.push(childEntry); - }); - remainingLevelEntries--; } - if (row.length) { - result.push(row); + for (var eventName in events) { + map.data.addListener(eventName, events[eventName]); } - return result; - } + }); } - return function(element, event, options) { - options = prepareAnimationOptions(options); - var isStructural = [ "enter", "move", "leave" ].indexOf(event) >= 0; - var runner = new $$AnimateRunner({ - end: function() { - close(); - }, - cancel: function() { - close(true); + }; + } ]); +})(); + +(function() { + "use strict"; + var $timeout, $compile, src, savedHtml; + var preLinkFunc = function(scope, element, attrs) { + var mapsUrl = attrs.mapLazyLoadParams || attrs.mapLazyLoad; + window.lazyLoadCallback = function() { + void 0; + $timeout(function() { + element.html(savedHtml); + $compile(element.contents())(scope); + }, 100); + }; + if (window.google === undefined || window.google.maps === undefined) { + var scriptEl = document.createElement("script"); + void 0; + scriptEl.src = mapsUrl + (mapsUrl.indexOf("?") > -1 ? "&" : "?") + "callback=lazyLoadCallback"; + document.body.appendChild(scriptEl); + } else { + element.html(savedHtml); + $compile(element.contents())(scope); + } + }; + var compileFunc = function(tElement, tAttrs) { + !tAttrs.mapLazyLoad && void 0; + savedHtml = tElement.html(); + src = tAttrs.mapLazyLoad; + if (document.querySelector('script[src="' + src + (src.indexOf("?") > -1 ? "&" : "?") + 'callback=lazyLoadCallback"]')) { + return false; + } + tElement.html(""); + return { + pre: preLinkFunc + }; + }; + var mapLazyLoad = function(_$compile_, _$timeout_) { + $compile = _$compile_, $timeout = _$timeout_; + return { + compile: compileFunc + }; + }; + mapLazyLoad.$inject = [ "$compile", "$timeout" ]; + angular.module("ngMap").directive("mapLazyLoad", mapLazyLoad); +})(); + +(function() { + "use strict"; + angular.module("ngMap").directive("mapType", [ "$parse", "NgMap", function($parse, NgMap) { + return { + restrict: "E", + require: [ "?^map", "?^ngMap" ], + link: function(scope, element, attrs, mapController) { + mapController = mapController[0] || mapController[1]; + var mapTypeName = attrs.name, mapTypeObject; + if (!mapTypeName) { + throw "invalid map-type name"; + } + mapTypeObject = $parse(attrs.object)(scope); + if (!mapTypeObject) { + throw "invalid map-type object"; + } + NgMap.getMap().then(function(map) { + map.mapTypes.set(mapTypeName, mapTypeObject); + }); + mapController.addObject("mapTypes", mapTypeObject); + } + }; + } ]); +})(); + +(function() { + "use strict"; + var mapDirective = function() { + return { + restrict: "AE", + controller: "__MapController", + conrollerAs: "ngmap" + }; + }; + angular.module("ngMap").directive("map", [ mapDirective ]); + angular.module("ngMap").directive("ngMap", [ mapDirective ]); +})(); + +(function() { + "use strict"; + angular.module("ngMap").directive("mapsEngineLayer", [ "Attr2MapOptions", function(Attr2MapOptions) { + var parser = Attr2MapOptions; + var getMapsEngineLayer = function(options, events) { + var layer = new google.maps.visualization.MapsEngineLayer(options); + for (var eventName in events) { + google.maps.event.addListener(layer, eventName, events[eventName]); + } + return layer; + }; + return { + restrict: "E", + require: [ "?^map", "?^ngMap" ], + link: function(scope, element, attrs, mapController) { + mapController = mapController[0] || mapController[1]; + var filtered = parser.filter(attrs); + var options = parser.getOptions(filtered); + var events = parser.getEvents(scope, filtered, events); + void 0; + var layer = getMapsEngineLayer(options, events); + mapController.addObject("mapsEngineLayers", layer); + } + }; + } ]); +})(); + +(function() { + "use strict"; + var parser, $parse, NgMap; + var getMarker = function(options, events) { + var marker; + if (NgMap.defaultOptions.marker) { + for (var key in NgMap.defaultOptions.marker) { + if (typeof options[key] == "undefined") { + void 0; + options[key] = NgMap.defaultOptions.marker[key]; + } + } + } + if (!(options.position instanceof google.maps.LatLng)) { + options.position = new google.maps.LatLng(0, 0); + } + marker = new google.maps.Marker(options); + if (Object.keys(events).length > 0) { + void 0; + } + for (var eventName in events) { + if (eventName) { + google.maps.event.addListener(marker, eventName, events[eventName]); + } + } + return marker; + }; + var linkFunc = function(scope, element, attrs, mapController) { + mapController = mapController[0] || mapController[1]; + var orgAttrs = parser.orgAttributes(element); + var filtered = parser.filter(attrs); + var markerOptions = parser.getOptions(filtered, scope); + var markerEvents = parser.getEvents(scope, filtered); + void 0; + var address; + if (!(markerOptions.position instanceof google.maps.LatLng)) { + address = markerOptions.position; + } + var marker = getMarker(markerOptions, markerEvents); + mapController.addObject("markers", marker); + if (address) { + NgMap.getGeoLocation(address).then(function(latlng) { + marker.setPosition(latlng); + markerOptions.centered && marker.map.setCenter(latlng); + var geoCallback = attrs.geoCallback; + geoCallback && $parse(geoCallback)(scope); + }); + } + mapController.observeAttrSetObj(orgAttrs, attrs, marker); + element.bind("$destroy", function() { + mapController.deleteObject("markers", marker); + }); + }; + var marker = function(Attr2MapOptions, _$parse_, _NgMap_) { + parser = Attr2MapOptions; + $parse = _$parse_; + NgMap = _NgMap_; + return { + restrict: "E", + require: [ "^?map", "?^ngMap" ], + link: linkFunc + }; + }; + marker.$inject = [ "Attr2MapOptions", "$parse", "NgMap" ]; + angular.module("ngMap").directive("marker", marker); +})(); + +(function() { + "use strict"; + angular.module("ngMap").directive("overlayMapType", [ "NgMap", function(NgMap) { + return { + restrict: "E", + require: [ "?^map", "?^ngMap" ], + link: function(scope, element, attrs, mapController) { + mapController = mapController[0] || mapController[1]; + var initMethod = attrs.initMethod || "insertAt"; + var overlayMapTypeObject = scope[attrs.object]; + NgMap.getMap().then(function(map) { + if (initMethod == "insertAt") { + var index = parseInt(attrs.index, 10); + map.overlayMapTypes.insertAt(index, overlayMapTypeObject); + } else if (initMethod == "push") { + map.overlayMapTypes.push(overlayMapTypeObject); } }); - if (!drivers.length) { - close(); - return runner; - } - setRunner(element, runner); - var classes = mergeClasses(element.attr("class"), mergeClasses(options.addClass, options.removeClass)); - var tempClasses = options.tempClasses; - if (tempClasses) { - classes += " " + tempClasses; - options.tempClasses = null; + mapController.addObject("overlayMapTypes", overlayMapTypeObject); + } + }; + } ]); +})(); + +(function() { + "use strict"; + var placesAutoComplete = function(Attr2MapOptions, $timeout) { + var parser = Attr2MapOptions; + var linkFunc = function(scope, element, attrs, ngModelCtrl) { + if (attrs.placesAutoComplete === "false") { + return false; + } + var filtered = parser.filter(attrs); + var options = parser.getOptions(filtered); + var events = parser.getEvents(scope, filtered); + void 0; + var autocomplete = new google.maps.places.Autocomplete(element[0], options); + for (var eventName in events) { + google.maps.event.addListener(autocomplete, eventName, events[eventName]); + } + var updateModel = function() { + $timeout(function() { + ngModelCtrl && ngModelCtrl.$setViewValue(element.val()); + }, 100); + }; + google.maps.event.addListener(autocomplete, "place_changed", updateModel); + element[0].addEventListener("change", updateModel); + attrs.$observe("types", function(val) { + if (val) { + void 0; + var optionValue = parser.toOptionValue(val, { + key: "types" + }); + void 0; + autocomplete.setTypes(optionValue); } - animationQueue.push({ - element: element, - classes: classes, - event: event, - structural: isStructural, - options: options, - beforeStart: beforeStart, - close: close + }); + }; + return { + restrict: "A", + require: "?ngModel", + link: linkFunc + }; + }; + placesAutoComplete.$inject = [ "Attr2MapOptions", "$timeout" ]; + angular.module("ngMap").directive("placesAutoComplete", placesAutoComplete); +})(); + +(function() { + "use strict"; + var getShape = function(options, events) { + var shape; + var shapeName = options.name; + delete options.name; + void 0; + switch (shapeName) { + case "circle": + if (!(options.center instanceof google.maps.LatLng)) { + options.center = new google.maps.LatLng(0, 0); + } + shape = new google.maps.Circle(options); + break; + + case "polygon": + shape = new google.maps.Polygon(options); + break; + + case "polyline": + shape = new google.maps.Polyline(options); + break; + + case "rectangle": + shape = new google.maps.Rectangle(options); + break; + + case "groundOverlay": + case "image": + var url = options.url; + var opts = { + opacity: options.opacity, + clickable: options.clickable, + id: options.id + }; + shape = new google.maps.GroundOverlay(url, options.bounds, opts); + break; + } + for (var eventName in events) { + if (events[eventName]) { + google.maps.event.addListener(shape, eventName, events[eventName]); + } + } + return shape; + }; + var shape = function(Attr2MapOptions, $parse, NgMap) { + var parser = Attr2MapOptions; + var linkFunc = function(scope, element, attrs, mapController) { + mapController = mapController[0] || mapController[1]; + var orgAttrs = parser.orgAttributes(element); + var filtered = parser.filter(attrs); + var shapeOptions = parser.getOptions(filtered); + var shapeEvents = parser.getEvents(scope, filtered); + var address, shapeType; + shapeType = shapeOptions.name; + if (!(shapeOptions.center instanceof google.maps.LatLng)) { + address = shapeOptions.center; + } + var shape = getShape(shapeOptions, shapeEvents); + mapController.addObject("shapes", shape); + if (address && shapeType == "circle") { + NgMap.getGeoLocation(address).then(function(latlng) { + shape.setCenter(latlng); + shape.centered && shape.map.setCenter(latlng); + var geoCallback = attrs.geoCallback; + geoCallback && $parse(geoCallback)(scope); }); - element.on("$destroy", handleDestroyedElement); - if (animationQueue.length > 1) return runner; - $rootScope.$$postDigest(function() { - var animations = []; - forEach(animationQueue, function(entry) { - if (getRunner(entry.element)) { - animations.push(entry); - } else { - entry.close(); - } - }); - animationQueue.length = 0; - var groupedAnimations = groupAnimations(animations); - var toBeSortedAnimations = []; - forEach(groupedAnimations, function(animationEntry) { - toBeSortedAnimations.push({ - domNode: getDomNode(animationEntry.from ? animationEntry.from.element : animationEntry.element), - fn: function triggerAnimationStart() { - animationEntry.beforeStart(); - var startAnimationFn, closeFn = animationEntry.close; - var targetElement = animationEntry.anchors ? animationEntry.from.element || animationEntry.to.element : animationEntry.element; - if (getRunner(targetElement)) { - var operation = invokeFirstDriver(animationEntry); - if (operation) { - startAnimationFn = operation.start; - } - } - if (!startAnimationFn) { - closeFn(); - } else { - var animationRunner = startAnimationFn(); - animationRunner.done(function(status) { - closeFn(!status); - }); - updateAnimationRunners(animationEntry, animationRunner); - } - } - }); - }); - $$rAFScheduler(sortAnimations(toBeSortedAnimations)); + } + mapController.observeAttrSetObj(orgAttrs, attrs, shape); + element.bind("$destroy", function() { + mapController.deleteObject("shapes", shape); + }); + }; + return { + restrict: "E", + require: [ "?^map", "?^ngMap" ], + link: linkFunc + }; + }; + shape.$inject = [ "Attr2MapOptions", "$parse", "NgMap" ]; + angular.module("ngMap").directive("shape", shape); +})(); + +(function() { + "use strict"; + var streetViewPanorama = function(Attr2MapOptions, NgMap) { + var parser = Attr2MapOptions; + var getStreetViewPanorama = function(map, options, events) { + var svp, container; + if (options.container) { + container = document.getElementById(options.container); + container = container || document.querySelector(options.container); + } + if (container) { + svp = new google.maps.StreetViewPanorama(container, options); + } else { + svp = map.getStreetView(); + svp.setOptions(options); + } + for (var eventName in events) { + eventName && google.maps.event.addListener(svp, eventName, events[eventName]); + } + return svp; + }; + var linkFunc = function(scope, element, attrs) { + var filtered = parser.filter(attrs); + var options = parser.getOptions(filtered); + var controlOptions = parser.getControlOptions(filtered); + var svpOptions = angular.extend(options, controlOptions); + var svpEvents = parser.getEvents(scope, filtered); + void 0; + NgMap.getMap().then(function(map) { + var svp = getStreetViewPanorama(map, svpOptions, svpEvents); + map.setStreetView(svp); + !svp.getPosition() && svp.setPosition(map.getCenter()); + google.maps.event.addListener(svp, "position_changed", function() { + if (svp.getPosition() !== map.getCenter()) { + map.setCenter(svp.getPosition()); + } + }); + var listener = google.maps.event.addListener(map, "center_changed", function() { + svp.setPosition(map.getCenter()); + google.maps.event.removeListener(listener); + }); + }); + }; + return { + restrict: "E", + require: [ "?^map", "?^ngMap" ], + link: linkFunc + }; + }; + streetViewPanorama.$inject = [ "Attr2MapOptions", "NgMap" ]; + angular.module("ngMap").directive("streetViewPanorama", streetViewPanorama); +})(); + +(function() { + "use strict"; + angular.module("ngMap").directive("trafficLayer", [ "Attr2MapOptions", function(Attr2MapOptions) { + var parser = Attr2MapOptions; + var getLayer = function(options, events) { + var layer = new google.maps.TrafficLayer(options); + for (var eventName in events) { + google.maps.event.addListener(layer, eventName, events[eventName]); + } + return layer; + }; + return { + restrict: "E", + require: [ "?^map", "?^ngMap" ], + link: function(scope, element, attrs, mapController) { + mapController = mapController[0] || mapController[1]; + var orgAttrs = parser.orgAttributes(element); + var filtered = parser.filter(attrs); + var options = parser.getOptions(filtered); + var events = parser.getEvents(scope, filtered); + void 0; + var layer = getLayer(options, events); + mapController.addObject("trafficLayers", layer); + mapController.observeAttrSetObj(orgAttrs, attrs, layer); + element.bind("$destroy", function() { + mapController.deleteObject("trafficLayers", layer); + }); + } + }; + } ]); +})(); + +(function() { + "use strict"; + angular.module("ngMap").directive("transitLayer", [ "Attr2MapOptions", function(Attr2MapOptions) { + var parser = Attr2MapOptions; + var getLayer = function(options, events) { + var layer = new google.maps.TransitLayer(options); + for (var eventName in events) { + google.maps.event.addListener(layer, eventName, events[eventName]); + } + return layer; + }; + return { + restrict: "E", + require: [ "?^map", "?^ngMap" ], + link: function(scope, element, attrs, mapController) { + mapController = mapController[0] || mapController[1]; + var orgAttrs = parser.orgAttributes(element); + var filtered = parser.filter(attrs); + var options = parser.getOptions(filtered); + var events = parser.getEvents(scope, filtered); + void 0; + var layer = getLayer(options, events); + mapController.addObject("transitLayers", layer); + mapController.observeAttrSetObj(orgAttrs, attrs, layer); + element.bind("$destroy", function() { + mapController.deleteObject("transitLayers", layer); }); - return runner; - function getAnchorNodes(node) { - var SELECTOR = "[" + NG_ANIMATE_REF_ATTR + "]"; - var items = node.hasAttribute(NG_ANIMATE_REF_ATTR) ? [ node ] : node.querySelectorAll(SELECTOR); - var anchors = []; - forEach(items, function(node) { - var attr = node.getAttribute(NG_ANIMATE_REF_ATTR); - if (attr && attr.length) { - anchors.push(node); - } - }); - return anchors; - } - function groupAnimations(animations) { - var preparedAnimations = []; - var refLookup = {}; - forEach(animations, function(animation, index) { - var element = animation.element; - var node = getDomNode(element); - var event = animation.event; - var enterOrMove = [ "enter", "move" ].indexOf(event) >= 0; - var anchorNodes = animation.structural ? getAnchorNodes(node) : []; - if (anchorNodes.length) { - var direction = enterOrMove ? "to" : "from"; - forEach(anchorNodes, function(anchor) { - var key = anchor.getAttribute(NG_ANIMATE_REF_ATTR); - refLookup[key] = refLookup[key] || {}; - refLookup[key][direction] = { - animationID: index, - element: jqLite(anchor) - }; - }); + } + }; + } ]); +})(); + +(function() { + "use strict"; + var SPECIAL_CHARS_REGEXP = /([\:\-\_]+(.))/g; + var MOZ_HACK_REGEXP = /^moz([A-Z])/; + var camelCaseFilter = function() { + return function(name) { + return name.replace(SPECIAL_CHARS_REGEXP, function(_, separator, letter, offset) { + return offset ? letter.toUpperCase() : letter; + }).replace(MOZ_HACK_REGEXP, "Moz$1"); + }; + }; + angular.module("ngMap").filter("camelCase", camelCaseFilter); +})(); + +(function() { + "use strict"; + var jsonizeFilter = function() { + return function(str) { + try { + JSON.parse(str); + return str; + } catch (e) { + return str.replace(/([\$\w]+)\s*:/g, function(_, $1) { + return '"' + $1 + '":'; + }).replace(/'([^']+)'/g, function(_, $1) { + return '"' + $1 + '"'; + }); + } + }; + }; + angular.module("ngMap").filter("jsonize", jsonizeFilter); +})(); + +(function() { + "use strict"; + var isoDateRE = /^(\d{4}\-\d\d\-\d\d([tT][\d:\.]*)?)([zZ]|([+\-])(\d\d):?(\d\d))?$/; + var Attr2MapOptions = function($parse, $timeout, $log, NavigatorGeolocation, GeoCoder, camelCaseFilter, jsonizeFilter) { + var orgAttributes = function(el) { + el.length > 0 && (el = el[0]); + var orgAttributes = {}; + for (var i = 0; i < el.attributes.length; i++) { + var attr = el.attributes[i]; + orgAttributes[attr.name] = attr.value; + } + return orgAttributes; + }; + var getJSON = function(input) { + var re = /^[\+\-]?[0-9\.]+,[ ]*\ ?[\+\-]?[0-9\.]+$/; + if (input.match(re)) { + input = "[" + input + "]"; + } + return JSON.parse(jsonizeFilter(input)); + }; + var getLatLng = function(input) { + var output = input; + if (input[0].constructor == Array) { + output = input.map(function(el) { + return new google.maps.LatLng(el[0], el[1]); + }); + } else if (!isNaN(parseFloat(input[0])) && isFinite(input[0])) { + output = new google.maps.LatLng(output[0], output[1]); + } + return output; + }; + var toOptionValue = function(input, options) { + var output; + try { + output = getNumber(input); + } catch (err) { + try { + var output = getJSON(input); + if (output instanceof Array) { + if (output[0].constructor == Object) { + output = output; } else { - preparedAnimations.push(animation); + output = getLatLng(output); } - }); - var usedIndicesLookup = {}; - var anchorGroups = {}; - forEach(refLookup, function(operations, key) { - var from = operations.from; - var to = operations.to; - if (!from || !to) { - var index = from ? from.animationID : to.animationID; - var indexKey = index.toString(); - if (!usedIndicesLookup[indexKey]) { - usedIndicesLookup[indexKey] = true; - preparedAnimations.push(animations[index]); - } - return; + } else if (output === Object(output)) { + var newOptions = options; + newOptions.doNotConverStringToNumber = true; + output = getOptions(output, newOptions); + } + } catch (err2) { + if (input.match(/^[A-Z][a-zA-Z0-9]+\(.*\)$/)) { + try { + var exp = "new google.maps." + input; + output = eval(exp); + } catch (e) { + output = input; } - var fromAnimation = animations[from.animationID]; - var toAnimation = animations[to.animationID]; - var lookupKey = from.animationID.toString(); - if (!anchorGroups[lookupKey]) { - var group = anchorGroups[lookupKey] = { - structural: true, - beforeStart: function() { - fromAnimation.beforeStart(); - toAnimation.beforeStart(); - }, - close: function() { - fromAnimation.close(); - toAnimation.close(); - }, - classes: cssClassesIntersection(fromAnimation.classes, toAnimation.classes), - from: fromAnimation, - to: toAnimation, - anchors: [] - }; - if (group.classes.length) { - preparedAnimations.push(group); + } else if (input.match(/^([A-Z][a-zA-Z0-9]+)\.([A-Z]+)$/)) { + try { + var matches = input.match(/^([A-Z][a-zA-Z0-9]+)\.([A-Z]+)$/); + output = google.maps[matches[1]][matches[2]]; + } catch (e) { + output = input; + } + } else if (input.match(/^[A-Z]+$/)) { + try { + var capitalizedKey = options.key.charAt(0).toUpperCase() + options.key.slice(1); + if (options.key.match(/temperatureUnit|windSpeedUnit|labelColor/)) { + capitalizedKey = capitalizedKey.replace(/s$/, ""); + output = google.maps.weather[capitalizedKey][input]; } else { - preparedAnimations.push(fromAnimation); - preparedAnimations.push(toAnimation); + output = google.maps[capitalizedKey][input]; } + } catch (e) { + output = input; } - anchorGroups[lookupKey].anchors.push({ - out: from.element, - "in": to.element - }); - }); - return preparedAnimations; - } - function cssClassesIntersection(a, b) { - a = a.split(" "); - b = b.split(" "); - var matches = []; - for (var i = 0; i < a.length; i++) { - var aa = a[i]; - if (aa.substring(0, 3) === "ng-") continue; - for (var j = 0; j < b.length; j++) { - if (aa === b[j]) { - matches.push(aa); - break; - } + } else if (input.match(isoDateRE)) { + try { + output = new Date(input); + } catch (e) { + output = input; } + } else { + output = input; } - return matches.join(" "); } - function invokeFirstDriver(animationDetails) { - for (var i = drivers.length - 1; i >= 0; i--) { - var driverName = drivers[i]; - if (!$injector.has(driverName)) continue; - var factory = $injector.get(driverName); - var driver = factory(animationDetails); - if (driver) { - return driver; - } + } + if (options.key == "bounds" && output instanceof Array) { + output = new google.maps.LatLngBounds(output[0], output[1]); + } + if (options.key == "icons" && output instanceof Array) { + for (var i = 0; i < output.length; i++) { + var el = output[i]; + if (el.icon.path.match(/^[A-Z_]+$/)) { + el.icon.path = google.maps.SymbolPath[el.icon.path]; } } - function beforeStart() { - element.addClass(NG_ANIMATE_CLASSNAME); - if (tempClasses) { - $$jqLite.addClass(element, tempClasses); + } + if (options.key == "icon" && output instanceof Object) { + if (("" + output.path).match(/^[A-Z_]+$/)) { + output.path = google.maps.SymbolPath[output.path]; + } + for (var key in output) { + var arr = output[key]; + if (key == "anchor" || key == "origin") { + output[key] = new google.maps.Point(arr[0], arr[1]); + } else if (key == "size" || key == "scaledSize") { + output[key] = new google.maps.Size(arr[0], arr[1]); } } - function updateAnimationRunners(animation, newRunner) { - if (animation.from && animation.to) { - update(animation.from.element); - update(animation.to.element); + } + return output; + }; + var getAttrsToObserve = function(attrs) { + var attrsToObserve = []; + if (!attrs.noWatcher) { + for (var attrName in attrs) { + var attrValue = attrs[attrName]; + void 0; + if (attrValue && attrValue.match(/\{\{.*\}\}/)) { + void 0; + attrsToObserve.push(camelCaseFilter(attrName)); + } + } + } + return attrsToObserve; + }; + var filter = function(attrs) { + var options = {}; + for (var key in attrs) { + if (key.match(/^\$/) || key.match(/^ng[A-Z]/)) { + void 0; + } else { + options[key] = attrs[key]; + } + } + return options; + }; + var getOptions = function(attrs, params) { + var options = {}; + for (var key in attrs) { + if (attrs[key] || attrs[key] === 0) { + if (key.match(/^on[A-Z]/)) { + continue; + } else if (key.match(/ControlOptions$/)) { + continue; } else { - update(animation.element); + if (typeof attrs[key] !== "string") { + options[key] = attrs[key]; + } else { + if (params && params.doNotConverStringToNumber && attrs[key].match(/^[0-9]+$/)) { + options[key] = attrs[key]; + } else { + options[key] = toOptionValue(attrs[key], { + key: key + }); + } + } } - function update(element) { - getRunner(element).setHost(newRunner); + } + } + return options; + }; + var getEvents = function(scope, attrs) { + var events = {}; + var toLowercaseFunc = function($1) { + return "_" + $1.toLowerCase(); + }; + var EventFunc = function(attrValue) { + var matches = attrValue.match(/([^\(]+)\(([^\)]*)\)/); + var funcName = matches[1]; + var argsStr = matches[2].replace(/event[ ,]*/, ""); + var argsExpr = $parse("[" + argsStr + "]"); + return function(event) { + var args = argsExpr(scope); + function index(obj, i) { + return obj[i]; + } + var f = funcName.split(".").reduce(index, scope); + f && f.apply(this, [ event ].concat(args)); + $timeout(function() { + scope.$apply(); + }); + }; + }; + for (var key in attrs) { + if (attrs[key]) { + if (!key.match(/^on[A-Z]/)) { + continue; } + var eventName = key.replace(/^on/, ""); + eventName = eventName.charAt(0).toLowerCase() + eventName.slice(1); + eventName = eventName.replace(/([A-Z])/g, toLowercaseFunc); + var attrValue = attrs[key]; + events[eventName] = new EventFunc(attrValue); } - function handleDestroyedElement() { - var runner = getRunner(element); - if (runner && (event !== "leave" || !options.$$domOperationFired)) { - runner.end(); + } + return events; + }; + var getControlOptions = function(filtered) { + var controlOptions = {}; + if (typeof filtered != "object") { + return false; + } + for (var attr in filtered) { + if (filtered[attr]) { + if (!attr.match(/(.*)ControlOptions$/)) { + continue; + } + var orgValue = filtered[attr]; + var newValue = orgValue.replace(/'/g, '"'); + newValue = newValue.replace(/([^"]+)|("[^"]+")/g, function($0, $1, $2) { + if ($1) { + return $1.replace(/([a-zA-Z0-9]+?):/g, '"$1":'); + } else { + return $2; + } + }); + try { + var options = JSON.parse(newValue); + for (var key in options) { + if (options[key]) { + var value = options[key]; + if (typeof value === "string") { + value = value.toUpperCase(); + } else if (key === "mapTypeIds") { + value = value.map(function(str) { + if (str.match(/^[A-Z]+$/)) { + return google.maps.MapTypeId[str.toUpperCase()]; + } else { + return str; + } + }); + } + if (key === "style") { + var str = attr.charAt(0).toUpperCase() + attr.slice(1); + var objName = str.replace(/Options$/, "") + "Style"; + options[key] = google.maps[objName][value]; + } else if (key === "position") { + options[key] = google.maps.ControlPosition[value]; + } else { + options[key] = value; + } + } + } + controlOptions[attr] = options; + } catch (e) { + void 0; } } - function close(rejected) { - element.off("$destroy", handleDestroyedElement); - removeRunner(element); - applyAnimationClasses(element, options); - applyAnimationStyles(element, options); - options.domOperation(); - if (tempClasses) { - $$jqLite.removeClass(element, tempClasses); + } + return controlOptions; + }; + return { + filter: filter, + getOptions: getOptions, + getEvents: getEvents, + getControlOptions: getControlOptions, + toOptionValue: toOptionValue, + getAttrsToObserve: getAttrsToObserve, + orgAttributes: orgAttributes + }; + }; + Attr2MapOptions.$inject = [ "$parse", "$timeout", "$log", "NavigatorGeolocation", "GeoCoder", "camelCaseFilter", "jsonizeFilter" ]; + angular.module("ngMap").service("Attr2MapOptions", Attr2MapOptions); +})(); + +(function() { + "use strict"; + var $q; + var geocodeFunc = function(options) { + var deferred = $q.defer(); + var geocoder = new google.maps.Geocoder(); + geocoder.geocode(options, function(results, status) { + if (status == google.maps.GeocoderStatus.OK) { + deferred.resolve(results); + } else { + deferred.reject(status); + } + }); + return deferred.promise; + }; + var GeoCoder = function(_$q_) { + $q = _$q_; + return { + geocode: geocodeFunc + }; + }; + GeoCoder.$inject = [ "$q" ]; + angular.module("ngMap").service("GeoCoder", GeoCoder); +})(); + +(function() { + "use strict"; + var $q; + var getCurrentPosition = function(geoLocationOptions) { + var deferred = $q.defer(); + if (navigator.geolocation) { + if (geoLocationOptions === undefined) { + geoLocationOptions = { + timeout: 5e3 + }; + } else if (geoLocationOptions.timeout === undefined) { + geoLocationOptions.timeout = 5e3; + } + navigator.geolocation.getCurrentPosition(function(position) { + deferred.resolve(position); + }, function(evt) { + void 0; + deferred.reject(evt); + }, geoLocationOptions); + } else { + deferred.reject("Browser Geolocation service failed."); + } + return deferred.promise; + }; + var NavigatorGeolocation = function(_$q_) { + $q = _$q_; + return { + getCurrentPosition: getCurrentPosition + }; + }; + NavigatorGeolocation.$inject = [ "$q" ]; + angular.module("ngMap").service("NavigatorGeolocation", NavigatorGeolocation); +})(); + +(function() { + "use strict"; + var $window, $document, $q; + var NavigatorGeolocation, Attr2MapOptions, GeoCoder, camelCaseFilter; + var mapControllers = {}; + var initMap = function(id) { + var ctrl = mapControllers[id || 0]; + ctrl.initializeMap(); + }; + var getMap = function(options) { + options = options || {}; + var deferred = $q.defer(); + var id = options.id || 0; + var timeout = options.timeout || 2e3; + function waitForMap(timeElapsed) { + if (mapControllers[id]) { + deferred.resolve(mapControllers[id].map); + } else if (timeElapsed > timeout) { + deferred.reject("could not find map"); + } else { + $window.setTimeout(function() { + waitForMap(timeElapsed + 100); + }, 100); + } + } + waitForMap(0); + return deferred.promise; + }; + var addMap = function(mapCtrl) { + var len = Object.keys(mapControllers).length; + mapControllers[mapCtrl.map.id || len] = mapCtrl; + }; + var deleteMap = function(mapCtrl) { + var len = Object.keys(mapControllers).length - 1; + delete mapControllers[mapCtrl.map.id || len]; + }; + var getStyle = function(el, styleProp) { + var y; + if (el.currentStyle) { + y = el.currentStyle[styleProp]; + } else if ($window.getComputedStyle) { + y = $document.defaultView.getComputedStyle(el, null).getPropertyValue(styleProp); + } + return y; + }; + var getNgMapDiv = function(ngMapEl) { + var el = $document.createElement("div"); + var defaultStyle = ngMapEl.getAttribute("default-style"); + el.style.width = "100%"; + el.style.height = "100%"; + if (defaultStyle == "true") { + ngMapEl.style.display = "block"; + ngMapEl.style.height = "300px"; + } else { + if (getStyle(ngMapEl, "display") != "block") { + ngMapEl.style.display = "block"; + } + if (getStyle(ngMapEl, "height").match(/^(0|auto)/)) { + ngMapEl.style.height = "300px"; + } + } + el.addEventListener("dragstart", function(event) { + event.preventDefault(); + return false; + }); + return el; + }; + var getGeoLocation = function(string, options) { + var deferred = $q.defer(); + if (!string || string.match(/^current/i)) { + NavigatorGeolocation.getCurrentPosition(options).then(function(position) { + var lat = position.coords.latitude; + var lng = position.coords.longitude; + var latLng = new google.maps.LatLng(lat, lng); + deferred.resolve(latLng); + }, function(error) { + deferred.reject(error); + }); + } else { + GeoCoder.geocode({ + address: string + }).then(function(results) { + deferred.resolve(results[0].geometry.location); + }, function(error) { + deferred.reject(error); + }); + } + return deferred.promise; + }; + var observeAndSet = function(attrName, object) { + return function(val) { + if (val) { + void 0; + var setMethod = camelCaseFilter("set-" + attrName); + var optionValue = Attr2MapOptions.toOptionValue(val, { + key: attrName + }); + void 0; + if (object[setMethod]) { + if (attrName.match(/center|position/) && typeof optionValue == "string") { + getGeoLocation(optionValue).then(function(latlng) { + object[setMethod](latlng); + }); + } else { + object[setMethod](optionValue); } - element.removeClass(NG_ANIMATE_CLASSNAME); - runner.complete(!rejected); } - }; - } ]; - } ]; - angular.module("ngAnimate", []).provider("$$body", $$BodyProvider).directive("ngAnimateChildren", $$AnimateChildrenDirective).factory("$$rAFScheduler", $$rAFSchedulerFactory).factory("$$AnimateRunner", $$AnimateRunnerFactory).factory("$$animateAsyncRun", $$AnimateAsyncRunFactory).provider("$$animateQueue", $$AnimateQueueProvider).provider("$$animation", $$AnimationProvider).provider("$animateCss", $AnimateCssProvider).provider("$$animateCssDriver", $$AnimateCssDriverProvider).provider("$$animateJs", $$AnimateJsProvider).provider("$$animateJsDriver", $$AnimateJsDriverProvider); -})(window, window.angular); + } + }; + }; + angular.module("ngMap").provider("NgMap", function() { + var defaultOptions = {}; + var useTinfoilShielding = false; + this.setDefaultOptions = function(options) { + defaultOptions = options; + }; + var NgMap = function(_$window_, _$document_, _$q_, _NavigatorGeolocation_, _Attr2MapOptions_, _GeoCoder_, _camelCaseFilter_) { + $window = _$window_; + $document = _$document_[0]; + $q = _$q_; + NavigatorGeolocation = _NavigatorGeolocation_; + Attr2MapOptions = _Attr2MapOptions_; + GeoCoder = _GeoCoder_; + camelCaseFilter = _camelCaseFilter_; + return { + defaultOptions: defaultOptions, + addMap: addMap, + deleteMap: deleteMap, + getMap: getMap, + initMap: initMap, + getStyle: getStyle, + getNgMapDiv: getNgMapDiv, + getGeoLocation: getGeoLocation, + observeAndSet: observeAndSet + }; + }; + NgMap.$inject = [ "$window", "$document", "$q", "NavigatorGeolocation", "Attr2MapOptions", "GeoCoder", "camelCaseFilter" ]; + this.$get = NgMap; + }); +})(); + +(function() { + "use strict"; + var $q; + var getPanorama = function(map, latlng) { + latlng = latlng || map.getCenter(); + var deferred = $q.defer(); + var svs = new google.maps.StreetViewService(); + svs.getPanoramaByLocation(latlng || map.getCenter, 100, function(data, status) { + if (status === google.maps.StreetViewStatus.OK) { + deferred.resolve(data.location.pano); + } else { + deferred.resolve(false); + } + }); + return deferred.promise; + }; + var setPanorama = function(map, panoId) { + var svp = new google.maps.StreetViewPanorama(map.getDiv(), { + enableCloseButton: true + }); + svp.setPano(panoId); + }; + var StreetView = function(_$q_) { + $q = _$q_; + return { + getPanorama: getPanorama, + setPanorama: setPanorama + }; + }; + StreetView.$inject = [ "$q" ]; + angular.module("ngMap").service("StreetView", StreetView); +})(); -var app = angular.module("autocomplete", []); +"use strict"; -app.directive("autocomplete", function() { - var index = -1; - return { - restrict: "E", - scope: { - searchParam: "=ngModel", - suggestions: "=data", - onType: "=onType", - onSelect: "=onSelect", - autocompleteRequired: "=" - }, - controller: [ "$scope", function($scope) { - $scope.selectedIndex = -1; - $scope.initLock = true; - $scope.setIndex = function(i) { - $scope.selectedIndex = parseInt(i); - }; - this.setIndex = function(i) { - $scope.setIndex(i); - $scope.$apply(); - }; - $scope.getIndex = function(i) { - return $scope.selectedIndex; - }; - var watching = true; - $scope.completing = false; - $scope.$watch("searchParam", function(newValue, oldValue) { - if (oldValue === newValue || !oldValue && $scope.initLock) { - return; - } - if (watching && typeof $scope.searchParam !== "undefined" && $scope.searchParam !== null) { - $scope.completing = true; - $scope.searchFilter = $scope.searchParam; - $scope.selectedIndex = -1; - } - if ($scope.onType) $scope.onType($scope.searchParam); +var WaveSurfer = { + defaultParams: { + height: 128, + waveColor: "#999", + progressColor: "#555", + cursorColor: "#333", + cursorWidth: 1, + skipLength: 2, + minPxPerSec: 20, + pixelRatio: window.devicePixelRatio, + fillParent: !0, + scrollParent: !1, + hideScrollbar: !1, + normalize: !1, + audioContext: null, + container: null, + dragSelection: !0, + loopSelection: !0, + audioRate: 1, + interact: !0, + splitChannels: !1, + renderer: "Canvas", + backend: "WebAudio", + mediaType: "audio" + }, + init: function(a) { + if (this.params = WaveSurfer.util.extend({}, this.defaultParams, a), this.container = "string" == typeof a.container ? document.querySelector(this.params.container) : this.params.container, + !this.container) throw new Error("Container element not found"); + if ("undefined" == typeof this.params.mediaContainer ? this.mediaContainer = this.container : "string" == typeof this.params.mediaContainer ? this.mediaContainer = document.querySelector(this.params.mediaContainer) : this.mediaContainer = this.params.mediaContainer, + !this.mediaContainer) throw new Error("Media Container element not found"); + this.savedVolume = 0, this.isMuted = !1, this.tmpEvents = [], this.createDrawer(), + this.createBackend(); + }, + createDrawer: function() { + var a = this; + this.drawer = Object.create(WaveSurfer.Drawer[this.params.renderer]), this.drawer.init(this.container, this.params), + this.drawer.on("redraw", function() { + a.drawBuffer(), a.drawer.progress(a.backend.getPlayedPercents()); + }), this.drawer.on("click", function(b, c) { + setTimeout(function() { + a.seekTo(c); + }, 0); + }), this.drawer.on("scroll", function(b) { + a.fireEvent("scroll", b); + }); + }, + createBackend: function() { + var a = this; + this.backend && this.backend.destroy(), "AudioElement" == this.params.backend && (this.params.backend = "MediaElement"), + "WebAudio" != this.params.backend || WaveSurfer.WebAudio.supportsWebAudio() || (this.params.backend = "MediaElement"), + this.backend = Object.create(WaveSurfer[this.params.backend]), this.backend.init(this.params), + this.backend.on("finish", function() { + a.fireEvent("finish"); + }), this.backend.on("play", function() { + a.fireEvent("play"); + }), this.backend.on("pause", function() { + a.fireEvent("pause"); + }), this.backend.on("audioprocess", function(b) { + a.drawer.progress(a.backend.getPlayedPercents()), a.fireEvent("audioprocess", b); + }); + }, + getDuration: function() { + return this.backend.getDuration(); + }, + getCurrentTime: function() { + return this.backend.getCurrentTime(); + }, + play: function(a, b) { + this.backend.play(a, b); + }, + pause: function() { + this.backend.pause(); + }, + playPause: function() { + this.backend.isPaused() ? this.play() : this.pause(); + }, + isPlaying: function() { + return !this.backend.isPaused(); + }, + skipBackward: function(a) { + this.skip(-a || -this.params.skipLength); + }, + skipForward: function(a) { + this.skip(a || this.params.skipLength); + }, + skip: function(a) { + var b = this.getCurrentTime() || 0, c = this.getDuration() || 1; + b = Math.max(0, Math.min(c, b + (a || 0))), this.seekAndCenter(b / c); + }, + seekAndCenter: function(a) { + this.seekTo(a), this.drawer.recenter(a); + }, + seekTo: function(a) { + var b = this.backend.isPaused(), c = this.params.scrollParent; + b && (this.params.scrollParent = !1), this.backend.seekTo(a * this.getDuration()), + this.drawer.progress(this.backend.getPlayedPercents()), b || (this.backend.pause(), + this.backend.play()), this.params.scrollParent = c, this.fireEvent("seek", a); + }, + stop: function() { + this.pause(), this.seekTo(0), this.drawer.progress(0); + }, + setVolume: function(a) { + this.backend.setVolume(a); + }, + setPlaybackRate: function(a) { + this.backend.setPlaybackRate(a); + }, + toggleMute: function() { + this.isMuted ? (this.backend.setVolume(this.savedVolume), this.isMuted = !1) : (this.savedVolume = this.backend.getVolume(), + this.backend.setVolume(0), this.isMuted = !0); + }, + toggleScroll: function() { + this.params.scrollParent = !this.params.scrollParent, this.drawBuffer(); + }, + toggleInteraction: function() { + this.params.interact = !this.params.interact; + }, + drawBuffer: function() { + var a = Math.round(this.getDuration() * this.params.minPxPerSec * this.params.pixelRatio), b = this.drawer.getWidth(), c = a; + this.params.fillParent && (!this.params.scrollParent || b > a) && (c = b); + var d = this.backend.getPeaks(c); + this.drawer.drawPeaks(d, c), this.fireEvent("redraw", d, c); + }, + zoom: function(a) { + this.params.minPxPerSec = a, this.params.scrollParent = !0, this.drawBuffer(), this.seekAndCenter(this.getCurrentTime() / this.getDuration()); + }, + loadArrayBuffer: function(a) { + this.decodeArrayBuffer(a, function(a) { + this.loadDecodedBuffer(a); + }.bind(this)); + }, + loadDecodedBuffer: function(a) { + this.backend.load(a), this.drawBuffer(), this.fireEvent("ready"); + }, + loadBlob: function(a) { + var b = this, c = new FileReader(); + c.addEventListener("progress", function(a) { + b.onProgress(a); + }), c.addEventListener("load", function(a) { + b.loadArrayBuffer(a.target.result); + }), c.addEventListener("error", function() { + b.fireEvent("error", "Error reading file"); + }), c.readAsArrayBuffer(a), this.empty(); + }, + load: function(a, b) { + switch (this.params.backend) { + case "WebAudio": + return this.loadBuffer(a); + + case "MediaElement": + return this.loadMediaElement(a, b); + } + }, + loadBuffer: function(a) { + return this.empty(), this.getArrayBuffer(a, this.loadArrayBuffer.bind(this)); + }, + loadMediaElement: function(a, b) { + this.empty(), this.backend.load(a, this.mediaContainer, b), this.tmpEvents.push(this.backend.once("canplay", function() { + this.drawBuffer(), this.fireEvent("ready"); + }.bind(this)), this.backend.once("error", function(a) { + this.fireEvent("error", a); + }.bind(this))), !b && this.backend.supportsWebAudio() && this.getArrayBuffer(a, function(a) { + this.decodeArrayBuffer(a, function(a) { + this.backend.buffer = a, this.drawBuffer(); + }.bind(this)); + }.bind(this)); + }, + decodeArrayBuffer: function(a, b) { + this.backend.decodeArrayBuffer(a, this.fireEvent.bind(this, "decoded"), this.fireEvent.bind(this, "error", "Error decoding audiobuffer")), + this.tmpEvents.push(this.once("decoded", b)); + }, + getArrayBuffer: function(a, b) { + var c = this, d = WaveSurfer.util.ajax({ + url: a, + responseType: "arraybuffer" + }); + return this.tmpEvents.push(d.on("progress", function(a) { + c.onProgress(a); + }), d.on("success", b), d.on("error", function(a) { + c.fireEvent("error", "XHR error: " + a.target.statusText); + })), d; + }, + onProgress: function(a) { + if (a.lengthComputable) var b = a.loaded / a.total; else b = a.loaded / (a.loaded + 1e6); + this.fireEvent("loading", Math.round(100 * b), a.target); + }, + exportPCM: function(a, b, c) { + a = a || 1024, b = b || 1e4, c = c || !1; + var d = this.backend.getPeaks(a, b), e = [].map.call(d, function(a) { + return Math.round(a * b) / b; + }), f = JSON.stringify(e); + return c || window.open("data:application/json;charset=utf-8," + encodeURIComponent(f)), + f; + }, + clearTmpEvents: function() { + this.tmpEvents.forEach(function(a) { + a.un(); + }); + }, + empty: function() { + this.backend.isPaused() || (this.stop(), this.backend.disconnectSource()), this.clearTmpEvents(), + this.drawer.progress(0), this.drawer.setWidth(0), this.drawer.drawPeaks({ + length: this.drawer.getWidth() + }, 0); + }, + destroy: function() { + this.fireEvent("destroy"), this.clearTmpEvents(), this.unAll(), this.backend.destroy(), + this.drawer.destroy(); + } +}; + +WaveSurfer.create = function(a) { + var b = Object.create(WaveSurfer); + return b.init(a), b; +}, WaveSurfer.util = { + extend: function(a) { + var b = Array.prototype.slice.call(arguments, 1); + return b.forEach(function(b) { + Object.keys(b).forEach(function(c) { + a[c] = b[c]; }); - this.preSelect = function(suggestion) { - watching = false; - $scope.$apply(); - watching = true; - }; - $scope.preSelect = this.preSelect; - this.preSelectOff = function() { - watching = true; - }; - $scope.preSelectOff = this.preSelectOff; - $scope.select = function(suggestion) { - if (suggestion) { - $scope.searchParam = suggestion; - $scope.searchFilter = suggestion; - if ($scope.onSelect) $scope.onSelect(suggestion); - } - watching = false; - $scope.completing = false; - setTimeout(function() { - watching = true; - }, 1e3); - $scope.setIndex(-1); - }; - } ], - link: function(scope, element, attrs) { - setTimeout(function() { - scope.initLock = false; - scope.$apply(); - }, 250); - var attr = ""; - scope.attrs = { - placeholder: "start typing...", - "class": "", - id: "", - inputclass: "", - inputid: "" - }; - for (var a in attrs) { - attr = a.replace("attr", "").toLowerCase(); - if (a.indexOf("attr") === 0) { - scope.attrs[attr] = attrs[a]; - } - } - if (attrs.clickActivation) { - element[0].onclick = function(e) { - if (!scope.searchParam) { - setTimeout(function() { - scope.completing = true; - scope.$apply(); - }, 200); - } - }; + }), a; + }, + getId: function() { + return "wavesurfer_" + Math.random().toString(32).substring(2); + }, + ajax: function(a) { + var b = Object.create(WaveSurfer.Observer), c = new XMLHttpRequest(), d = !1; + return c.open(a.method || "GET", a.url, !0), c.responseType = a.responseType || "json", + c.addEventListener("progress", function(a) { + b.fireEvent("progress", a), a.lengthComputable && a.loaded == a.total && (d = !0); + }), c.addEventListener("load", function(a) { + d || b.fireEvent("progress", a), b.fireEvent("load", a), 200 == c.status || 206 == c.status ? b.fireEvent("success", c.response, a) : b.fireEvent("error", a); + }), c.addEventListener("error", function(a) { + b.fireEvent("error", a); + }), c.send(), b.xhr = c, b; + } +}, WaveSurfer.Observer = { + on: function(a, b) { + this.handlers || (this.handlers = {}); + var c = this.handlers[a]; + return c || (c = this.handlers[a] = []), c.push(b), { + name: a, + callback: b, + un: this.un.bind(this, a, b) + }; + }, + un: function(a, b) { + if (this.handlers) { + var c = this.handlers[a]; + if (c) if (b) for (var d = c.length - 1; d >= 0; d--) c[d] == b && c.splice(d, 1); else c.length = 0; + } + }, + unAll: function() { + this.handlers = null; + }, + once: function(a, b) { + var c = this, d = function() { + b.apply(this, arguments), setTimeout(function() { + c.un(a, d); + }, 0); + }; + return this.on(a, d); + }, + fireEvent: function(a) { + if (this.handlers) { + var b = this.handlers[a], c = Array.prototype.slice.call(arguments, 1); + b && b.forEach(function(a) { + a.apply(null, c); + }); + } + } +}, WaveSurfer.util.extend(WaveSurfer, WaveSurfer.Observer), WaveSurfer.WebAudio = { + scriptBufferSize: 256, + PLAYING_STATE: 0, + PAUSED_STATE: 1, + FINISHED_STATE: 2, + supportsWebAudio: function() { + return !(!window.AudioContext && !window.webkitAudioContext); + }, + getAudioContext: function() { + return WaveSurfer.WebAudio.audioContext || (WaveSurfer.WebAudio.audioContext = new (window.AudioContext || window.webkitAudioContext)()), + WaveSurfer.WebAudio.audioContext; + }, + getOfflineAudioContext: function(a) { + return WaveSurfer.WebAudio.offlineAudioContext || (WaveSurfer.WebAudio.offlineAudioContext = new (window.OfflineAudioContext || window.webkitOfflineAudioContext)(1, 2, a)), + WaveSurfer.WebAudio.offlineAudioContext; + }, + init: function(a) { + this.params = a, this.ac = a.audioContext || this.getAudioContext(), this.lastPlay = this.ac.currentTime, + this.startPosition = 0, this.scheduledPause = null, this.states = [ Object.create(WaveSurfer.WebAudio.state.playing), Object.create(WaveSurfer.WebAudio.state.paused), Object.create(WaveSurfer.WebAudio.state.finished) ], + this.createVolumeNode(), this.createScriptNode(), this.createAnalyserNode(), this.setState(this.PAUSED_STATE), + this.setPlaybackRate(this.params.audioRate); + }, + disconnectFilters: function() { + this.filters && (this.filters.forEach(function(a) { + a && a.disconnect(); + }), this.filters = null, this.analyser.connect(this.gainNode)); + }, + setState: function(a) { + this.state !== this.states[a] && (this.state = this.states[a], this.state.init.call(this)); + }, + setFilter: function() { + this.setFilters([].slice.call(arguments)); + }, + setFilters: function(a) { + this.disconnectFilters(), a && a.length && (this.filters = a, this.analyser.disconnect(), + a.reduce(function(a, b) { + return a.connect(b), b; + }, this.analyser).connect(this.gainNode)); + }, + createScriptNode: function() { + this.ac.createScriptProcessor ? this.scriptNode = this.ac.createScriptProcessor(this.scriptBufferSize) : this.scriptNode = this.ac.createJavaScriptNode(this.scriptBufferSize), + this.scriptNode.connect(this.ac.destination); + }, + addOnAudioProcess: function() { + var a = this; + this.scriptNode.onaudioprocess = function() { + var b = a.getCurrentTime(); + b >= a.getDuration() ? (a.setState(a.FINISHED_STATE), a.fireEvent("pause")) : b >= a.scheduledPause ? (a.setState(a.PAUSED_STATE), + a.fireEvent("pause")) : a.state === a.states[a.PLAYING_STATE] && a.fireEvent("audioprocess", b); + }; + }, + removeOnAudioProcess: function() { + this.scriptNode.onaudioprocess = null; + }, + createAnalyserNode: function() { + this.analyser = this.ac.createAnalyser(), this.analyser.connect(this.gainNode); + }, + createVolumeNode: function() { + this.ac.createGain ? this.gainNode = this.ac.createGain() : this.gainNode = this.ac.createGainNode(), + this.gainNode.connect(this.ac.destination); + }, + setVolume: function(a) { + this.gainNode.gain.value = a; + }, + getVolume: function() { + return this.gainNode.gain.value; + }, + decodeArrayBuffer: function(a, b, c) { + this.offlineAc || (this.offlineAc = this.getOfflineAudioContext(this.ac ? this.ac.sampleRate : 44100)), + this.offlineAc.decodeAudioData(a, function(a) { + b(a); + }.bind(this), c); + }, + getPeaks: function(a) { + for (var b = this.buffer.length / a, c = ~~(b / 10) || 1, d = this.buffer.numberOfChannels, e = [], f = [], g = 0; d > g; g++) for (var h = e[g] = [], i = this.buffer.getChannelData(g), j = 0; a > j; j++) { + for (var k = ~~(j * b), l = ~~(k + b), m = i[0], n = i[0], o = k; l > o; o += c) { + var p = i[o]; + p > n && (n = p), m > p && (m = p); + } + h[2 * j] = n, h[2 * j + 1] = m, (0 == g || n > f[2 * j]) && (f[2 * j] = n), (0 == g || m < f[2 * j + 1]) && (f[2 * j + 1] = m); + } + return this.params.splitChannels ? e : f; + }, + getPlayedPercents: function() { + return this.state.getPlayedPercents.call(this); + }, + disconnectSource: function() { + this.source && this.source.disconnect(); + }, + destroy: function() { + this.isPaused() || this.pause(), this.unAll(), this.buffer = null, this.disconnectFilters(), + this.disconnectSource(), this.gainNode.disconnect(), this.scriptNode.disconnect(), + this.analyser.disconnect(); + }, + load: function(a) { + this.startPosition = 0, this.lastPlay = this.ac.currentTime, this.buffer = a, this.createSource(); + }, + createSource: function() { + this.disconnectSource(), this.source = this.ac.createBufferSource(), this.source.start = this.source.start || this.source.noteGrainOn, + this.source.stop = this.source.stop || this.source.noteOff, this.source.playbackRate.value = this.playbackRate, + this.source.buffer = this.buffer, this.source.connect(this.analyser); + }, + isPaused: function() { + return this.state !== this.states[this.PLAYING_STATE]; + }, + getDuration: function() { + return this.buffer ? this.buffer.duration : 0; + }, + seekTo: function(a, b) { + return this.scheduledPause = null, null == a && (a = this.getCurrentTime(), a >= this.getDuration() && (a = 0)), + null == b && (b = this.getDuration()), this.startPosition = a, this.lastPlay = this.ac.currentTime, + this.state === this.states[this.FINISHED_STATE] && this.setState(this.PAUSED_STATE), + { + start: a, + end: b + }; + }, + getPlayedTime: function() { + return (this.ac.currentTime - this.lastPlay) * this.playbackRate; + }, + play: function(a, b) { + this.createSource(); + var c = this.seekTo(a, b); + a = c.start, b = c.end, this.scheduledPause = b, this.source.start(0, a, b - a), + this.setState(this.PLAYING_STATE), this.fireEvent("play"); + }, + pause: function() { + this.scheduledPause = null, this.startPosition += this.getPlayedTime(), this.source && this.source.stop(0), + this.setState(this.PAUSED_STATE), this.fireEvent("pause"); + }, + getCurrentTime: function() { + return this.state.getCurrentTime.call(this); + }, + setPlaybackRate: function(a) { + a = a || 1, this.isPaused() ? this.playbackRate = a : (this.pause(), this.playbackRate = a, + this.play()); + } +}, WaveSurfer.WebAudio.state = {}, WaveSurfer.WebAudio.state.playing = { + init: function() { + this.addOnAudioProcess(); + }, + getPlayedPercents: function() { + var a = this.getDuration(); + return this.getCurrentTime() / a || 0; + }, + getCurrentTime: function() { + return this.startPosition + this.getPlayedTime(); + } +}, WaveSurfer.WebAudio.state.paused = { + init: function() { + this.removeOnAudioProcess(); + }, + getPlayedPercents: function() { + var a = this.getDuration(); + return this.getCurrentTime() / a || 0; + }, + getCurrentTime: function() { + return this.startPosition; + } +}, WaveSurfer.WebAudio.state.finished = { + init: function() { + this.removeOnAudioProcess(), this.fireEvent("finish"); + }, + getPlayedPercents: function() { + return 1; + }, + getCurrentTime: function() { + return this.getDuration(); + } +}, WaveSurfer.util.extend(WaveSurfer.WebAudio, WaveSurfer.Observer), WaveSurfer.MediaElement = Object.create(WaveSurfer.WebAudio), +WaveSurfer.util.extend(WaveSurfer.MediaElement, { + init: function(a) { + this.params = a, this.media = { + currentTime: 0, + duration: 0, + paused: !0, + playbackRate: 1, + play: function() {}, + pause: function() {} + }, this.mediaType = a.mediaType.toLowerCase(), this.elementPosition = a.elementPosition; + }, + load: function(a, b, c) { + var d = this, e = document.createElement(this.mediaType); + e.controls = !1, e.autoplay = !1, e.preload = "auto", e.src = a, e.addEventListener("error", function() { + d.fireEvent("error", "Error loading media element"); + }), e.addEventListener("canplay", function() { + d.fireEvent("canplay"); + }), e.addEventListener("ended", function() { + d.fireEvent("finish"); + }), e.addEventListener("timeupdate", function() { + d.fireEvent("audioprocess", d.getCurrentTime()); + }); + var f = b.querySelector(this.mediaType); + f && b.removeChild(f), b.appendChild(e), this.media = e, this.peaks = c, this.onPlayEnd = null, + this.buffer = null, this.setPlaybackRate(this.playbackRate); + }, + isPaused: function() { + return !this.media || this.media.paused; + }, + getDuration: function() { + var a = this.media.duration; + return a >= 1 / 0 && (a = this.media.seekable.end()), a; + }, + getCurrentTime: function() { + return this.media && this.media.currentTime; + }, + getPlayedPercents: function() { + return this.getCurrentTime() / this.getDuration() || 0; + }, + setPlaybackRate: function(a) { + this.playbackRate = a || 1, this.media.playbackRate = this.playbackRate; + }, + seekTo: function(a) { + null != a && (this.media.currentTime = a), this.clearPlayEnd(); + }, + play: function(a, b) { + this.seekTo(a), this.media.play(), b && this.setPlayEnd(b), this.fireEvent("play"); + }, + pause: function() { + this.media && this.media.pause(), this.clearPlayEnd(), this.fireEvent("pause"); + }, + setPlayEnd: function(a) { + var b = this; + this.onPlayEnd = function(c) { + c >= a && (b.pause(), b.seekTo(a)); + }, this.on("audioprocess", this.onPlayEnd); + }, + clearPlayEnd: function() { + this.onPlayEnd && (this.un("audioprocess", this.onPlayEnd), this.onPlayEnd = null); + }, + getPeaks: function(a) { + return this.buffer ? WaveSurfer.WebAudio.getPeaks.call(this, a) : this.peaks || []; + }, + getVolume: function() { + return this.media.volume; + }, + setVolume: function(a) { + this.media.volume = a; + }, + destroy: function() { + this.pause(), this.unAll(), this.media && this.media.parentNode && this.media.parentNode.removeChild(this.media), + this.media = null; + } +}), WaveSurfer.AudioElement = WaveSurfer.MediaElement, WaveSurfer.Drawer = { + init: function(a, b) { + this.container = a, this.params = b, this.width = 0, this.height = b.height * this.params.pixelRatio, + this.lastPos = 0, this.createWrapper(), this.createElements(); + }, + createWrapper: function() { + this.wrapper = this.container.appendChild(document.createElement("wave")), this.style(this.wrapper, { + display: "block", + position: "relative", + userSelect: "none", + webkitUserSelect: "none", + height: this.params.height + "px" + }), (this.params.fillParent || this.params.scrollParent) && this.style(this.wrapper, { + width: "100%", + overflowX: this.params.hideScrollbar ? "hidden" : "auto", + overflowY: "hidden" + }), this.setupWrapperEvents(); + }, + handleEvent: function(a) { + a.preventDefault(); + var b = this.wrapper.getBoundingClientRect(); + return (a.clientX - b.left + this.wrapper.scrollLeft) / this.wrapper.scrollWidth || 0; + }, + setupWrapperEvents: function() { + var a = this; + this.wrapper.addEventListener("click", function(b) { + var c = a.wrapper.offsetHeight - a.wrapper.clientHeight; + if (0 != c) { + var d = a.wrapper.getBoundingClientRect(); + if (b.clientY >= d.bottom - c) return; } - var key = { - left: 37, - up: 38, - right: 39, - down: 40, - enter: 13, - esc: 27, - tab: 9 - }; - document.addEventListener("keydown", function(e) { - var keycode = e.keyCode || e.which; - switch (keycode) { - case key.esc: - scope.select(); - scope.setIndex(-1); - scope.$apply(); - e.preventDefault(); - } - }, true); - document.addEventListener("blur", function(e) { - setTimeout(function() { - scope.select(); - scope.setIndex(-1); - scope.$apply(); - }, 150); - }, true); - element[0].addEventListener("keydown", function(e) { - var keycode = e.keyCode || e.which; - var l = angular.element(this).find("li").length; - if (!scope.completing || l == 0) return; - switch (keycode) { - case key.up: - index = scope.getIndex() - 1; - if (index < -1) { - index = l - 1; - } else if (index >= l) { - index = -1; - scope.setIndex(index); - scope.preSelectOff(); - break; - } - scope.setIndex(index); - if (index !== -1) scope.preSelect(angular.element(angular.element(this).find("li")[index]).text()); - scope.$apply(); - break; - - case key.down: - index = scope.getIndex() + 1; - if (index < -1) { - index = l - 1; - } else if (index >= l) { - index = -1; - scope.setIndex(index); - scope.preSelectOff(); - scope.$apply(); - break; - } - scope.setIndex(index); - if (index !== -1) scope.preSelect(angular.element(angular.element(this).find("li")[index]).text()); - break; - - case key.left: - break; - - case key.right: - case key.enter: - case key.tab: - index = scope.getIndex(); - if (index !== -1) { - scope.select(angular.element(angular.element(this).find("li")[index]).text()); - if (keycode == key.enter) { - e.preventDefault(); - } - } else { - if (keycode == key.enter) { - scope.select(); - } - } - scope.setIndex(-1); - scope.$apply(); - break; - - case key.esc: - scope.select(); - scope.setIndex(-1); - scope.$apply(); - e.preventDefault(); - break; - - default: - return; - } - }); - }, - template: '
              ' - }; -}); - -app.filter("highlight", [ "$sce", function($sce) { - return function(input, searchParam) { - if (typeof input === "function") return ""; - if (searchParam) { - var words = "(" + searchParam.split(/\ /).join(" |") + "|" + searchParam.split(/\ /).join("|") + ")", exp = new RegExp(words, "gi"); - if (words.length) { - input = input.replace(exp, '$1'); + a.params.interact && a.fireEvent("click", b, a.handleEvent(b)); + }), this.wrapper.addEventListener("scroll", function(b) { + a.fireEvent("scroll", b); + }); + }, + drawPeaks: function(a, b) { + this.resetScroll(), this.setWidth(b), this.params.barWidth ? this.drawBars(a) : this.drawWave(a); + }, + style: function(a, b) { + return Object.keys(b).forEach(function(c) { + a.style[c] !== b[c] && (a.style[c] = b[c]); + }), a; + }, + resetScroll: function() { + null !== this.wrapper && (this.wrapper.scrollLeft = 0); + }, + recenter: function(a) { + var b = this.wrapper.scrollWidth * a; + this.recenterOnPosition(b, !0); + }, + recenterOnPosition: function(a, b) { + var c = this.wrapper.scrollLeft, d = ~~(this.wrapper.clientWidth / 2), e = a - d, f = e - c, g = this.wrapper.scrollWidth - this.wrapper.clientWidth; + if (0 != g) { + if (!b && f >= -d && d > f) { + var h = 5; + f = Math.max(-h, Math.min(h, f)), e = c + f; } + e = Math.max(0, Math.min(g, e)), e != c && (this.wrapper.scrollLeft = e); } - return $sce.trustAsHtml(input); - }; -} ]); - -app.directive("suggestion", function() { - return { - restrict: "A", - require: "^autocomplete", - link: function(scope, element, attrs, autoCtrl) { - element.bind("mouseenter", function() { - autoCtrl.preSelect(attrs.val); - autoCtrl.setIndex(attrs.index); - }); - element.bind("mouseleave", function() { - autoCtrl.preSelectOff(); - }); - } - }; -}); - -"use strict"; - -var Value = function(lang, content) { - this.lang = lang; - this.content = content; -}; - -var TextTitle = function(lang, content) { - Value.call(this, lang, content); -}; - -TextTitle.prototype = new Value(); - -var TextComment = function(lang, content) { - Value.call(this, lang, content); -}; - -TextComment.prototype = new Value(); - -var Item = function(lang, content, type) { - this.type = type; - Value.call(this, lang, content); -}; - -Item.prototype = new Value(); - -var Translation = function(lang, content) { - Value.call(this, lang, content); -}; - -Translation.prototype = new Value(); - -var DictItem = function(url) { - this.type = "lingvodoc_metaword"; - this.url = url; -}; - -var Word = function(items) { - this.items = items; - this.hasDictionaryEntry = function() { - for (var i = 0; i < this.items.length; i++) { - if (this.items[i].type == "lingvodoc_metaword") { - return true; + }, + getWidth: function() { + return Math.round(this.container.clientWidth * this.params.pixelRatio); + }, + setWidth: function(a) { + a != this.width && (this.width = a, this.params.fillParent || this.params.scrollParent ? this.style(this.wrapper, { + width: "" + }) : this.style(this.wrapper, { + width: ~~(this.width / this.params.pixelRatio) + "px" + }), this.updateSize()); + }, + setHeight: function(a) { + a != this.height && (this.height = a, this.style(this.wrapper, { + height: ~~(this.height / this.params.pixelRatio) + "px" + }), this.updateSize()); + }, + progress: function(a) { + var b = 1 / this.params.pixelRatio, c = Math.round(a * this.width) * b; + if (c < this.lastPos || c - this.lastPos >= b) { + if (this.lastPos = c, this.params.scrollParent) { + var d = ~~(this.wrapper.scrollWidth * a); + this.recenterOnPosition(d); } + this.updateProgress(a); + } + }, + destroy: function() { + this.unAll(), this.wrapper && (this.container.removeChild(this.wrapper), this.wrapper = null); + }, + createElements: function() {}, + updateSize: function() {}, + drawWave: function(a, b) {}, + clearWave: function() {}, + updateProgress: function(a) {} +}, WaveSurfer.util.extend(WaveSurfer.Drawer, WaveSurfer.Observer), WaveSurfer.Drawer.Canvas = Object.create(WaveSurfer.Drawer), +WaveSurfer.util.extend(WaveSurfer.Drawer.Canvas, { + createElements: function() { + var a = this.wrapper.appendChild(this.style(document.createElement("canvas"), { + position: "absolute", + zIndex: 1, + left: 0, + top: 0, + bottom: 0 + })); + if (this.waveCc = a.getContext("2d"), this.progressWave = this.wrapper.appendChild(this.style(document.createElement("wave"), { + position: "absolute", + zIndex: 2, + left: 0, + top: 0, + bottom: 0, + overflow: "hidden", + width: "0", + display: "none", + boxSizing: "border-box", + borderRightStyle: "solid", + borderRightWidth: this.params.cursorWidth + "px", + borderRightColor: this.params.cursorColor + })), this.params.waveColor != this.params.progressColor) { + var b = this.progressWave.appendChild(document.createElement("canvas")); + this.progressCc = b.getContext("2d"); + } + }, + updateSize: function() { + var a = Math.round(this.width / this.params.pixelRatio); + this.waveCc.canvas.width = this.width, this.waveCc.canvas.height = this.height, + this.style(this.waveCc.canvas, { + width: a + "px" + }), this.style(this.progressWave, { + display: "block" + }), this.progressCc && (this.progressCc.canvas.width = this.width, this.progressCc.canvas.height = this.height, + this.style(this.progressCc.canvas, { + width: a + "px" + })), this.clearWave(); + }, + clearWave: function() { + this.waveCc.clearRect(0, 0, this.width, this.height), this.progressCc && this.progressCc.clearRect(0, 0, this.width, this.height); + }, + drawBars: function(a, b) { + if (a[0] instanceof Array) { + var c = a; + if (this.params.splitChannels) return this.setHeight(c.length * this.params.height * this.params.pixelRatio), + void c.forEach(this.drawBars, this); + a = c[0]; } - return false; - }.bind(this); - this.getDictionaryEntry = function() { - for (var i = 0; i < this.items.length; i++) { - var item = this.items[i]; - if (item.type == "lingvodoc_metaword") { - return item; - } + var d = .5 / this.params.pixelRatio, e = this.width, f = this.params.height * this.params.pixelRatio, g = f * b || 0, h = f / 2, i = ~~(a.length / 2), j = this.params.barWidth * this.params.pixelRatio, k = Math.max(this.params.pixelRatio, ~~(j / 2)), l = j + k, m = 1; + if (this.params.normalize) { + var n, o; + o = Math.max.apply(Math, a), n = Math.min.apply(Math, a), m = o, -n > m && (m = -n); } - return null; - }.bind(this); - this.getTextEntry = function() { - for (var i = 0; i < this.items.length; i++) { - var item = this.items[i]; - if (item.type == "txt") { - return item; + var p = i / e; + this.waveCc.fillStyle = this.params.waveColor, this.progressCc && (this.progressCc.fillStyle = this.params.progressColor), + [ this.waveCc, this.progressCc ].forEach(function(b) { + if (b) if (this.params.reflection) for (var c = 0; e > c; c += l) { + var f = Math.round(a[2 * c * p] / m * h); + b.fillRect(c + d, h - f + g, j + d, 2 * f); + } else { + for (var c = 0; e > c; c += l) { + var f = Math.round(a[2 * c * p] / m * h); + b.fillRect(c + d, h - f + g, j + d, f); + } + for (var c = 0; e > c; c += l) { + var f = Math.round(a[2 * c * p + 1] / m * h); + b.fillRect(c + d, h - f + g, j + d, f); + } } + }, this); + }, + drawWave: function(a, b) { + if (a[0] instanceof Array) { + var c = a; + if (this.params.splitChannels) return this.setHeight(c.length * this.params.height * this.params.pixelRatio), + void c.forEach(this.drawWave, this); + a = c[0]; } - return null; - }.bind(this); -}; - -Word.fromJS = function(word) { - var items = []; - for (var i = 0; i < word.items.length; i++) { - var item = word.items[i]; - if (item.type === "lingvodoc_metaword") { - items.push(new DictItem(item.url)); - } else { - items.push(new Item(item.lang, item.content, item.type)); + var d = .5 / this.params.pixelRatio, e = this.params.height * this.params.pixelRatio, f = e * b || 0, g = e / 2, h = ~~(a.length / 2), i = 1; + this.params.fillParent && this.width != h && (i = this.width / h); + var j = 1; + if (this.params.normalize) { + var k, l; + l = Math.max.apply(Math, a), k = Math.min.apply(Math, a), j = l, -k > j && (j = -k); } + this.waveCc.fillStyle = this.params.waveColor, this.progressCc && (this.progressCc.fillStyle = this.params.progressColor), + [ this.waveCc, this.progressCc ].forEach(function(b) { + if (b) { + b.beginPath(), b.moveTo(d, g + f); + for (var c = 0; h > c; c++) { + var e = Math.round(a[2 * c] / j * g); + b.lineTo(c * i + d, g - e + f); + } + for (var c = h - 1; c >= 0; c--) { + var e = Math.round(a[2 * c + 1] / j * g); + b.lineTo(c * i + d, g - e + f); + } + b.closePath(), b.fill(), b.fillRect(0, g + f - d, this.width, d); + } + }, this); + }, + updateProgress: function(a) { + var b = Math.round(this.width * a) / this.params.pixelRatio; + this.style(this.progressWave, { + width: b + "px" + }); } - return new Word(items); -}; - -var Phrase = function(words, translations) { - this.words = words; - this.translations = translations; -}; - -Phrase.fromJS = function(phrase) { - var i = 0, words = [], translations = []; - for (i = 0; i < phrase.words.length; i++) { - var word = phrase.words[i]; - words.push(Word.fromJS(word)); - } - for (i = 0; i < phrase.translations.length; i++) { - var translation = phrase.translations[i]; - translations.push(new Translation(translation.lang, translation.content)); - } - return new Phrase(words, translations); -}; - -var Paragraph = function(phrases) { - this.phrases = phrases; -}; - -Paragraph.fromJS = function(paragraph) { - var phrases = []; - for (var i = 0; i < paragraph.phrases.length; i++) { - var phrase = paragraph.phrases[i]; - phrases.push(Phrase.fromJS(phrase)); - } - return new Paragraph(phrases); -}; +}); -var Text = function(text_id, client_id, text_titles, paragraphs) { - this.text_id = text_id; - this.client_id = client_id; - this.text_titles = text_titles; - this.paragraphs = paragraphs; -}; +"use strict"; -Text.fromJS = function(text) { - var i; - var text_titles = [], paragraphs = []; - for (i = 0; i < text.text_titles.length; i++) { - var title = text.text_titles[i]; - text_titles.push(new TextTitle(title.lang, title.content)); +WaveSurfer.Regions = { + init: function(a) { + this.wavesurfer = a, this.wrapper = this.wavesurfer.drawer.wrapper, this.list = {}; + }, + add: function(a) { + var b = Object.create(WaveSurfer.Region); + return b.init(a, this.wavesurfer), this.list[b.id] = b, b.on("remove", function() { + delete this.list[b.id]; + }.bind(this)), b; + }, + clear: function() { + Object.keys(this.list).forEach(function(a) { + this.list[a].remove(); + }, this); + }, + enableDragSelection: function(a) { + var b, c, d, e = this; + this.wrapper.addEventListener("mousedown", function(a) { + b = !0, c = e.wavesurfer.drawer.handleEvent(a), d = null; + }), this.wrapper.addEventListener("mouseup", function(a) { + b = !1, d && (d.fireEvent("update-end", a), e.wavesurfer.fireEvent("region-update-end", d, a)), + d = null; + }), this.wrapper.addEventListener("mousemove", function(f) { + if (b) { + d || (d = e.add(a || {})); + var g = e.wavesurfer.getDuration(), h = e.wavesurfer.drawer.handleEvent(f); + d.update({ + start: Math.min(h * g, c * g), + end: Math.max(h * g, c * g) + }); + } + }); } - for (i = 0; i < text.paragraphs.length; i++) { - var paragraph = text.paragraphs[i]; - paragraphs.push(Paragraph.fromJS(paragraph)); +}, WaveSurfer.Region = { + style: WaveSurfer.Drawer.style, + init: function(a, b) { + this.wavesurfer = b, this.wrapper = b.drawer.wrapper, this.id = null == a.id ? WaveSurfer.util.getId() : a.id, + this.start = Number(a.start) || 0, this.end = null == a.end ? this.start + 4 / this.wrapper.scrollWidth * this.wavesurfer.getDuration() : Number(a.end), + this.resize = void 0 === a.resize ? !0 : Boolean(a.resize), this.drag = void 0 === a.drag ? !0 : Boolean(a.drag), + this.loop = Boolean(a.loop), this.color = a.color || "rgba(0, 0, 0, 0.1)", this.data = a.data || {}, + this.maxLength = a.maxLength, this.minLength = a.minLength, this.bindInOut(), this.render(), + this.wavesurfer.fireEvent("region-created", this); + }, + update: function(a) { + null != a.start && (this.start = Number(a.start)), null != a.end && (this.end = Number(a.end)), + null != a.loop && (this.loop = Boolean(a.loop)), null != a.color && (this.color = a.color), + null != a.data && (this.data = a.data), null != a.resize && (this.resize = Boolean(a.resize)), + null != a.drag && (this.drag = Boolean(a.drag)), null != a.maxLength && (this.maxLength = Number(a.maxLength)), + null != a.minLength && (this.minLength = Number(a.minLength)), this.updateRender(), + this.fireEvent("update"), this.wavesurfer.fireEvent("region-updated", this); + }, + remove: function(a) { + this.element && (this.wrapper.removeChild(this.element), this.element = null, this.fireEvent("remove"), + this.wavesurfer.fireEvent("region-removed", this)); + }, + play: function() { + this.wavesurfer.play(this.start, this.end), this.fireEvent("play"), this.wavesurfer.fireEvent("region-play", this); + }, + playLoop: function() { + this.play(), this.once("out", this.playLoop.bind(this)); + }, + render: function() { + var a = document.createElement("region"); + a.className = "wavesurfer-region", a.title = this.formatTime(this.start, this.end), + a.setAttribute("data-id", this.id); + this.wrapper.scrollWidth; + if (this.style(a, { + position: "absolute", + zIndex: 2, + height: "100%", + top: "0px" + }), this.resize) { + var b = a.appendChild(document.createElement("handle")), c = a.appendChild(document.createElement("handle")); + b.className = "wavesurfer-handle wavesurfer-handle-start", c.className = "wavesurfer-handle wavesurfer-handle-end"; + var d = { + cursor: "col-resize", + position: "absolute", + left: "0px", + top: "0px", + width: "1%", + maxWidth: "4px", + height: "100%" + }; + this.style(b, d), this.style(c, d), this.style(c, { + left: "100%" + }); + } + this.element = this.wrapper.appendChild(a), this.updateRender(), this.bindEvents(a); + }, + formatTime: function(a, b) { + return (a == b ? [ a ] : [ a, b ]).map(function(a) { + return [ Math.floor(a % 3600 / 60), ("00" + Math.floor(a % 60)).slice(-2) ].join(":"); + }).join("–"); + }, + updateRender: function() { + var a = this.wavesurfer.getDuration(), b = this.wrapper.scrollWidth; + this.start < 0 && (this.start = 0, this.end = this.end - this.start), this.end > a && (this.end = a, + this.start = a - (this.end - this.start)), null != this.minLength && (this.end = Math.max(this.start + this.minLength, this.end)), + null != this.maxLength && (this.end = Math.min(this.start + this.maxLength, this.end)), + this.style(this.element, { + left: ~~(this.start / a * b) + "px", + width: ~~((this.end - this.start) / a * b) + "px", + backgroundColor: this.color, + cursor: this.drag ? "move" : "default" + }), this.element.title = this.formatTime(this.start, this.end); + }, + bindInOut: function() { + var a = this, b = function() { + a.firedIn = !1, a.firedOut = !1; + }, c = function(b) { + !a.firedIn && a.start <= b && a.end > b && (a.firedIn = !0, a.fireEvent("in"), a.wavesurfer.fireEvent("region-in", a)), + !a.firedOut && a.firedIn && a.end <= Math.round(100 * b) / 100 && (a.firedOut = !0, + a.fireEvent("out"), a.wavesurfer.fireEvent("region-out", a)); + }; + this.wavesurfer.on("play", b), this.wavesurfer.backend.on("audioprocess", c), this.on("remove", function() { + a.wavesurfer.un("play", b), a.wavesurfer.backend.un("audioprocess", c); + }), this.on("out", function() { + a.loop && a.wavesurfer.play(a.start); + }); + }, + bindEvents: function() { + var a = this; + this.element.addEventListener("mouseenter", function(b) { + a.fireEvent("mouseenter", b), a.wavesurfer.fireEvent("region-mouseenter", a, b); + }), this.element.addEventListener("mouseleave", function(b) { + a.fireEvent("mouseleave", b), a.wavesurfer.fireEvent("region-mouseleave", a, b); + }), this.element.addEventListener("click", function(b) { + b.preventDefault(), a.fireEvent("click", b), a.wavesurfer.fireEvent("region-click", a, b); + }), this.element.addEventListener("dblclick", function(b) { + b.stopPropagation(), b.preventDefault(), a.fireEvent("dblclick", b), a.wavesurfer.fireEvent("region-dblclick", a, b); + }), (this.drag || this.resize) && function() { + var b, c, d, e = a.wavesurfer.getDuration(), f = function(f) { + f.stopPropagation(), d = a.wavesurfer.drawer.handleEvent(f) * e, "handle" == f.target.tagName.toLowerCase() ? c = f.target.classList.contains("wavesurfer-handle-start") ? "start" : "end" : b = !0; + }, g = function(d) { + (b || c) && (b = !1, c = !1, d.stopPropagation(), d.preventDefault(), a.fireEvent("update-end", d), + a.wavesurfer.fireEvent("region-update-end", a, d)); + }, h = function(f) { + if (b || c) { + var g = a.wavesurfer.drawer.handleEvent(f) * e, h = g - d; + d = g, a.drag && b && a.onDrag(h), a.resize && c && a.onResize(h, c); + } + }; + a.element.addEventListener("mousedown", f), a.wrapper.addEventListener("mousemove", h), + document.body.addEventListener("mouseup", g), a.on("remove", function() { + document.body.removeEventListener("mouseup", g), a.wrapper.removeEventListener("mousemove", h); + }), a.wavesurfer.on("destroy", function() { + document.body.removeEventListener("mouseup", g); + }); + }(); + }, + onDrag: function(a) { + this.update({ + start: this.start + a, + end: this.end + a + }); + }, + onResize: function(a, b) { + "start" == b ? this.update({ + start: Math.min(this.start + a, this.end), + end: Math.max(this.start + a, this.end) + }) : this.update({ + start: Math.min(this.end + a, this.start), + end: Math.max(this.end + a, this.start) + }); } - return new Text(text.text_id, text.client_id, text_titles, paragraphs); +}, WaveSurfer.util.extend(WaveSurfer.Region, WaveSurfer.Observer), WaveSurfer.initRegions = function() { + this.regions || (this.regions = Object.create(WaveSurfer.Regions), this.regions.init(this)); +}, WaveSurfer.addRegion = function(a) { + return this.initRegions(), this.regions.add(a); +}, WaveSurfer.clearRegions = function() { + this.regions && this.regions.clear(); +}, WaveSurfer.enableDragSelection = function(a) { + this.initRegions(), this.regions.enableDragSelection(a); }; -var app = angular.module("demoModule", [ "ui.bootstrap" ]); +"use strict"; -app.directive("wavesurfer", function() { - return { - restrict: "E", - link: function($scope, $element, $attrs) { - $element.css("display", "block"); - var options = angular.extend({ - container: $element[0] - }, $attrs); - var wavesurfer = WaveSurfer.create(options); - if ($attrs.url) { - wavesurfer.load($attrs.url, $attrs.data || null); - } - $scope.$emit("wavesurferInit", wavesurfer); +WaveSurfer.Spectrogram = { + init: function(a) { + this.params = a; + var b = this.wavesurfer = a.wavesurfer; + if (!this.wavesurfer) throw Error("No WaveSurfer instance provided"); + this.frequenciesDataUrl = a.frequenciesDataUrl; + var c = this.drawer = this.wavesurfer.drawer; + if (this.buffer = this.wavesurfer.backend.buffer, this.container = "string" == typeof a.container ? document.querySelector(a.container) : a.container, + !this.container) throw Error("No container for WaveSurfer spectrogram"); + this.width = c.width, this.pixelRatio = this.params.pixelRatio || b.params.pixelRatio, + this.fftSamples = this.params.fftSamples || b.params.fftSamples || 512, this.height = this.fftSamples / 2, + this.createWrapper(), this.createCanvas(), this.render(), b.drawer.wrapper.onscroll = this.updateScroll.bind(this), + b.on("destroy", this.destroy.bind(this)); + }, + destroy: function() { + this.unAll(), this.wrapper && (this.wrapper.parentNode.removeChild(this.wrapper), + this.wrapper = null); + }, + createWrapper: function() { + var a = this.container.querySelector("spectrogram"); + a && this.container.removeChild(a); + var b = this.wavesurfer.params; + this.wrapper = this.container.appendChild(document.createElement("spectrogram")), + this.drawer.style(this.wrapper, { + display: "block", + position: "relative", + userSelect: "none", + webkitUserSelect: "none", + height: this.height + "px" + }), (b.fillParent || b.scrollParent) && this.drawer.style(this.wrapper, { + width: "100%", + overflowX: "hidden", + overflowY: "hidden" + }); + var c = this; + this.wrapper.addEventListener("click", function(a) { + a.preventDefault(); + var b = "offsetX" in a ? a.offsetX : a.layerX; + c.fireEvent("click", b / c.scrollWidth || 0); + }); + }, + createCanvas: function() { + var a = this.canvas = this.wrapper.appendChild(document.createElement("canvas")); + this.spectrCc = a.getContext("2d"), this.wavesurfer.drawer.style(a, { + position: "absolute", + zIndex: 4 + }); + }, + render: function() { + this.updateCanvasStyle(), this.frequenciesDataUrl ? this.loadFrequenciesData(this.frequenciesDataUrl) : this.getFrequencies(this.drawSpectrogram); + }, + updateCanvasStyle: function() { + var a = Math.round(this.width / this.pixelRatio) + "px"; + this.canvas.width = this.width, this.canvas.height = this.height, this.canvas.style.width = a; + }, + drawSpectrogram: function(a, b) { + for (var c = (b.spectrCc, b.wavesurfer.backend.getDuration(), b.height), d = b.resample(a), e = 2 / b.buffer.numberOfChannels, f = 0; f < d.length; f++) for (var g = 0; g < d[f].length; g++) { + var h = 255 - d[f][g]; + b.spectrCc.fillStyle = "rgb(" + h + ", " + h + ", " + h + ")", b.spectrCc.fillRect(f, c - g * e, 1, 1 * e); } - }; -}); - -app.controller("DemoController", [ "$scope", "$http", "$modal", function($scope, $http, $modal) { - $scope.texts = []; - var url = $("#getCorpusUrl").data("lingvodoc"); - $http.get(url).success(function(data, status, headers, config) { - if (data.corpus_id && data.corpus_client_id) { - for (var i = 0; i < data.texts.length; i++) { - $scope.texts.push(Text.fromJS(data.texts[i])); - if (i > 5) break; + }, + getFrequencies: function(a) { + var b = this.fftSamples, c = this.buffer, d = [], e = new window.OfflineAudioContext(1, c.length, c.sampleRate), f = e.createBufferSource(), g = e.createScriptProcessor(0, 1, 1), h = e.createAnalyser(); + h.fftSize = b, h.smoothingTimeConstant = this.width / c.duration < 10 ? .75 : .25, + f.buffer = c, f.connect(h), h.connect(g), g.connect(e.destination), g.onaudioprocess = function() { + var a = new Uint8Array(h.frequencyBinCount); + h.getByteFrequencyData(a), d.push(a); + }, f.start(0), e.startRendering(); + var i = this; + e.oncomplete = function() { + a(d, i); + }; + }, + loadFrequenciesData: function(a) { + var b = this, c = WaveSurfer.util.ajax({ + url: a + }); + return c.on("success", function(a) { + b.drawSpectrogram(JSON.parse(a), b); + }), c.on("error", function(a) { + b.fireEvent("error", "XHR error: " + a.target.statusText); + }), c; + }, + updateScroll: function(a) { + this.wrapper.scrollLeft = a.target.scrollLeft; + }, + resample: function(a, b) { + for (var b = this.width, c = [], d = 1 / a.length, e = 1 / b, f = 0; b > f; f++) { + for (var g = new Array(a[0].length), h = 0; h < a.length; h++) { + var i = h * d, j = i + d, k = f * e, l = k + e, m = k >= j || i >= l ? 0 : Math.min(Math.max(j, k), Math.max(l, i)) - Math.max(Math.min(j, k), Math.min(l, i)); + if (m > 0) for (var n = 0; n < a[0].length; n++) null == g[n] && (g[n] = 0), g[n] += m / e * a[h][n]; } + for (var o = new Uint8Array(a[0].length), n = 0; n < a[0].length; n++) o[n] = g[n]; + c.push(o); } - }).error(function(data, status, headers, config) {}); - $scope.showWordInfo = function(word) { - var modalInstance = $modal.open({ - animation: true, - templateUrl: "wordItemsTtemplate.html", - controller: "ShowWordController", - size: "lg", - resolve: { - items: function() { - return word.items; - }, - title: function() { - return word.getTextEntry(); + return c; + } +}, WaveSurfer.util.extend(WaveSurfer.Spectrogram, WaveSurfer.Observer); + +"use strict"; + +var elan = function() { + var elan = {}; + var _forEach = Array.prototype.forEach; + var _map = Array.prototype.map; + elan.TimeSlot = function(id, value) { + this.id = id; + this.value = value; + }; + elan.Annotation = function(id, value, timeslotRef1, timeslotRef2) { + this.id = id; + this.value = value; + this.timeslotRef1 = timeslotRef1; + this.timeslotRef2 = timeslotRef2; + }; + elan.Tier = function(id, linguisticTypeRef, defaultLocale, annotations) { + this.id = id; + this.defaultLocale = defaultLocale; + this.linguisticTypeRef = linguisticTypeRef; + this.annotations = annotations; + }; + elan.Document = function() { + this.mediaFile = ""; + this.mediaUrl = ""; + this.mediaType = ""; + this.timeslots = []; + this.tiers = []; + this.lastUsedTierId = 0; + this.lastUsedAnnoationId = 0; + this.lastUsedTimeSlotId = 0; + var timeslotExists = function(ts, list) { + for (var i = 0; i < list.length; i++) { + if (list[i].id == ts.id) { + return true; } } - }); - }; - $scope.showMetawordInfo = function(word) { - if (word.url && word.paradigm_url && word.etymology_url) { - var modalInstance = $modal.open({ - animation: true, - templateUrl: "wordMetawordTemplate.html", - controller: "ShowMetawordController", - size: "lg", - resolve: { - metawordUrl: function() { - return word.url; - }, - etymologyUrl: function() { - return word.paradigm_url; - }, - paradigmUrl: function() { - return word.etymology_url; + return false; + }; + this.getTimeSlot = function(slotId) { + for (var i = 0; i < this.timeslots.length; i++) { + var timeslot = this.timeslots[i]; + if (timeslot.id == slotId) { + return timeslot; + } + } + }.bind(this); + this.getTimeSlotByValue = function(value) { + for (var i = 0; i < this.timeslots.length; i++) { + var timeslot = this.timeslots[i]; + if (timeslot.value === value) { + return timeslot; + } + } + }.bind(this); + this.timeSlotRefToSeconds = function(slotId) { + var slot = this.getTimeSlot(slotId); + if (slot) { + return parseInt(slot.value) / 1e3; + } + }.bind(this); + this.getValidTimeslots = function() { + var validTimeslots = []; + for (var i = 0; i < this.tiers.length; i++) { + var tier = this.tiers[i]; + for (var j = 0; j < tier.annotations.length; j++) { + var annotation = tier.annotations[j]; + if (annotation instanceof elan.Annotation) { + var timeslot1 = this.getTimeSlot(annotation.timeslotRef1); + var timeslot2 = this.getTimeSlot(annotation.timeslotRef2); + if (typeof timeslot1 != "undefined" && typeof timeslot2 != "undefined") { + if (!timeslotExists(timeslot1, validTimeslots)) { + validTimeslots.push(timeslot1); + } + if (!timeslotExists(timeslot2, validTimeslots)) { + validTimeslots.push(timeslot2); + } + } } } + } + validTimeslots.sort(function(a, b) { + if (a.value > b.value) { + return 1; + } + if (a.value < b.value) { + return -1; + } + return 0; }); - } + return validTimeslots; + }.bind(this); + this.getTier = function(id) { + var tier = null; + for (var i = 0; i < this.tiers.length; i++) { + if (this.tiers[i].id === id) { + tier = this.tiers[i]; + break; + } + } + return tier; + }.bind(this); + this.importXML = function(xml) { + var header = xml.querySelector("HEADER"); + var inMilliseconds = header.getAttribute("TIME_UNITS") == "milliseconds"; + var media = header.querySelector("MEDIA_DESCRIPTOR"); + if (media) { + this.mediaUrl = media.getAttribute("MEDIA_URL"); + this.mediaType = media.getAttribute("MIME_TYPE"); + } + var properties = xml.querySelectorAll("PROPERTY"); + _forEach.call(properties, function(prop) { + var name = prop.getAttribute("NAME"); + if (name === "lastUsedAnnotationId") { + var c = prop.textContent.trim(); + this.lastUsedAnnoationId = parseInt(c); + } + }.bind(this)); + var timeSlots = xml.querySelectorAll("TIME_ORDER TIME_SLOT"); + _forEach.call(timeSlots, function(slot) { + var slotId = slot.getAttribute("TIME_SLOT_ID"); + var value = parseFloat(slot.getAttribute("TIME_VALUE")); + if (!inMilliseconds) { + value = Math.floor(value * 1e3); + } + var s = this.getTimeSlot(slotId); + if (typeof s == "undefined") { + this.timeslots.push(new elan.TimeSlot(slotId, value)); + } + }.bind(this)); + this.tiers = _map.call(xml.querySelectorAll("TIER"), function(tier) { + var tierId = tier.getAttribute("TIER_ID"); + var linguisticTypeRef = tier.getAttribute("LINGUISTIC_TYPE_REF"); + var defaultLocale = tier.getAttribute("DEFAULT_LOCALE"); + var annotations = _map.call(tier.querySelectorAll("ALIGNABLE_ANNOTATION"), function(node) { + var annotationId = node.getAttribute("ANNOTATION_ID"); + var value = node.querySelector("ANNOTATION_VALUE").textContent.trim(); + var start = node.getAttribute("TIME_SLOT_REF1"); + var end = node.getAttribute("TIME_SLOT_REF2"); + return new elan.Annotation(annotationId, value, start, end); + }, this); + return new elan.Tier(tierId, linguisticTypeRef, defaultLocale, annotations); + }, this); + }.bind(this); + this.exportXML = function() { + var doc = document.implementation.createDocument(null, "ANNOTATION_DOCUMENT", null); + var headerElement = doc.createElement("HEADER"); + headerElement.setAttribute("MEDIA_FILE", this.mediaFile); + headerElement.setAttribute("TIME_UNITS", "milliseconds"); + var mediaDescriptorElement = doc.createElement("MEDIA_DESCRIPTOR"); + mediaDescriptorElement.setAttribute("MEDIA_URL", this.mediaUrl); + headerElement.appendChild(mediaDescriptorElement); + var prop1Element = doc.createElement("PROPERTY"); + prop1Element.setAttribute("NAME", "URN"); + prop1Element.textContent = "urn:nl-mpi-tools-elan-eaf:dd04600d-3cc3-41a3-a102-548c7b8c0e45"; + headerElement.appendChild(prop1Element); + var prop2Element = doc.createElement("PROPERTY"); + prop2Element.setAttribute("NAME", "lastUsedAnnotationId"); + prop2Element.textContent = this.lastUsedAnnoationId.toString(); + headerElement.appendChild(prop2Element); + doc.documentElement.appendChild(headerElement); + var validTimeslots = this.getValidTimeslots(); + var timeOrderElement = doc.createElement("TIME_ORDER"); + validTimeslots.forEach(function(slot) { + var slotElement = doc.createElement("TIME_SLOT"); + slotElement.setAttribute("TIME_SLOT_ID", slot.id); + slotElement.setAttribute("TIME_VALUE", slot.value); + timeOrderElement.appendChild(slotElement); + }); + doc.documentElement.appendChild(timeOrderElement); + for (var i = 0; i < this.tiers.length; i++) { + var tier = this.tiers[i]; + var tierElement = doc.createElement("TIER"); + tierElement.setAttribute("TIER_ID", tier.id); + tierElement.setAttribute("LINGUISTIC_TYPE_REF", tier.linguisticTypeRef); + tierElement.setAttribute("DEFAULT_LOCALE", tier.defaultLocale); + for (var j = 0; j < tier.annotations.length; j++) { + var an = tier.annotations[j]; + var annotationElement = doc.createElement("ANNOTATION"); + var allignableAnnotationElement = doc.createElement("ALIGNABLE_ANNOTATION"); + allignableAnnotationElement.setAttribute("ANNOTATION_ID", an.id); + allignableAnnotationElement.setAttribute("TIME_SLOT_REF1", an.timeslotRef1); + allignableAnnotationElement.setAttribute("TIME_SLOT_REF2", an.timeslotRef2); + var annotationValueElement = doc.createElement("ANNOTATION_VALUE"); + annotationValueElement.textContent = an.value; + allignableAnnotationElement.appendChild(annotationValueElement); + annotationElement.appendChild(allignableAnnotationElement); + tierElement.appendChild(annotationElement); + } + doc.documentElement.appendChild(tierElement); + } + var serializer = new XMLSerializer(); + return serializer.serializeToString(doc); + }.bind(this); + this.createTier = function(linguisticTypeRef, defaultLocale) { + var tierId = "tier" + this.lastUsedTierId; + this.lastUsedTierId++; + this.tiers.push(new elan.Tier(tierId, linguisticTypeRef, "default-locale", [])); + return tierId; + }.bind(this); + this.createAnnotation = function(tierId, value, from, to) { + var tier = this.getTier(tierId); + if (tier != null) { + var ts1 = this.getTimeSlotByValue(from); + if (typeof ts1 == "undefined") { + ts1 = new elan.TimeSlot("ts" + this.lastUsedTimeSlotId, from); + this.lastUsedTimeSlotId++; + this.timeslots.push(ts1); + } + var ts2 = this.getTimeSlotByValue(to); + if (typeof ts2 == "undefined") { + ts2 = new elan.TimeSlot("ts" + this.lastUsedTimeSlotId, to); + this.lastUsedTimeSlotId++; + this.timeslots.push(ts2); + } + var annotationId = "an" + this.lastUsedAnnoationId; + this.lastUsedAnnoationId++; + var annotation = new elan.Annotation(annotationId, value, ts1.id, ts2.id); + tier.annotations.push(annotation); + return annotationId; + } + return null; + }.bind(this); }; -} ]); - -app.controller("ShowWordController", [ "$scope", "items", "title", function($scope, items, title) { - $scope.title = title; - $scope.items = items; -} ]); + return elan; +}(); -app.controller("ShowMetawordController", [ "$scope", "$http", "metawordUrl", "etymologyUrl", "paradigmUrl", function($scope, $http, metawordUrl, etymologyUrl, paradigmUrl) { +function WaveSurferController($scope) { var activeUrl = null; $scope.play = function(url) { if (!$scope.wavesurfer) { @@ -31825,7 +35280,7 @@ app.controller("ShowMetawordController", [ "$scope", "$http", "metawordUrl", "et $scope.isMediaFileAvailable = function() { return activeUrl != null; }; - $scope.$on("wavesurferInit", function(e, wavesurfer) { + $scope.$on("wavesurferInit", function(e, wavesurfer, container) { $scope.wavesurfer = wavesurfer; $scope.wavesurfer.on("play", function() { $scope.paused = false; @@ -31839,26 +35294,219 @@ app.controller("ShowMetawordController", [ "$scope", "$http", "metawordUrl", "et $scope.$apply(); }); }); - $http.get(metawordUrl).success(function(data, status, headers, config) { - if (data.corpus_id && data.corpus_client_id) { - $scope.metaword = data; + $scope.$on("modal.closing", function(e) { + $scope.wavesurfer.stop(); + $scope.wavesurfer.destroy(); + }); +} + +function getCookie(name) { + var nameEQ = name + "="; + var ca = document.cookie.split(";"); + for (var i = 0; i < ca.length; i++) { + var c = ca[i]; + while (c.charAt(0) == " ") c = c.substring(1, c.length); + if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length, c.length); + } + return null; +} + +var wrapPerspective = function(perspective) { + if (typeof perspective.fields == "undefined") { + return; + } + for (var i = 0; i < perspective.fields.length; i++) { + if (typeof perspective.fields[i].group !== "undefined") { + perspective.fields[i]._groupEnabled = true; } - }).error(function(data, status, headers, config) {}); - $http.get(etymologyUrl).success(function(data, status, headers, config) { - if (data.corpus_id && data.corpus_client_id) { - $scope.etymologies = data; + if (typeof perspective.fields[i].contains !== "undefined") { + perspective.fields[i]._containsEnabled = true; } - }).error(function(data, status, headers, config) {}); - $http.get(paradigmUrl).success(function(data, status, headers, config) { - if (data.corpus_id && data.corpus_client_id) { - $scope.paradigms = data; + } + return perspective; +}; + +var exportPerspective = function(perspective) { + var jsPerspective = { + fields: [] + }; + var positionCount = 1; + for (var i = 0; i < perspective.fields.length; i++) { + var field = JSON.parse(JSON.stringify(perspective.fields[i])); + field["position"] = positionCount; + positionCount += 1; + if (field.data_type !== "grouping_tag") { + field["level"] = "leveloneentity"; + } else { + field["level"] = "groupingentity"; } - }).error(function(data, status, headers, config) {}); -} ]); + if (field._groupEnabled) { + delete field._groupEnabled; + } + if (field._containsEnabled) { + delete field._containsEnabled; + } + if (field.contains) { + for (var j = 0; j < field.contains.length; j++) { + field.contains[j].level = "leveltwoentity"; + field.contains[j].position = positionCount; + positionCount += 1; + } + } + jsPerspective.fields.push(field); + } + return jsPerspective; +}; + +var cloneObject = function(oldObject) { + return JSON.parse(JSON.stringify(oldObject)); +}; + +var enableControls = function(controls, enabled) { + _.each(controls, function(value, key) { + controls[key] = enabled; + }); +}; + +var lingvodoc = {}; + +lingvodoc.Object = function(clientId, objectId) { + this.client_id = clientId; + this.object_id = objectId; + this.type = "abstract"; + this.getId = function() { + return this.client_id + "_" + this.object_id; + }; +}; + +lingvodoc.Object.prototype.equals = function(obj) { + return !!(this.client_id == obj.client_id && this.object_id == obj.object_id); +}; + +lingvodoc.Language = function(clientId, objectId, translation, translation_string) { + lingvodoc.Object.call(this, clientId, objectId); + this.type = "language"; + this.translation = translation; + this.translation_string = translation_string; + this.languages = []; + this.dictionaries = []; + this.equals = function(obj) { + return !!(this.client_id == obj.client_id && this.object_id == obj.object_id); + }; +}; + +lingvodoc.Language.fromJS = function(js) { + return new lingvodoc.Language(js.client_id, js.object_id, js.translation, js.translation_string); +}; + +lingvodoc.Language.prototype = new lingvodoc.Object(); + +lingvodoc.Language.prototype.constructor = lingvodoc.Language; + +lingvodoc.Dictionary = function(clientId, objectId, parentClientId, parentObjectId, translation, translation_string, status) { + lingvodoc.Object.call(this, clientId, objectId); + this.type = "dictionary"; + this.parent_client_id = parentClientId; + this.parent_object_id = parentObjectId; + this.translation = translation; + this.translation_string = translation_string; + this.status = status; + this.perspectives = []; + this.equals = function(obj) { + return lingvodoc.Object.prototype.equals.call(this, obj) && this.translation == obj.translation; + }; +}; + +lingvodoc.Dictionary.fromJS = function(js) { + return new lingvodoc.Dictionary(js.client_id, js.object_id, js.parent_client_id, js.parent_object_id, js.translation, js.translation_string, js.status); +}; + +lingvodoc.Dictionary.prototype = new lingvodoc.Object(); + +lingvodoc.Dictionary.prototype.constructor = lingvodoc.Dictionary; + +lingvodoc.Perspective = function(client_id, object_id, parent_client_id, parent_object_id, translation, translation_string, status, is_template, marked_for_deletion) { + lingvodoc.Object.call(this, client_id, object_id); + this.type = "perspective"; + this.parent_client_id = parent_client_id; + this.parent_object_id = parent_object_id; + this.translation = translation; + this.translation_string = translation_string; + this.status = status; + this.is_template = is_template; + this.marked_for_deletion = marked_for_deletion; + this.fields = []; + this.location = null; + this.blobs = []; + this.additional_metadata = {}; + this.equals = function(obj) { + return lingvodoc.Object.prototype.equals.call(this, obj) && this.translation == obj.translation; + }; +}; + +lingvodoc.Perspective.fromJS = function(js) { + var perspective = new lingvodoc.Perspective(js.client_id, js.object_id, js.parent_client_id, js.parent_object_id, js.translation, js.translation_string, js.status, js.is_template, js.marked_for_deletion); + if (_.has(js, "location") && _.has(js.location, "content")) { + perspective["location"] = { + lat: js.location.content.lat, + lng: js.location.content.lng + }; + } + if (_.has(js, "info") && js.info.type == "list") { + if (_.isArray(js.info.content)) { + perspective["blobs"] = _.map(js.info.content, function(e) { + var blob = new lingvodoc.Blob(e.info.content.client_id, e.info.content.object_id, e.info.content.name, e.info.content.data_type); + blob.url = e.info.content.content; + return blob; + }); + } + } + perspective.additional_metadata = js.additional_metadata; + return perspective; +}; + +lingvodoc.Perspective.prototype = new lingvodoc.Object(); + +lingvodoc.Perspective.prototype.constructor = lingvodoc.Perspective; + +lingvodoc.User = function(id, login, name, email, intl_name, about, signup_date, organizations) { + this.id = id; + this.login = login; + this.name = name; + this.email = email; + this.intl_name = intl_name; + this.about = about; + this.signup_date = signup_date; + this.organizations = organizations; + this.equals = function(obj) { + return this.id == obj.id; + }; +}; + +lingvodoc.User.fromJS = function(js) { + return new lingvodoc.User(js.id, js.login, js.name, js.email, js.intl_name, js.about, js.signup_date, js.organizations); +}; -"use strict"; +lingvodoc.Blob = function(clientId, objectId, name, data_type) { + lingvodoc.Object.call(this, clientId, objectId); + this.type = "blob"; + this.name = name; + this.data_type = data_type; + this.url = null; + this.equals = function(obj) { + return lingvodoc.Object.prototype.equals.call(this, obj) && this.name == obj.name; + }; +}; + +lingvodoc.Blob.fromJS = function(js) { + return new lingvodoc.Blob(js.client_id, js.object_id, js.name, js.data_type); +}; + +lingvodoc.Blob.prototype = new lingvodoc.Object(); + +lingvodoc.Blob.prototype.constructor = lingvodoc.Blob; -angular.module("EditDictionaryModule", [ "ui.bootstrap" ]).service("dictionaryService", function($http, $q) { +function lingvodocAPI($http, $q) { var addUrlParameter = function(url, key, value) { return url + (url.indexOf("?") >= 0 ? "&" : "?") + encodeURIComponent(key) + "=" + encodeURIComponent(value); }; @@ -31892,7 +35540,7 @@ angular.module("EditDictionaryModule", [ "ui.bootstrap" ]).service("dictionarySe var allLexicalEntriesUrl = url; allLexicalEntriesUrl = addUrlParameter(allLexicalEntriesUrl, "start_from", offset); allLexicalEntriesUrl = addUrlParameter(allLexicalEntriesUrl, "count", count); - $http.get(url).success(function(data, status, headers, config) { + $http.get(allLexicalEntriesUrl).success(function(data, status, headers, config) { if (data.lexical_entries && angular.isArray(data.lexical_entries)) { deferred.resolve(data.lexical_entries); } else { @@ -31917,7 +35565,7 @@ angular.module("EditDictionaryModule", [ "ui.bootstrap" ]).service("dictionarySe }); return deferred.promise; }; - var getPerspectiveFields = function(url) { + var getPerspectiveDictionaryFields = function(url) { var deferred = $q.defer(); $http.get(url).success(function(data, status, headers, config) { if (angular.isArray(data.fields)) { @@ -31931,6 +35579,21 @@ angular.module("EditDictionaryModule", [ "ui.bootstrap" ]).service("dictionarySe }); return deferred.promise; }; + var getPerspectiveDictionaryFieldsNew = function(perspective) { + var deferred = $q.defer(); + var url = "/dictionary/" + perspective.parent_client_id + "/" + perspective.parent_object_id + "/perspective/" + perspective.client_id + "/" + perspective.object_id + "/fields"; + $http.get(url).success(function(data, status, headers, config) { + if (_.isArray(data.fields)) { + var fields = perspectiveToDictionaryFields(data.fields); + deferred.resolve(fields); + } else { + deferred.reject("An error occurred while fetching perspective fields"); + } + }).error(function(data, status, headers, config) { + deferred.reject("An error occurred while fetching perspective fields"); + }); + return deferred.promise; + }; var removeValue = function(entry, field, fieldValue, parent) { var deferred = $q.defer(); var url; @@ -31963,18 +35626,18 @@ angular.module("EditDictionaryModule", [ "ui.bootstrap" ]).service("dictionarySe } return deferred.promise; }; - var saveValue = function(entry, field, value, parent) { + var saveValue = function(dictionaryClientId, dictionaryObjectId, perspectiveClientId, perspectiveObjectId, entry, field, value, parent) { var deferred = $q.defer(); var url; if (field.level) { switch (field.level) { case "leveloneentity": - url = "/dictionary/" + encodeURIComponent(dictionaryClientId) + "/" + encodeURIComponent(dictionaryObjectId) + "/perspective/" + encodeURIComponent(perspectiveClientId) + "/" + encodeURIComponent(perspectiveId) + "/lexical_entry/" + encodeURIComponent(entry.client_id) + "/" + encodeURIComponent(entry.object_id) + "/leveloneentity"; + url = "/dictionary/" + encodeURIComponent(dictionaryClientId) + "/" + encodeURIComponent(dictionaryObjectId) + "/perspective/" + encodeURIComponent(perspectiveClientId) + "/" + encodeURIComponent(perspectiveObjectId) + "/lexical_entry/" + encodeURIComponent(entry.client_id) + "/" + encodeURIComponent(entry.object_id) + "/leveloneentity"; break; case "leveltwoentity": if (parent.client_id && parent.object_id) { - url = "/dictionary/" + encodeURIComponent(dictionaryClientId) + "/" + encodeURIComponent(dictionaryObjectId) + "/perspective/" + encodeURIComponent(perspectiveClientId) + "/" + encodeURIComponent(perspectiveId) + "/lexical_entry/" + encodeURIComponent(entry.client_id) + "/" + encodeURIComponent(entry.object_id) + "/leveloneentity/" + encodeURIComponent(parent.client_id) + "/" + encodeURIComponent(parent.object_id) + "/leveltwoentity"; + url = "/dictionary/" + encodeURIComponent(dictionaryClientId) + "/" + encodeURIComponent(dictionaryObjectId) + "/perspective/" + encodeURIComponent(perspectiveClientId) + "/" + encodeURIComponent(perspectiveObjectId) + "/lexical_entry/" + encodeURIComponent(entry.client_id) + "/" + encodeURIComponent(entry.object_id) + "/leveloneentity/" + encodeURIComponent(parent.client_id) + "/" + encodeURIComponent(parent.object_id) + "/leveltwoentity"; } else { deferred.reject("Attempting to save Level2 entry with no Level1 entry."); return deferred.promise; @@ -31985,14 +35648,10 @@ angular.module("EditDictionaryModule", [ "ui.bootstrap" ]).service("dictionarySe deferred.reject("Unknown level."); return deferred.promise; } - var entryObject = value.export(); - entryObject["entity_type"] = field.entity_type; - entryObject["locale_id"] = 1; - entryObject["additional_metadata"] = {}; - $http.post(url, entryObject).success(function(data, status, headers, config) { - entryObject.client_id = data.client_id; - entryObject.object_id = data.object_id; - deferred.resolve(entryObject); + $http.post(url, value).success(function(data, status, headers, config) { + value.client_id = data.client_id; + value.object_id = data.object_id; + deferred.resolve(value); }).error(function(data, status, headers, config) { deferred.reject("An error occurred while saving value"); }); @@ -32010,811 +35669,970 @@ angular.module("EditDictionaryModule", [ "ui.bootstrap" ]).service("dictionarySe }); return deferred.promise; }; - return { - getLexicalEntries: getLexicalEntries, - getLexicalEntriesCount: getLexicalEntriesCount, - getPerspectiveFields: getPerspectiveFields, - addNewLexicalEntry: addNewLexicalEntry, - saveValue: saveValue, - removeValue: removeValue - }; -}).directive("wavesurfer", function() { - return { - restrict: "E", - link: function($scope, $element, $attrs) { - $element.css("display", "block"); - var options = angular.extend({ - container: $element[0] - }, $attrs); - var wavesurfer = WaveSurfer.create(options); - if ($attrs.url) { - wavesurfer.load($attrs.url, $attrs.data || null); - } - $scope.$emit("wavesurferInit", wavesurfer); - } - }; -}).directive("onReadFile", function($parse) { - return { - restrict: "A", - scope: false, - link: function(scope, element, attrs) { - var fn = $parse(attrs.onReadFile); - element.on("change", function(onChangeEvent) { - var reader = new FileReader(); - var file = (onChangeEvent.srcElement || onChangeEvent.target).files[0]; - reader.onload = function(onLoadEvent) { - scope.$apply(function() { - var b64file = btoa(onLoadEvent.target.result); - fn(scope, { - $fileName: file.name, - $fileType: file.type, - $fileContent: b64file - }); - }); - }; - reader.readAsBinaryString(file); - }); - } - }; -}).controller("EditDictionaryController", [ "$scope", "$http", "$modal", "$log", "dictionaryService", function($scope, $http, $modal, $log, dictionaryService) { - var currentClientId = $("#clientId").data("lingvodoc"); - var dictionaryClientId = $("#dictionaryClientId").data("lingvodoc"); - var dictionaryObjectId = $("#dictionaryObjectId").data("lingvodoc"); - var perspectiveClientId = $("#perspectiveClientId").data("lingvodoc"); - var perspectiveId = $("#perspectiveId").data("lingvodoc"); - WaveSurferController.call(this, $scope); - $scope.perspectiveFields = []; - $scope.lexicalEntries = []; - $scope.fields = []; - $scope.dictionaryTable = []; - $scope.pageIndex = 1; - $scope.pageSize = 50; - $scope.pageCount = 1; - var enabledInputs = []; - $scope.getFieldValues = function(entry, field) { - var value; - var values = []; - if (entry && entry.contains) { - if (field.isGroup) { - for (var fieldIndex = 0; fieldIndex < field.contains.length; fieldIndex++) { - var subField = field.contains[fieldIndex]; - for (var valueIndex = 0; valueIndex < entry.contains.length; valueIndex++) { - value = entry.contains[valueIndex]; - if (value.entity_type == subField.entity_type) { - values.push(value); - } - } - } + var getConnectedWords = function(clientId, objectId) { + var deferred = $q.defer(); + var url = "/lexical_entry/" + encodeURIComponent(clientId) + "/" + encodeURIComponent(objectId) + "/connected"; + $http.get(url).success(function(data, status, headers, config) { + if (angular.isArray(data.words)) { + deferred.resolve(data.words); } else { - for (var i = 0; i < entry.contains.length; i++) { - value = entry.contains[i]; - if (value.entity_type == field.entity_type) { - values.push(value); - } - } + deferred.reject("An error occurred while fetching connected words"); } - } - return values; + }).error(function(data, status, headers, config) { + deferred.reject("An error occurred while fetching connected words"); + }); + return deferred.promise; }; - $scope.getPage = function(pageNumber) { - if (pageNumber > 0 && pageNumber <= $scope.pageCount) { - $scope.pageIndex = pageNumber; - var r = dictionaryService.getLexicalEntries(url, (pageNumber - 1) * $scope.pageSize, $scope.pageSize); - r.then(function() {}); - } + var linkEntries = function(e1, e2, entityType) { + var deferred = $q.defer(); + var linkObject = { + entity_type: entityType, + connections: [ { + client_id: e1.client_id, + object_id: e1.object_id + }, { + client_id: e2.client_id, + object_id: e2.object_id + } ] + }; + var url = "/group_entity"; + $http.post(url, linkObject).success(function(data, status, headers, config) { + deferred.resolve(data); + }).error(function(data, status, headers, config) { + deferred.reject("An error occurred while connecting 2 entries"); + }); + return deferred.promise; }; - $scope.range = function(min, max, step) { - step = step || 1; - var input = []; - for (var i = min; i <= max; i += step) { - input.push(i); - } - return input; + var search = function(query, tagsOnly) { + var deferred = $q.defer(); + var url = "/basic_search?leveloneentity=" + encodeURIComponent(query) + "&can_add_tags=" + encodeURIComponent((!!tagsOnly).toString()); + $http.get(url).success(function(data, status, headers, config) { + var r = data.map(function(e) { + var perspective = lingvodoc.Perspective.fromJS(e); + return getPerspectiveOriginById(perspective.client_id, perspective.object_id); + }); + $q.all(r).then(function(paths) { + var out = []; + angular.forEach(data, function(entry, i) { + entry.lexical_entry["origin"] = paths[i]; + out.push(entry.lexical_entry); + }); + deferred.resolve(out); + }, function(reason) { + deferred.reject("An error occurred while doing basic search"); + }); + }).error(function(data, status, headers, config) { + deferred.reject("An error occurred while doing basic search"); + }); + return deferred.promise; }; - $scope.enableInput = function(clientId, objectId, entityType) { - if (!$scope.isInputEnabled(clientId, objectId, entityType)) { - enabledInputs.push({ - clientId: clientId, - objectId: objectId, - entityType: entityType + var approve = function(url, entity, status) { + var deferred = $q.defer(); + if (status) { + $http.patch(url, entity).success(function(data, status, headers, config) { + deferred.resolve(data); + }).error(function(data, status, headers, config) { + deferred.reject("An error occurred while trying to change approval status "); }); } else { - $scope.disableInput(clientId, objectId, entityType); - } - }; - $scope.isInputEnabled = function(clientId, objectId, entityType) { - for (var i = 0; i < enabledInputs.length; i++) { - var checkItem = enabledInputs[i]; - if (checkItem.clientId === clientId && checkItem.objectId == objectId && checkItem.entityType === entityType) { - return true; - } - } - return false; - }; - $scope.disableInput = function(clientId, objectId, entityType) { - var removeIndex = -1; - for (var i = 0; i < enabledInputs.length; i++) { - var checkItem = enabledInputs[i]; - if (checkItem.clientId === clientId && checkItem.objectId == objectId && checkItem.entityType === entityType) { - removeIndex = i; - break; - } - } - if (removeIndex >= 0) { - enabledInputs.splice(removeIndex, 1); - } - }; - $scope.addedByUser = function(entry) { - return entry.client_id == $("#clientId").data("lingvodoc"); - }; - $scope.addNewLexicalEntry = function() { - var createLexicalEntryUrl = $("#createLexicalEntryUrl").data("lingvodoc"); - dictionaryService.addNewLexicalEntry(createLexicalEntryUrl).then(function(data) { - $scope.lexicalEntries.unshift({ - client_id: data.client_id, - object_id: data.object_id, - contains: [] + var config = { + method: "DELETE", + url: url, + data: entity, + headers: { + "Content-Type": "application/json;charset=utf-8" + } + }; + $http(config).success(function(data, status, headers, config) { + deferred.resolve(data); + }).error(function(data, status, headers, config) { + deferred.reject("An error occurred while trying to change approval status "); }); - }, function(reason) { - $log.error(reason); - }); - }; - $scope.saveTextValue = function(entry, field, event, parent) { - if (event.target.value) { - $scope.saveValue(entry, field, new model.TextValue(event.target.value), parent); } + return deferred.promise; }; - $scope.saveSoundValue = function(entry, field, fileName, fileType, fileContent, parent) { - var value = new model.SoundValue(fileName, fileType, fileContent); - $scope.saveValue(entry, field, value, parent); - }; - $scope.saveImageValue = function(entry, field, fileName, fileType, fileContent, parent) { - var value = new model.ImageValue(fileName, fileType, fileContent); - $scope.saveValue(entry, field, value, parent); + var approveAll = function(url) { + var deferred = $q.defer(); + $http.patch(url).success(function(data, status, headers, config) { + deferred.resolve(data); + }).error(function(data, status, headers, config) { + deferred.reject("An error occurred while trying to change approval status "); + }); + return deferred.promise; }; - $scope.saveMarkupValue = function(entry, field, fileName, fileType, fileContent, parent) { - var value = new model.MarkupValue(fileName, fileType, fileContent); - $scope.saveValue(entry, field, value, parent); + var getDictionaryProperties = function(dictionary) { + var deferred = $q.defer(); + var url = "/dictionary/" + encodeURIComponent(dictionary.client_id) + "/" + encodeURIComponent(dictionary.object_id); + $http.get(url).success(function(data, status, headers, config) { + deferred.resolve(data); + }).error(function(data, status, headers, config) { + deferred.reject("An error occurred while trying to get dictionary properties"); + }); + return deferred.promise; }; - $scope.saveValue = function(entry, field, value, parent) { - dictionaryService.saveValue(entry, field, value, parent).then(function(data) { - for (var i = 0; i < $scope.lexicalEntries.length; i++) { - if ($scope.lexicalEntries[i].object_id == entry.object_id && $scope.lexicalEntries[i].client_id == entry.client_id) { - $scope.lexicalEntries[i].contains.push(data); - break; - } - } - $scope.disableInput(entry.client_id, entry.object_id, field.entity_type); - }, function(reason) { - $log.error(reason); + var setDictionaryProperties = function(dictionary, properties) { + var deferred = $q.defer(); + var url = "/dictionary/" + encodeURIComponent(dictionary.client_id) + "/" + encodeURIComponent(dictionary.object_id); + $http.put(url, properties).success(function(data, status, headers, config) { + deferred.resolve(data); + }).error(function(data, status, headers, config) { + deferred.reject("An error occurred while trying to get dictionary properties"); }); + return deferred.promise; }; - $scope.removeValue = function(entry, field, fieldValue, parent) { - dictionaryService.removeValue(entry, field, fieldValue, parent).then(function(data) { - for (var i = 0; i < $scope.lexicalEntries.length; i++) { - if ($scope.lexicalEntries[i].object_id == entry.object_id && $scope.lexicalEntries[i].client_id == entry.client_id) { - var lexicalEntry = $scope.lexicalEntries[i]; - for (var j = 0; j < lexicalEntry.contains.length; j++) { - if (lexicalEntry.contains[j].client_id == fieldValue.client_id && lexicalEntry.contains[j].object_id == fieldValue.object_id) { - $scope.lexicalEntries[i].contains[j].marked_for_deletion = true; - } - } - break; - } - } - }, function(reason) { - $log.error(reason); + var removeDictionary = function(dictionary) { + var deferred = $q.defer(); + var url = "/dictionary/" + encodeURIComponent(dictionary.client_id) + "/" + encodeURIComponent(dictionary.object_id); + $http.delete(url).success(function(data, status, headers, config) { + deferred.resolve(); + }).error(function(data, status, headers, config) { + deferred.reject("An error occurred while trying to delete dictionary"); }); + return deferred.promise; }; - $scope.editGroup = function(entry, field, values) { - var modalInstance = $modal.open({ - animation: true, - templateUrl: "editGroupModal.html", - controller: "editGroupController", - size: "lg", - resolve: { - groupParams: function() { - return { - entry: entry, - field: field, - values: values - }; + var getLanguages = function(url) { + var deferred = $q.defer(); + var flatLanguages = function(languages) { + var flat = []; + for (var i = 0; i < languages.length; i++) { + var language = languages[i]; + flat.push(languages[i]); + if (language.contains && language.contains.length > 0) { + var childLangs = flatLanguages(language.contains); + flat = flat.concat(childLangs); } } + return flat; + }; + $http.get(url).success(function(data, status, headers, config) { + deferred.resolve(flatLanguages(data.languages)); + }).error(function(data, status, headers, config) { + deferred.reject("An error occurred while trying to get languages"); }); - modalInstance.result.then(function(value) {}, function() {}); + return deferred.promise; }; - $scope.editGroupingTag = function(entry, field, values) { - var modalInstance = $modal.open({ - animation: true, - templateUrl: "editGroupingTagModal.html", - controller: "editGroupingTagController", - size: "lg", - resolve: { - groupParams: function() { - return { - clientId: entry.client_id, - objectId: entry.object_id, - fields: $scope.fields - }; - } - } + var setDictionaryStatus = function(dictionary, status) { + var deferred = $q.defer(); + var url = "/dictionary/" + dictionary.client_id + "/" + dictionary.object_id + "/state"; + $http.put(url, { + status: status + }).success(function(data, status, headers, config) { + deferred.resolve(data); + }).error(function(data, status, headers, config) { + deferred.reject("An error occurred while trying to set dictionary status"); }); - modalInstance.result.then(function(value) {}, function() {}); + return deferred.promise; }; - $scope.annotate = function(soundEntity, markupEntity) { - var modalInstance = $modal.open({ - animation: true, - templateUrl: "annotationModal.html", - controller: "AnnotationController", - size: "lg", - resolve: { - soundUrl: function() { - return soundEntity.content; - }, - annotationUrl: function() { - return markupEntity.content; - } - } + var setPerspectiveStatus = function(dictionary, perspective, status) { + var deferred = $q.defer(); + var url = "/dictionary/" + dictionary.client_id + "/" + dictionary.object_id + "/perspective/" + perspective.client_id + "/" + perspective.object_id + "/state"; + $http.put(url, { + status: status + }).success(function(data, status, headers, config) { + deferred.resolve(data); + }).error(function(data, status, headers, config) { + deferred.reject("An error occurred while trying to set perspective status"); }); + return deferred.promise; }; - $scope.$watch("lexicalEntries", function(updatedEntries) { - var getFieldValues = function(entry, field) { - var value; - var values = []; - if (entry && entry.contains) { - if (field.isGroup) { - for (var fieldIndex = 0; fieldIndex < field.contains.length; fieldIndex++) { - var subField = field.contains[fieldIndex]; - for (var valueIndex = 0; valueIndex < entry.contains.length; valueIndex++) { - value = entry.contains[valueIndex]; - if (value.entity_type == subField.entity_type) { - values.push(value); - } - } - } - } else { - for (var i = 0; i < entry.contains.length; i++) { - value = entry.contains[i]; - if (value.entity_type == field.entity_type) { - values.push(value); - } - } - } - } - return values; - }; - var mapFieldValues = function(allEntries, allFields) { - var result = []; - for (var i = 0; i < allEntries.length; i++) { - var entryRow = []; - for (var j = 0; j < allFields.length; j++) { - entryRow.push(getFieldValues(allEntries[i], allFields[j])); - } - result.push(entryRow); - } - return result; - }; - $scope.dictionaryTable = mapFieldValues(updatedEntries, $scope.fields); - }, true); - dictionaryService.getPerspectiveFields($("#getPerspectiveFieldsUrl").data("lingvodoc")).then(function(fields) { - $scope.fields = fields; - dictionaryService.getLexicalEntries($("#allLexicalEntriesUrl").data("lingvodoc"), $scope.pageIndex, $scope.pageSize).then(function(lexicalEntries) { - $scope.lexicalEntries = lexicalEntries; - }, function(reason) { - $log.error(reason); + var setPerspectiveProperties = function(dictionary, perspective) { + var deferred = $q.defer(); + var url = "/dictionary/" + dictionary.client_id + "/" + dictionary.object_id + "/perspective/" + perspective.client_id + "/" + perspective.object_id; + $http.put(url, perspective).success(function(data, status, headers, config) { + deferred.resolve(data); + }).error(function(data, status, headers, config) { + deferred.reject("Failed to update perspective properties"); }); - }, function(reason) { - $log.error(reason); - }); - dictionaryService.getLexicalEntriesCount($("#allLexicalEntriesCountUrl").data("lingvodoc")).then(function(totalEntriesCount) { - $scope.pageCount = Math.ceil(totalEntriesCount / $scope.pageSize); - }, function(reason) { - $log.error(reason); - }); -} ]).controller("AnnotationController", [ "$scope", "$http", "soundUrl", "annotationUrl", function($scope, $http, soundUrl, annotationUrl) { - var activeUrl = null; - var createRegions = function(annotaion) { - if (annotaion instanceof elan.Document) { - annotaion.tiers.forEach(function(tier) { - tier.annotations.forEach(function(a) { - var offset1 = annotaion.timeSlotRefToSeconds(a.timeslotRef1); - var offset2 = annotaion.timeSlotRefToSeconds(a.timeslotRef2); - var r = $scope.wavesurfer.addRegion({ - id: a.id, - start: offset1, - end: offset2, - color: "rgba(0, 255, 0, 0.1)" - }); - }); - }); - } + return deferred.promise; }; - var loadAnnotation = function(url) { + var getPerspectiveFieldsNew = function(perspective) { + var deferred = $q.defer(); + var url = "/dictionary/" + perspective.parent_client_id + "/" + perspective.parent_object_id + "/perspective/" + perspective.client_id + "/" + perspective.object_id + "/fields"; $http.get(url).success(function(data, status, headers, config) { - try { - var xml = new DOMParser().parseFromString(data, "application/xml"); - var annotation = new elan.Document(); - annotation.importXML(xml); - $scope.annotation = annotation; - createRegions(annotation); - } catch (e) { - alert("Failed to parse ELAN annotation: " + e); - } - }).error(function(data, status, headers, config) {}); + deferred.resolve(data.fields); + }).error(function(data, status, headers, config) { + deferred.reject("Failed to load perspective fields"); + }); + return deferred.promise; }; - $scope.paused = true; - $scope.annotation = null; - $scope.playPause = function() { - if ($scope.wavesurfer) { - $scope.wavesurfer.playPause(); - } + var getPerspectiveFields = function(url) { + var deferred = $q.defer(); + $http.get(url).success(function(data, status, headers, config) { + deferred.resolve(data.fields); + }).error(function(data, status, headers, config) { + deferred.reject("Failed to load perspective fields"); + }); + return deferred.promise; }; - $scope.playAnnotation = function(a) { - if ($scope.wavesurfer && $scope.annotation) { - var offset1 = $scope.annotation.timeSlotRefToSeconds(a.timeslotRef1); - var offset2 = $scope.annotation.timeSlotRefToSeconds(a.timeslotRef2); - $scope.wavesurfer.play(offset1, offset2); - } + var setPerspectiveFields = function(url, fields) { + var deferred = $q.defer(); + $http.post(url, fields).success(function(data, status, headers, config) { + deferred.resolve(data.fields); + }).error(function(data, status, headers, config) { + deferred.reject("Failed to save perspective fields"); + }); + return deferred.promise; }; - $scope.selectRegion = function() {}; - $scope.$on("wavesurferInit", function(e, wavesurfer) { - $scope.wavesurfer = wavesurfer; - if ($scope.wavesurfer.enableDragSelection) { - $scope.wavesurfer.enableDragSelection({ - color: "rgba(0, 255, 0, 0.1)" - }); - } - $scope.wavesurfer.on("play", function() { - $scope.paused = false; + var removePerspective = function(perspective) { + var deferred = $q.defer(); + var url = "/dictionary/" + perspective.parent_client_id + "/" + perspective.parent_object_id + "/perspective/" + perspective.client_id + "/" + perspective.object_id; + $http.delete(url).success(function(data, status, headers, config) { + deferred.resolve(); + }).error(function(data, status, headers, config) { + deferred.reject("An error occurred while trying to delete perspective"); }); - $scope.wavesurfer.on("pause", function() { - $scope.paused = true; + return deferred.promise; + }; + var getUserInfo = function(userId, clientId) { + var deferred = $q.defer(); + var url = "/user" + "?client_id= " + encodeURIComponent(clientId) + "&user_id= " + encodeURIComponent(userId); + $http.get(url).success(function(data, status, headers, config) { + deferred.resolve(data); + }).error(function(data, status, headers, config) { + deferred.reject("Failed to get user info"); }); - $scope.wavesurfer.on("finish", function() { - $scope.paused = true; - $scope.wavesurfer.seekTo(0); - $scope.$apply(); + return deferred.promise; + }; + var setUserInfo = function(userId, clientId, userInfo) { + var deferred = $q.defer(); + var url = "/user" + "?client_id= " + encodeURIComponent(clientId) + "&user_id= " + encodeURIComponent(userId); + $http.post(url, userInfo).success(function(data, status, headers, config) { + deferred.resolve(data); + }).error(function(data, status, headers, config) { + deferred.reject("Failed to set user info"); }); - $scope.wavesurfer.on("region-click", function(region, event) {}); - $scope.wavesurfer.on("region-dblclick", function(region, event) { - region.remove(region); + return deferred.promise; + }; + var getOrganizations = function() { + var deferred = $q.defer(); + $http.get("/organization_list").success(function(data, status, headers, config) { + deferred.resolve(data.organizations); + }).error(function(data, status, headers, config) { + deferred.reject("Failed to fetch list of organizations"); }); - $scope.wavesurfer.once("ready", function() { - loadAnnotation(annotationUrl); - $scope.$apply(); + return deferred.promise; + }; + var createOrganization = function(org) { + var deferred = $q.defer(); + $http.post("/organization", org).success(function(data, status, headers, config) { + deferred.resolve(data); + }).error(function(data, status, headers, config) { + deferred.reject("Failed to create organization"); }); - $scope.wavesurfer.load(soundUrl); - }); - $scope.$on("modal.closing", function(e) { - $scope.wavesurfer.stop(); - $scope.wavesurfer.destroy(); - }); -} ]).controller("editGroupController", [ "$scope", "$http", "$modalInstance", "$log", "groupParams", function($scope, $http, $modalInstance, $log, groupParams) { - var dictionaryClientId = $("#dictionaryClientId").data("lingvodoc"); - var dictionaryObjectId = $("#dictionaryObjectId").data("lingvodoc"); - var perspectiveClientId = $("#perspectiveClientId").data("lingvodoc"); - var perspectiveId = $("#perspectiveId").data("lingvodoc"); - var enabledInputs = []; - WaveSurferController.call(this, $scope); - $scope.title = groupParams.field.entity_type; - $scope.fields = groupParams.field.contains; - $scope.parentEntry = groupParams.entry; - var createVirtualEntries = function(values) { - var virtualEntries = []; - var addValue = function(value, entries) { - var createNewEntry = true; - if (value.additional_metadata) { - for (var entryIndex = 0; entryIndex < entries.length; entryIndex++) { - var currentEntry = entries[entryIndex]; - if (entries[entryIndex].client_id == value.client_id && entries[entryIndex].row_id == value.additional_metadata.row_id) { - entries[entryIndex].contains.push(value); - return; - } - } - entries.push({ - client_id: $scope.parentEntry.client_id, - object_id: $scope.parentEntry.object_id, - row_id: value.additional_metadata.row_id, - contains: [ value ] + return deferred.promise; + }; + var getOrganization = function(orgId) { + var deferred = $q.defer(); + var url = "/organization/" + encodeURIComponent(orgId); + $http.get(url).success(function(data, status, headers, config) { + var requests = []; + var users = []; + var promises = data.users.map(function(userId) { + return $http.get("/user" + "?user_id= " + encodeURIComponent(userId)); + }); + $q.all(promises).then(function(results) { + angular.forEach(results, function(result) { + users.push(result.data); }); - } - }; - for (var i = 0; i < values.length; i++) { - var value = values[i]; - addValue(value, virtualEntries); - } - return virtualEntries; + data.users = users; + deferred.resolve(data); + }); + }).error(function(data, status, headers, config) { + deferred.reject("Failed to get information about organization"); + }); + return deferred.promise; }; - $scope.entries = createVirtualEntries(groupParams.values); - $scope.fieldsIdx = []; - $scope.fieldsValues = []; - $scope.mapFieldValues = function(allEntries, allFields) { - $scope.fieldsValues = []; - $scope.fieldsIdx = []; - for (var i = 0; i < allEntries.length; i++) { - var entryRow = []; - for (var j = 0; j < allFields.length; j++) { - entryRow.push($scope.getFieldValues(allEntries[i], allFields[j])); - } - $scope.fieldsValues.push(entryRow); - } - for (var k = 0; k < allFields.length; k++) { - $scope.fieldsIdx.push(allFields[k]); - } + var editOrganization = function(org) { + var deferred = $q.defer(); + var url = "/organization/" + encodeURIComponent(org.organization_id); + $http.put(url, org).success(function(data, status, headers, config) { + deferred.resolve(data); + }).error(function(data, status, headers, config) { + deferred.reject("Failed to change information about organization"); + }); + return deferred.promise; }; - $scope.getFieldValues = function(entry, field) { - var value; - var values = []; - if (entry && entry.contains) { - if (field.isGroup) { - for (var fieldIndex = 0; fieldIndex < field.contains.length; fieldIndex++) { - var subField = field.contains[fieldIndex]; - for (var valueIndex = 0; valueIndex < entry.contains.length; valueIndex++) { - value = entry.contains[valueIndex]; - if (value.entity_type == subField.entity_type) { - values.push(value); - } - } - } + var searchUsers = function(query) { + var deferred = $q.defer(); + $http.get("/users?search=" + encodeURIComponent(query)).success(function(data, status, headers, config) { + deferred.resolve(data.users); + }).error(function(data, status, headers, config) { + deferred.reject("Failed to search for users"); + }); + return deferred.promise; + }; + var getDictionaries = function(query) { + var deferred = $q.defer(); + $http.post("/dictionaries", query).success(function(data, status, headers, config) { + if (_.isArray(data.dictionaries)) { + deferred.resolve(_.map(data.dictionaries, function(d) { + return lingvodoc.Dictionary.fromJS(d); + })); } else { - for (var i = 0; i < entry.contains.length; i++) { - value = entry.contains[i]; - if (value.entity_type == field.entity_type) { - values.push(value); - } - } + deferred.reject("Failed to fetch dictionaries list. Malformed response."); } - } - return values; - }; - $scope.addNewEntry = function() { - var maxRowId = 0; - for (var i = 0; i < $scope.entries.length; i++) { - maxRowId = Math.max(maxRowId, $scope.entries[i].row_id); - } - var rowId = maxRowId + 1; - $scope.entries.push({ - row_id: rowId, - client_id: dictionaryClientId, - object_id: $scope.parentEntry.object_id, - contains: [] + }).error(function(data, status, headers, config) { + deferred.reject("Failed to fetch dictionaries list"); }); + return deferred.promise; }; - $scope.enableInput = function(clientId, objectId, entityType) { - if (!$scope.isInputEnabled(clientId, objectId, entityType)) { - enabledInputs.push({ - clientId: clientId, - objectId: objectId, - entityType: entityType - }); - } + var getPerspectiveById = function(client_id, object_id) { + var deferred = $q.defer(); + var url = "/perspective/" + encodeURIComponent(client_id) + "/" + encodeURIComponent(object_id); + $http.get(url).success(function(data, status, headers, config) { + deferred.resolve(lingvodoc.Perspective.fromJS(data)); + }).error(function(data, status, headers, config) { + deferred.reject("Failed to fetch perspective"); + }); + return deferred.promise; }; - $scope.isInputEnabled = function(clientId, objectId, entityType) { - for (var i = 0; i < enabledInputs.length; i++) { - var checkItem = enabledInputs[i]; - if (checkItem.clientId === clientId && checkItem.objectId == objectId && checkItem.entityType === entityType) { - return true; + var createPerspective = function(dictionary, perspective, fields) { + var deferred = $q.defer(); + var createPerspectiveUrl = "/dictionary/" + encodeURIComponent(dictionary.client_id) + "/" + encodeURIComponent(dictionary.object_id) + "/" + "perspective"; + $http.post(createPerspectiveUrl, perspective).success(function(data, status, headers, config) { + if (data.object_id && data.client_id) { + var perspective_client_id = data.client_id; + var perspective_object_id = data.object_id; + var setFieldsUrl = "/dictionary/" + encodeURIComponent(dictionary.client_id) + "/" + encodeURIComponent(dictionary.object_id) + "/perspective/" + encodeURIComponent(data.client_id) + "/" + encodeURIComponent(data.object_id) + "/fields"; + $http.post(setFieldsUrl, fields).success(function(data, status, headers, config) { + getPerspectiveById(perspective_client_id, perspective_object_id).then(function(perspective) { + deferred.resolve(perspective); + }, function(reason) { + deferred.reject(reason); + }); + }).error(function(data, status, headers, config) { + deferred.reject("Failed to create perspective fields"); + }); + } else { + deferred.reject("Failed to create perspective"); } - } - return false; + }).error(function(data, status, headers, config) { + deferred.reject("Failed to create perspective"); + }); + return deferred.promise; }; - $scope.disableInput = function(clientId, objectId, entityType) { - var removeIndex = -1; - for (var i = 0; i < enabledInputs.length; i++) { - var checkItem = enabledInputs[i]; - if (checkItem.clientId === clientId && checkItem.objectId == objectId && checkItem.entityType === entityType) { - removeIndex = i; - break; - } - } - if (removeIndex >= 0) { - enabledInputs.splice(removeIndex, 1); - } + var getAllPerspectives = function() { + var deferred = $q.defer(); + $http.get("/perspectives").success(function(data, status, headers, config) { + deferred.resolve(data.perspectives.map(function(p) { + return lingvodoc.Perspective.fromJS(p); + })); + }).error(function(data, status, headers, config) { + deferred.reject("Failed to fetch perspectives list"); + }); + return deferred.promise; }; - $scope.saveTextValue = function(entry, field, event, parent) { - if (event.target.value) { - $scope.saveValue(entry, field, new model.TextValue(event.target.value), parent); - } + var getDictionaryPerspectives = function(dictionary) { + var deferred = $q.defer(); + var perspectives = []; + var getPerspectivesUrl = "/dictionary/" + encodeURIComponent(dictionary.client_id) + "/" + encodeURIComponent(dictionary.object_id) + "/perspectives"; + $http.get(getPerspectivesUrl).success(function(data, status, headers, config) { + angular.forEach(data.perspectives, function(jspers) { + perspectives.push(lingvodoc.Perspective.fromJS(jspers)); + }); + deferred.resolve(perspectives); + }).error(function(data, status, headers, config) { + deferred.reject("Failed to fetch perspectives list"); + }); + return deferred.promise; }; - $scope.saveSoundValue = function(entry, field, fileName, fileType, fileContent, parent) { - var value = new model.SoundValue(fileName, fileType, fileContent); - $scope.saveValue(entry, field, value, parent); + var getDictionariesWithPerspectives = function(query) { + var deferred = $q.defer(); + getDictionaries(query).then(function(dictionaries) { + var r = dictionaries.map(function(d) { + return getDictionaryPerspectives(d); + }); + $q.all(r).then(function(results) { + angular.forEach(dictionaries, function(dictionary, index) { + dictionary.perspectives = results[index]; + }); + deferred.resolve(dictionaries); + }); + }, function() {}); + return deferred.promise; }; - $scope.saveImageValue = function(entry, field, fileName, fileType, fileContent, parent) { - var value = new model.ImageValue(fileName, fileType, fileContent); - $scope.saveValue(entry, field, value, parent); + var mergeDictionaries = function(tranlation, translation_string, d1, d2) { + var deferred = $q.defer(); + var req = { + translation: tranlation, + translation_string: translation_string, + language_client_id: d1.parent_client_id, + language_object_id: d1.parent_object_id, + dictionaries: [ { + client_id: d1.client_id, + object_id: d1.object_id + }, { + client_id: d2.client_id, + object_id: d2.object_id + } ] + }; + $http.post("/merge/dictionaries", req).success(function(data, status, headers, config) { + console.log(data); + deferred.resolve(data); + }).error(function(data, status, headers, config) { + deferred.reject("Failed to merge dictionaries"); + }); + return deferred.promise; }; - $scope.saveMarkupValue = function(entry, field, fileName, fileType, fileContent, parent) { - var value = new model.MarkupValue(fileName, fileType, fileContent); - $scope.saveValue(entry, field, value, parent); + var mergePerspectives = function(req) { + var deferred = $q.defer(); + $http.post("/merge/perspectives", req).success(function(data, status, headers, config) { + deferred.resolve(data); + }).error(function(data, status, headers, config) { + deferred.reject("Failed to merge perspectives"); + }); + return deferred.promise; }; - $scope.addedByUser = function(entry) { - return entry.client_id == $("#clientId").data("lingvodoc"); + var getSuggestionLexicalEntry = function(entry) { + var deferred = $q.defer(); + getLexicalEntry(entry.suggestion[0].lexical_entry_client_id, entry.suggestion[0].lexical_entry_object_id).then(function(e1) { + getLexicalEntry(entry.suggestion[1].lexical_entry_client_id, entry.suggestion[1].lexical_entry_object_id).then(function(e2) { + deferred.resolve({ + confidence: entry.confidence, + suggestion: [ e1, e2 ] + }); + }, function(reason) { + deferred.reject("Failed to fetch lexical entry: " + reason); + }); + }, function(reason) { + deferred.reject("Failed to fetch lexical entry: " + reason); + }); + return deferred.promise; }; - $scope.saveValue = function(entry, field, value, parent) { - var url; - if (field.level) { - switch (field.level) { - case "leveloneentity": - url = "/dictionary/" + encodeURIComponent(dictionaryClientId) + "/" + encodeURIComponent(dictionaryObjectId) + "/perspective/" + encodeURIComponent(perspectiveClientId) + "/" + encodeURIComponent(perspectiveId) + "/lexical_entry/" + encodeURIComponent($scope.parentEntry.client_id) + "/" + encodeURIComponent($scope.parentEntry.object_id) + "/leveloneentity"; - break; - - case "leveltwoentity": - if (parent.client_id && parent.object_id) { - url = "/dictionary/" + encodeURIComponent(dictionaryClientId) + "/" + encodeURIComponent(dictionaryObjectId) + "/perspective/" + encodeURIComponent(perspectiveClientId) + "/" + encodeURIComponent(perspectiveId) + "/lexical_entry/" + encodeURIComponent($scope.parentEntry.client_id) + "/" + encodeURIComponent($scope.parentEntry.object_id) + "/leveloneentity/" + encodeURIComponent(parent.client_id) + "/" + encodeURIComponent(parent.object_id) + "/leveltwoentity"; - } else { - $log.error("Attempting to create Level2 entry with no Level1 entry."); - return; - } - break; + var getPerspectiveOriginById = function(client_id, object_id) { + var deferred = $q.defer(); + var url = "/perspective/" + encodeURIComponent(client_id) + "/" + encodeURIComponent(object_id) + "/tree"; + $http.get(url).success(function(data, status, headers, config) { + var path = data.map(function(e) { + var r = null; + switch (e.type) { + case "dictionary": + r = lingvodoc.Dictionary.fromJS(e); + break; - case "groupingentity": - return; - break; - } - var entryObject = value.export(); - entryObject["entity_type"] = field.entity_type; - entryObject["locale_id"] = 1; - entryObject["additional_metadata"] = { - row_id: entry.row_id, - client_id: entry.client_id - }; - $http.post(url, entryObject).success(function(data, status, headers, config) { - if (data.client_id && data.object_id) { - entryObject.client_id = data.client_id; - entryObject.object_id = data.object_id; - var getSavedEntityUrl = "/leveloneentity/" + data.client_id + "/" + data.object_id; - $http.get(getSavedEntityUrl).success(function(data, status, headers, config) { - for (var i = 0; i < $scope.entries.length; i++) { - if ($scope.entries[i].row_id == entry.row_id && $scope.entries[i].client_id == entry.client_id) { - $scope.entries[i].contains.push(data); - break; - } - } - $scope.disableInput(entry.client_id, entry.object_id, field.entity_type); - }).error(function(data, status, headers, config) {}); - } - }).error(function(data, status, headers, config) {}); - } - }; - $scope.removeValue = function(entry, field, fieldValue, parent) { - var url; - if (field.level) { - switch (field.level) { - case "leveloneentity": - url = "/dictionary/" + encodeURIComponent(dictionaryClientId) + "/" + encodeURIComponent(dictionaryObjectId) + "/perspective/" + encodeURIComponent(perspectiveClientId) + "/" + encodeURIComponent(perspectiveId) + "/lexical_entry/" + encodeURIComponent(entry.client_id) + "/" + encodeURIComponent(entry.object_id) + "/leveloneentity/" + encodeURIComponent(fieldValue.client_id) + "/" + encodeURIComponent(fieldValue.object_id); - break; + case "perspective": + r = lingvodoc.Perspective.fromJS(e); + break; - case "leveltwoentity": - if (parentClientId && parentObjectId) { - url = "/dictionary/" + encodeURIComponent(dictionaryClientId) + "/" + encodeURIComponent(dictionaryObjectId) + "/perspective/" + encodeURIComponent(perspectiveClientId) + "/" + encodeURIComponent(perspectiveId) + "/lexical_entry/" + encodeURIComponent(fieldValue.client_id) + "/" + encodeURIComponent(fieldValue.object_id) + "/leveloneentity/" + encodeURIComponent(parent.client_id) + "/" + encodeURIComponent(parent.object_id) + "/leveltwoentity/" + encodeURIComponent(fieldValue.client_id) + "/" + encodeURIComponent(fieldValue.object_id); - } else { - $log.error("Attempting to delete Level2 entry with no Level1 entry."); - return; - } - break; + case "language": + r = lingvodoc.Language.fromJS(e); + break; - case "groupingentity": - return; - break; - } - $http.delete(url).success(function(data, status, headers, config) { - for (var i = 0; i < $scope.entries.length; i++) { - if ($scope.entries[i].row_id == entry.row_id && $scope.entries[i].client_id == entry.client_id) { - var lexicalEntry = $scope.entries[i]; - for (var j = 0; j < lexicalEntry.contains.length; j++) { - if (lexicalEntry.contains[j].client_id == fieldValue.client_id && lexicalEntry.contains[j].object_id == fieldValue.object_id) { - $scope.entries[i].contains[j].marked_for_deletion = true; - } - } - break; - } + default: + r = null; } - }).error(function(data, status, headers, config) {}); - } + return r; + }); + deferred.resolve(path); + }).error(function(data, status, headers, config) { + deferred.reject("Failed to get perspective origin"); + }); + return deferred.promise; }; - $scope.ok = function() { - $modalInstance.close(); + var mergeSuggestions = function(perspective) { + var deferred = $q.defer(); + var body = { + entity_type_primary: "Translation", + entity_type_secondary: "Transcription", + threshold: .6, + levenstein: 3, + client_id: perspective.client_id, + object_id: perspective.object_id + }; + $http.post("/merge/suggestions", body).success(function(data, status, headers, config) { + if (angular.isArray(data)) { + var r = data.map(function(e) { + return getSuggestionLexicalEntry(e); + }); + $q.all(r).then(function(results) { + deferred.resolve(results); + }); + } else { + deferred.resolve([]); + } + }).error(function(data, status, headers, config) { + deferred.reject("Failed to fetch merge suggestions"); + }); + return deferred.promise; }; - $scope.cancel = function() { - $modalInstance.dismiss("cancel"); + var getLexicalEntry = function(clientId, objectId) { + var deferred = $q.defer(); + $http.get("/lexical_entry/" + encodeURIComponent(clientId) + "/" + encodeURIComponent(objectId)).success(function(data, status, headers, config) { + deferred.resolve(data.lexical_entry); + }).error(function(data, status, headers, config) { + deferred.reject("Failed to fetch lexical entry"); + }); + return deferred.promise; }; - $scope.$watch("entries", function(updatedEntries) { - $scope.mapFieldValues(updatedEntries, $scope.fields); - }, true); -} ]).controller("editGroupingTagController", [ "$scope", "$http", "$modalInstance", "$q", "$log", "groupParams", function($scope, $http, $modalInstance, $q, $log, groupParams) { - var dictionaryClientId = $("#dictionaryClientId").data("lingvodoc"); - var dictionaryObjectId = $("#dictionaryObjectId").data("lingvodoc"); - var perspectiveClientId = $("#perspectiveClientId").data("lingvodoc"); - var perspectiveId = $("#perspectiveId").data("lingvodoc"); - var enabledInputs = []; - WaveSurferController.call(this, $scope); - $scope.fields = groupParams.fields; - $scope.connectedEntries = []; - $scope.suggestedEntries = []; - $scope.searchQuery = ""; - $scope.fieldsIdx = []; - for (var k = 0; k < $scope.fields.length; k++) { - $scope.fieldsIdx.push($scope.fields[k]); - } - $scope.fieldsValues = []; - $scope.suggestedFieldsValues = []; - $scope.mapFieldValues = function(allEntries, allFields) { - var result = []; - $scope.fieldsValues = []; - for (var i = 0; i < allEntries.length; i++) { - var entryRow = []; - for (var j = 0; j < allFields.length; j++) { - entryRow.push($scope.getFieldValues(allEntries[i], allFields[j])); + var moveLexicalEntry = function(clientId, objectId, toClientId, toObjectId) { + var deferred = $q.defer(); + var req = { + client_id: toClientId, + object_id: toObjectId + }; + $http.patch("/lexical_entry/" + encodeURIComponent(clientId) + "/" + encodeURIComponent(objectId) + "/move", req).success(function(data, status, headers, config) { + deferred.resolve(data); + }).error(function(data, status, headers, config) { + deferred.reject("Failed to move lexical entry"); + }); + return deferred.promise; + }; + var getDictionariesByLanguage = function(language) { + var deferred = $q.defer(); + var req = { + languages: [ { + client_id: language.client_id, + object_id: language.object_id + } ] + }; + $http.post("/dictionaries", req).success(function(data, status, headers, config) { + var dictionaries = []; + if (_.isArray(data.dictionaries)) { + _.forEach(data.dictionaries, function(jsdict) { + var dictionary = lingvodoc.Dictionary.fromJS(jsdict); + if (language.client_id == dictionary.parent_client_id && language.object_id == dictionary.parent_object_id) { + dictionaries.push(dictionary); + } + }); } - result.push(entryRow); - } - return result; + deferred.resolve(dictionaries); + }).error(function(data, status, headers, config) { + deferred.reject("Failed to fetch list of dictionaries"); + }); + return deferred.promise; }; - $scope.getFieldValues = function(entry, field) { - var value; - var values = []; - if (entry && entry.contains) { - if (field.isGroup) { - for (var fieldIndex = 0; fieldIndex < field.contains.length; fieldIndex++) { - var subField = field.contains[fieldIndex]; - for (var valueIndex = 0; valueIndex < entry.contains.length; valueIndex++) { - value = entry.contains[valueIndex]; - if (value.entity_type == subField.entity_type) { - values.push(value); - } + var getLanguagesFull = function() { + var deferred = $q.defer(); + var flatLanguages = function(languages) { + var flat = []; + for (var i = 0; i < languages.length; i++) { + var language = languages[i]; + flat.push(language); + if (language.languages.length > 0) { + var childLangs = flatLanguages(language.languages); + flat = flat.concat(childLangs); + } + } + return flat; + }; + var setDictionaries = function(language, languages, dictionaries) { + for (var i = 0; i < languages.length; ++i) { + var lang = languages[i]; + if (language.equals(lang)) { + language.dictionaries = dictionaries; + return true; + } else { + if (setDictionaries(language, lang.languages, dictionaries)) { + return true; } } - } else { - for (var i = 0; i < entry.contains.length; i++) { - value = entry.contains[i]; - if (value.entity_type == field.entity_type) { - values.push(value); - } + } + return false; + }; + var parseResponse = function(langs) { + var responseLangs = []; + angular.forEach(langs, function(lang) { + var responseLang = lingvodoc.Language.fromJS(lang); + if (angular.isArray(lang.contains)) { + responseLang.languages = parseResponse(lang.contains); } + responseLangs.push(responseLang); + }); + return responseLangs; + }; + $http.get("/languages").success(function(data, status, headers, config) { + var languages = []; + if (angular.isArray(data.languages)) { + languages = parseResponse(data.languages); } - } - return values; + var flat = flatLanguages(languages); + var reqs = flat.map(function(l) { + return getDictionariesByLanguage(l); + }); + $q.all(reqs).then(function(allLangsDictionaries) { + angular.forEach(allLangsDictionaries, function(dictionaries, index) { + setDictionaries(flat[index], languages, dictionaries); + }); + deferred.resolve(languages); + }, function(reason) { + deferred.reject(reason); + }); + }).error(function(data, status, headers, config) { + deferred.reject("An error occurred while trying to get languages"); + }); + return deferred.promise; }; - $scope.linkEntry = function(index) { - var linkObject = { - entity_type: "Etymology", - connections: [ { - client_id: groupParams.clientId, - object_id: groupParams.objectId - }, { - client_id: $scope.suggestedEntries[index].clientId, - object_id: $scope.suggestedEntries[index].objectId - } ] + var getPublishedDictionaries = function() { + var deferred = $q.defer(); + var req = { + group_by_lang: true, + group_by_org: false }; - var url = "/group_entity"; - $http.post(url, linkObject).success(function(data, status, headers, config) { - $scope.connectedEntries.push($scope.suggestedEntries[index]); - }).error(function(data, status, headers, config) {}); - }; - $scope.unlinkEntry = function(index) { - $scope.connectedEntries.splice(index); - }; - $scope.ok = function() { - $modalInstance.close(); + $http.post("/published_dictionaries", req).success(function(data, status, headers, config) { + deferred.resolve(data); + }).error(function(data, status, headers, config) { + deferred.reject("Failed to move lexical entry"); + }); + return deferred.promise; }; - $scope.cancel = function() { - $modalInstance.dismiss("cancel"); + var getUser = function(id) { + var deferred = $q.defer(); + $http.get("/user" + "?user_id=" + encodeURIComponent(id)).success(function(data, status, headers, config) { + deferred.resolve(lingvodoc.User.fromJS(data)); + }).error(function(data, status, headers, config) { + deferred.reject("Failed to move lexical entry"); + }); + return deferred.promise; }; - $scope.$watch("connectedEntries", function(updatedEntries) { - $scope.fieldsValues = $scope.mapFieldValues(updatedEntries, $scope.fields); - }, true); - $scope.$watch("suggestedEntries", function(updatedEntries) { - $scope.suggestedFieldsValues = $scope.mapFieldValues(updatedEntries, $scope.fields); - }, true); - $scope.$watch("searchQuery", function(updatedQuery) { - if (!updatedQuery || updatedQuery.length < 3) { - return; - } - var url = "/basic_search?leveloneentity=" + encodeURIComponent(updatedQuery); + var getRoles = function(url) { + var deferred = $q.defer(); $http.get(url).success(function(data, status, headers, config) { - $scope.suggestedEntries = []; - var urls = []; - for (var i = 0; i < data.length; i++) { - var entr = data[i]; - var getEntryUrl = "/dictionary/" + encodeURIComponent(entr.origin_dictionary_client_id) + "/" + encodeURIComponent(entr.origin_dictionary_object_id) + "/perspective/" + encodeURIComponent(entr.origin_perspective_client_id) + "/" + encodeURIComponent(entr.origin_perspective_object_id) + "/lexical_entry/" + encodeURIComponent(entr.client_id) + "/" + encodeURIComponent(entr.object_id); - urls.push(getEntryUrl); - } - var uniqueUrls = urls.filter(function(item, pos) { - return urls.indexOf(item) == pos; - }); - var requests = []; - for (var j = 0; j < uniqueUrls.length; j++) { - var r = $http.get(uniqueUrls[j]); - requests.push(r); - } - $q.all(requests).then(function(results) { - for (var k = 0; k < results.length; k++) { - if (results[k].data) { - $scope.suggestedEntries.push(results[k].data.lexical_entry); + var userIds = []; + angular.forEach(data.roles_users, function(role) { + angular.forEach(role, function(userId) { + if (userIds.indexOf(userId) < 0) { + userIds.push(userId); } - } + }); }); - }).error(function(data, status, headers, config) {}); - }, true); - var loadConnectedWords = function() { - var url = "/lexical_entry/" + encodeURIComponent(groupParams.clientId) + "/" + encodeURIComponent(groupParams.objectId) + "/connected"; - $http.get(url).success(function(data, status, headers, config) {}).error(function(data, status, headers, config) {}); + var reqs = userIds.map(function(id) { + return getUser(id); + }); + $q.all(reqs).then(function(users) { + var resultRoles = {}; + angular.forEach(data.roles_users, function(roleUsers, roleName) { + resultRoles[roleName] = roleUsers.map(function(userId) { + return users.filter(function(u) { + return u.id == userId; + })[0]; + }); + }); + deferred.resolve(resultRoles); + }, function(reason) { + deferred.reject("An error occurred while trying to get dictionary roles"); + }); + }).error(function(data, status, headers, config) { + deferred.reject("An error occurred while trying to get dictionary roles"); + }); + return deferred.promise; }; - loadConnectedWords(); -} ]); - -"use strict"; - -var model = {}; - -model.Value = function() { - this.export = function() { - return {}; + var getDictionaryRoles = function(dictionary) { + var url = "/dictionary/" + encodeURIComponent(dictionary.client_id) + "/" + encodeURIComponent(dictionary.object_id) + "/roles"; + return getRoles(url); }; -}; - -model.TextValue = function(content) { - this.content = content; - this.export = function() { - return { - content: content, - data_type: "text" + var addDictionaryRoles = function(dictionary, roles) { + var deferred = $q.defer(); + var url = "/dictionary/" + encodeURIComponent(dictionary.client_id) + "/" + encodeURIComponent(dictionary.object_id) + "/roles"; + $http.post(url, roles).success(function(data, status, headers, config) { + deferred.resolve(); + }).error(function(data, status, headers, config) { + deferred.reject("Failed to add roles"); + }); + return deferred.promise; + }; + var deleteDictionaryRoles = function(dictionary, roles) { + var deferred = $q.defer(); + var url = "/dictionary/" + encodeURIComponent(dictionary.client_id) + "/" + encodeURIComponent(dictionary.object_id) + "/roles"; + var config = { + method: "DELETE", + url: url, + data: roles, + headers: { + "Content-Type": "application/json;charset=utf-8" + } }; + $http(config).success(function(data, status, headers, config) { + deferred.resolve(); + }).error(function(data, status, headers, config) { + deferred.reject("Failed to delete roles"); + }); + return deferred.promise; }; -}; - -model.TextValue.prototype = new model.Value(); - -model.SoundValue = function(name, mime, content) { - this.name = name; - this.mime = mime; - this.content = content; - this.export = function() { - return { - content: content, - filename: name, - data_type: "sound" + var getPerspectiveRoles = function(dictionary, perspective, roles) { + var url = "/dictionary/" + encodeURIComponent(dictionary.client_id) + "/" + encodeURIComponent(dictionary.object_id) + "/perspective/" + encodeURIComponent(perspective.client_id) + "/" + encodeURIComponent(perspective.object_id) + "/roles"; + return getRoles(url); + }; + var addPerspectiveRoles = function(dictionary, perspective, roles) { + var deferred = $q.defer(); + var url = "/dictionary/" + encodeURIComponent(dictionary.client_id) + "/" + encodeURIComponent(dictionary.object_id) + "/perspective/" + encodeURIComponent(perspective.client_id) + "/" + encodeURIComponent(perspective.object_id) + "/roles"; + $http.post(url, roles).success(function(data, status, headers, config) { + deferred.resolve(); + }).error(function(data, status, headers, config) { + deferred.reject("Failed to update roles"); + }); + return deferred.promise; + }; + var deletePerspectiveRoles = function(dictionary, perspective, roles) { + var deferred = $q.defer(); + var url = "/dictionary/" + encodeURIComponent(dictionary.client_id) + "/" + encodeURIComponent(dictionary.object_id) + "/perspective/" + encodeURIComponent(perspective.client_id) + "/" + encodeURIComponent(perspective.object_id) + "/roles"; + var config = { + method: "DELETE", + url: url, + data: roles, + headers: { + "Content-Type": "application/json;charset=utf-8" + } }; + $http(config).success(function(data, status, headers, config) { + deferred.resolve(); + }).error(function(data, status, headers, config) { + deferred.reject("Failed to update roles"); + }); + return deferred.promise; }; -}; - -model.SoundValue.prototype = new model.Value(); - -model.ImageValue = function(name, mime, content) { - this.name = name; - this.mime = mime; - this.content = content; - this.export = function() { - return { - content: content, - filename: name, - data_type: "image" + var getUserBlobs = function() { + var deferred = $q.defer(); + $http.get("/blobs").success(function(data, status, headers, config) { + var blobs = _.map(data, lingvodoc.Blob.fromJS); + deferred.resolve(blobs); + }).error(function(data, status, headers, config) { + deferred.reject("Failed to fetch list of available blobs"); + }); + return deferred.promise; + }; + var checkDictionaryBlob = function(blob, parent) { + var deferred = $q.defer(); + var query = { + blob_client_id: blob.client_id, + blob_object_id: blob.object_id, + parent_client_id: parent.client_id, + parent_object_id: parent.object_id + }; + $http.post("/convert_check", query).success(function(data, status, headers, config) { + var perspectives = _.map(data, lingvodoc.Perspective.fromJS); + deferred.resolve(perspectives); + }).error(function(data, status, headers, config) { + deferred.reject("Failed to convert dictionary"); + }); + return deferred.promise; + }; + var convertDictionary = function(req) { + var deferred = $q.defer(); + $http.post("/convert", req).success(function(data, status, headers, config) { + deferred.resolve(data); + }).error(function(data, status, headers, config) { + deferred.reject("Failed to convert dictionary"); + }); + return deferred.promise; + }; + var getPerspectiveMeta = function(dictionary, perspective) { + var deferred = $q.defer(); + var url = "/dictionary/" + encodeURIComponent(dictionary.client_id) + "/" + encodeURIComponent(dictionary.object_id) + "/perspective/" + encodeURIComponent(perspective.client_id) + "/" + encodeURIComponent(perspective.object_id) + "/meta"; + $http.get(url).success(function(data, status, headers, config) { + deferred.resolve(data); + }).error(function(data, status, headers, config) { + deferred.reject("Failed to get perspective meta data!"); + }); + return deferred.promise; + }; + var setPerspectiveMeta = function(dictionary, perspective, meta) { + var deferred = $q.defer(); + var url = "/dictionary/" + encodeURIComponent(dictionary.client_id) + "/" + encodeURIComponent(dictionary.object_id) + "/perspective/" + encodeURIComponent(perspective.client_id) + "/" + encodeURIComponent(perspective.object_id) + "/meta"; + $http.put(url, meta).success(function(data, status, headers, config) { + deferred.resolve(data); + }).error(function(data, status, headers, config) { + deferred.reject("Failed to set perspective meta data!"); + }); + return deferred.promise; + }; + var removePerspectiveMeta = function(dictionary, perspective, meta) { + var deferred = $q.defer(); + var url = "/dictionary/" + encodeURIComponent(dictionary.client_id) + "/" + encodeURIComponent(dictionary.object_id) + "/perspective/" + encodeURIComponent(perspective.client_id) + "/" + encodeURIComponent(perspective.object_id) + "/meta"; + var config = { + method: "DELETE", + url: url, + data: meta, + headers: { + "Content-Type": "application/json;charset=utf-8" + } }; + $http(config).success(function(data, status, headers, config) { + deferred.resolve(data); + }).error(function(data, status, headers, config) { + deferred.reject("Failed to remove perspective meta data!"); + }); + return deferred.promise; }; -}; - -model.ImageValue.prototype = new model.Value(); + var advancedSearch = function(query, where, adopted, etymology) { + var deferred = $q.defer(); + var url = "/advanced_search"; + var perspectives = where.map(function(o) { + if (o.type == "perspective") { + return { + client_id: o.client_id, + object_id: o.object_id + }; + } + }).filter(function(o) { + return typeof o !== "undefined"; + }); + var req = { + searchstrings: query, + perspectives: perspectives + }; + if (_.isBoolean(adopted)) { + req.adopted = adopted; + } + if (_.isBoolean(etymology)) { + req.with_etimology = etymology; + } + $http.post(url, req).success(function(data, status, headers, config) { + var r = data.map(function(e) { + var perspective = lingvodoc.Perspective.fromJS(e); + return getPerspectiveOriginById(perspective.client_id, perspective.object_id); + }); + $q.all(r).then(function(paths) { + var out = []; + _.each(data, function(entry, i) { + entry.lexical_entry["origin"] = paths[i]; + out.push(entry.lexical_entry); + }); + deferred.resolve(out); + }, function(reason) { + deferred.reject("An error occurred while doing basic search"); + }); + }).error(function(data, status, headers, config) { + deferred.reject("An error occurred while doing advanced search"); + }); + return deferred.promise; + }; + var convertMarkup = function(object) { + var deferred = $q.defer(); + var obj = { + client_id: object.client_id, + object_id: object.object_id + }; + $http.post("/convert/markup", obj).success(function(data, status, headers, config) { + deferred.resolve(data); + }).error(function(data, status, headers, config) { + deferred.reject("Failed to convert markup!"); + }); + return deferred.promise; + }; + return { + getLexicalEntries: getLexicalEntries, + getLexicalEntriesCount: getLexicalEntriesCount, + getPerspectiveDictionaryFields: getPerspectiveDictionaryFields, + getPerspectiveDictionaryFieldsNew: getPerspectiveDictionaryFieldsNew, + addNewLexicalEntry: addNewLexicalEntry, + saveValue: saveValue, + removeValue: removeValue, + getConnectedWords: getConnectedWords, + linkEntries: linkEntries, + search: search, + approve: approve, + approveAll: approveAll, + getDictionaryProperties: getDictionaryProperties, + setDictionaryProperties: setDictionaryProperties, + removeDictionary: removeDictionary, + getLanguages: getLanguages, + setDictionaryStatus: setDictionaryStatus, + setPerspectiveStatus: setPerspectiveStatus, + setPerspectiveProperties: setPerspectiveProperties, + getPerspectiveFields: getPerspectiveFields, + setPerspectiveFields: setPerspectiveFields, + getPerspectiveFieldsNew: getPerspectiveFieldsNew, + removePerspective: removePerspective, + getUserInfo: getUserInfo, + setUserInfo: setUserInfo, + getOrganizations: getOrganizations, + createOrganization: createOrganization, + getOrganization: getOrganization, + editOrganization: editOrganization, + searchUsers: searchUsers, + getDictionaries: getDictionaries, + getAllPerspectives: getAllPerspectives, + getPerspectiveById: getPerspectiveById, + createPerspective: createPerspective, + getDictionaryPerspectives: getDictionaryPerspectives, + getDictionariesWithPerspectives: getDictionariesWithPerspectives, + mergeDictionaries: mergeDictionaries, + mergePerspectives: mergePerspectives, + mergeSuggestions: mergeSuggestions, + getPerspectiveOriginById: getPerspectiveOriginById, + getLexicalEntry: getLexicalEntry, + moveLexicalEntry: moveLexicalEntry, + getLanguagesFull: getLanguagesFull, + getPublishedDictionaries: getPublishedDictionaries, + getDictionaryRoles: getDictionaryRoles, + addDictionaryRoles: addDictionaryRoles, + deleteDictionaryRoles: deleteDictionaryRoles, + getPerspectiveRoles: getPerspectiveRoles, + addPerspectiveRoles: addPerspectiveRoles, + deletePerspectiveRoles: deletePerspectiveRoles, + getUserBlobs: getUserBlobs, + checkDictionaryBlob: checkDictionaryBlob, + convertDictionary: convertDictionary, + getPerspectiveMeta: getPerspectiveMeta, + setPerspectiveMeta: setPerspectiveMeta, + removePerspectiveMeta: removePerspectiveMeta, + advancedSearch: advancedSearch, + convertMarkup: convertMarkup + }; +} -model.MarkupValue = function(name, mime, content) { - this.name = name; - this.mime = mime; - this.content = content; - this.export = function() { - return { - content: content, - filename: name, - data_type: "markup" +function responseHandler($timeout, $modal) { + function show(status, message, t) { + var timeout = t || 2e3; + var controller = function($scope, $modalInstance) { + $scope.status = status; + $scope.message = message; + $scope.ok = function() { + $modalInstance.close(); + }; + }; + var inst = $modal.open({ + animation: true, + templateUrl: "responseHandlerModal.html", + controller: controller, + size: "sm", + backdrop: "static", + keyboard: false + }); + $timeout(function() { + inst.dismiss(); + }, timeout); + } + function success(message) { + show("success", message, 5e3); + } + function error(message) { + show("error", message, 5e3); + } + function yesno(status, message, callback) { + var controller = function($scope, $modalInstance) { + $scope.status = status; + $scope.message = message; + $scope.yes = function() { + $modalInstance.close(true); + }; + $scope.no = function() { + $modalInstance.close(false); + }; }; + $modal.open({ + animation: true, + templateUrl: "responseHandlerYesNoModal.html", + controller: controller, + size: "lg", + backdrop: "static", + keyboard: false + }).result.then(function(result) { + callback(result); + }, function() { + callback(false); + }); + } + return { + success: success, + error: error, + yesno: yesno }; -}; - -model.MarkupValue.prototype = new model.Value(); +} -var app = angular.module("ViewDictionaryModule", [ "ui.bootstrap" ]); +"use strict"; -app.directive("wavesurfer", function() { +angular.module("MapsModule", [ "ui.bootstrap", "ngAnimate", "ngMap" ]).factory("responseHandler", [ "$timeout", "$modal", responseHandler ]).factory("dictionaryService", [ "$http", "$q", lingvodocAPI ]).directive("wavesurfer", function() { return { restrict: "E", link: function($scope, $element, $attrs) { @@ -32826,113 +36644,210 @@ app.directive("wavesurfer", function() { if ($attrs.url) { wavesurfer.load($attrs.url, $attrs.data || null); } - $scope.$emit("wavesurferInit", wavesurfer); + $scope.$emit("wavesurferInit", wavesurfer, $element); } }; -}); - -app.directive("onReadFile", function($parse) { +}).directive("indeterminate", [ function() { return { - restrict: "A", - scope: false, - link: function(scope, element, attrs) { - var fn = $parse(attrs.onReadFile); - element.on("change", function(onChangeEvent) { - var reader = new FileReader(); - var file = (onChangeEvent.srcElement || onChangeEvent.target).files[0]; - reader.onload = function(onLoadEvent) { - scope.$apply(function() { - var b64file = btoa(onLoadEvent.target.result); - fn(scope, { - $fileName: file.name, - $fileType: file.type, - $fileContent: b64file - }); - }); - }; - reader.readAsBinaryString(file); + require: "?ngModel", + link: function(scope, el, attrs, ctrl) { + ctrl.$formatters = []; + ctrl.$parsers = []; + ctrl.$render = function() { + var d = ctrl.$viewValue; + el.data("checked", d); + switch (d) { + case true: + el.prop("indeterminate", false); + el.prop("checked", true); + break; + + case false: + el.prop("indeterminate", false); + el.prop("checked", false); + break; + + default: + el.prop("indeterminate", true); + } + }; + el.bind("click", function() { + var d; + switch (el.data("checked")) { + case false: + d = true; + break; + + case true: + d = null; + break; + + default: + d = false; + } + ctrl.$setViewValue(d); + scope.$apply(ctrl.$render); }); } }; -}); - -app.controller("ViewDictionaryController", [ "$scope", "$http", "$modal", "$log", "$timeout", function($scope, $http, $modal, $log, $timeout) { - var currentClientId = $("#clientId").data("lingvodoc"); - var dictionaryClientId = $("#dictionaryClientId").data("lingvodoc"); - var dictionaryObjectId = $("#dictionaryObjectId").data("lingvodoc"); - var perspectiveClientId = $("#perspectiveClientId").data("lingvodoc"); - var perspectiveId = $("#perspectiveId").data("lingvodoc"); +} ]).controller("MapsController", [ "$scope", "$http", "$q", "$log", "$modal", "NgMap", "dictionaryService", "responseHandler", function($scope, $http, $q, $log, $modal, NgMap, dictionaryService, responseHandler) { WaveSurferController.call(this, $scope); - $scope.perspective = { - fields: [] - }; + var key = "AIzaSyB6l1ciVMcP1pIUkqvSx8vmuRJL14lbPXk"; + $scope.googleMapsUrl = "http://maps.google.com/maps/api/js?v=3.20&key=" + encodeURIComponent(key); + $scope.perspectives = []; + $scope.activePerspectives = []; + $scope.adoptedSearch = null; + $scope.etymologySearch = null; + $scope.entries = []; $scope.fields = []; - $scope.lexicalEntries = []; - $scope.dictionaryMatrix = []; - $scope.pageIndex = 1; - $scope.pageSize = 50; - $scope.pageCount = 1; - $scope.getFieldValues = function(entry, field) { - var value; - var values = []; - if (entry && entry.contains) { - if (field.isGroup) { - for (var fieldIndex = 0; fieldIndex < field.contains.length; fieldIndex++) { - var subField = field.contains[fieldIndex]; - for (var valueIndex = 0; valueIndex < entry.contains.length; valueIndex++) { - value = entry.contains[valueIndex]; - if (value.entity_type == subField.entity_type) { - values.push(value); + $scope.groups = []; + $scope.ge = []; + $scope.allFields = []; + $scope.searchFields = []; + $scope.fieldsIdx = []; + $scope.fieldsValues = []; + $scope.search = [ { + query: "", + type: "", + orFlag: true + } ]; + $scope.searchComplete = true; + var mapFieldValues = function(allEntries, allFields) { + var result = []; + var getFieldValues = function(entry, field) { + var value; + var values = []; + if (entry && entry.contains) { + if (field.isGroup) { + for (var fieldIndex = 0; fieldIndex < field.contains.length; fieldIndex++) { + var subField = field.contains[fieldIndex]; + for (var valueIndex = 0; valueIndex < entry.contains.length; valueIndex++) { + value = entry.contains[valueIndex]; + if (value.entity_type == subField.entity_type) { + values.push(value); + } } } - } - } else { - for (var i = 0; i < entry.contains.length; i++) { - value = entry.contains[i]; - if (value.entity_type == field.entity_type) { - values.push(value); + } else { + for (var i = 0; i < entry.contains.length; i++) { + value = entry.contains[i]; + if (value.entity_type == field.entity_type) { + values.push(value); + } } } } + return values; + }; + for (var i = 0; i < allEntries.length; i++) { + var entryRow = []; + for (var j = 0; j < allFields.length; j++) { + entryRow.push(getFieldValues(allEntries[i], allFields[j])); + } + result.push(entryRow); } - return values; + return result; }; - $scope.annotate = function(soundEntity, markupEntity) { - var modalInstance = $modal.open({ - animation: true, - templateUrl: "annotationModal.html", - controller: "AnnotationController", - size: "lg", - resolve: { - soundUrl: function() { - return soundEntity.content; - }, - annotationUrl: function() { - return markupEntity.content; + $scope.getPerspectivesWithLocation = function() { + return _.filter($scope.perspectives, function(p) { + return _.has(p, "location") && !_.isEmpty(p, "location") && _.has(p.location, "lat") && _.has(p.location, "lng"); + }); + }; + $scope.getDictionary = function(perspective) { + return _.find($scope.dictionaries, function(d) { + return d.client_id == perspective.parent_client_id && d.object_id == perspective.parent_object_id; + }); + }; + $scope.isPerspectiveActive = function(perspective) { + return !!_.find($scope.activePerspectives, function(p) { + return p.equals(perspective); + }); + }; + $scope.getSearchFields = function() { + var activeFields = _.clone($scope.allFields); + _.remove(activeFields, function(f, i) { + var perspective = $scope.perspectives[i]; + return !_.find($scope.activePerspectives, function(p) { + return p.equals(perspective); + }); + }); + var fields = _.reduce(activeFields, function(acc, perspectiveFields) { + var fields = []; + _.each(perspectiveFields, function(f) { + if (f.level === "leveloneentity" && f.data_type === "text") { + fields.push(f); } + if (_.isArray(f.contains)) { + _.each(f.contains, function(cf) { + if (cf.level === "leveloneentity" && cf.data_type === "text") { + fields.push(cf); + } + }); + } + }); + return acc.concat(fields); + }, []); + var names = []; + var removed = _.remove(fields, function(f) { + if (_.indexOf(names, f.entity_type) >= 0) { + return true; } + names.push(f.entity_type); + return false; + }); + $scope.searchFields = fields; + return $scope.searchFields; + }; + $scope.addSearchField = function() { + $scope.search.push({ + query: "", + type: "", + orFlag: false }); }; - $scope.getPage = function(pageNumber) { - if (pageNumber > 0 && pageNumber <= $scope.pageCount) { - $scope.pageIndex = pageNumber; - loadEntries(); - } + $scope.info = function(event, perspective) { + var self = this; + $scope.selectedPerspective = perspective; + NgMap.getMap().then(function(map) { + map.showInfoWindow("bar", self); + }); }; - $scope.range = function(min, max, step) { - step = step || 1; - var input = []; - for (var i = min; i <= max; i += step) { - input.push(i); + $scope.toggle = function(event, perspective) { + if (!_.find($scope.activePerspectives, function(p) { + return p.equals(perspective); + })) { + $scope.activePerspectives.push(perspective); + } else { + _.remove($scope.activePerspectives, function(p) { + return p.equals(perspective); + }); } - return input; + }; + $scope.showBlob = function(blob) { + $modal.open({ + animation: true, + templateUrl: "blobModal.html", + controller: "BlobController", + size: "lg", + backdrop: "static", + keyboard: false, + resolve: { + params: function() { + return { + blob: blob + }; + } + } + }).result.then(function(req) {}, function() {}); }; $scope.viewGroup = function(entry, field, values) { - var modalInstance = $modal.open({ + $modal.open({ animation: true, templateUrl: "viewGroupModal.html", controller: "viewGroupController", size: "lg", + backdrop: "static", + keyboard: false, resolve: { groupParams: function() { return { @@ -32943,10 +36858,9 @@ app.controller("ViewDictionaryController", [ "$scope", "$http", "$modal", "$log" } } }); - modalInstance.result.then(function(value) {}, function() {}); }; $scope.viewGroupingTag = function(entry, field, values) { - var modalInstance = $modal.open({ + $modal.open({ animation: true, templateUrl: "viewGroupingTagModal.html", controller: "viewGroupingTagController", @@ -32954,204 +36868,108 @@ app.controller("ViewDictionaryController", [ "$scope", "$http", "$modal", "$log" resolve: { groupParams: function() { return { - clientId: entry.client_id, - objectId: entry.object_id, + entry: entry, fields: $scope.fields }; } } }); - modalInstance.result.then(function(value) {}, function() {}); - }; - $scope.$watch("lexicalEntries", function(updatedEntries) { - var getFieldValues = function(entry, field) { - var value; - var values = []; - if (entry && entry.contains) { - if (field.isGroup) { - for (var fieldIndex = 0; fieldIndex < field.contains.length; fieldIndex++) { - var subField = field.contains[fieldIndex]; - for (var valueIndex = 0; valueIndex < entry.contains.length; valueIndex++) { - value = entry.contains[valueIndex]; - if (value.entity_type == subField.entity_type) { - values.push(value); - } - } - } - } else { - for (var i = 0; i < entry.contains.length; i++) { - value = entry.contains[i]; - if (value.entity_type == field.entity_type) { - values.push(value); - } - } - } - } - return values; - }; - var mapFieldValues = function(allEntries, allFields) { - var result = []; - for (var i = 0; i < allEntries.length; i++) { - var entryRow = []; - for (var j = 0; j < allFields.length; j++) { - entryRow.push(getFieldValues(allEntries[i], allFields[j])); - } - result.push(entryRow); - } - return result; - }; - $scope.dictionaryMatrix = mapFieldValues(updatedEntries, $scope.fields); - }, true); - var addUrlParameter = function(url, key, value) { - return url + (url.indexOf("?") >= 0 ? "&" : "?") + encodeURIComponent(key) + "=" + encodeURIComponent(value); }; - var perspectiveToDictionaryFields = function(perspective) { - var fields = []; - for (var i = 0; i < perspective.fields.length; i++) { - var field = perspective.fields[i]; - if (typeof field.group == "string") { - var createNewGroup = true; - for (var j = 0; j < fields.length; j++) { - if (fields[j].entity_type == field.group && fields[j].isGroup) { - fields[j].contains.push(field); - createNewGroup = false; - break; - } - } - if (createNewGroup) { - fields.push({ - entity_type: field.group, - isGroup: true, - contains: [ field ] - }); + $scope.annotate = function(sound, markup) { + var modalInstance = $modal.open({ + animation: true, + templateUrl: "annotationModal.html", + controller: "AnnotationController", + size: "lg", + resolve: { + params: function() { + return { + sound: sound, + markup: markup + }; } - } else { - fields.push(field); } - } - return fields; - }; - var getDictStats = function() { - var getDictStatsUrl = $("#allLexicalEntriesCountUrl").data("lingvodoc"); - $http.get(getDictStatsUrl).success(function(data, status, headers, config) { - var totalEntries = data.count; - $scope.pageCount = Math.ceil(totalEntries / $scope.pageSize); - loadEntries(); - }).error(function(data, status, headers, config) { - $log.error("Failed to load dictionary size!"); - $scope.pageCount = Math.ceil(5e3 / $scope.pageSize); - loadEntries(); }); }; - var loadEntries = function() { - var allLexicalEntriesUrl = $("#allLexicalEntriesUrl").data("lingvodoc"); - allLexicalEntriesUrl = addUrlParameter(allLexicalEntriesUrl, "start_from", ($scope.pageIndex - 1) * $scope.pageSize); - allLexicalEntriesUrl = addUrlParameter(allLexicalEntriesUrl, "count", $scope.pageSize); - $http.get(allLexicalEntriesUrl).success(function(data, status, headers, config) { - $scope.lexicalEntries = data.lexical_entries; - }).error(function(data, status, headers, config) { - $log.error("Failed to load entries!"); - }); - }; - var loadPerspective = function() { - var getFieldsUrl = $("#getPerspectiveFieldsUrl").data("lingvodoc"); - $http.get(getFieldsUrl).success(function(data, status, headers, config) { - $scope.perspective["fields"] = data.fields; - $scope.fields = perspectiveToDictionaryFields($scope.perspective); - getDictStats(); - }).error(function(data, status, headers, config) { - $log.error("Failed to load perspective!"); - }); - }; - loadPerspective(); -} ]); - -app.controller("AnnotationController", [ "$scope", "$http", "soundUrl", "annotationUrl", function($scope, $http, soundUrl, annotationUrl) { - var activeUrl = null; - var createRegions = function(annotaion) { - if (annotaion instanceof elan.Document) { - annotaion.tiers.forEach(function(tier) { - tier.annotations.forEach(function(a) { - var offset1 = annotaion.timeSlotRefToSeconds(a.timeslotRef1); - var offset2 = annotaion.timeSlotRefToSeconds(a.timeslotRef2); - var r = $scope.wavesurfer.addRegion({ - id: a.id, - start: offset1, - end: offset2, - color: "rgba(0, 255, 0, 0.1)" - }); - }); - }); - } - }; - var loadAnnotation = function(url) { - $http.get(url).success(function(data, status, headers, config) { - try { - var xml = new DOMParser().parseFromString(data, "application/xml"); - var annotation = new elan.Document(); - annotation.importXML(xml); - $scope.annotation = annotation; - createRegions(annotation); - } catch (e) { - alert("Failed to parse ELAN annotation: " + e); - } - }).error(function(data, status, headers, config) {}); - }; - $scope.paused = true; - $scope.annotation = null; - $scope.playPause = function() { - if ($scope.wavesurfer) { - $scope.wavesurfer.playPause(); - } - }; - $scope.playAnnotation = function(a) { - if ($scope.wavesurfer && $scope.annotation) { - var offset1 = $scope.annotation.timeSlotRefToSeconds(a.timeslotRef1); - var offset2 = $scope.annotation.timeSlotRefToSeconds(a.timeslotRef2); - $scope.wavesurfer.play(offset1, offset2); - } - }; - $scope.selectRegion = function() {}; - $scope.$on("wavesurferInit", function(e, wavesurfer) { - $scope.wavesurfer = wavesurfer; - if ($scope.wavesurfer.enableDragSelection) { - $scope.wavesurfer.enableDragSelection({ - color: "rgba(0, 255, 0, 0.1)" - }); - } - $scope.wavesurfer.on("play", function() { - $scope.paused = false; + $scope.doSearch = function() { + var q = _.map($scope.search, function(s) { + return { + searchstring: s.query, + entity_type: s.type.entity_type, + search_by_or: s.orFlag + }; }); - $scope.wavesurfer.on("pause", function() { - $scope.paused = true; + _.remove(q, function(s) { + _.isEmpty(s.searchstring) || _.isUndefined(s.entity_type); }); - $scope.wavesurfer.on("finish", function() { - $scope.paused = true; - $scope.wavesurfer.seekTo(0); - $scope.$apply(); + $scope.searchComplete = false; + dictionaryService.advancedSearch(q, $scope.activePerspectives, $scope.adoptedSearch, $scope.etymologySearch).then(function(entries) { + $scope.searchComplete = true; + if (!_.isEmpty(entries)) { + var p = _.find(_.first(entries)["origin"], function(o) { + return o.type == "perspective"; + }); + var groups = []; + var ge = _.groupBy(entries, function(e) { + var entryDictionary = _.find(e["origin"], function(o) { + return o.type == "dictionary"; + }); + var entryPerspective = _.find(e["origin"], function(o) { + return o.type == "perspective"; + }); + var i = _.findIndex(groups, function(g) { + return g.perspective.equals(entryPerspective) && g.dictionary.equals(entryDictionary); + }); + if (i < 0) { + groups.push({ + dictionary: entryDictionary, + perspective: entryPerspective, + origin: e["origin"] + }); + return _.size(groups) - 1; + } + return i; + }); + dictionaryService.getPerspectiveDictionaryFieldsNew(p).then(function(fields) { + $scope.fields = fields; + $scope.entries = entries; + _.each(groups, function(g, i) { + g["matrix"] = mapFieldValues(ge[i], fields); + }); + $scope.groups = groups; + $scope.ge = ge; + }, function(reason) { + responseHandler.error(reason); + }); + } else { + $scope.fields = []; + $scope.groups = []; + $scope.ge = []; + } + }, function(reason) { + responseHandler.error(reason); }); - $scope.wavesurfer.on("region-click", function(region, event) {}); - $scope.wavesurfer.on("region-dblclick", function(region, event) { - region.remove(region); + }; + dictionaryService.getAllPerspectives().then(function(perspectives) { + $scope.perspectives = _.clone(perspectives); + $scope.activePerspectives = _.clone($scope.getPerspectivesWithLocation()); + var reqs = _.map($scope.perspectives, function(p) { + return dictionaryService.getPerspectiveDictionaryFieldsNew(p); }); - $scope.wavesurfer.once("ready", function() { - loadAnnotation(annotationUrl); - $scope.$apply(); + $q.all(reqs).then(function(allFields) { + $scope.allFields = allFields; + }, function(reason) { + responseHandler.error(reason); }); - $scope.wavesurfer.load(soundUrl); + }, function(reason) { + responseHandler.error(reason); }); - $scope.$on("modal.closing", function(e) { - $scope.wavesurfer.stop(); - $scope.wavesurfer.destroy(); + dictionaryService.getDictionaries({}).then(function(dictionaries) { + $scope.dictionaries = dictionaries; + }, function(reason) { + responseHandler.error(reason); }); -} ]); - -app.controller("viewGroupController", [ "$scope", "$http", "$modalInstance", "$log", "groupParams", function($scope, $http, $modalInstance, $log, groupParams) { - var dictionaryClientId = $("#dictionaryClientId").data("lingvodoc"); - var dictionaryObjectId = $("#dictionaryObjectId").data("lingvodoc"); - var perspectiveClientId = $("#perspectiveClientId").data("lingvodoc"); - var perspectiveId = $("#perspectiveId").data("lingvodoc"); - var enabledInputs = []; +} ]).controller("viewGroupController", [ "$scope", "$http", "$modalInstance", "$log", "dictionaryService", "responseHandler", "groupParams", function($scope, $http, $modalInstance, $log, dictionaryService, responseHandler, groupParams) { WaveSurferController.call(this, $scope); $scope.title = groupParams.field.entity_type; $scope.fields = groupParams.field.contains; @@ -33159,10 +36977,8 @@ app.controller("viewGroupController", [ "$scope", "$http", "$modalInstance", "$l var createVirtualEntries = function(values) { var virtualEntries = []; var addValue = function(value, entries) { - var createNewEntry = true; if (value.additional_metadata) { for (var entryIndex = 0; entryIndex < entries.length; entryIndex++) { - var currentEntry = entries[entryIndex]; if (entries[entryIndex].client_id == value.client_id && entries[entryIndex].row_id == value.additional_metadata.row_id) { entries[entryIndex].contains.push(value); return; @@ -33176,13 +36992,11 @@ app.controller("viewGroupController", [ "$scope", "$http", "$modalInstance", "$l }); } }; - for (var i = 0; i < values.length; i++) { - var value = values[i]; - addValue(value, virtualEntries); - } + _.forEach(values, function(v) { + addValue(v, virtualEntries); + }); return virtualEntries; }; - $scope.entries = createVirtualEntries(groupParams.values); $scope.fieldsIdx = []; $scope.fieldsValues = []; $scope.mapFieldValues = function(allEntries, allFields) { @@ -33225,24 +37039,15 @@ app.controller("viewGroupController", [ "$scope", "$http", "$modalInstance", "$l return values; }; $scope.ok = function() { - $modalInstance.close(); + $modalInstance.close($scope.entries); }; - $scope.$watch("entries", function(updatedEntries) { - $scope.mapFieldValues(updatedEntries, $scope.fields); - }, true); -} ]); - -app.controller("viewGroupingTagController", [ "$scope", "$http", "$modalInstance", "$q", "$log", "groupParams", function($scope, $http, $modalInstance, $q, $log, groupParams) { - var dictionaryClientId = $("#dictionaryClientId").data("lingvodoc"); - var dictionaryObjectId = $("#dictionaryObjectId").data("lingvodoc"); - var perspectiveClientId = $("#perspectiveClientId").data("lingvodoc"); - var perspectiveId = $("#perspectiveId").data("lingvodoc"); - var enabledInputs = []; + $scope.entries = createVirtualEntries(groupParams.values); + $scope.mapFieldValues($scope.entries, $scope.fields); +} ]).controller("viewGroupingTagController", [ "$scope", "$http", "$modalInstance", "$q", "$log", "dictionaryService", "responseHandler", "groupParams", function($scope, $http, $modalInstance, $q, $log, dictionaryService, responseHandler, groupParams) { WaveSurferController.call(this, $scope); $scope.fields = groupParams.fields; $scope.connectedEntries = []; $scope.suggestedEntries = []; - $scope.searchQuery = ""; $scope.fieldsIdx = []; for (var k = 0; k < $scope.fields.length; k++) { $scope.fieldsIdx.push($scope.fields[k]); @@ -33251,7 +37056,6 @@ app.controller("viewGroupingTagController", [ "$scope", "$http", "$modalInstance $scope.suggestedFieldsValues = []; $scope.mapFieldValues = function(allEntries, allFields) { var result = []; - $scope.fieldsValues = []; for (var i = 0; i < allEntries.length; i++) { var entryRow = []; for (var j = 0; j < allFields.length; j++) { @@ -33286,76 +37090,71 @@ app.controller("viewGroupingTagController", [ "$scope", "$http", "$modalInstance } return values; }; + $scope.getPerspectiveLink = function(p) { + return "/dictionary/" + encodeURIComponent(p.parent_client_id) + "/" + encodeURIComponent(p.parent_object_id) + "/perspective/" + encodeURIComponent(p.client_id) + "/" + encodeURIComponent(p.object_id) + "/view"; + }; $scope.ok = function() { $modalInstance.close(); }; $scope.$watch("connectedEntries", function(updatedEntries) { $scope.fieldsValues = $scope.mapFieldValues(updatedEntries, $scope.fields); }, true); - $scope.$watch("suggestedEntries", function(updatedEntries) { - $scope.suggestedFieldsValues = $scope.mapFieldValues(updatedEntries, $scope.fields); - }, true); - $scope.$watch("searchQuery", function(updatedQuery) { - if (!updatedQuery || updatedQuery.length < 3) { - return; - } - var url = "/basic_search?leveloneentity=" + encodeURIComponent(updatedQuery); - $http.get(url).success(function(data, status, headers, config) { - $scope.suggestedEntries = []; - var urls = []; - for (var i = 0; i < data.length; i++) { - var entr = data[i]; - var getEntryUrl = "/dictionary/" + encodeURIComponent(entr.origin_dictionary_client_id) + "/" + encodeURIComponent(entr.origin_dictionary_object_id) + "/perspective/" + encodeURIComponent(entr.origin_perspective_client_id) + "/" + encodeURIComponent(entr.origin_perspective_object_id) + "/lexical_entry/" + encodeURIComponent(entr.client_id) + "/" + encodeURIComponent(entr.object_id); - urls.push(getEntryUrl); - } - var uniqueUrls = urls.filter(function(item, pos) { - return urls.indexOf(item) == pos; - }); - var requests = []; - for (var j = 0; j < uniqueUrls.length; j++) { - var r = $http.get(uniqueUrls[j]); - requests.push(r); - } - $q.all(requests).then(function(results) { - for (var k = 0; k < results.length; k++) { - if (results[k].data) { - $scope.suggestedEntries.push(results[k].data.lexical_entry); - } - } + dictionaryService.getConnectedWords(groupParams.entry.client_id, groupParams.entry.object_id).then(function(entries) { + var r = entries.map(function(entry) { + var lexicalEntry = entry.lexical_entry; + return dictionaryService.getPerspectiveOriginById(lexicalEntry.parent_client_id, lexicalEntry.parent_object_id); + }); + $q.all(r).then(function(paths) { + angular.forEach(entries, function(entry, i) { + entry.lexical_entry["origin"] = paths[i]; + $scope.connectedEntries.push(entry.lexical_entry); }); - }).error(function(data, status, headers, config) {}); - }, true); - var loadConnectedWords = function() { - var url = "/lexical_entry/" + encodeURIComponent(groupParams.clientId) + "/" + encodeURIComponent(groupParams.objectId) + "/connected"; - $http.get(url).success(function(data, status, headers, config) {}).error(function(data, status, headers, config) {}); - }; - loadConnectedWords(); -} ]); - -function WaveSurferController($scope) { + }, function(reason) { + responseHandler.error(reason); + }); + }, function(reason) { + responseHandler.error(reason); + }); +} ]).controller("AnnotationController", [ "$scope", "$http", "dictionaryService", "responseHandler", "params", function($scope, $http, dictionaryService, responseHandler, params) { var activeUrl = null; - $scope.play = function(url) { - if (!$scope.wavesurfer) { - return; + var createRegions = function(annotaion) { + if (annotaion instanceof elan.Document) { + annotaion.tiers.forEach(function(tier) { + tier.annotations.forEach(function(a) { + var offset1 = annotaion.timeSlotRefToSeconds(a.timeslotRef1); + var offset2 = annotaion.timeSlotRefToSeconds(a.timeslotRef2); + var r = $scope.wavesurfer.addRegion({ + id: a.id, + start: offset1, + end: offset2, + color: "rgba(0, 255, 0, 0.1)" + }); + }); + }); } - activeUrl = url; - $scope.wavesurfer.once("ready", function() { - $scope.wavesurfer.play(); - $scope.$apply(); - }); - $scope.wavesurfer.load(activeUrl); }; + $scope.paused = true; + $scope.annotation = null; $scope.playPause = function() { - $scope.wavesurfer.playPause(); - }; - $scope.isPlaying = function(url) { - return url == activeUrl; + if ($scope.wavesurfer) { + $scope.wavesurfer.playPause(); + } }; - $scope.isMediaFileAvailable = function() { - return activeUrl != null; + $scope.playAnnotation = function(a) { + if ($scope.wavesurfer && $scope.annotation) { + var offset1 = $scope.annotation.timeSlotRefToSeconds(a.timeslotRef1); + var offset2 = $scope.annotation.timeSlotRefToSeconds(a.timeslotRef2); + $scope.wavesurfer.play(offset1, offset2); + } }; + $scope.selectRegion = function() {}; $scope.$on("wavesurferInit", function(e, wavesurfer) { $scope.wavesurfer = wavesurfer; + if ($scope.wavesurfer.enableDragSelection) { + $scope.wavesurfer.enableDragSelection({ + color: "rgba(0, 255, 0, 0.1)" + }); + } $scope.wavesurfer.on("play", function() { $scope.paused = false; }); @@ -33367,460 +37166,35 @@ function WaveSurferController($scope) { $scope.wavesurfer.seekTo(0); $scope.$apply(); }); - }); - $scope.$on("modal.closing", function(e) { - $scope.wavesurfer.stop(); - $scope.wavesurfer.destroy(); - }); -} - -"use strict"; - -var app = angular.module("DashboardModule", [ "ui.bootstrap" ]); - -app.controller("DashboardController", [ "$scope", "$http", "$interval", "$log", function($scope, $http, $modal, $interval, $log) { - var userId = $("#userId").data("lingvodoc"); - var languagesUrl = $("#languagesUrl").data("lingvodoc"); - var dictionariesUrl = $("#dictionariesUrl").data("lingvodoc"); - var getUserInfoUrl = $("#getUserInfoUrl").data("lingvodoc"); - $scope.dictionaries = []; - var getObjectByCompositeKey = function(id, arr) { - if (typeof id == "string") { - var ids = id.split("_"); - for (var i = 0; i < arr.length; i++) { - if (arr[i].client_id == ids[0] && arr[i].object_id == ids[1]) return arr[i]; - } - } - }; - $scope.getActionDictionaryLink = function(dictionary, action) { - if (dictionary.selectedPerspectiveId != -1) { - var perspective = getObjectByCompositeKey(dictionary.selectedPerspectiveId, dictionary.perspectives); - if (perspective) { - var perspectiveClientId = perspective.client_id; - var perspectiveObjectId = perspective.object_id; - } - return "/dictionary/" + encodeURIComponent(dictionary.client_id) + "/" + encodeURIComponent(dictionary.object_id) + "/perspective/" + encodeURIComponent(perspectiveClientId) + "/" + encodeURIComponent(perspectiveObjectId) + "/" + action; - } - }; - $scope.follow = function(link) { - if (!link) { - alert("Please, select perspective first."); - return; - } - window.location = link; - }; - $scope.getCompositeKey = function(object) { - if (object) { - return object.client_id + "_" + object.object_id; - } - }; - var dictionaryQuery = { - user_created: [ userId ] - }; - $http.post(dictionariesUrl, dictionaryQuery).success(function(data, status, headers, config) { - $scope.dictionaries = data.dictionaries; - for (var i = 0; i < $scope.dictionaries.length; i++) { - var dictionary = $scope.dictionaries[i]; - var getPerspectivesUrl = "/dictionary/" + encodeURIComponent(dictionary.client_id) + "/" + encodeURIComponent(dictionary.object_id) + "/perspectives"; - $http.get(getPerspectivesUrl).success(function(index) { - return function(data, status, headers, config) { - $scope.dictionaries[index]["perspectives"] = data.perspectives; - $scope.dictionaries[index]["selectedPerspectiveId"] = -1; - }; - }(i)).error(function(data, status, headers, config) {}); - } - }).error(function(data, status, headers, config) {}); -} ]); - -"use strict"; - -var app = angular.module("LanguagesModule", [ "ui.bootstrap" ]); - -app.controller("LanguagesController", [ "$scope", "$http", "$modal", "$interval", "$log", function($scope, $http, $modal, $interval, $log) { - var clientId = $("#clientId").data("lingvodoc"); - var userId = $("#userId").data("lingvodoc"); - var languagesUrl = $("#languagesUrl").data("lingvodoc"); - var createLanguageUrl = $("#createLanguageUrl").data("lingvodoc"); - var createLanguage = function(lang) { - $http.post(createLanguageUrl, lang).success(function(data, status, headers, config) {}).error(function(data, status, headers, config) {}); - }; - $scope.languages = []; - $http.get(languagesUrl).success(function(data, status, headers, config) { - $scope.languages = data.languages; - $interval(function() { - $http.get(languagesUrl).success(function(data, status, headers, config) { - $scope.languages = data.languages; - }).error(function(data, status, headers, config) {}); - }, 3e4); - }).error(function(data, status, headers, config) {}); - $scope.createLanguage = function() { - var modalInstance = $modal.open({ - animation: true, - templateUrl: "createLanguageModal.html", - controller: "CreateLanguageController", - size: "lg" - }); - modalInstance.result.then(function(languageObj) { - createLanguage(languageObj); - }, function() { - $log.info("Modal dismissed at: " + new Date()); + $scope.wavesurfer.on("region-click", function(region, event) {}); + $scope.wavesurfer.on("region-dblclick", function(region, event) { + region.remove(region); }); - }; -} ]); - -var app = angular.module("CreateDictionaryModule", [ "ui.router", "ngAnimate", "ui.bootstrap", "autocomplete" ]); - -app.config(function($stateProvider, $urlRouterProvider) { - $stateProvider.state("create", { - url: "/create", - templateUrl: "createDictionary.html", - controller: "CreateDictionaryController" - }).state("create.step1", { - url: "/step1", - templateUrl: "createDictionaryStep1.html" - }).state("create.step2", { - url: "/step2", - templateUrl: "createDictionaryStep2.html" - }).state("create.step3", { - url: "/step3", - templateUrl: "createDictionaryStep3.html" - }); - $urlRouterProvider.otherwise("/create/step1"); -}); - -app.controller("CreateDictionaryController", [ "$scope", "$http", "$modal", "$interval", "$state", "$location", "$log", function($scope, $http, $modal, $interval, $state, $location, $log) { - var clientId = $("#clientId").data("lingvodoc"); - var userId = $("#userId").data("lingvodoc"); - var languagesUrl = $("#languagesUrl").data("lingvodoc"); - var createLanguageUrl = $("#createLanguageUrl").data("lingvodoc"); - var createDictionaryUrl = $("#createDictionaryUrl").data("lingvodoc"); - var allPerspectivesUrl = $("#allPerspectivesUrl").data("lingvodoc"); - var perspectiveFieldsUrl = "/dictionary"; - var listBlobsUrl = $("#listBlobsUrl").data("lingvodoc"); - $scope.wizard = { - mode: "create", - importedDictionaryId: -1 - }; - $scope.users = []; - $scope.userLogins = []; - $scope.uploadedDictionaries = []; - var wrapPerspective = function(perspective) { - if (typeof perspective.fields == "undefined") { - return; - } - for (var i = 0; i < perspective.fields.length; i++) { - if (typeof perspective.fields[i].group !== "undefined") { - perspective.fields[i]._groupEnabled = true; - } - if (typeof perspective.fields[i].contains !== "undefined") { - perspective.fields[i]._containsEnabled = true; - } - } - return perspective; - }; - var exportPerpective = function(perspective) { - var jsPerspective = { - fields: [] - }; - var positionCount = 1; - for (var i = 0; i < perspective.fields.length; i++) { - var field = JSON.parse(JSON.stringify(perspective.fields[i])); - field["position"] = positionCount; - positionCount += 1; - if (field.data_type !== "grouping_tag") { - field["level"] = "leveloneentity"; - } else { - field["level"] = "groupingentity"; - } - if (field._groupEnabled) { - delete field._groupEnabled; - } - if (field._containsEnabled) { - delete field._containsEnabled; - } - if (field.contains) { - for (var j = 0; j < field.contains.length; j++) { - field.contains[j].level = "leveltwoentity"; - field.contains[j].position = positionCount; - positionCount += 1; + $scope.wavesurfer.once("ready", function() { + dictionaryService.convertMarkup(params.markup).then(function(data) { + try { + var xml = new DOMParser().parseFromString(data.content, "application/xml"); + var annotation = new elan.Document(); + annotation.importXML(xml); + $scope.annotation = annotation; + createRegions(annotation); + } catch (e) { + responseHandler.error("Failed to parse ELAN annotation: " + e); } - } - jsPerspective.fields.push(field); - } - return jsPerspective; - }; - var flatLanguages = function(languages) { - var flat = []; - for (var i = 0; i < languages.length; i++) { - var language = languages[i]; - flat.push(languages[i]); - if (language.contains && language.contains.length > 0) { - var childLangs = flatLanguages(language.contains); - flat = flat.concat(childLangs); - } - } - return flat; - }; - var getLanguageById = function(id) { - if (typeof id == "string") { - var ids = id.split("_"); - for (var i = 0; i < $scope.languages.length; i++) { - if ($scope.languages[i].client_id == ids[0] && $scope.languages[i].object_id == ids[1]) return $scope.languages[i]; - } - } - }; - $scope.languages = []; - $scope.perspectives = []; - $scope.dictionaryData = { - languageId: -1, - perspectiveName: "", - perspectiveId: -1 - }; - $scope.perspective = { - fields: [] - }; - $scope.getLanguageId = function(language) { - if (language) { - return language.client_id + "_" + language.object_id; - } - }; - $scope.newLanguage = function() { - var modalInstance = $modal.open({ - animation: true, - templateUrl: "createLanguageModal.html", - controller: "CreateLanguageController", - size: "lg" - }); - modalInstance.result.then(function(languageObj) { - $http.post(createLanguageUrl, languageObj).success(function(data, status, headers, config) { - loadLanguages(); - }).error(function(data, status, headers, config) { - alert("Failed to save language!"); + }, function(reason) { + responseHandler.error(reason); }); - }, function() {}); - }; - $scope.addField = function() { - $scope.perspective.fields.push({ - entity_type: "", - data_type: "text", - status: "enabled" - }); - }; - $scope.enableGroup = function(fieldIndex) { - if (typeof $scope.perspective.fields[fieldIndex].group === "undefined") { - $scope.perspective.fields[fieldIndex].group = ""; - } else { - delete $scope.perspective.fields[fieldIndex].group; - } - }; - $scope.enableLinkedField = function(fieldIndex) { - if (typeof $scope.perspective.fields[fieldIndex].contains === "undefined") { - $scope.perspective.fields[fieldIndex].contains = [ { - entity_type: "", - data_type: "markup", - status: "enabled" - } ]; - } else { - delete $scope.perspective.fields[fieldIndex].contains; - } - }; - $scope.createDictionary = function() { - var language = getLanguageById($scope.dictionaryData.languageId); - if (!$scope.dictionaryData.name && $scope.wizard.mode == "create" || typeof $scope.wizard.importedDictionaryId != "string" && $scope.wizard.mode == "import" || !language) { - return; - } - if ($scope.wizard.mode == "create") { - var dictionaryObj = { - parent_client_id: language.client_id, - parent_object_id: language.object_id, - name: $scope.dictionaryData.name, - translation: $scope.dictionaryData.name - }; - $http.post(createDictionaryUrl, dictionaryObj).success(function(data, status, headers, config) { - if (data.object_id && data.client_id) { - $scope.dictionaryData.dictionary_client_id = data.client_id; - $scope.dictionaryData.dictionary_object_id = data.object_id; - $state.go("create.step2"); - } else { - alert("Failed to create dictionary!"); - } - }).error(function(data, status, headers, config) { - alert("Failed to create dictionary!"); - }); - } - if ($scope.wizard.mode == "import") { - if (typeof $scope.wizard.importedDictionaryId == "string") { - var ids = $scope.wizard.importedDictionaryId.split("_"); - var url = $("#convertUrl").data("lingvodoc"); - var convertObject = { - blob_client_id: parseInt(ids[0]), - blob_object_id: parseInt(ids[1]), - parent_client_id: language.client_id, - parent_object_id: language.object_id - }; - $http.post(url, convertObject).success(function(data, status, headers, config) { - alert(data.status); - }).error(function(data, status, headers, config) {}); - } - } - }; - $scope.createPerspective = function() { - if (!$scope.dictionaryData.perspectiveName) { - return; - } - var createPerspectiveUrl = "/dictionary/" + encodeURIComponent($scope.dictionaryData.dictionary_client_id) + "/" + encodeURIComponent($scope.dictionaryData.dictionary_object_id) + "/" + "perspective"; - var perspectiveObj = { - name: $scope.dictionaryData.perspectiveName, - translation: $scope.dictionaryData.perspectiveName - }; - $http.post(createPerspectiveUrl, perspectiveObj).success(function(data, status, headers, config) { - if (data.object_id && data.client_id) { - $scope.dictionaryData.perspective_client_id = data.client_id; - $scope.dictionaryData.perspective_object_id = data.object_id; - var setFieldsUrl = "/dictionary/" + encodeURIComponent($scope.dictionaryData.dictionary_client_id) + "/" + encodeURIComponent($scope.dictionaryData.dictionary_object_id) + "/perspective/" + encodeURIComponent($scope.dictionaryData.perspective_client_id) + "/" + encodeURIComponent($scope.dictionaryData.perspective_object_id) + "/fields"; - $http.post(setFieldsUrl, exportPerpective($scope.perspective)).success(function(data, status, headers, config) { - window.location = "/dashboard"; - }).error(function(data, status, headers, config) { - alert("Failed to create perspective!"); - }); - } else { - alert("Failed to create perspective!"); - } - }).error(function(data, status, headers, config) { - alert("Failed to create perspective!"); - }); - }; - $scope.searchUsers = function(query) { - var promise = $http.get("/users?search=" + encodeURIComponent(query)).then(function(response) { - return response.data; - }); - promise.then(function(data) { - var userLogins = []; - if (data.users) { - for (var i = 0; i < data.users.length; i++) { - var user = data.users[i]; - userLogins.push(user.login); - } - $scope.userLogins = userLogins; - $scope.users = data.users; - } + $scope.$apply(); }); - }; - $scope.addUser = function(userLogin) {}; - var loadLanguages = function() { - $http.get(languagesUrl).success(function(data, status, headers, config) { - $scope.languages = flatLanguages(data.languages); - }).error(function(data, status, headers, config) {}); - }; - var loadPerspectives = function() { - var perspectives = []; - $http.get(allPerspectivesUrl).success(function(data, status, headers, config) { - for (var i = 0; i < data.perspectives.length; i++) { - var perspective = data.perspectives[i]; - var url = "/dictionary/" + perspective.parent_client_id + "/" + perspective.parent_object_id + "/perspective/" + perspective.client_id + "/" + perspective.object_id + "/fields"; - $http.get(url).success(function(perspective) { - return function(data, status, headers, config) { - var p = {}; - p.name = perspective.name; - p.object_id = perspective.object_id; - p.client_id = perspective.client_id; - p.fields = data.fields; - var wrappedPerspective = wrapPerspective(p); - if (wrappedPerspective) { - $scope.perspectives.push(wrappedPerspective); - } - }; - }(perspective)).error(function(data, status, headers, config) { - $log.error("Failed to load perspectives!"); - }); - } - }).error(function(data, status, headers, config) { - $log.error("Failed to load perspectives!"); - }); - }; - var loadBlobs = function() { - $http.get(listBlobsUrl).success(function(data, status, headers, config) { - $scope.uploadedDictionaries = []; - for (var i = 0; i < data.length; i++) { - if (data[i].data_type = "dialeqt_dictionary") { - var id = data[i].client_id + "_" + data[i].object_id; - $scope.uploadedDictionaries.push({ - id: id, - data: data[i] - }); - } - } - }).error(function(data, status, headers, config) {}); - }; - $scope.$watch("dictionaryData.perspectiveId", function(id) { - if (typeof id == "string") { - var ids = id.split("_"); - for (var i = 0; i < $scope.perspectives.length; i++) { - if ($scope.perspectives[i].client_id == ids[0] && $scope.perspectives[i].object_id == ids[1]) { - $scope.perspective = $scope.perspectives[i]; - break; - } - } - } + $scope.wavesurfer.load(params.sound.content); }); - loadLanguages(); - loadPerspectives(); - loadBlobs(); -} ]); - -app.controller("CreateLanguageController", [ "$scope", "$http", "$interval", "$modalInstance", function($scope, $http, $interval, $modalInstance) { - var clientId = $("#clientId").data("lingvodoc"); - var userId = $("#userId").data("lingvodoc"); - var languagesUrl = $("#languagesUrl").data("lingvodoc"); - var createLanguageUrl = $("#createLanguageUrl").data("lingvodoc"); - $scope.languages = []; - $scope.parentLanguageId = -1; - $scope.translation = ""; - $scope.translationString = ""; - var getLanguageById = function(id) { - var ids = id.split("_"); - for (var i = 0; i < $scope.languages.length; i++) { - if ($scope.languages[i].client_id == ids[0] && $scope.languages[i].object_id == ids[1]) return $scope.languages[i]; - } - }; - var flatLanguages = function(languages) { - var flat = []; - for (var i = 0; i < languages.length; i++) { - var language = languages[i]; - flat.push(languages[i]); - if (language.contains && language.contains.length > 0) { - var childLangs = flatLanguages(language.contains); - flat = flat.concat(childLangs); - } - } - return flat; - }; - $scope.getLanguageId = function(language) { - if (language) { - return language.client_id + "_" + language.object_id; - } - }; + $scope.$on("modal.closing", function(e) { + $scope.wavesurfer.stop(); + $scope.wavesurfer.destroy(); + }); +} ]).controller("BlobController", [ "$scope", "$http", "$log", "$modal", "$modalInstance", "NgMap", "dictionaryService", "responseHandler", "params", function($scope, $http, $log, $modal, $modalInstance, NgMap, dictionaryService, responseHandler, params) { + $scope.blob = params.blob; $scope.ok = function() { - if (!$scope.translation) { - return; - } - var languageObj = { - translation: $scope.translation, - translation_string: $scope.translation - }; - if ($scope.parentLanguageId != "-1") { - var parentLanguage = getLanguageById($scope.parentLanguageId); - if (parentLanguage) { - languageObj["parent_client_id"] = parentLanguage.client_id; - languageObj["parent_object_id"] = parentLanguage.object_id; - } - } - $modalInstance.close(languageObj); - }; - $scope.cancel = function() { - $modalInstance.dismiss("cancel"); + $modalInstance.close(); }; - $http.get(languagesUrl).success(function(data, status, headers, config) { - $scope.languages = flatLanguages(data.languages); - }).error(function(data, status, headers, config) {}); } ]); \ No newline at end of file diff --git a/lingvodoc/static/js/merge-master.js b/lingvodoc/static/js/merge-master.js index 2206b516c..4a9fdc92e 100644 --- a/lingvodoc/static/js/merge-master.js +++ b/lingvodoc/static/js/merge-master.js @@ -5377,6 +5377,3947 @@ return jQuery; }); +(function() { + var undefined; + var VERSION = "3.10.1"; + var BIND_FLAG = 1, BIND_KEY_FLAG = 2, CURRY_BOUND_FLAG = 4, CURRY_FLAG = 8, CURRY_RIGHT_FLAG = 16, PARTIAL_FLAG = 32, PARTIAL_RIGHT_FLAG = 64, ARY_FLAG = 128, REARG_FLAG = 256; + var DEFAULT_TRUNC_LENGTH = 30, DEFAULT_TRUNC_OMISSION = "..."; + var HOT_COUNT = 150, HOT_SPAN = 16; + var LARGE_ARRAY_SIZE = 200; + var LAZY_FILTER_FLAG = 1, LAZY_MAP_FLAG = 2; + var FUNC_ERROR_TEXT = "Expected a function"; + var PLACEHOLDER = "__lodash_placeholder__"; + var argsTag = "[object Arguments]", arrayTag = "[object Array]", boolTag = "[object Boolean]", dateTag = "[object Date]", errorTag = "[object Error]", funcTag = "[object Function]", mapTag = "[object Map]", numberTag = "[object Number]", objectTag = "[object Object]", regexpTag = "[object RegExp]", setTag = "[object Set]", stringTag = "[object String]", weakMapTag = "[object WeakMap]"; + var arrayBufferTag = "[object ArrayBuffer]", float32Tag = "[object Float32Array]", float64Tag = "[object Float64Array]", int8Tag = "[object Int8Array]", int16Tag = "[object Int16Array]", int32Tag = "[object Int32Array]", uint8Tag = "[object Uint8Array]", uint8ClampedTag = "[object Uint8ClampedArray]", uint16Tag = "[object Uint16Array]", uint32Tag = "[object Uint32Array]"; + var reEmptyStringLeading = /\b__p \+= '';/g, reEmptyStringMiddle = /\b(__p \+=) '' \+/g, reEmptyStringTrailing = /(__e\(.*?\)|\b__t\)) \+\n'';/g; + var reEscapedHtml = /&(?:amp|lt|gt|quot|#39|#96);/g, reUnescapedHtml = /[&<>"'`]/g, reHasEscapedHtml = RegExp(reEscapedHtml.source), reHasUnescapedHtml = RegExp(reUnescapedHtml.source); + var reEscape = /<%-([\s\S]+?)%>/g, reEvaluate = /<%([\s\S]+?)%>/g, reInterpolate = /<%=([\s\S]+?)%>/g; + var reIsDeepProp = /\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\n\\]|\\.)*?\1)\]/, reIsPlainProp = /^\w*$/, rePropName = /[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\n\\]|\\.)*?)\2)\]/g; + var reRegExpChars = /^[:!,]|[\\^$.*+?()[\]{}|\/]|(^[0-9a-fA-Fnrtuvx])|([\n\r\u2028\u2029])/g, reHasRegExpChars = RegExp(reRegExpChars.source); + var reComboMark = /[\u0300-\u036f\ufe20-\ufe23]/g; + var reEscapeChar = /\\(\\)?/g; + var reEsTemplate = /\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g; + var reFlags = /\w*$/; + var reHasHexPrefix = /^0[xX]/; + var reIsHostCtor = /^\[object .+?Constructor\]$/; + var reIsUint = /^\d+$/; + var reLatin1 = /[\xc0-\xd6\xd8-\xde\xdf-\xf6\xf8-\xff]/g; + var reNoMatch = /($^)/; + var reUnescapedString = /['\n\r\u2028\u2029\\]/g; + var reWords = function() { + var upper = "[A-Z\\xc0-\\xd6\\xd8-\\xde]", lower = "[a-z\\xdf-\\xf6\\xf8-\\xff]+"; + return RegExp(upper + "+(?=" + upper + lower + ")|" + upper + "?" + lower + "|" + upper + "+|[0-9]+", "g"); + }(); + var contextProps = [ "Array", "ArrayBuffer", "Date", "Error", "Float32Array", "Float64Array", "Function", "Int8Array", "Int16Array", "Int32Array", "Math", "Number", "Object", "RegExp", "Set", "String", "_", "clearTimeout", "isFinite", "parseFloat", "parseInt", "setTimeout", "TypeError", "Uint8Array", "Uint8ClampedArray", "Uint16Array", "Uint32Array", "WeakMap" ]; + var templateCounter = -1; + var typedArrayTags = {}; + typedArrayTags[float32Tag] = typedArrayTags[float64Tag] = typedArrayTags[int8Tag] = typedArrayTags[int16Tag] = typedArrayTags[int32Tag] = typedArrayTags[uint8Tag] = typedArrayTags[uint8ClampedTag] = typedArrayTags[uint16Tag] = typedArrayTags[uint32Tag] = true; + typedArrayTags[argsTag] = typedArrayTags[arrayTag] = typedArrayTags[arrayBufferTag] = typedArrayTags[boolTag] = typedArrayTags[dateTag] = typedArrayTags[errorTag] = typedArrayTags[funcTag] = typedArrayTags[mapTag] = typedArrayTags[numberTag] = typedArrayTags[objectTag] = typedArrayTags[regexpTag] = typedArrayTags[setTag] = typedArrayTags[stringTag] = typedArrayTags[weakMapTag] = false; + var cloneableTags = {}; + cloneableTags[argsTag] = cloneableTags[arrayTag] = cloneableTags[arrayBufferTag] = cloneableTags[boolTag] = cloneableTags[dateTag] = cloneableTags[float32Tag] = cloneableTags[float64Tag] = cloneableTags[int8Tag] = cloneableTags[int16Tag] = cloneableTags[int32Tag] = cloneableTags[numberTag] = cloneableTags[objectTag] = cloneableTags[regexpTag] = cloneableTags[stringTag] = cloneableTags[uint8Tag] = cloneableTags[uint8ClampedTag] = cloneableTags[uint16Tag] = cloneableTags[uint32Tag] = true; + cloneableTags[errorTag] = cloneableTags[funcTag] = cloneableTags[mapTag] = cloneableTags[setTag] = cloneableTags[weakMapTag] = false; + var deburredLetters = { + "À": "A", + "Á": "A", + "Â": "A", + "Ã": "A", + "Ä": "A", + "Å": "A", + "à": "a", + "á": "a", + "â": "a", + "ã": "a", + "ä": "a", + "å": "a", + "Ç": "C", + "ç": "c", + "Ð": "D", + "ð": "d", + "È": "E", + "É": "E", + "Ê": "E", + "Ë": "E", + "è": "e", + "é": "e", + "ê": "e", + "ë": "e", + "Ì": "I", + "Í": "I", + "Î": "I", + "Ï": "I", + "ì": "i", + "í": "i", + "î": "i", + "ï": "i", + "Ñ": "N", + "ñ": "n", + "Ò": "O", + "Ó": "O", + "Ô": "O", + "Õ": "O", + "Ö": "O", + "Ø": "O", + "ò": "o", + "ó": "o", + "ô": "o", + "õ": "o", + "ö": "o", + "ø": "o", + "Ù": "U", + "Ú": "U", + "Û": "U", + "Ü": "U", + "ù": "u", + "ú": "u", + "û": "u", + "ü": "u", + "Ý": "Y", + "ý": "y", + "ÿ": "y", + "Æ": "Ae", + "æ": "ae", + "Þ": "Th", + "þ": "th", + "ß": "ss" + }; + var htmlEscapes = { + "&": "&", + "<": "<", + ">": ">", + '"': """, + "'": "'", + "`": "`" + }; + var htmlUnescapes = { + "&": "&", + "<": "<", + ">": ">", + """: '"', + "'": "'", + "`": "`" + }; + var objectTypes = { + "function": true, + object: true + }; + var regexpEscapes = { + "0": "x30", + "1": "x31", + "2": "x32", + "3": "x33", + "4": "x34", + "5": "x35", + "6": "x36", + "7": "x37", + "8": "x38", + "9": "x39", + A: "x41", + B: "x42", + C: "x43", + D: "x44", + E: "x45", + F: "x46", + a: "x61", + b: "x62", + c: "x63", + d: "x64", + e: "x65", + f: "x66", + n: "x6e", + r: "x72", + t: "x74", + u: "x75", + v: "x76", + x: "x78" + }; + var stringEscapes = { + "\\": "\\", + "'": "'", + "\n": "n", + "\r": "r", + "\u2028": "u2028", + "\u2029": "u2029" + }; + var freeExports = objectTypes[typeof exports] && exports && !exports.nodeType && exports; + var freeModule = objectTypes[typeof module] && module && !module.nodeType && module; + var freeGlobal = freeExports && freeModule && typeof global == "object" && global && global.Object && global; + var freeSelf = objectTypes[typeof self] && self && self.Object && self; + var freeWindow = objectTypes[typeof window] && window && window.Object && window; + var moduleExports = freeModule && freeModule.exports === freeExports && freeExports; + var root = freeGlobal || freeWindow !== (this && this.window) && freeWindow || freeSelf || this; + function baseCompareAscending(value, other) { + if (value !== other) { + var valIsNull = value === null, valIsUndef = value === undefined, valIsReflexive = value === value; + var othIsNull = other === null, othIsUndef = other === undefined, othIsReflexive = other === other; + if (value > other && !othIsNull || !valIsReflexive || valIsNull && !othIsUndef && othIsReflexive || valIsUndef && othIsReflexive) { + return 1; + } + if (value < other && !valIsNull || !othIsReflexive || othIsNull && !valIsUndef && valIsReflexive || othIsUndef && valIsReflexive) { + return -1; + } + } + return 0; + } + function baseFindIndex(array, predicate, fromRight) { + var length = array.length, index = fromRight ? length : -1; + while (fromRight ? index-- : ++index < length) { + if (predicate(array[index], index, array)) { + return index; + } + } + return -1; + } + function baseIndexOf(array, value, fromIndex) { + if (value !== value) { + return indexOfNaN(array, fromIndex); + } + var index = fromIndex - 1, length = array.length; + while (++index < length) { + if (array[index] === value) { + return index; + } + } + return -1; + } + function baseIsFunction(value) { + return typeof value == "function" || false; + } + function baseToString(value) { + return value == null ? "" : value + ""; + } + function charsLeftIndex(string, chars) { + var index = -1, length = string.length; + while (++index < length && chars.indexOf(string.charAt(index)) > -1) {} + return index; + } + function charsRightIndex(string, chars) { + var index = string.length; + while (index-- && chars.indexOf(string.charAt(index)) > -1) {} + return index; + } + function compareAscending(object, other) { + return baseCompareAscending(object.criteria, other.criteria) || object.index - other.index; + } + function compareMultiple(object, other, orders) { + var index = -1, objCriteria = object.criteria, othCriteria = other.criteria, length = objCriteria.length, ordersLength = orders.length; + while (++index < length) { + var result = baseCompareAscending(objCriteria[index], othCriteria[index]); + if (result) { + if (index >= ordersLength) { + return result; + } + var order = orders[index]; + return result * (order === "asc" || order === true ? 1 : -1); + } + } + return object.index - other.index; + } + function deburrLetter(letter) { + return deburredLetters[letter]; + } + function escapeHtmlChar(chr) { + return htmlEscapes[chr]; + } + function escapeRegExpChar(chr, leadingChar, whitespaceChar) { + if (leadingChar) { + chr = regexpEscapes[chr]; + } else if (whitespaceChar) { + chr = stringEscapes[chr]; + } + return "\\" + chr; + } + function escapeStringChar(chr) { + return "\\" + stringEscapes[chr]; + } + function indexOfNaN(array, fromIndex, fromRight) { + var length = array.length, index = fromIndex + (fromRight ? 0 : -1); + while (fromRight ? index-- : ++index < length) { + var other = array[index]; + if (other !== other) { + return index; + } + } + return -1; + } + function isObjectLike(value) { + return !!value && typeof value == "object"; + } + function isSpace(charCode) { + return charCode <= 160 && (charCode >= 9 && charCode <= 13) || charCode == 32 || charCode == 160 || charCode == 5760 || charCode == 6158 || charCode >= 8192 && (charCode <= 8202 || charCode == 8232 || charCode == 8233 || charCode == 8239 || charCode == 8287 || charCode == 12288 || charCode == 65279); + } + function replaceHolders(array, placeholder) { + var index = -1, length = array.length, resIndex = -1, result = []; + while (++index < length) { + if (array[index] === placeholder) { + array[index] = PLACEHOLDER; + result[++resIndex] = index; + } + } + return result; + } + function sortedUniq(array, iteratee) { + var seen, index = -1, length = array.length, resIndex = -1, result = []; + while (++index < length) { + var value = array[index], computed = iteratee ? iteratee(value, index, array) : value; + if (!index || seen !== computed) { + seen = computed; + result[++resIndex] = value; + } + } + return result; + } + function trimmedLeftIndex(string) { + var index = -1, length = string.length; + while (++index < length && isSpace(string.charCodeAt(index))) {} + return index; + } + function trimmedRightIndex(string) { + var index = string.length; + while (index-- && isSpace(string.charCodeAt(index))) {} + return index; + } + function unescapeHtmlChar(chr) { + return htmlUnescapes[chr]; + } + function runInContext(context) { + context = context ? _.defaults(root.Object(), context, _.pick(root, contextProps)) : root; + var Array = context.Array, Date = context.Date, Error = context.Error, Function = context.Function, Math = context.Math, Number = context.Number, Object = context.Object, RegExp = context.RegExp, String = context.String, TypeError = context.TypeError; + var arrayProto = Array.prototype, objectProto = Object.prototype, stringProto = String.prototype; + var fnToString = Function.prototype.toString; + var hasOwnProperty = objectProto.hasOwnProperty; + var idCounter = 0; + var objToString = objectProto.toString; + var oldDash = root._; + var reIsNative = RegExp("^" + fnToString.call(hasOwnProperty).replace(/[\\^$.*+?()[\]{}|]/g, "\\$&").replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g, "$1.*?") + "$"); + var ArrayBuffer = context.ArrayBuffer, clearTimeout = context.clearTimeout, parseFloat = context.parseFloat, pow = Math.pow, propertyIsEnumerable = objectProto.propertyIsEnumerable, Set = getNative(context, "Set"), setTimeout = context.setTimeout, splice = arrayProto.splice, Uint8Array = context.Uint8Array, WeakMap = getNative(context, "WeakMap"); + var nativeCeil = Math.ceil, nativeCreate = getNative(Object, "create"), nativeFloor = Math.floor, nativeIsArray = getNative(Array, "isArray"), nativeIsFinite = context.isFinite, nativeKeys = getNative(Object, "keys"), nativeMax = Math.max, nativeMin = Math.min, nativeNow = getNative(Date, "now"), nativeParseInt = context.parseInt, nativeRandom = Math.random; + var NEGATIVE_INFINITY = Number.NEGATIVE_INFINITY, POSITIVE_INFINITY = Number.POSITIVE_INFINITY; + var MAX_ARRAY_LENGTH = 4294967295, MAX_ARRAY_INDEX = MAX_ARRAY_LENGTH - 1, HALF_MAX_ARRAY_LENGTH = MAX_ARRAY_LENGTH >>> 1; + var MAX_SAFE_INTEGER = 9007199254740991; + var metaMap = WeakMap && new WeakMap(); + var realNames = {}; + function lodash(value) { + if (isObjectLike(value) && !isArray(value) && !(value instanceof LazyWrapper)) { + if (value instanceof LodashWrapper) { + return value; + } + if (hasOwnProperty.call(value, "__chain__") && hasOwnProperty.call(value, "__wrapped__")) { + return wrapperClone(value); + } + } + return new LodashWrapper(value); + } + function baseLodash() {} + function LodashWrapper(value, chainAll, actions) { + this.__wrapped__ = value; + this.__actions__ = actions || []; + this.__chain__ = !!chainAll; + } + var support = lodash.support = {}; + lodash.templateSettings = { + escape: reEscape, + evaluate: reEvaluate, + interpolate: reInterpolate, + variable: "", + imports: { + _: lodash + } + }; + function LazyWrapper(value) { + this.__wrapped__ = value; + this.__actions__ = []; + this.__dir__ = 1; + this.__filtered__ = false; + this.__iteratees__ = []; + this.__takeCount__ = POSITIVE_INFINITY; + this.__views__ = []; + } + function lazyClone() { + var result = new LazyWrapper(this.__wrapped__); + result.__actions__ = arrayCopy(this.__actions__); + result.__dir__ = this.__dir__; + result.__filtered__ = this.__filtered__; + result.__iteratees__ = arrayCopy(this.__iteratees__); + result.__takeCount__ = this.__takeCount__; + result.__views__ = arrayCopy(this.__views__); + return result; + } + function lazyReverse() { + if (this.__filtered__) { + var result = new LazyWrapper(this); + result.__dir__ = -1; + result.__filtered__ = true; + } else { + result = this.clone(); + result.__dir__ *= -1; + } + return result; + } + function lazyValue() { + var array = this.__wrapped__.value(), dir = this.__dir__, isArr = isArray(array), isRight = dir < 0, arrLength = isArr ? array.length : 0, view = getView(0, arrLength, this.__views__), start = view.start, end = view.end, length = end - start, index = isRight ? end : start - 1, iteratees = this.__iteratees__, iterLength = iteratees.length, resIndex = 0, takeCount = nativeMin(length, this.__takeCount__); + if (!isArr || arrLength < LARGE_ARRAY_SIZE || arrLength == length && takeCount == length) { + return baseWrapperValue(array, this.__actions__); + } + var result = []; + outer: while (length-- && resIndex < takeCount) { + index += dir; + var iterIndex = -1, value = array[index]; + while (++iterIndex < iterLength) { + var data = iteratees[iterIndex], iteratee = data.iteratee, type = data.type, computed = iteratee(value); + if (type == LAZY_MAP_FLAG) { + value = computed; + } else if (!computed) { + if (type == LAZY_FILTER_FLAG) { + continue outer; + } else { + break outer; + } + } + } + result[resIndex++] = value; + } + return result; + } + function MapCache() { + this.__data__ = {}; + } + function mapDelete(key) { + return this.has(key) && delete this.__data__[key]; + } + function mapGet(key) { + return key == "__proto__" ? undefined : this.__data__[key]; + } + function mapHas(key) { + return key != "__proto__" && hasOwnProperty.call(this.__data__, key); + } + function mapSet(key, value) { + if (key != "__proto__") { + this.__data__[key] = value; + } + return this; + } + function SetCache(values) { + var length = values ? values.length : 0; + this.data = { + hash: nativeCreate(null), + set: new Set() + }; + while (length--) { + this.push(values[length]); + } + } + function cacheIndexOf(cache, value) { + var data = cache.data, result = typeof value == "string" || isObject(value) ? data.set.has(value) : data.hash[value]; + return result ? 0 : -1; + } + function cachePush(value) { + var data = this.data; + if (typeof value == "string" || isObject(value)) { + data.set.add(value); + } else { + data.hash[value] = true; + } + } + function arrayConcat(array, other) { + var index = -1, length = array.length, othIndex = -1, othLength = other.length, result = Array(length + othLength); + while (++index < length) { + result[index] = array[index]; + } + while (++othIndex < othLength) { + result[index++] = other[othIndex]; + } + return result; + } + function arrayCopy(source, array) { + var index = -1, length = source.length; + array || (array = Array(length)); + while (++index < length) { + array[index] = source[index]; + } + return array; + } + function arrayEach(array, iteratee) { + var index = -1, length = array.length; + while (++index < length) { + if (iteratee(array[index], index, array) === false) { + break; + } + } + return array; + } + function arrayEachRight(array, iteratee) { + var length = array.length; + while (length--) { + if (iteratee(array[length], length, array) === false) { + break; + } + } + return array; + } + function arrayEvery(array, predicate) { + var index = -1, length = array.length; + while (++index < length) { + if (!predicate(array[index], index, array)) { + return false; + } + } + return true; + } + function arrayExtremum(array, iteratee, comparator, exValue) { + var index = -1, length = array.length, computed = exValue, result = computed; + while (++index < length) { + var value = array[index], current = +iteratee(value); + if (comparator(current, computed)) { + computed = current; + result = value; + } + } + return result; + } + function arrayFilter(array, predicate) { + var index = -1, length = array.length, resIndex = -1, result = []; + while (++index < length) { + var value = array[index]; + if (predicate(value, index, array)) { + result[++resIndex] = value; + } + } + return result; + } + function arrayMap(array, iteratee) { + var index = -1, length = array.length, result = Array(length); + while (++index < length) { + result[index] = iteratee(array[index], index, array); + } + return result; + } + function arrayPush(array, values) { + var index = -1, length = values.length, offset = array.length; + while (++index < length) { + array[offset + index] = values[index]; + } + return array; + } + function arrayReduce(array, iteratee, accumulator, initFromArray) { + var index = -1, length = array.length; + if (initFromArray && length) { + accumulator = array[++index]; + } + while (++index < length) { + accumulator = iteratee(accumulator, array[index], index, array); + } + return accumulator; + } + function arrayReduceRight(array, iteratee, accumulator, initFromArray) { + var length = array.length; + if (initFromArray && length) { + accumulator = array[--length]; + } + while (length--) { + accumulator = iteratee(accumulator, array[length], length, array); + } + return accumulator; + } + function arraySome(array, predicate) { + var index = -1, length = array.length; + while (++index < length) { + if (predicate(array[index], index, array)) { + return true; + } + } + return false; + } + function arraySum(array, iteratee) { + var length = array.length, result = 0; + while (length--) { + result += +iteratee(array[length]) || 0; + } + return result; + } + function assignDefaults(objectValue, sourceValue) { + return objectValue === undefined ? sourceValue : objectValue; + } + function assignOwnDefaults(objectValue, sourceValue, key, object) { + return objectValue === undefined || !hasOwnProperty.call(object, key) ? sourceValue : objectValue; + } + function assignWith(object, source, customizer) { + var index = -1, props = keys(source), length = props.length; + while (++index < length) { + var key = props[index], value = object[key], result = customizer(value, source[key], key, object, source); + if ((result === result ? result !== value : value === value) || value === undefined && !(key in object)) { + object[key] = result; + } + } + return object; + } + function baseAssign(object, source) { + return source == null ? object : baseCopy(source, keys(source), object); + } + function baseAt(collection, props) { + var index = -1, isNil = collection == null, isArr = !isNil && isArrayLike(collection), length = isArr ? collection.length : 0, propsLength = props.length, result = Array(propsLength); + while (++index < propsLength) { + var key = props[index]; + if (isArr) { + result[index] = isIndex(key, length) ? collection[key] : undefined; + } else { + result[index] = isNil ? undefined : collection[key]; + } + } + return result; + } + function baseCopy(source, props, object) { + object || (object = {}); + var index = -1, length = props.length; + while (++index < length) { + var key = props[index]; + object[key] = source[key]; + } + return object; + } + function baseCallback(func, thisArg, argCount) { + var type = typeof func; + if (type == "function") { + return thisArg === undefined ? func : bindCallback(func, thisArg, argCount); + } + if (func == null) { + return identity; + } + if (type == "object") { + return baseMatches(func); + } + return thisArg === undefined ? property(func) : baseMatchesProperty(func, thisArg); + } + function baseClone(value, isDeep, customizer, key, object, stackA, stackB) { + var result; + if (customizer) { + result = object ? customizer(value, key, object) : customizer(value); + } + if (result !== undefined) { + return result; + } + if (!isObject(value)) { + return value; + } + var isArr = isArray(value); + if (isArr) { + result = initCloneArray(value); + if (!isDeep) { + return arrayCopy(value, result); + } + } else { + var tag = objToString.call(value), isFunc = tag == funcTag; + if (tag == objectTag || tag == argsTag || isFunc && !object) { + result = initCloneObject(isFunc ? {} : value); + if (!isDeep) { + return baseAssign(result, value); + } + } else { + return cloneableTags[tag] ? initCloneByTag(value, tag, isDeep) : object ? value : {}; + } + } + stackA || (stackA = []); + stackB || (stackB = []); + var length = stackA.length; + while (length--) { + if (stackA[length] == value) { + return stackB[length]; + } + } + stackA.push(value); + stackB.push(result); + (isArr ? arrayEach : baseForOwn)(value, function(subValue, key) { + result[key] = baseClone(subValue, isDeep, customizer, key, value, stackA, stackB); + }); + return result; + } + var baseCreate = function() { + function object() {} + return function(prototype) { + if (isObject(prototype)) { + object.prototype = prototype; + var result = new object(); + object.prototype = undefined; + } + return result || {}; + }; + }(); + function baseDelay(func, wait, args) { + if (typeof func != "function") { + throw new TypeError(FUNC_ERROR_TEXT); + } + return setTimeout(function() { + func.apply(undefined, args); + }, wait); + } + function baseDifference(array, values) { + var length = array ? array.length : 0, result = []; + if (!length) { + return result; + } + var index = -1, indexOf = getIndexOf(), isCommon = indexOf === baseIndexOf, cache = isCommon && values.length >= LARGE_ARRAY_SIZE ? createCache(values) : null, valuesLength = values.length; + if (cache) { + indexOf = cacheIndexOf; + isCommon = false; + values = cache; + } + outer: while (++index < length) { + var value = array[index]; + if (isCommon && value === value) { + var valuesIndex = valuesLength; + while (valuesIndex--) { + if (values[valuesIndex] === value) { + continue outer; + } + } + result.push(value); + } else if (indexOf(values, value, 0) < 0) { + result.push(value); + } + } + return result; + } + var baseEach = createBaseEach(baseForOwn); + var baseEachRight = createBaseEach(baseForOwnRight, true); + function baseEvery(collection, predicate) { + var result = true; + baseEach(collection, function(value, index, collection) { + result = !!predicate(value, index, collection); + return result; + }); + return result; + } + function baseExtremum(collection, iteratee, comparator, exValue) { + var computed = exValue, result = computed; + baseEach(collection, function(value, index, collection) { + var current = +iteratee(value, index, collection); + if (comparator(current, computed) || current === exValue && current === result) { + computed = current; + result = value; + } + }); + return result; + } + function baseFill(array, value, start, end) { + var length = array.length; + start = start == null ? 0 : +start || 0; + if (start < 0) { + start = -start > length ? 0 : length + start; + } + end = end === undefined || end > length ? length : +end || 0; + if (end < 0) { + end += length; + } + length = start > end ? 0 : end >>> 0; + start >>>= 0; + while (start < length) { + array[start++] = value; + } + return array; + } + function baseFilter(collection, predicate) { + var result = []; + baseEach(collection, function(value, index, collection) { + if (predicate(value, index, collection)) { + result.push(value); + } + }); + return result; + } + function baseFind(collection, predicate, eachFunc, retKey) { + var result; + eachFunc(collection, function(value, key, collection) { + if (predicate(value, key, collection)) { + result = retKey ? key : value; + return false; + } + }); + return result; + } + function baseFlatten(array, isDeep, isStrict, result) { + result || (result = []); + var index = -1, length = array.length; + while (++index < length) { + var value = array[index]; + if (isObjectLike(value) && isArrayLike(value) && (isStrict || isArray(value) || isArguments(value))) { + if (isDeep) { + baseFlatten(value, isDeep, isStrict, result); + } else { + arrayPush(result, value); + } + } else if (!isStrict) { + result[result.length] = value; + } + } + return result; + } + var baseFor = createBaseFor(); + var baseForRight = createBaseFor(true); + function baseForIn(object, iteratee) { + return baseFor(object, iteratee, keysIn); + } + function baseForOwn(object, iteratee) { + return baseFor(object, iteratee, keys); + } + function baseForOwnRight(object, iteratee) { + return baseForRight(object, iteratee, keys); + } + function baseFunctions(object, props) { + var index = -1, length = props.length, resIndex = -1, result = []; + while (++index < length) { + var key = props[index]; + if (isFunction(object[key])) { + result[++resIndex] = key; + } + } + return result; + } + function baseGet(object, path, pathKey) { + if (object == null) { + return; + } + if (pathKey !== undefined && pathKey in toObject(object)) { + path = [ pathKey ]; + } + var index = 0, length = path.length; + while (object != null && index < length) { + object = object[path[index++]]; + } + return index && index == length ? object : undefined; + } + function baseIsEqual(value, other, customizer, isLoose, stackA, stackB) { + if (value === other) { + return true; + } + if (value == null || other == null || !isObject(value) && !isObjectLike(other)) { + return value !== value && other !== other; + } + return baseIsEqualDeep(value, other, baseIsEqual, customizer, isLoose, stackA, stackB); + } + function baseIsEqualDeep(object, other, equalFunc, customizer, isLoose, stackA, stackB) { + var objIsArr = isArray(object), othIsArr = isArray(other), objTag = arrayTag, othTag = arrayTag; + if (!objIsArr) { + objTag = objToString.call(object); + if (objTag == argsTag) { + objTag = objectTag; + } else if (objTag != objectTag) { + objIsArr = isTypedArray(object); + } + } + if (!othIsArr) { + othTag = objToString.call(other); + if (othTag == argsTag) { + othTag = objectTag; + } else if (othTag != objectTag) { + othIsArr = isTypedArray(other); + } + } + var objIsObj = objTag == objectTag, othIsObj = othTag == objectTag, isSameTag = objTag == othTag; + if (isSameTag && !(objIsArr || objIsObj)) { + return equalByTag(object, other, objTag); + } + if (!isLoose) { + var objIsWrapped = objIsObj && hasOwnProperty.call(object, "__wrapped__"), othIsWrapped = othIsObj && hasOwnProperty.call(other, "__wrapped__"); + if (objIsWrapped || othIsWrapped) { + return equalFunc(objIsWrapped ? object.value() : object, othIsWrapped ? other.value() : other, customizer, isLoose, stackA, stackB); + } + } + if (!isSameTag) { + return false; + } + stackA || (stackA = []); + stackB || (stackB = []); + var length = stackA.length; + while (length--) { + if (stackA[length] == object) { + return stackB[length] == other; + } + } + stackA.push(object); + stackB.push(other); + var result = (objIsArr ? equalArrays : equalObjects)(object, other, equalFunc, customizer, isLoose, stackA, stackB); + stackA.pop(); + stackB.pop(); + return result; + } + function baseIsMatch(object, matchData, customizer) { + var index = matchData.length, length = index, noCustomizer = !customizer; + if (object == null) { + return !length; + } + object = toObject(object); + while (index--) { + var data = matchData[index]; + if (noCustomizer && data[2] ? data[1] !== object[data[0]] : !(data[0] in object)) { + return false; + } + } + while (++index < length) { + data = matchData[index]; + var key = data[0], objValue = object[key], srcValue = data[1]; + if (noCustomizer && data[2]) { + if (objValue === undefined && !(key in object)) { + return false; + } + } else { + var result = customizer ? customizer(objValue, srcValue, key) : undefined; + if (!(result === undefined ? baseIsEqual(srcValue, objValue, customizer, true) : result)) { + return false; + } + } + } + return true; + } + function baseMap(collection, iteratee) { + var index = -1, result = isArrayLike(collection) ? Array(collection.length) : []; + baseEach(collection, function(value, key, collection) { + result[++index] = iteratee(value, key, collection); + }); + return result; + } + function baseMatches(source) { + var matchData = getMatchData(source); + if (matchData.length == 1 && matchData[0][2]) { + var key = matchData[0][0], value = matchData[0][1]; + return function(object) { + if (object == null) { + return false; + } + return object[key] === value && (value !== undefined || key in toObject(object)); + }; + } + return function(object) { + return baseIsMatch(object, matchData); + }; + } + function baseMatchesProperty(path, srcValue) { + var isArr = isArray(path), isCommon = isKey(path) && isStrictComparable(srcValue), pathKey = path + ""; + path = toPath(path); + return function(object) { + if (object == null) { + return false; + } + var key = pathKey; + object = toObject(object); + if ((isArr || !isCommon) && !(key in object)) { + object = path.length == 1 ? object : baseGet(object, baseSlice(path, 0, -1)); + if (object == null) { + return false; + } + key = last(path); + object = toObject(object); + } + return object[key] === srcValue ? srcValue !== undefined || key in object : baseIsEqual(srcValue, object[key], undefined, true); + }; + } + function baseMerge(object, source, customizer, stackA, stackB) { + if (!isObject(object)) { + return object; + } + var isSrcArr = isArrayLike(source) && (isArray(source) || isTypedArray(source)), props = isSrcArr ? undefined : keys(source); + arrayEach(props || source, function(srcValue, key) { + if (props) { + key = srcValue; + srcValue = source[key]; + } + if (isObjectLike(srcValue)) { + stackA || (stackA = []); + stackB || (stackB = []); + baseMergeDeep(object, source, key, baseMerge, customizer, stackA, stackB); + } else { + var value = object[key], result = customizer ? customizer(value, srcValue, key, object, source) : undefined, isCommon = result === undefined; + if (isCommon) { + result = srcValue; + } + if ((result !== undefined || isSrcArr && !(key in object)) && (isCommon || (result === result ? result !== value : value === value))) { + object[key] = result; + } + } + }); + return object; + } + function baseMergeDeep(object, source, key, mergeFunc, customizer, stackA, stackB) { + var length = stackA.length, srcValue = source[key]; + while (length--) { + if (stackA[length] == srcValue) { + object[key] = stackB[length]; + return; + } + } + var value = object[key], result = customizer ? customizer(value, srcValue, key, object, source) : undefined, isCommon = result === undefined; + if (isCommon) { + result = srcValue; + if (isArrayLike(srcValue) && (isArray(srcValue) || isTypedArray(srcValue))) { + result = isArray(value) ? value : isArrayLike(value) ? arrayCopy(value) : []; + } else if (isPlainObject(srcValue) || isArguments(srcValue)) { + result = isArguments(value) ? toPlainObject(value) : isPlainObject(value) ? value : {}; + } else { + isCommon = false; + } + } + stackA.push(srcValue); + stackB.push(result); + if (isCommon) { + object[key] = mergeFunc(result, srcValue, customizer, stackA, stackB); + } else if (result === result ? result !== value : value === value) { + object[key] = result; + } + } + function baseProperty(key) { + return function(object) { + return object == null ? undefined : object[key]; + }; + } + function basePropertyDeep(path) { + var pathKey = path + ""; + path = toPath(path); + return function(object) { + return baseGet(object, path, pathKey); + }; + } + function basePullAt(array, indexes) { + var length = array ? indexes.length : 0; + while (length--) { + var index = indexes[length]; + if (index != previous && isIndex(index)) { + var previous = index; + splice.call(array, index, 1); + } + } + return array; + } + function baseRandom(min, max) { + return min + nativeFloor(nativeRandom() * (max - min + 1)); + } + function baseReduce(collection, iteratee, accumulator, initFromCollection, eachFunc) { + eachFunc(collection, function(value, index, collection) { + accumulator = initFromCollection ? (initFromCollection = false, value) : iteratee(accumulator, value, index, collection); + }); + return accumulator; + } + var baseSetData = !metaMap ? identity : function(func, data) { + metaMap.set(func, data); + return func; + }; + function baseSlice(array, start, end) { + var index = -1, length = array.length; + start = start == null ? 0 : +start || 0; + if (start < 0) { + start = -start > length ? 0 : length + start; + } + end = end === undefined || end > length ? length : +end || 0; + if (end < 0) { + end += length; + } + length = start > end ? 0 : end - start >>> 0; + start >>>= 0; + var result = Array(length); + while (++index < length) { + result[index] = array[index + start]; + } + return result; + } + function baseSome(collection, predicate) { + var result; + baseEach(collection, function(value, index, collection) { + result = predicate(value, index, collection); + return !result; + }); + return !!result; + } + function baseSortBy(array, comparer) { + var length = array.length; + array.sort(comparer); + while (length--) { + array[length] = array[length].value; + } + return array; + } + function baseSortByOrder(collection, iteratees, orders) { + var callback = getCallback(), index = -1; + iteratees = arrayMap(iteratees, function(iteratee) { + return callback(iteratee); + }); + var result = baseMap(collection, function(value) { + var criteria = arrayMap(iteratees, function(iteratee) { + return iteratee(value); + }); + return { + criteria: criteria, + index: ++index, + value: value + }; + }); + return baseSortBy(result, function(object, other) { + return compareMultiple(object, other, orders); + }); + } + function baseSum(collection, iteratee) { + var result = 0; + baseEach(collection, function(value, index, collection) { + result += +iteratee(value, index, collection) || 0; + }); + return result; + } + function baseUniq(array, iteratee) { + var index = -1, indexOf = getIndexOf(), length = array.length, isCommon = indexOf === baseIndexOf, isLarge = isCommon && length >= LARGE_ARRAY_SIZE, seen = isLarge ? createCache() : null, result = []; + if (seen) { + indexOf = cacheIndexOf; + isCommon = false; + } else { + isLarge = false; + seen = iteratee ? [] : result; + } + outer: while (++index < length) { + var value = array[index], computed = iteratee ? iteratee(value, index, array) : value; + if (isCommon && value === value) { + var seenIndex = seen.length; + while (seenIndex--) { + if (seen[seenIndex] === computed) { + continue outer; + } + } + if (iteratee) { + seen.push(computed); + } + result.push(value); + } else if (indexOf(seen, computed, 0) < 0) { + if (iteratee || isLarge) { + seen.push(computed); + } + result.push(value); + } + } + return result; + } + function baseValues(object, props) { + var index = -1, length = props.length, result = Array(length); + while (++index < length) { + result[index] = object[props[index]]; + } + return result; + } + function baseWhile(array, predicate, isDrop, fromRight) { + var length = array.length, index = fromRight ? length : -1; + while ((fromRight ? index-- : ++index < length) && predicate(array[index], index, array)) {} + return isDrop ? baseSlice(array, fromRight ? 0 : index, fromRight ? index + 1 : length) : baseSlice(array, fromRight ? index + 1 : 0, fromRight ? length : index); + } + function baseWrapperValue(value, actions) { + var result = value; + if (result instanceof LazyWrapper) { + result = result.value(); + } + var index = -1, length = actions.length; + while (++index < length) { + var action = actions[index]; + result = action.func.apply(action.thisArg, arrayPush([ result ], action.args)); + } + return result; + } + function binaryIndex(array, value, retHighest) { + var low = 0, high = array ? array.length : low; + if (typeof value == "number" && value === value && high <= HALF_MAX_ARRAY_LENGTH) { + while (low < high) { + var mid = low + high >>> 1, computed = array[mid]; + if ((retHighest ? computed <= value : computed < value) && computed !== null) { + low = mid + 1; + } else { + high = mid; + } + } + return high; + } + return binaryIndexBy(array, value, identity, retHighest); + } + function binaryIndexBy(array, value, iteratee, retHighest) { + value = iteratee(value); + var low = 0, high = array ? array.length : 0, valIsNaN = value !== value, valIsNull = value === null, valIsUndef = value === undefined; + while (low < high) { + var mid = nativeFloor((low + high) / 2), computed = iteratee(array[mid]), isDef = computed !== undefined, isReflexive = computed === computed; + if (valIsNaN) { + var setLow = isReflexive || retHighest; + } else if (valIsNull) { + setLow = isReflexive && isDef && (retHighest || computed != null); + } else if (valIsUndef) { + setLow = isReflexive && (retHighest || isDef); + } else if (computed == null) { + setLow = false; + } else { + setLow = retHighest ? computed <= value : computed < value; + } + if (setLow) { + low = mid + 1; + } else { + high = mid; + } + } + return nativeMin(high, MAX_ARRAY_INDEX); + } + function bindCallback(func, thisArg, argCount) { + if (typeof func != "function") { + return identity; + } + if (thisArg === undefined) { + return func; + } + switch (argCount) { + case 1: + return function(value) { + return func.call(thisArg, value); + }; + + case 3: + return function(value, index, collection) { + return func.call(thisArg, value, index, collection); + }; + + case 4: + return function(accumulator, value, index, collection) { + return func.call(thisArg, accumulator, value, index, collection); + }; + + case 5: + return function(value, other, key, object, source) { + return func.call(thisArg, value, other, key, object, source); + }; + } + return function() { + return func.apply(thisArg, arguments); + }; + } + function bufferClone(buffer) { + var result = new ArrayBuffer(buffer.byteLength), view = new Uint8Array(result); + view.set(new Uint8Array(buffer)); + return result; + } + function composeArgs(args, partials, holders) { + var holdersLength = holders.length, argsIndex = -1, argsLength = nativeMax(args.length - holdersLength, 0), leftIndex = -1, leftLength = partials.length, result = Array(leftLength + argsLength); + while (++leftIndex < leftLength) { + result[leftIndex] = partials[leftIndex]; + } + while (++argsIndex < holdersLength) { + result[holders[argsIndex]] = args[argsIndex]; + } + while (argsLength--) { + result[leftIndex++] = args[argsIndex++]; + } + return result; + } + function composeArgsRight(args, partials, holders) { + var holdersIndex = -1, holdersLength = holders.length, argsIndex = -1, argsLength = nativeMax(args.length - holdersLength, 0), rightIndex = -1, rightLength = partials.length, result = Array(argsLength + rightLength); + while (++argsIndex < argsLength) { + result[argsIndex] = args[argsIndex]; + } + var offset = argsIndex; + while (++rightIndex < rightLength) { + result[offset + rightIndex] = partials[rightIndex]; + } + while (++holdersIndex < holdersLength) { + result[offset + holders[holdersIndex]] = args[argsIndex++]; + } + return result; + } + function createAggregator(setter, initializer) { + return function(collection, iteratee, thisArg) { + var result = initializer ? initializer() : {}; + iteratee = getCallback(iteratee, thisArg, 3); + if (isArray(collection)) { + var index = -1, length = collection.length; + while (++index < length) { + var value = collection[index]; + setter(result, value, iteratee(value, index, collection), collection); + } + } else { + baseEach(collection, function(value, key, collection) { + setter(result, value, iteratee(value, key, collection), collection); + }); + } + return result; + }; + } + function createAssigner(assigner) { + return restParam(function(object, sources) { + var index = -1, length = object == null ? 0 : sources.length, customizer = length > 2 ? sources[length - 2] : undefined, guard = length > 2 ? sources[2] : undefined, thisArg = length > 1 ? sources[length - 1] : undefined; + if (typeof customizer == "function") { + customizer = bindCallback(customizer, thisArg, 5); + length -= 2; + } else { + customizer = typeof thisArg == "function" ? thisArg : undefined; + length -= customizer ? 1 : 0; + } + if (guard && isIterateeCall(sources[0], sources[1], guard)) { + customizer = length < 3 ? undefined : customizer; + length = 1; + } + while (++index < length) { + var source = sources[index]; + if (source) { + assigner(object, source, customizer); + } + } + return object; + }); + } + function createBaseEach(eachFunc, fromRight) { + return function(collection, iteratee) { + var length = collection ? getLength(collection) : 0; + if (!isLength(length)) { + return eachFunc(collection, iteratee); + } + var index = fromRight ? length : -1, iterable = toObject(collection); + while (fromRight ? index-- : ++index < length) { + if (iteratee(iterable[index], index, iterable) === false) { + break; + } + } + return collection; + }; + } + function createBaseFor(fromRight) { + return function(object, iteratee, keysFunc) { + var iterable = toObject(object), props = keysFunc(object), length = props.length, index = fromRight ? length : -1; + while (fromRight ? index-- : ++index < length) { + var key = props[index]; + if (iteratee(iterable[key], key, iterable) === false) { + break; + } + } + return object; + }; + } + function createBindWrapper(func, thisArg) { + var Ctor = createCtorWrapper(func); + function wrapper() { + var fn = this && this !== root && this instanceof wrapper ? Ctor : func; + return fn.apply(thisArg, arguments); + } + return wrapper; + } + function createCache(values) { + return nativeCreate && Set ? new SetCache(values) : null; + } + function createCompounder(callback) { + return function(string) { + var index = -1, array = words(deburr(string)), length = array.length, result = ""; + while (++index < length) { + result = callback(result, array[index], index); + } + return result; + }; + } + function createCtorWrapper(Ctor) { + return function() { + var args = arguments; + switch (args.length) { + case 0: + return new Ctor(); + + case 1: + return new Ctor(args[0]); + + case 2: + return new Ctor(args[0], args[1]); + + case 3: + return new Ctor(args[0], args[1], args[2]); + + case 4: + return new Ctor(args[0], args[1], args[2], args[3]); + + case 5: + return new Ctor(args[0], args[1], args[2], args[3], args[4]); + + case 6: + return new Ctor(args[0], args[1], args[2], args[3], args[4], args[5]); + + case 7: + return new Ctor(args[0], args[1], args[2], args[3], args[4], args[5], args[6]); + } + var thisBinding = baseCreate(Ctor.prototype), result = Ctor.apply(thisBinding, args); + return isObject(result) ? result : thisBinding; + }; + } + function createCurry(flag) { + function curryFunc(func, arity, guard) { + if (guard && isIterateeCall(func, arity, guard)) { + arity = undefined; + } + var result = createWrapper(func, flag, undefined, undefined, undefined, undefined, undefined, arity); + result.placeholder = curryFunc.placeholder; + return result; + } + return curryFunc; + } + function createDefaults(assigner, customizer) { + return restParam(function(args) { + var object = args[0]; + if (object == null) { + return object; + } + args.push(customizer); + return assigner.apply(undefined, args); + }); + } + function createExtremum(comparator, exValue) { + return function(collection, iteratee, thisArg) { + if (thisArg && isIterateeCall(collection, iteratee, thisArg)) { + iteratee = undefined; + } + iteratee = getCallback(iteratee, thisArg, 3); + if (iteratee.length == 1) { + collection = isArray(collection) ? collection : toIterable(collection); + var result = arrayExtremum(collection, iteratee, comparator, exValue); + if (!(collection.length && result === exValue)) { + return result; + } + } + return baseExtremum(collection, iteratee, comparator, exValue); + }; + } + function createFind(eachFunc, fromRight) { + return function(collection, predicate, thisArg) { + predicate = getCallback(predicate, thisArg, 3); + if (isArray(collection)) { + var index = baseFindIndex(collection, predicate, fromRight); + return index > -1 ? collection[index] : undefined; + } + return baseFind(collection, predicate, eachFunc); + }; + } + function createFindIndex(fromRight) { + return function(array, predicate, thisArg) { + if (!(array && array.length)) { + return -1; + } + predicate = getCallback(predicate, thisArg, 3); + return baseFindIndex(array, predicate, fromRight); + }; + } + function createFindKey(objectFunc) { + return function(object, predicate, thisArg) { + predicate = getCallback(predicate, thisArg, 3); + return baseFind(object, predicate, objectFunc, true); + }; + } + function createFlow(fromRight) { + return function() { + var wrapper, length = arguments.length, index = fromRight ? length : -1, leftIndex = 0, funcs = Array(length); + while (fromRight ? index-- : ++index < length) { + var func = funcs[leftIndex++] = arguments[index]; + if (typeof func != "function") { + throw new TypeError(FUNC_ERROR_TEXT); + } + if (!wrapper && LodashWrapper.prototype.thru && getFuncName(func) == "wrapper") { + wrapper = new LodashWrapper([], true); + } + } + index = wrapper ? -1 : length; + while (++index < length) { + func = funcs[index]; + var funcName = getFuncName(func), data = funcName == "wrapper" ? getData(func) : undefined; + if (data && isLaziable(data[0]) && data[1] == (ARY_FLAG | CURRY_FLAG | PARTIAL_FLAG | REARG_FLAG) && !data[4].length && data[9] == 1) { + wrapper = wrapper[getFuncName(data[0])].apply(wrapper, data[3]); + } else { + wrapper = func.length == 1 && isLaziable(func) ? wrapper[funcName]() : wrapper.thru(func); + } + } + return function() { + var args = arguments, value = args[0]; + if (wrapper && args.length == 1 && isArray(value) && value.length >= LARGE_ARRAY_SIZE) { + return wrapper.plant(value).value(); + } + var index = 0, result = length ? funcs[index].apply(this, args) : value; + while (++index < length) { + result = funcs[index].call(this, result); + } + return result; + }; + }; + } + function createForEach(arrayFunc, eachFunc) { + return function(collection, iteratee, thisArg) { + return typeof iteratee == "function" && thisArg === undefined && isArray(collection) ? arrayFunc(collection, iteratee) : eachFunc(collection, bindCallback(iteratee, thisArg, 3)); + }; + } + function createForIn(objectFunc) { + return function(object, iteratee, thisArg) { + if (typeof iteratee != "function" || thisArg !== undefined) { + iteratee = bindCallback(iteratee, thisArg, 3); + } + return objectFunc(object, iteratee, keysIn); + }; + } + function createForOwn(objectFunc) { + return function(object, iteratee, thisArg) { + if (typeof iteratee != "function" || thisArg !== undefined) { + iteratee = bindCallback(iteratee, thisArg, 3); + } + return objectFunc(object, iteratee); + }; + } + function createObjectMapper(isMapKeys) { + return function(object, iteratee, thisArg) { + var result = {}; + iteratee = getCallback(iteratee, thisArg, 3); + baseForOwn(object, function(value, key, object) { + var mapped = iteratee(value, key, object); + key = isMapKeys ? mapped : key; + value = isMapKeys ? value : mapped; + result[key] = value; + }); + return result; + }; + } + function createPadDir(fromRight) { + return function(string, length, chars) { + string = baseToString(string); + return (fromRight ? string : "") + createPadding(string, length, chars) + (fromRight ? "" : string); + }; + } + function createPartial(flag) { + var partialFunc = restParam(function(func, partials) { + var holders = replaceHolders(partials, partialFunc.placeholder); + return createWrapper(func, flag, undefined, partials, holders); + }); + return partialFunc; + } + function createReduce(arrayFunc, eachFunc) { + return function(collection, iteratee, accumulator, thisArg) { + var initFromArray = arguments.length < 3; + return typeof iteratee == "function" && thisArg === undefined && isArray(collection) ? arrayFunc(collection, iteratee, accumulator, initFromArray) : baseReduce(collection, getCallback(iteratee, thisArg, 4), accumulator, initFromArray, eachFunc); + }; + } + function createHybridWrapper(func, bitmask, thisArg, partials, holders, partialsRight, holdersRight, argPos, ary, arity) { + var isAry = bitmask & ARY_FLAG, isBind = bitmask & BIND_FLAG, isBindKey = bitmask & BIND_KEY_FLAG, isCurry = bitmask & CURRY_FLAG, isCurryBound = bitmask & CURRY_BOUND_FLAG, isCurryRight = bitmask & CURRY_RIGHT_FLAG, Ctor = isBindKey ? undefined : createCtorWrapper(func); + function wrapper() { + var length = arguments.length, index = length, args = Array(length); + while (index--) { + args[index] = arguments[index]; + } + if (partials) { + args = composeArgs(args, partials, holders); + } + if (partialsRight) { + args = composeArgsRight(args, partialsRight, holdersRight); + } + if (isCurry || isCurryRight) { + var placeholder = wrapper.placeholder, argsHolders = replaceHolders(args, placeholder); + length -= argsHolders.length; + if (length < arity) { + var newArgPos = argPos ? arrayCopy(argPos) : undefined, newArity = nativeMax(arity - length, 0), newsHolders = isCurry ? argsHolders : undefined, newHoldersRight = isCurry ? undefined : argsHolders, newPartials = isCurry ? args : undefined, newPartialsRight = isCurry ? undefined : args; + bitmask |= isCurry ? PARTIAL_FLAG : PARTIAL_RIGHT_FLAG; + bitmask &= ~(isCurry ? PARTIAL_RIGHT_FLAG : PARTIAL_FLAG); + if (!isCurryBound) { + bitmask &= ~(BIND_FLAG | BIND_KEY_FLAG); + } + var newData = [ func, bitmask, thisArg, newPartials, newsHolders, newPartialsRight, newHoldersRight, newArgPos, ary, newArity ], result = createHybridWrapper.apply(undefined, newData); + if (isLaziable(func)) { + setData(result, newData); + } + result.placeholder = placeholder; + return result; + } + } + var thisBinding = isBind ? thisArg : this, fn = isBindKey ? thisBinding[func] : func; + if (argPos) { + args = reorder(args, argPos); + } + if (isAry && ary < args.length) { + args.length = ary; + } + if (this && this !== root && this instanceof wrapper) { + fn = Ctor || createCtorWrapper(func); + } + return fn.apply(thisBinding, args); + } + return wrapper; + } + function createPadding(string, length, chars) { + var strLength = string.length; + length = +length; + if (strLength >= length || !nativeIsFinite(length)) { + return ""; + } + var padLength = length - strLength; + chars = chars == null ? " " : chars + ""; + return repeat(chars, nativeCeil(padLength / chars.length)).slice(0, padLength); + } + function createPartialWrapper(func, bitmask, thisArg, partials) { + var isBind = bitmask & BIND_FLAG, Ctor = createCtorWrapper(func); + function wrapper() { + var argsIndex = -1, argsLength = arguments.length, leftIndex = -1, leftLength = partials.length, args = Array(leftLength + argsLength); + while (++leftIndex < leftLength) { + args[leftIndex] = partials[leftIndex]; + } + while (argsLength--) { + args[leftIndex++] = arguments[++argsIndex]; + } + var fn = this && this !== root && this instanceof wrapper ? Ctor : func; + return fn.apply(isBind ? thisArg : this, args); + } + return wrapper; + } + function createRound(methodName) { + var func = Math[methodName]; + return function(number, precision) { + precision = precision === undefined ? 0 : +precision || 0; + if (precision) { + precision = pow(10, precision); + return func(number * precision) / precision; + } + return func(number); + }; + } + function createSortedIndex(retHighest) { + return function(array, value, iteratee, thisArg) { + var callback = getCallback(iteratee); + return iteratee == null && callback === baseCallback ? binaryIndex(array, value, retHighest) : binaryIndexBy(array, value, callback(iteratee, thisArg, 1), retHighest); + }; + } + function createWrapper(func, bitmask, thisArg, partials, holders, argPos, ary, arity) { + var isBindKey = bitmask & BIND_KEY_FLAG; + if (!isBindKey && typeof func != "function") { + throw new TypeError(FUNC_ERROR_TEXT); + } + var length = partials ? partials.length : 0; + if (!length) { + bitmask &= ~(PARTIAL_FLAG | PARTIAL_RIGHT_FLAG); + partials = holders = undefined; + } + length -= holders ? holders.length : 0; + if (bitmask & PARTIAL_RIGHT_FLAG) { + var partialsRight = partials, holdersRight = holders; + partials = holders = undefined; + } + var data = isBindKey ? undefined : getData(func), newData = [ func, bitmask, thisArg, partials, holders, partialsRight, holdersRight, argPos, ary, arity ]; + if (data) { + mergeData(newData, data); + bitmask = newData[1]; + arity = newData[9]; + } + newData[9] = arity == null ? isBindKey ? 0 : func.length : nativeMax(arity - length, 0) || 0; + if (bitmask == BIND_FLAG) { + var result = createBindWrapper(newData[0], newData[2]); + } else if ((bitmask == PARTIAL_FLAG || bitmask == (BIND_FLAG | PARTIAL_FLAG)) && !newData[4].length) { + result = createPartialWrapper.apply(undefined, newData); + } else { + result = createHybridWrapper.apply(undefined, newData); + } + var setter = data ? baseSetData : setData; + return setter(result, newData); + } + function equalArrays(array, other, equalFunc, customizer, isLoose, stackA, stackB) { + var index = -1, arrLength = array.length, othLength = other.length; + if (arrLength != othLength && !(isLoose && othLength > arrLength)) { + return false; + } + while (++index < arrLength) { + var arrValue = array[index], othValue = other[index], result = customizer ? customizer(isLoose ? othValue : arrValue, isLoose ? arrValue : othValue, index) : undefined; + if (result !== undefined) { + if (result) { + continue; + } + return false; + } + if (isLoose) { + if (!arraySome(other, function(othValue) { + return arrValue === othValue || equalFunc(arrValue, othValue, customizer, isLoose, stackA, stackB); + })) { + return false; + } + } else if (!(arrValue === othValue || equalFunc(arrValue, othValue, customizer, isLoose, stackA, stackB))) { + return false; + } + } + return true; + } + function equalByTag(object, other, tag) { + switch (tag) { + case boolTag: + case dateTag: + return +object == +other; + + case errorTag: + return object.name == other.name && object.message == other.message; + + case numberTag: + return object != +object ? other != +other : object == +other; + + case regexpTag: + case stringTag: + return object == other + ""; + } + return false; + } + function equalObjects(object, other, equalFunc, customizer, isLoose, stackA, stackB) { + var objProps = keys(object), objLength = objProps.length, othProps = keys(other), othLength = othProps.length; + if (objLength != othLength && !isLoose) { + return false; + } + var index = objLength; + while (index--) { + var key = objProps[index]; + if (!(isLoose ? key in other : hasOwnProperty.call(other, key))) { + return false; + } + } + var skipCtor = isLoose; + while (++index < objLength) { + key = objProps[index]; + var objValue = object[key], othValue = other[key], result = customizer ? customizer(isLoose ? othValue : objValue, isLoose ? objValue : othValue, key) : undefined; + if (!(result === undefined ? equalFunc(objValue, othValue, customizer, isLoose, stackA, stackB) : result)) { + return false; + } + skipCtor || (skipCtor = key == "constructor"); + } + if (!skipCtor) { + var objCtor = object.constructor, othCtor = other.constructor; + if (objCtor != othCtor && ("constructor" in object && "constructor" in other) && !(typeof objCtor == "function" && objCtor instanceof objCtor && typeof othCtor == "function" && othCtor instanceof othCtor)) { + return false; + } + } + return true; + } + function getCallback(func, thisArg, argCount) { + var result = lodash.callback || callback; + result = result === callback ? baseCallback : result; + return argCount ? result(func, thisArg, argCount) : result; + } + var getData = !metaMap ? noop : function(func) { + return metaMap.get(func); + }; + function getFuncName(func) { + var result = func.name + "", array = realNames[result], length = array ? array.length : 0; + while (length--) { + var data = array[length], otherFunc = data.func; + if (otherFunc == null || otherFunc == func) { + return data.name; + } + } + return result; + } + function getIndexOf(collection, target, fromIndex) { + var result = lodash.indexOf || indexOf; + result = result === indexOf ? baseIndexOf : result; + return collection ? result(collection, target, fromIndex) : result; + } + var getLength = baseProperty("length"); + function getMatchData(object) { + var result = pairs(object), length = result.length; + while (length--) { + result[length][2] = isStrictComparable(result[length][1]); + } + return result; + } + function getNative(object, key) { + var value = object == null ? undefined : object[key]; + return isNative(value) ? value : undefined; + } + function getView(start, end, transforms) { + var index = -1, length = transforms.length; + while (++index < length) { + var data = transforms[index], size = data.size; + switch (data.type) { + case "drop": + start += size; + break; + + case "dropRight": + end -= size; + break; + + case "take": + end = nativeMin(end, start + size); + break; + + case "takeRight": + start = nativeMax(start, end - size); + break; + } + } + return { + start: start, + end: end + }; + } + function initCloneArray(array) { + var length = array.length, result = new array.constructor(length); + if (length && typeof array[0] == "string" && hasOwnProperty.call(array, "index")) { + result.index = array.index; + result.input = array.input; + } + return result; + } + function initCloneObject(object) { + var Ctor = object.constructor; + if (!(typeof Ctor == "function" && Ctor instanceof Ctor)) { + Ctor = Object; + } + return new Ctor(); + } + function initCloneByTag(object, tag, isDeep) { + var Ctor = object.constructor; + switch (tag) { + case arrayBufferTag: + return bufferClone(object); + + case boolTag: + case dateTag: + return new Ctor(+object); + + case float32Tag: + case float64Tag: + case int8Tag: + case int16Tag: + case int32Tag: + case uint8Tag: + case uint8ClampedTag: + case uint16Tag: + case uint32Tag: + var buffer = object.buffer; + return new Ctor(isDeep ? bufferClone(buffer) : buffer, object.byteOffset, object.length); + + case numberTag: + case stringTag: + return new Ctor(object); + + case regexpTag: + var result = new Ctor(object.source, reFlags.exec(object)); + result.lastIndex = object.lastIndex; + } + return result; + } + function invokePath(object, path, args) { + if (object != null && !isKey(path, object)) { + path = toPath(path); + object = path.length == 1 ? object : baseGet(object, baseSlice(path, 0, -1)); + path = last(path); + } + var func = object == null ? object : object[path]; + return func == null ? undefined : func.apply(object, args); + } + function isArrayLike(value) { + return value != null && isLength(getLength(value)); + } + function isIndex(value, length) { + value = typeof value == "number" || reIsUint.test(value) ? +value : -1; + length = length == null ? MAX_SAFE_INTEGER : length; + return value > -1 && value % 1 == 0 && value < length; + } + function isIterateeCall(value, index, object) { + if (!isObject(object)) { + return false; + } + var type = typeof index; + if (type == "number" ? isArrayLike(object) && isIndex(index, object.length) : type == "string" && index in object) { + var other = object[index]; + return value === value ? value === other : other !== other; + } + return false; + } + function isKey(value, object) { + var type = typeof value; + if (type == "string" && reIsPlainProp.test(value) || type == "number") { + return true; + } + if (isArray(value)) { + return false; + } + var result = !reIsDeepProp.test(value); + return result || object != null && value in toObject(object); + } + function isLaziable(func) { + var funcName = getFuncName(func), other = lodash[funcName]; + if (typeof other != "function" || !(funcName in LazyWrapper.prototype)) { + return false; + } + if (func === other) { + return true; + } + var data = getData(other); + return !!data && func === data[0]; + } + function isLength(value) { + return typeof value == "number" && value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER; + } + function isStrictComparable(value) { + return value === value && !isObject(value); + } + function mergeData(data, source) { + var bitmask = data[1], srcBitmask = source[1], newBitmask = bitmask | srcBitmask, isCommon = newBitmask < ARY_FLAG; + var isCombo = srcBitmask == ARY_FLAG && bitmask == CURRY_FLAG || srcBitmask == ARY_FLAG && bitmask == REARG_FLAG && data[7].length <= source[8] || srcBitmask == (ARY_FLAG | REARG_FLAG) && bitmask == CURRY_FLAG; + if (!(isCommon || isCombo)) { + return data; + } + if (srcBitmask & BIND_FLAG) { + data[2] = source[2]; + newBitmask |= bitmask & BIND_FLAG ? 0 : CURRY_BOUND_FLAG; + } + var value = source[3]; + if (value) { + var partials = data[3]; + data[3] = partials ? composeArgs(partials, value, source[4]) : arrayCopy(value); + data[4] = partials ? replaceHolders(data[3], PLACEHOLDER) : arrayCopy(source[4]); + } + value = source[5]; + if (value) { + partials = data[5]; + data[5] = partials ? composeArgsRight(partials, value, source[6]) : arrayCopy(value); + data[6] = partials ? replaceHolders(data[5], PLACEHOLDER) : arrayCopy(source[6]); + } + value = source[7]; + if (value) { + data[7] = arrayCopy(value); + } + if (srcBitmask & ARY_FLAG) { + data[8] = data[8] == null ? source[8] : nativeMin(data[8], source[8]); + } + if (data[9] == null) { + data[9] = source[9]; + } + data[0] = source[0]; + data[1] = newBitmask; + return data; + } + function mergeDefaults(objectValue, sourceValue) { + return objectValue === undefined ? sourceValue : merge(objectValue, sourceValue, mergeDefaults); + } + function pickByArray(object, props) { + object = toObject(object); + var index = -1, length = props.length, result = {}; + while (++index < length) { + var key = props[index]; + if (key in object) { + result[key] = object[key]; + } + } + return result; + } + function pickByCallback(object, predicate) { + var result = {}; + baseForIn(object, function(value, key, object) { + if (predicate(value, key, object)) { + result[key] = value; + } + }); + return result; + } + function reorder(array, indexes) { + var arrLength = array.length, length = nativeMin(indexes.length, arrLength), oldArray = arrayCopy(array); + while (length--) { + var index = indexes[length]; + array[length] = isIndex(index, arrLength) ? oldArray[index] : undefined; + } + return array; + } + var setData = function() { + var count = 0, lastCalled = 0; + return function(key, value) { + var stamp = now(), remaining = HOT_SPAN - (stamp - lastCalled); + lastCalled = stamp; + if (remaining > 0) { + if (++count >= HOT_COUNT) { + return key; + } + } else { + count = 0; + } + return baseSetData(key, value); + }; + }(); + function shimKeys(object) { + var props = keysIn(object), propsLength = props.length, length = propsLength && object.length; + var allowIndexes = !!length && isLength(length) && (isArray(object) || isArguments(object)); + var index = -1, result = []; + while (++index < propsLength) { + var key = props[index]; + if (allowIndexes && isIndex(key, length) || hasOwnProperty.call(object, key)) { + result.push(key); + } + } + return result; + } + function toIterable(value) { + if (value == null) { + return []; + } + if (!isArrayLike(value)) { + return values(value); + } + return isObject(value) ? value : Object(value); + } + function toObject(value) { + return isObject(value) ? value : Object(value); + } + function toPath(value) { + if (isArray(value)) { + return value; + } + var result = []; + baseToString(value).replace(rePropName, function(match, number, quote, string) { + result.push(quote ? string.replace(reEscapeChar, "$1") : number || match); + }); + return result; + } + function wrapperClone(wrapper) { + return wrapper instanceof LazyWrapper ? wrapper.clone() : new LodashWrapper(wrapper.__wrapped__, wrapper.__chain__, arrayCopy(wrapper.__actions__)); + } + function chunk(array, size, guard) { + if (guard ? isIterateeCall(array, size, guard) : size == null) { + size = 1; + } else { + size = nativeMax(nativeFloor(size) || 1, 1); + } + var index = 0, length = array ? array.length : 0, resIndex = -1, result = Array(nativeCeil(length / size)); + while (index < length) { + result[++resIndex] = baseSlice(array, index, index += size); + } + return result; + } + function compact(array) { + var index = -1, length = array ? array.length : 0, resIndex = -1, result = []; + while (++index < length) { + var value = array[index]; + if (value) { + result[++resIndex] = value; + } + } + return result; + } + var difference = restParam(function(array, values) { + return isObjectLike(array) && isArrayLike(array) ? baseDifference(array, baseFlatten(values, false, true)) : []; + }); + function drop(array, n, guard) { + var length = array ? array.length : 0; + if (!length) { + return []; + } + if (guard ? isIterateeCall(array, n, guard) : n == null) { + n = 1; + } + return baseSlice(array, n < 0 ? 0 : n); + } + function dropRight(array, n, guard) { + var length = array ? array.length : 0; + if (!length) { + return []; + } + if (guard ? isIterateeCall(array, n, guard) : n == null) { + n = 1; + } + n = length - (+n || 0); + return baseSlice(array, 0, n < 0 ? 0 : n); + } + function dropRightWhile(array, predicate, thisArg) { + return array && array.length ? baseWhile(array, getCallback(predicate, thisArg, 3), true, true) : []; + } + function dropWhile(array, predicate, thisArg) { + return array && array.length ? baseWhile(array, getCallback(predicate, thisArg, 3), true) : []; + } + function fill(array, value, start, end) { + var length = array ? array.length : 0; + if (!length) { + return []; + } + if (start && typeof start != "number" && isIterateeCall(array, value, start)) { + start = 0; + end = length; + } + return baseFill(array, value, start, end); + } + var findIndex = createFindIndex(); + var findLastIndex = createFindIndex(true); + function first(array) { + return array ? array[0] : undefined; + } + function flatten(array, isDeep, guard) { + var length = array ? array.length : 0; + if (guard && isIterateeCall(array, isDeep, guard)) { + isDeep = false; + } + return length ? baseFlatten(array, isDeep) : []; + } + function flattenDeep(array) { + var length = array ? array.length : 0; + return length ? baseFlatten(array, true) : []; + } + function indexOf(array, value, fromIndex) { + var length = array ? array.length : 0; + if (!length) { + return -1; + } + if (typeof fromIndex == "number") { + fromIndex = fromIndex < 0 ? nativeMax(length + fromIndex, 0) : fromIndex; + } else if (fromIndex) { + var index = binaryIndex(array, value); + if (index < length && (value === value ? value === array[index] : array[index] !== array[index])) { + return index; + } + return -1; + } + return baseIndexOf(array, value, fromIndex || 0); + } + function initial(array) { + return dropRight(array, 1); + } + var intersection = restParam(function(arrays) { + var othLength = arrays.length, othIndex = othLength, caches = Array(length), indexOf = getIndexOf(), isCommon = indexOf === baseIndexOf, result = []; + while (othIndex--) { + var value = arrays[othIndex] = isArrayLike(value = arrays[othIndex]) ? value : []; + caches[othIndex] = isCommon && value.length >= 120 ? createCache(othIndex && value) : null; + } + var array = arrays[0], index = -1, length = array ? array.length : 0, seen = caches[0]; + outer: while (++index < length) { + value = array[index]; + if ((seen ? cacheIndexOf(seen, value) : indexOf(result, value, 0)) < 0) { + var othIndex = othLength; + while (--othIndex) { + var cache = caches[othIndex]; + if ((cache ? cacheIndexOf(cache, value) : indexOf(arrays[othIndex], value, 0)) < 0) { + continue outer; + } + } + if (seen) { + seen.push(value); + } + result.push(value); + } + } + return result; + }); + function last(array) { + var length = array ? array.length : 0; + return length ? array[length - 1] : undefined; + } + function lastIndexOf(array, value, fromIndex) { + var length = array ? array.length : 0; + if (!length) { + return -1; + } + var index = length; + if (typeof fromIndex == "number") { + index = (fromIndex < 0 ? nativeMax(length + fromIndex, 0) : nativeMin(fromIndex || 0, length - 1)) + 1; + } else if (fromIndex) { + index = binaryIndex(array, value, true) - 1; + var other = array[index]; + if (value === value ? value === other : other !== other) { + return index; + } + return -1; + } + if (value !== value) { + return indexOfNaN(array, index, true); + } + while (index--) { + if (array[index] === value) { + return index; + } + } + return -1; + } + function pull() { + var args = arguments, array = args[0]; + if (!(array && array.length)) { + return array; + } + var index = 0, indexOf = getIndexOf(), length = args.length; + while (++index < length) { + var fromIndex = 0, value = args[index]; + while ((fromIndex = indexOf(array, value, fromIndex)) > -1) { + splice.call(array, fromIndex, 1); + } + } + return array; + } + var pullAt = restParam(function(array, indexes) { + indexes = baseFlatten(indexes); + var result = baseAt(array, indexes); + basePullAt(array, indexes.sort(baseCompareAscending)); + return result; + }); + function remove(array, predicate, thisArg) { + var result = []; + if (!(array && array.length)) { + return result; + } + var index = -1, indexes = [], length = array.length; + predicate = getCallback(predicate, thisArg, 3); + while (++index < length) { + var value = array[index]; + if (predicate(value, index, array)) { + result.push(value); + indexes.push(index); + } + } + basePullAt(array, indexes); + return result; + } + function rest(array) { + return drop(array, 1); + } + function slice(array, start, end) { + var length = array ? array.length : 0; + if (!length) { + return []; + } + if (end && typeof end != "number" && isIterateeCall(array, start, end)) { + start = 0; + end = length; + } + return baseSlice(array, start, end); + } + var sortedIndex = createSortedIndex(); + var sortedLastIndex = createSortedIndex(true); + function take(array, n, guard) { + var length = array ? array.length : 0; + if (!length) { + return []; + } + if (guard ? isIterateeCall(array, n, guard) : n == null) { + n = 1; + } + return baseSlice(array, 0, n < 0 ? 0 : n); + } + function takeRight(array, n, guard) { + var length = array ? array.length : 0; + if (!length) { + return []; + } + if (guard ? isIterateeCall(array, n, guard) : n == null) { + n = 1; + } + n = length - (+n || 0); + return baseSlice(array, n < 0 ? 0 : n); + } + function takeRightWhile(array, predicate, thisArg) { + return array && array.length ? baseWhile(array, getCallback(predicate, thisArg, 3), false, true) : []; + } + function takeWhile(array, predicate, thisArg) { + return array && array.length ? baseWhile(array, getCallback(predicate, thisArg, 3)) : []; + } + var union = restParam(function(arrays) { + return baseUniq(baseFlatten(arrays, false, true)); + }); + function uniq(array, isSorted, iteratee, thisArg) { + var length = array ? array.length : 0; + if (!length) { + return []; + } + if (isSorted != null && typeof isSorted != "boolean") { + thisArg = iteratee; + iteratee = isIterateeCall(array, isSorted, thisArg) ? undefined : isSorted; + isSorted = false; + } + var callback = getCallback(); + if (!(iteratee == null && callback === baseCallback)) { + iteratee = callback(iteratee, thisArg, 3); + } + return isSorted && getIndexOf() === baseIndexOf ? sortedUniq(array, iteratee) : baseUniq(array, iteratee); + } + function unzip(array) { + if (!(array && array.length)) { + return []; + } + var index = -1, length = 0; + array = arrayFilter(array, function(group) { + if (isArrayLike(group)) { + length = nativeMax(group.length, length); + return true; + } + }); + var result = Array(length); + while (++index < length) { + result[index] = arrayMap(array, baseProperty(index)); + } + return result; + } + function unzipWith(array, iteratee, thisArg) { + var length = array ? array.length : 0; + if (!length) { + return []; + } + var result = unzip(array); + if (iteratee == null) { + return result; + } + iteratee = bindCallback(iteratee, thisArg, 4); + return arrayMap(result, function(group) { + return arrayReduce(group, iteratee, undefined, true); + }); + } + var without = restParam(function(array, values) { + return isArrayLike(array) ? baseDifference(array, values) : []; + }); + function xor() { + var index = -1, length = arguments.length; + while (++index < length) { + var array = arguments[index]; + if (isArrayLike(array)) { + var result = result ? arrayPush(baseDifference(result, array), baseDifference(array, result)) : array; + } + } + return result ? baseUniq(result) : []; + } + var zip = restParam(unzip); + function zipObject(props, values) { + var index = -1, length = props ? props.length : 0, result = {}; + if (length && !values && !isArray(props[0])) { + values = []; + } + while (++index < length) { + var key = props[index]; + if (values) { + result[key] = values[index]; + } else if (key) { + result[key[0]] = key[1]; + } + } + return result; + } + var zipWith = restParam(function(arrays) { + var length = arrays.length, iteratee = length > 2 ? arrays[length - 2] : undefined, thisArg = length > 1 ? arrays[length - 1] : undefined; + if (length > 2 && typeof iteratee == "function") { + length -= 2; + } else { + iteratee = length > 1 && typeof thisArg == "function" ? (--length, thisArg) : undefined; + thisArg = undefined; + } + arrays.length = length; + return unzipWith(arrays, iteratee, thisArg); + }); + function chain(value) { + var result = lodash(value); + result.__chain__ = true; + return result; + } + function tap(value, interceptor, thisArg) { + interceptor.call(thisArg, value); + return value; + } + function thru(value, interceptor, thisArg) { + return interceptor.call(thisArg, value); + } + function wrapperChain() { + return chain(this); + } + function wrapperCommit() { + return new LodashWrapper(this.value(), this.__chain__); + } + var wrapperConcat = restParam(function(values) { + values = baseFlatten(values); + return this.thru(function(array) { + return arrayConcat(isArray(array) ? array : [ toObject(array) ], values); + }); + }); + function wrapperPlant(value) { + var result, parent = this; + while (parent instanceof baseLodash) { + var clone = wrapperClone(parent); + if (result) { + previous.__wrapped__ = clone; + } else { + result = clone; + } + var previous = clone; + parent = parent.__wrapped__; + } + previous.__wrapped__ = value; + return result; + } + function wrapperReverse() { + var value = this.__wrapped__; + var interceptor = function(value) { + return value.reverse(); + }; + if (value instanceof LazyWrapper) { + var wrapped = value; + if (this.__actions__.length) { + wrapped = new LazyWrapper(this); + } + wrapped = wrapped.reverse(); + wrapped.__actions__.push({ + func: thru, + args: [ interceptor ], + thisArg: undefined + }); + return new LodashWrapper(wrapped, this.__chain__); + } + return this.thru(interceptor); + } + function wrapperToString() { + return this.value() + ""; + } + function wrapperValue() { + return baseWrapperValue(this.__wrapped__, this.__actions__); + } + var at = restParam(function(collection, props) { + return baseAt(collection, baseFlatten(props)); + }); + var countBy = createAggregator(function(result, value, key) { + hasOwnProperty.call(result, key) ? ++result[key] : result[key] = 1; + }); + function every(collection, predicate, thisArg) { + var func = isArray(collection) ? arrayEvery : baseEvery; + if (thisArg && isIterateeCall(collection, predicate, thisArg)) { + predicate = undefined; + } + if (typeof predicate != "function" || thisArg !== undefined) { + predicate = getCallback(predicate, thisArg, 3); + } + return func(collection, predicate); + } + function filter(collection, predicate, thisArg) { + var func = isArray(collection) ? arrayFilter : baseFilter; + predicate = getCallback(predicate, thisArg, 3); + return func(collection, predicate); + } + var find = createFind(baseEach); + var findLast = createFind(baseEachRight, true); + function findWhere(collection, source) { + return find(collection, baseMatches(source)); + } + var forEach = createForEach(arrayEach, baseEach); + var forEachRight = createForEach(arrayEachRight, baseEachRight); + var groupBy = createAggregator(function(result, value, key) { + if (hasOwnProperty.call(result, key)) { + result[key].push(value); + } else { + result[key] = [ value ]; + } + }); + function includes(collection, target, fromIndex, guard) { + var length = collection ? getLength(collection) : 0; + if (!isLength(length)) { + collection = values(collection); + length = collection.length; + } + if (typeof fromIndex != "number" || guard && isIterateeCall(target, fromIndex, guard)) { + fromIndex = 0; + } else { + fromIndex = fromIndex < 0 ? nativeMax(length + fromIndex, 0) : fromIndex || 0; + } + return typeof collection == "string" || !isArray(collection) && isString(collection) ? fromIndex <= length && collection.indexOf(target, fromIndex) > -1 : !!length && getIndexOf(collection, target, fromIndex) > -1; + } + var indexBy = createAggregator(function(result, value, key) { + result[key] = value; + }); + var invoke = restParam(function(collection, path, args) { + var index = -1, isFunc = typeof path == "function", isProp = isKey(path), result = isArrayLike(collection) ? Array(collection.length) : []; + baseEach(collection, function(value) { + var func = isFunc ? path : isProp && value != null ? value[path] : undefined; + result[++index] = func ? func.apply(value, args) : invokePath(value, path, args); + }); + return result; + }); + function map(collection, iteratee, thisArg) { + var func = isArray(collection) ? arrayMap : baseMap; + iteratee = getCallback(iteratee, thisArg, 3); + return func(collection, iteratee); + } + var partition = createAggregator(function(result, value, key) { + result[key ? 0 : 1].push(value); + }, function() { + return [ [], [] ]; + }); + function pluck(collection, path) { + return map(collection, property(path)); + } + var reduce = createReduce(arrayReduce, baseEach); + var reduceRight = createReduce(arrayReduceRight, baseEachRight); + function reject(collection, predicate, thisArg) { + var func = isArray(collection) ? arrayFilter : baseFilter; + predicate = getCallback(predicate, thisArg, 3); + return func(collection, function(value, index, collection) { + return !predicate(value, index, collection); + }); + } + function sample(collection, n, guard) { + if (guard ? isIterateeCall(collection, n, guard) : n == null) { + collection = toIterable(collection); + var length = collection.length; + return length > 0 ? collection[baseRandom(0, length - 1)] : undefined; + } + var index = -1, result = toArray(collection), length = result.length, lastIndex = length - 1; + n = nativeMin(n < 0 ? 0 : +n || 0, length); + while (++index < n) { + var rand = baseRandom(index, lastIndex), value = result[rand]; + result[rand] = result[index]; + result[index] = value; + } + result.length = n; + return result; + } + function shuffle(collection) { + return sample(collection, POSITIVE_INFINITY); + } + function size(collection) { + var length = collection ? getLength(collection) : 0; + return isLength(length) ? length : keys(collection).length; + } + function some(collection, predicate, thisArg) { + var func = isArray(collection) ? arraySome : baseSome; + if (thisArg && isIterateeCall(collection, predicate, thisArg)) { + predicate = undefined; + } + if (typeof predicate != "function" || thisArg !== undefined) { + predicate = getCallback(predicate, thisArg, 3); + } + return func(collection, predicate); + } + function sortBy(collection, iteratee, thisArg) { + if (collection == null) { + return []; + } + if (thisArg && isIterateeCall(collection, iteratee, thisArg)) { + iteratee = undefined; + } + var index = -1; + iteratee = getCallback(iteratee, thisArg, 3); + var result = baseMap(collection, function(value, key, collection) { + return { + criteria: iteratee(value, key, collection), + index: ++index, + value: value + }; + }); + return baseSortBy(result, compareAscending); + } + var sortByAll = restParam(function(collection, iteratees) { + if (collection == null) { + return []; + } + var guard = iteratees[2]; + if (guard && isIterateeCall(iteratees[0], iteratees[1], guard)) { + iteratees.length = 1; + } + return baseSortByOrder(collection, baseFlatten(iteratees), []); + }); + function sortByOrder(collection, iteratees, orders, guard) { + if (collection == null) { + return []; + } + if (guard && isIterateeCall(iteratees, orders, guard)) { + orders = undefined; + } + if (!isArray(iteratees)) { + iteratees = iteratees == null ? [] : [ iteratees ]; + } + if (!isArray(orders)) { + orders = orders == null ? [] : [ orders ]; + } + return baseSortByOrder(collection, iteratees, orders); + } + function where(collection, source) { + return filter(collection, baseMatches(source)); + } + var now = nativeNow || function() { + return new Date().getTime(); + }; + function after(n, func) { + if (typeof func != "function") { + if (typeof n == "function") { + var temp = n; + n = func; + func = temp; + } else { + throw new TypeError(FUNC_ERROR_TEXT); + } + } + n = nativeIsFinite(n = +n) ? n : 0; + return function() { + if (--n < 1) { + return func.apply(this, arguments); + } + }; + } + function ary(func, n, guard) { + if (guard && isIterateeCall(func, n, guard)) { + n = undefined; + } + n = func && n == null ? func.length : nativeMax(+n || 0, 0); + return createWrapper(func, ARY_FLAG, undefined, undefined, undefined, undefined, n); + } + function before(n, func) { + var result; + if (typeof func != "function") { + if (typeof n == "function") { + var temp = n; + n = func; + func = temp; + } else { + throw new TypeError(FUNC_ERROR_TEXT); + } + } + return function() { + if (--n > 0) { + result = func.apply(this, arguments); + } + if (n <= 1) { + func = undefined; + } + return result; + }; + } + var bind = restParam(function(func, thisArg, partials) { + var bitmask = BIND_FLAG; + if (partials.length) { + var holders = replaceHolders(partials, bind.placeholder); + bitmask |= PARTIAL_FLAG; + } + return createWrapper(func, bitmask, thisArg, partials, holders); + }); + var bindAll = restParam(function(object, methodNames) { + methodNames = methodNames.length ? baseFlatten(methodNames) : functions(object); + var index = -1, length = methodNames.length; + while (++index < length) { + var key = methodNames[index]; + object[key] = createWrapper(object[key], BIND_FLAG, object); + } + return object; + }); + var bindKey = restParam(function(object, key, partials) { + var bitmask = BIND_FLAG | BIND_KEY_FLAG; + if (partials.length) { + var holders = replaceHolders(partials, bindKey.placeholder); + bitmask |= PARTIAL_FLAG; + } + return createWrapper(key, bitmask, object, partials, holders); + }); + var curry = createCurry(CURRY_FLAG); + var curryRight = createCurry(CURRY_RIGHT_FLAG); + function debounce(func, wait, options) { + var args, maxTimeoutId, result, stamp, thisArg, timeoutId, trailingCall, lastCalled = 0, maxWait = false, trailing = true; + if (typeof func != "function") { + throw new TypeError(FUNC_ERROR_TEXT); + } + wait = wait < 0 ? 0 : +wait || 0; + if (options === true) { + var leading = true; + trailing = false; + } else if (isObject(options)) { + leading = !!options.leading; + maxWait = "maxWait" in options && nativeMax(+options.maxWait || 0, wait); + trailing = "trailing" in options ? !!options.trailing : trailing; + } + function cancel() { + if (timeoutId) { + clearTimeout(timeoutId); + } + if (maxTimeoutId) { + clearTimeout(maxTimeoutId); + } + lastCalled = 0; + maxTimeoutId = timeoutId = trailingCall = undefined; + } + function complete(isCalled, id) { + if (id) { + clearTimeout(id); + } + maxTimeoutId = timeoutId = trailingCall = undefined; + if (isCalled) { + lastCalled = now(); + result = func.apply(thisArg, args); + if (!timeoutId && !maxTimeoutId) { + args = thisArg = undefined; + } + } + } + function delayed() { + var remaining = wait - (now() - stamp); + if (remaining <= 0 || remaining > wait) { + complete(trailingCall, maxTimeoutId); + } else { + timeoutId = setTimeout(delayed, remaining); + } + } + function maxDelayed() { + complete(trailing, timeoutId); + } + function debounced() { + args = arguments; + stamp = now(); + thisArg = this; + trailingCall = trailing && (timeoutId || !leading); + if (maxWait === false) { + var leadingCall = leading && !timeoutId; + } else { + if (!maxTimeoutId && !leading) { + lastCalled = stamp; + } + var remaining = maxWait - (stamp - lastCalled), isCalled = remaining <= 0 || remaining > maxWait; + if (isCalled) { + if (maxTimeoutId) { + maxTimeoutId = clearTimeout(maxTimeoutId); + } + lastCalled = stamp; + result = func.apply(thisArg, args); + } else if (!maxTimeoutId) { + maxTimeoutId = setTimeout(maxDelayed, remaining); + } + } + if (isCalled && timeoutId) { + timeoutId = clearTimeout(timeoutId); + } else if (!timeoutId && wait !== maxWait) { + timeoutId = setTimeout(delayed, wait); + } + if (leadingCall) { + isCalled = true; + result = func.apply(thisArg, args); + } + if (isCalled && !timeoutId && !maxTimeoutId) { + args = thisArg = undefined; + } + return result; + } + debounced.cancel = cancel; + return debounced; + } + var defer = restParam(function(func, args) { + return baseDelay(func, 1, args); + }); + var delay = restParam(function(func, wait, args) { + return baseDelay(func, wait, args); + }); + var flow = createFlow(); + var flowRight = createFlow(true); + function memoize(func, resolver) { + if (typeof func != "function" || resolver && typeof resolver != "function") { + throw new TypeError(FUNC_ERROR_TEXT); + } + var memoized = function() { + var args = arguments, key = resolver ? resolver.apply(this, args) : args[0], cache = memoized.cache; + if (cache.has(key)) { + return cache.get(key); + } + var result = func.apply(this, args); + memoized.cache = cache.set(key, result); + return result; + }; + memoized.cache = new memoize.Cache(); + return memoized; + } + var modArgs = restParam(function(func, transforms) { + transforms = baseFlatten(transforms); + if (typeof func != "function" || !arrayEvery(transforms, baseIsFunction)) { + throw new TypeError(FUNC_ERROR_TEXT); + } + var length = transforms.length; + return restParam(function(args) { + var index = nativeMin(args.length, length); + while (index--) { + args[index] = transforms[index](args[index]); + } + return func.apply(this, args); + }); + }); + function negate(predicate) { + if (typeof predicate != "function") { + throw new TypeError(FUNC_ERROR_TEXT); + } + return function() { + return !predicate.apply(this, arguments); + }; + } + function once(func) { + return before(2, func); + } + var partial = createPartial(PARTIAL_FLAG); + var partialRight = createPartial(PARTIAL_RIGHT_FLAG); + var rearg = restParam(function(func, indexes) { + return createWrapper(func, REARG_FLAG, undefined, undefined, undefined, baseFlatten(indexes)); + }); + function restParam(func, start) { + if (typeof func != "function") { + throw new TypeError(FUNC_ERROR_TEXT); + } + start = nativeMax(start === undefined ? func.length - 1 : +start || 0, 0); + return function() { + var args = arguments, index = -1, length = nativeMax(args.length - start, 0), rest = Array(length); + while (++index < length) { + rest[index] = args[start + index]; + } + switch (start) { + case 0: + return func.call(this, rest); + + case 1: + return func.call(this, args[0], rest); + + case 2: + return func.call(this, args[0], args[1], rest); + } + var otherArgs = Array(start + 1); + index = -1; + while (++index < start) { + otherArgs[index] = args[index]; + } + otherArgs[start] = rest; + return func.apply(this, otherArgs); + }; + } + function spread(func) { + if (typeof func != "function") { + throw new TypeError(FUNC_ERROR_TEXT); + } + return function(array) { + return func.apply(this, array); + }; + } + function throttle(func, wait, options) { + var leading = true, trailing = true; + if (typeof func != "function") { + throw new TypeError(FUNC_ERROR_TEXT); + } + if (options === false) { + leading = false; + } else if (isObject(options)) { + leading = "leading" in options ? !!options.leading : leading; + trailing = "trailing" in options ? !!options.trailing : trailing; + } + return debounce(func, wait, { + leading: leading, + maxWait: +wait, + trailing: trailing + }); + } + function wrap(value, wrapper) { + wrapper = wrapper == null ? identity : wrapper; + return createWrapper(wrapper, PARTIAL_FLAG, undefined, [ value ], []); + } + function clone(value, isDeep, customizer, thisArg) { + if (isDeep && typeof isDeep != "boolean" && isIterateeCall(value, isDeep, customizer)) { + isDeep = false; + } else if (typeof isDeep == "function") { + thisArg = customizer; + customizer = isDeep; + isDeep = false; + } + return typeof customizer == "function" ? baseClone(value, isDeep, bindCallback(customizer, thisArg, 3)) : baseClone(value, isDeep); + } + function cloneDeep(value, customizer, thisArg) { + return typeof customizer == "function" ? baseClone(value, true, bindCallback(customizer, thisArg, 3)) : baseClone(value, true); + } + function gt(value, other) { + return value > other; + } + function gte(value, other) { + return value >= other; + } + function isArguments(value) { + return isObjectLike(value) && isArrayLike(value) && hasOwnProperty.call(value, "callee") && !propertyIsEnumerable.call(value, "callee"); + } + var isArray = nativeIsArray || function(value) { + return isObjectLike(value) && isLength(value.length) && objToString.call(value) == arrayTag; + }; + function isBoolean(value) { + return value === true || value === false || isObjectLike(value) && objToString.call(value) == boolTag; + } + function isDate(value) { + return isObjectLike(value) && objToString.call(value) == dateTag; + } + function isElement(value) { + return !!value && value.nodeType === 1 && isObjectLike(value) && !isPlainObject(value); + } + function isEmpty(value) { + if (value == null) { + return true; + } + if (isArrayLike(value) && (isArray(value) || isString(value) || isArguments(value) || isObjectLike(value) && isFunction(value.splice))) { + return !value.length; + } + return !keys(value).length; + } + function isEqual(value, other, customizer, thisArg) { + customizer = typeof customizer == "function" ? bindCallback(customizer, thisArg, 3) : undefined; + var result = customizer ? customizer(value, other) : undefined; + return result === undefined ? baseIsEqual(value, other, customizer) : !!result; + } + function isError(value) { + return isObjectLike(value) && typeof value.message == "string" && objToString.call(value) == errorTag; + } + function isFinite(value) { + return typeof value == "number" && nativeIsFinite(value); + } + function isFunction(value) { + return isObject(value) && objToString.call(value) == funcTag; + } + function isObject(value) { + var type = typeof value; + return !!value && (type == "object" || type == "function"); + } + function isMatch(object, source, customizer, thisArg) { + customizer = typeof customizer == "function" ? bindCallback(customizer, thisArg, 3) : undefined; + return baseIsMatch(object, getMatchData(source), customizer); + } + function isNaN(value) { + return isNumber(value) && value != +value; + } + function isNative(value) { + if (value == null) { + return false; + } + if (isFunction(value)) { + return reIsNative.test(fnToString.call(value)); + } + return isObjectLike(value) && reIsHostCtor.test(value); + } + function isNull(value) { + return value === null; + } + function isNumber(value) { + return typeof value == "number" || isObjectLike(value) && objToString.call(value) == numberTag; + } + function isPlainObject(value) { + var Ctor; + if (!(isObjectLike(value) && objToString.call(value) == objectTag && !isArguments(value)) || !hasOwnProperty.call(value, "constructor") && (Ctor = value.constructor, + typeof Ctor == "function" && !(Ctor instanceof Ctor))) { + return false; + } + var result; + baseForIn(value, function(subValue, key) { + result = key; + }); + return result === undefined || hasOwnProperty.call(value, result); + } + function isRegExp(value) { + return isObject(value) && objToString.call(value) == regexpTag; + } + function isString(value) { + return typeof value == "string" || isObjectLike(value) && objToString.call(value) == stringTag; + } + function isTypedArray(value) { + return isObjectLike(value) && isLength(value.length) && !!typedArrayTags[objToString.call(value)]; + } + function isUndefined(value) { + return value === undefined; + } + function lt(value, other) { + return value < other; + } + function lte(value, other) { + return value <= other; + } + function toArray(value) { + var length = value ? getLength(value) : 0; + if (!isLength(length)) { + return values(value); + } + if (!length) { + return []; + } + return arrayCopy(value); + } + function toPlainObject(value) { + return baseCopy(value, keysIn(value)); + } + var merge = createAssigner(baseMerge); + var assign = createAssigner(function(object, source, customizer) { + return customizer ? assignWith(object, source, customizer) : baseAssign(object, source); + }); + function create(prototype, properties, guard) { + var result = baseCreate(prototype); + if (guard && isIterateeCall(prototype, properties, guard)) { + properties = undefined; + } + return properties ? baseAssign(result, properties) : result; + } + var defaults = createDefaults(assign, assignDefaults); + var defaultsDeep = createDefaults(merge, mergeDefaults); + var findKey = createFindKey(baseForOwn); + var findLastKey = createFindKey(baseForOwnRight); + var forIn = createForIn(baseFor); + var forInRight = createForIn(baseForRight); + var forOwn = createForOwn(baseForOwn); + var forOwnRight = createForOwn(baseForOwnRight); + function functions(object) { + return baseFunctions(object, keysIn(object)); + } + function get(object, path, defaultValue) { + var result = object == null ? undefined : baseGet(object, toPath(path), path + ""); + return result === undefined ? defaultValue : result; + } + function has(object, path) { + if (object == null) { + return false; + } + var result = hasOwnProperty.call(object, path); + if (!result && !isKey(path)) { + path = toPath(path); + object = path.length == 1 ? object : baseGet(object, baseSlice(path, 0, -1)); + if (object == null) { + return false; + } + path = last(path); + result = hasOwnProperty.call(object, path); + } + return result || isLength(object.length) && isIndex(path, object.length) && (isArray(object) || isArguments(object)); + } + function invert(object, multiValue, guard) { + if (guard && isIterateeCall(object, multiValue, guard)) { + multiValue = undefined; + } + var index = -1, props = keys(object), length = props.length, result = {}; + while (++index < length) { + var key = props[index], value = object[key]; + if (multiValue) { + if (hasOwnProperty.call(result, value)) { + result[value].push(key); + } else { + result[value] = [ key ]; + } + } else { + result[value] = key; + } + } + return result; + } + var keys = !nativeKeys ? shimKeys : function(object) { + var Ctor = object == null ? undefined : object.constructor; + if (typeof Ctor == "function" && Ctor.prototype === object || typeof object != "function" && isArrayLike(object)) { + return shimKeys(object); + } + return isObject(object) ? nativeKeys(object) : []; + }; + function keysIn(object) { + if (object == null) { + return []; + } + if (!isObject(object)) { + object = Object(object); + } + var length = object.length; + length = length && isLength(length) && (isArray(object) || isArguments(object)) && length || 0; + var Ctor = object.constructor, index = -1, isProto = typeof Ctor == "function" && Ctor.prototype === object, result = Array(length), skipIndexes = length > 0; + while (++index < length) { + result[index] = index + ""; + } + for (var key in object) { + if (!(skipIndexes && isIndex(key, length)) && !(key == "constructor" && (isProto || !hasOwnProperty.call(object, key)))) { + result.push(key); + } + } + return result; + } + var mapKeys = createObjectMapper(true); + var mapValues = createObjectMapper(); + var omit = restParam(function(object, props) { + if (object == null) { + return {}; + } + if (typeof props[0] != "function") { + var props = arrayMap(baseFlatten(props), String); + return pickByArray(object, baseDifference(keysIn(object), props)); + } + var predicate = bindCallback(props[0], props[1], 3); + return pickByCallback(object, function(value, key, object) { + return !predicate(value, key, object); + }); + }); + function pairs(object) { + object = toObject(object); + var index = -1, props = keys(object), length = props.length, result = Array(length); + while (++index < length) { + var key = props[index]; + result[index] = [ key, object[key] ]; + } + return result; + } + var pick = restParam(function(object, props) { + if (object == null) { + return {}; + } + return typeof props[0] == "function" ? pickByCallback(object, bindCallback(props[0], props[1], 3)) : pickByArray(object, baseFlatten(props)); + }); + function result(object, path, defaultValue) { + var result = object == null ? undefined : object[path]; + if (result === undefined) { + if (object != null && !isKey(path, object)) { + path = toPath(path); + object = path.length == 1 ? object : baseGet(object, baseSlice(path, 0, -1)); + result = object == null ? undefined : object[last(path)]; + } + result = result === undefined ? defaultValue : result; + } + return isFunction(result) ? result.call(object) : result; + } + function set(object, path, value) { + if (object == null) { + return object; + } + var pathKey = path + ""; + path = object[pathKey] != null || isKey(path, object) ? [ pathKey ] : toPath(path); + var index = -1, length = path.length, lastIndex = length - 1, nested = object; + while (nested != null && ++index < length) { + var key = path[index]; + if (isObject(nested)) { + if (index == lastIndex) { + nested[key] = value; + } else if (nested[key] == null) { + nested[key] = isIndex(path[index + 1]) ? [] : {}; + } + } + nested = nested[key]; + } + return object; + } + function transform(object, iteratee, accumulator, thisArg) { + var isArr = isArray(object) || isTypedArray(object); + iteratee = getCallback(iteratee, thisArg, 4); + if (accumulator == null) { + if (isArr || isObject(object)) { + var Ctor = object.constructor; + if (isArr) { + accumulator = isArray(object) ? new Ctor() : []; + } else { + accumulator = baseCreate(isFunction(Ctor) ? Ctor.prototype : undefined); + } + } else { + accumulator = {}; + } + } + (isArr ? arrayEach : baseForOwn)(object, function(value, index, object) { + return iteratee(accumulator, value, index, object); + }); + return accumulator; + } + function values(object) { + return baseValues(object, keys(object)); + } + function valuesIn(object) { + return baseValues(object, keysIn(object)); + } + function inRange(value, start, end) { + start = +start || 0; + if (end === undefined) { + end = start; + start = 0; + } else { + end = +end || 0; + } + return value >= nativeMin(start, end) && value < nativeMax(start, end); + } + function random(min, max, floating) { + if (floating && isIterateeCall(min, max, floating)) { + max = floating = undefined; + } + var noMin = min == null, noMax = max == null; + if (floating == null) { + if (noMax && typeof min == "boolean") { + floating = min; + min = 1; + } else if (typeof max == "boolean") { + floating = max; + noMax = true; + } + } + if (noMin && noMax) { + max = 1; + noMax = false; + } + min = +min || 0; + if (noMax) { + max = min; + min = 0; + } else { + max = +max || 0; + } + if (floating || min % 1 || max % 1) { + var rand = nativeRandom(); + return nativeMin(min + rand * (max - min + parseFloat("1e-" + ((rand + "").length - 1))), max); + } + return baseRandom(min, max); + } + var camelCase = createCompounder(function(result, word, index) { + word = word.toLowerCase(); + return result + (index ? word.charAt(0).toUpperCase() + word.slice(1) : word); + }); + function capitalize(string) { + string = baseToString(string); + return string && string.charAt(0).toUpperCase() + string.slice(1); + } + function deburr(string) { + string = baseToString(string); + return string && string.replace(reLatin1, deburrLetter).replace(reComboMark, ""); + } + function endsWith(string, target, position) { + string = baseToString(string); + target = target + ""; + var length = string.length; + position = position === undefined ? length : nativeMin(position < 0 ? 0 : +position || 0, length); + position -= target.length; + return position >= 0 && string.indexOf(target, position) == position; + } + function escape(string) { + string = baseToString(string); + return string && reHasUnescapedHtml.test(string) ? string.replace(reUnescapedHtml, escapeHtmlChar) : string; + } + function escapeRegExp(string) { + string = baseToString(string); + return string && reHasRegExpChars.test(string) ? string.replace(reRegExpChars, escapeRegExpChar) : string || "(?:)"; + } + var kebabCase = createCompounder(function(result, word, index) { + return result + (index ? "-" : "") + word.toLowerCase(); + }); + function pad(string, length, chars) { + string = baseToString(string); + length = +length; + var strLength = string.length; + if (strLength >= length || !nativeIsFinite(length)) { + return string; + } + var mid = (length - strLength) / 2, leftLength = nativeFloor(mid), rightLength = nativeCeil(mid); + chars = createPadding("", rightLength, chars); + return chars.slice(0, leftLength) + string + chars; + } + var padLeft = createPadDir(); + var padRight = createPadDir(true); + function parseInt(string, radix, guard) { + if (guard ? isIterateeCall(string, radix, guard) : radix == null) { + radix = 0; + } else if (radix) { + radix = +radix; + } + string = trim(string); + return nativeParseInt(string, radix || (reHasHexPrefix.test(string) ? 16 : 10)); + } + function repeat(string, n) { + var result = ""; + string = baseToString(string); + n = +n; + if (n < 1 || !string || !nativeIsFinite(n)) { + return result; + } + do { + if (n % 2) { + result += string; + } + n = nativeFloor(n / 2); + string += string; + } while (n); + return result; + } + var snakeCase = createCompounder(function(result, word, index) { + return result + (index ? "_" : "") + word.toLowerCase(); + }); + var startCase = createCompounder(function(result, word, index) { + return result + (index ? " " : "") + (word.charAt(0).toUpperCase() + word.slice(1)); + }); + function startsWith(string, target, position) { + string = baseToString(string); + position = position == null ? 0 : nativeMin(position < 0 ? 0 : +position || 0, string.length); + return string.lastIndexOf(target, position) == position; + } + function template(string, options, otherOptions) { + var settings = lodash.templateSettings; + if (otherOptions && isIterateeCall(string, options, otherOptions)) { + options = otherOptions = undefined; + } + string = baseToString(string); + options = assignWith(baseAssign({}, otherOptions || options), settings, assignOwnDefaults); + var imports = assignWith(baseAssign({}, options.imports), settings.imports, assignOwnDefaults), importsKeys = keys(imports), importsValues = baseValues(imports, importsKeys); + var isEscaping, isEvaluating, index = 0, interpolate = options.interpolate || reNoMatch, source = "__p += '"; + var reDelimiters = RegExp((options.escape || reNoMatch).source + "|" + interpolate.source + "|" + (interpolate === reInterpolate ? reEsTemplate : reNoMatch).source + "|" + (options.evaluate || reNoMatch).source + "|$", "g"); + var sourceURL = "//# sourceURL=" + ("sourceURL" in options ? options.sourceURL : "lodash.templateSources[" + ++templateCounter + "]") + "\n"; + string.replace(reDelimiters, function(match, escapeValue, interpolateValue, esTemplateValue, evaluateValue, offset) { + interpolateValue || (interpolateValue = esTemplateValue); + source += string.slice(index, offset).replace(reUnescapedString, escapeStringChar); + if (escapeValue) { + isEscaping = true; + source += "' +\n__e(" + escapeValue + ") +\n'"; + } + if (evaluateValue) { + isEvaluating = true; + source += "';\n" + evaluateValue + ";\n__p += '"; + } + if (interpolateValue) { + source += "' +\n((__t = (" + interpolateValue + ")) == null ? '' : __t) +\n'"; + } + index = offset + match.length; + return match; + }); + source += "';\n"; + var variable = options.variable; + if (!variable) { + source = "with (obj) {\n" + source + "\n}\n"; + } + source = (isEvaluating ? source.replace(reEmptyStringLeading, "") : source).replace(reEmptyStringMiddle, "$1").replace(reEmptyStringTrailing, "$1;"); + source = "function(" + (variable || "obj") + ") {\n" + (variable ? "" : "obj || (obj = {});\n") + "var __t, __p = ''" + (isEscaping ? ", __e = _.escape" : "") + (isEvaluating ? ", __j = Array.prototype.join;\n" + "function print() { __p += __j.call(arguments, '') }\n" : ";\n") + source + "return __p\n}"; + var result = attempt(function() { + return Function(importsKeys, sourceURL + "return " + source).apply(undefined, importsValues); + }); + result.source = source; + if (isError(result)) { + throw result; + } + return result; + } + function trim(string, chars, guard) { + var value = string; + string = baseToString(string); + if (!string) { + return string; + } + if (guard ? isIterateeCall(value, chars, guard) : chars == null) { + return string.slice(trimmedLeftIndex(string), trimmedRightIndex(string) + 1); + } + chars = chars + ""; + return string.slice(charsLeftIndex(string, chars), charsRightIndex(string, chars) + 1); + } + function trimLeft(string, chars, guard) { + var value = string; + string = baseToString(string); + if (!string) { + return string; + } + if (guard ? isIterateeCall(value, chars, guard) : chars == null) { + return string.slice(trimmedLeftIndex(string)); + } + return string.slice(charsLeftIndex(string, chars + "")); + } + function trimRight(string, chars, guard) { + var value = string; + string = baseToString(string); + if (!string) { + return string; + } + if (guard ? isIterateeCall(value, chars, guard) : chars == null) { + return string.slice(0, trimmedRightIndex(string) + 1); + } + return string.slice(0, charsRightIndex(string, chars + "") + 1); + } + function trunc(string, options, guard) { + if (guard && isIterateeCall(string, options, guard)) { + options = undefined; + } + var length = DEFAULT_TRUNC_LENGTH, omission = DEFAULT_TRUNC_OMISSION; + if (options != null) { + if (isObject(options)) { + var separator = "separator" in options ? options.separator : separator; + length = "length" in options ? +options.length || 0 : length; + omission = "omission" in options ? baseToString(options.omission) : omission; + } else { + length = +options || 0; + } + } + string = baseToString(string); + if (length >= string.length) { + return string; + } + var end = length - omission.length; + if (end < 1) { + return omission; + } + var result = string.slice(0, end); + if (separator == null) { + return result + omission; + } + if (isRegExp(separator)) { + if (string.slice(end).search(separator)) { + var match, newEnd, substring = string.slice(0, end); + if (!separator.global) { + separator = RegExp(separator.source, (reFlags.exec(separator) || "") + "g"); + } + separator.lastIndex = 0; + while (match = separator.exec(substring)) { + newEnd = match.index; + } + result = result.slice(0, newEnd == null ? end : newEnd); + } + } else if (string.indexOf(separator, end) != end) { + var index = result.lastIndexOf(separator); + if (index > -1) { + result = result.slice(0, index); + } + } + return result + omission; + } + function unescape(string) { + string = baseToString(string); + return string && reHasEscapedHtml.test(string) ? string.replace(reEscapedHtml, unescapeHtmlChar) : string; + } + function words(string, pattern, guard) { + if (guard && isIterateeCall(string, pattern, guard)) { + pattern = undefined; + } + string = baseToString(string); + return string.match(pattern || reWords) || []; + } + var attempt = restParam(function(func, args) { + try { + return func.apply(undefined, args); + } catch (e) { + return isError(e) ? e : new Error(e); + } + }); + function callback(func, thisArg, guard) { + if (guard && isIterateeCall(func, thisArg, guard)) { + thisArg = undefined; + } + return isObjectLike(func) ? matches(func) : baseCallback(func, thisArg); + } + function constant(value) { + return function() { + return value; + }; + } + function identity(value) { + return value; + } + function matches(source) { + return baseMatches(baseClone(source, true)); + } + function matchesProperty(path, srcValue) { + return baseMatchesProperty(path, baseClone(srcValue, true)); + } + var method = restParam(function(path, args) { + return function(object) { + return invokePath(object, path, args); + }; + }); + var methodOf = restParam(function(object, args) { + return function(path) { + return invokePath(object, path, args); + }; + }); + function mixin(object, source, options) { + if (options == null) { + var isObj = isObject(source), props = isObj ? keys(source) : undefined, methodNames = props && props.length ? baseFunctions(source, props) : undefined; + if (!(methodNames ? methodNames.length : isObj)) { + methodNames = false; + options = source; + source = object; + object = this; + } + } + if (!methodNames) { + methodNames = baseFunctions(source, keys(source)); + } + var chain = true, index = -1, isFunc = isFunction(object), length = methodNames.length; + if (options === false) { + chain = false; + } else if (isObject(options) && "chain" in options) { + chain = options.chain; + } + while (++index < length) { + var methodName = methodNames[index], func = source[methodName]; + object[methodName] = func; + if (isFunc) { + object.prototype[methodName] = function(func) { + return function() { + var chainAll = this.__chain__; + if (chain || chainAll) { + var result = object(this.__wrapped__), actions = result.__actions__ = arrayCopy(this.__actions__); + actions.push({ + func: func, + args: arguments, + thisArg: object + }); + result.__chain__ = chainAll; + return result; + } + return func.apply(object, arrayPush([ this.value() ], arguments)); + }; + }(func); + } + } + return object; + } + function noConflict() { + root._ = oldDash; + return this; + } + function noop() {} + function property(path) { + return isKey(path) ? baseProperty(path) : basePropertyDeep(path); + } + function propertyOf(object) { + return function(path) { + return baseGet(object, toPath(path), path + ""); + }; + } + function range(start, end, step) { + if (step && isIterateeCall(start, end, step)) { + end = step = undefined; + } + start = +start || 0; + step = step == null ? 1 : +step || 0; + if (end == null) { + end = start; + start = 0; + } else { + end = +end || 0; + } + var index = -1, length = nativeMax(nativeCeil((end - start) / (step || 1)), 0), result = Array(length); + while (++index < length) { + result[index] = start; + start += step; + } + return result; + } + function times(n, iteratee, thisArg) { + n = nativeFloor(n); + if (n < 1 || !nativeIsFinite(n)) { + return []; + } + var index = -1, result = Array(nativeMin(n, MAX_ARRAY_LENGTH)); + iteratee = bindCallback(iteratee, thisArg, 1); + while (++index < n) { + if (index < MAX_ARRAY_LENGTH) { + result[index] = iteratee(index); + } else { + iteratee(index); + } + } + return result; + } + function uniqueId(prefix) { + var id = ++idCounter; + return baseToString(prefix) + id; + } + function add(augend, addend) { + return (+augend || 0) + (+addend || 0); + } + var ceil = createRound("ceil"); + var floor = createRound("floor"); + var max = createExtremum(gt, NEGATIVE_INFINITY); + var min = createExtremum(lt, POSITIVE_INFINITY); + var round = createRound("round"); + function sum(collection, iteratee, thisArg) { + if (thisArg && isIterateeCall(collection, iteratee, thisArg)) { + iteratee = undefined; + } + iteratee = getCallback(iteratee, thisArg, 3); + return iteratee.length == 1 ? arraySum(isArray(collection) ? collection : toIterable(collection), iteratee) : baseSum(collection, iteratee); + } + lodash.prototype = baseLodash.prototype; + LodashWrapper.prototype = baseCreate(baseLodash.prototype); + LodashWrapper.prototype.constructor = LodashWrapper; + LazyWrapper.prototype = baseCreate(baseLodash.prototype); + LazyWrapper.prototype.constructor = LazyWrapper; + MapCache.prototype["delete"] = mapDelete; + MapCache.prototype.get = mapGet; + MapCache.prototype.has = mapHas; + MapCache.prototype.set = mapSet; + SetCache.prototype.push = cachePush; + memoize.Cache = MapCache; + lodash.after = after; + lodash.ary = ary; + lodash.assign = assign; + lodash.at = at; + lodash.before = before; + lodash.bind = bind; + lodash.bindAll = bindAll; + lodash.bindKey = bindKey; + lodash.callback = callback; + lodash.chain = chain; + lodash.chunk = chunk; + lodash.compact = compact; + lodash.constant = constant; + lodash.countBy = countBy; + lodash.create = create; + lodash.curry = curry; + lodash.curryRight = curryRight; + lodash.debounce = debounce; + lodash.defaults = defaults; + lodash.defaultsDeep = defaultsDeep; + lodash.defer = defer; + lodash.delay = delay; + lodash.difference = difference; + lodash.drop = drop; + lodash.dropRight = dropRight; + lodash.dropRightWhile = dropRightWhile; + lodash.dropWhile = dropWhile; + lodash.fill = fill; + lodash.filter = filter; + lodash.flatten = flatten; + lodash.flattenDeep = flattenDeep; + lodash.flow = flow; + lodash.flowRight = flowRight; + lodash.forEach = forEach; + lodash.forEachRight = forEachRight; + lodash.forIn = forIn; + lodash.forInRight = forInRight; + lodash.forOwn = forOwn; + lodash.forOwnRight = forOwnRight; + lodash.functions = functions; + lodash.groupBy = groupBy; + lodash.indexBy = indexBy; + lodash.initial = initial; + lodash.intersection = intersection; + lodash.invert = invert; + lodash.invoke = invoke; + lodash.keys = keys; + lodash.keysIn = keysIn; + lodash.map = map; + lodash.mapKeys = mapKeys; + lodash.mapValues = mapValues; + lodash.matches = matches; + lodash.matchesProperty = matchesProperty; + lodash.memoize = memoize; + lodash.merge = merge; + lodash.method = method; + lodash.methodOf = methodOf; + lodash.mixin = mixin; + lodash.modArgs = modArgs; + lodash.negate = negate; + lodash.omit = omit; + lodash.once = once; + lodash.pairs = pairs; + lodash.partial = partial; + lodash.partialRight = partialRight; + lodash.partition = partition; + lodash.pick = pick; + lodash.pluck = pluck; + lodash.property = property; + lodash.propertyOf = propertyOf; + lodash.pull = pull; + lodash.pullAt = pullAt; + lodash.range = range; + lodash.rearg = rearg; + lodash.reject = reject; + lodash.remove = remove; + lodash.rest = rest; + lodash.restParam = restParam; + lodash.set = set; + lodash.shuffle = shuffle; + lodash.slice = slice; + lodash.sortBy = sortBy; + lodash.sortByAll = sortByAll; + lodash.sortByOrder = sortByOrder; + lodash.spread = spread; + lodash.take = take; + lodash.takeRight = takeRight; + lodash.takeRightWhile = takeRightWhile; + lodash.takeWhile = takeWhile; + lodash.tap = tap; + lodash.throttle = throttle; + lodash.thru = thru; + lodash.times = times; + lodash.toArray = toArray; + lodash.toPlainObject = toPlainObject; + lodash.transform = transform; + lodash.union = union; + lodash.uniq = uniq; + lodash.unzip = unzip; + lodash.unzipWith = unzipWith; + lodash.values = values; + lodash.valuesIn = valuesIn; + lodash.where = where; + lodash.without = without; + lodash.wrap = wrap; + lodash.xor = xor; + lodash.zip = zip; + lodash.zipObject = zipObject; + lodash.zipWith = zipWith; + lodash.backflow = flowRight; + lodash.collect = map; + lodash.compose = flowRight; + lodash.each = forEach; + lodash.eachRight = forEachRight; + lodash.extend = assign; + lodash.iteratee = callback; + lodash.methods = functions; + lodash.object = zipObject; + lodash.select = filter; + lodash.tail = rest; + lodash.unique = uniq; + mixin(lodash, lodash); + lodash.add = add; + lodash.attempt = attempt; + lodash.camelCase = camelCase; + lodash.capitalize = capitalize; + lodash.ceil = ceil; + lodash.clone = clone; + lodash.cloneDeep = cloneDeep; + lodash.deburr = deburr; + lodash.endsWith = endsWith; + lodash.escape = escape; + lodash.escapeRegExp = escapeRegExp; + lodash.every = every; + lodash.find = find; + lodash.findIndex = findIndex; + lodash.findKey = findKey; + lodash.findLast = findLast; + lodash.findLastIndex = findLastIndex; + lodash.findLastKey = findLastKey; + lodash.findWhere = findWhere; + lodash.first = first; + lodash.floor = floor; + lodash.get = get; + lodash.gt = gt; + lodash.gte = gte; + lodash.has = has; + lodash.identity = identity; + lodash.includes = includes; + lodash.indexOf = indexOf; + lodash.inRange = inRange; + lodash.isArguments = isArguments; + lodash.isArray = isArray; + lodash.isBoolean = isBoolean; + lodash.isDate = isDate; + lodash.isElement = isElement; + lodash.isEmpty = isEmpty; + lodash.isEqual = isEqual; + lodash.isError = isError; + lodash.isFinite = isFinite; + lodash.isFunction = isFunction; + lodash.isMatch = isMatch; + lodash.isNaN = isNaN; + lodash.isNative = isNative; + lodash.isNull = isNull; + lodash.isNumber = isNumber; + lodash.isObject = isObject; + lodash.isPlainObject = isPlainObject; + lodash.isRegExp = isRegExp; + lodash.isString = isString; + lodash.isTypedArray = isTypedArray; + lodash.isUndefined = isUndefined; + lodash.kebabCase = kebabCase; + lodash.last = last; + lodash.lastIndexOf = lastIndexOf; + lodash.lt = lt; + lodash.lte = lte; + lodash.max = max; + lodash.min = min; + lodash.noConflict = noConflict; + lodash.noop = noop; + lodash.now = now; + lodash.pad = pad; + lodash.padLeft = padLeft; + lodash.padRight = padRight; + lodash.parseInt = parseInt; + lodash.random = random; + lodash.reduce = reduce; + lodash.reduceRight = reduceRight; + lodash.repeat = repeat; + lodash.result = result; + lodash.round = round; + lodash.runInContext = runInContext; + lodash.size = size; + lodash.snakeCase = snakeCase; + lodash.some = some; + lodash.sortedIndex = sortedIndex; + lodash.sortedLastIndex = sortedLastIndex; + lodash.startCase = startCase; + lodash.startsWith = startsWith; + lodash.sum = sum; + lodash.template = template; + lodash.trim = trim; + lodash.trimLeft = trimLeft; + lodash.trimRight = trimRight; + lodash.trunc = trunc; + lodash.unescape = unescape; + lodash.uniqueId = uniqueId; + lodash.words = words; + lodash.all = every; + lodash.any = some; + lodash.contains = includes; + lodash.eq = isEqual; + lodash.detect = find; + lodash.foldl = reduce; + lodash.foldr = reduceRight; + lodash.head = first; + lodash.include = includes; + lodash.inject = reduce; + mixin(lodash, function() { + var source = {}; + baseForOwn(lodash, function(func, methodName) { + if (!lodash.prototype[methodName]) { + source[methodName] = func; + } + }); + return source; + }(), false); + lodash.sample = sample; + lodash.prototype.sample = function(n) { + if (!this.__chain__ && n == null) { + return sample(this.value()); + } + return this.thru(function(value) { + return sample(value, n); + }); + }; + lodash.VERSION = VERSION; + arrayEach([ "bind", "bindKey", "curry", "curryRight", "partial", "partialRight" ], function(methodName) { + lodash[methodName].placeholder = lodash; + }); + arrayEach([ "drop", "take" ], function(methodName, index) { + LazyWrapper.prototype[methodName] = function(n) { + var filtered = this.__filtered__; + if (filtered && !index) { + return new LazyWrapper(this); + } + n = n == null ? 1 : nativeMax(nativeFloor(n) || 0, 0); + var result = this.clone(); + if (filtered) { + result.__takeCount__ = nativeMin(result.__takeCount__, n); + } else { + result.__views__.push({ + size: n, + type: methodName + (result.__dir__ < 0 ? "Right" : "") + }); + } + return result; + }; + LazyWrapper.prototype[methodName + "Right"] = function(n) { + return this.reverse()[methodName](n).reverse(); + }; + }); + arrayEach([ "filter", "map", "takeWhile" ], function(methodName, index) { + var type = index + 1, isFilter = type != LAZY_MAP_FLAG; + LazyWrapper.prototype[methodName] = function(iteratee, thisArg) { + var result = this.clone(); + result.__iteratees__.push({ + iteratee: getCallback(iteratee, thisArg, 1), + type: type + }); + result.__filtered__ = result.__filtered__ || isFilter; + return result; + }; + }); + arrayEach([ "first", "last" ], function(methodName, index) { + var takeName = "take" + (index ? "Right" : ""); + LazyWrapper.prototype[methodName] = function() { + return this[takeName](1).value()[0]; + }; + }); + arrayEach([ "initial", "rest" ], function(methodName, index) { + var dropName = "drop" + (index ? "" : "Right"); + LazyWrapper.prototype[methodName] = function() { + return this.__filtered__ ? new LazyWrapper(this) : this[dropName](1); + }; + }); + arrayEach([ "pluck", "where" ], function(methodName, index) { + var operationName = index ? "filter" : "map", createCallback = index ? baseMatches : property; + LazyWrapper.prototype[methodName] = function(value) { + return this[operationName](createCallback(value)); + }; + }); + LazyWrapper.prototype.compact = function() { + return this.filter(identity); + }; + LazyWrapper.prototype.reject = function(predicate, thisArg) { + predicate = getCallback(predicate, thisArg, 1); + return this.filter(function(value) { + return !predicate(value); + }); + }; + LazyWrapper.prototype.slice = function(start, end) { + start = start == null ? 0 : +start || 0; + var result = this; + if (result.__filtered__ && (start > 0 || end < 0)) { + return new LazyWrapper(result); + } + if (start < 0) { + result = result.takeRight(-start); + } else if (start) { + result = result.drop(start); + } + if (end !== undefined) { + end = +end || 0; + result = end < 0 ? result.dropRight(-end) : result.take(end - start); + } + return result; + }; + LazyWrapper.prototype.takeRightWhile = function(predicate, thisArg) { + return this.reverse().takeWhile(predicate, thisArg).reverse(); + }; + LazyWrapper.prototype.toArray = function() { + return this.take(POSITIVE_INFINITY); + }; + baseForOwn(LazyWrapper.prototype, function(func, methodName) { + var checkIteratee = /^(?:filter|map|reject)|While$/.test(methodName), retUnwrapped = /^(?:first|last)$/.test(methodName), lodashFunc = lodash[retUnwrapped ? "take" + (methodName == "last" ? "Right" : "") : methodName]; + if (!lodashFunc) { + return; + } + lodash.prototype[methodName] = function() { + var args = retUnwrapped ? [ 1 ] : arguments, chainAll = this.__chain__, value = this.__wrapped__, isHybrid = !!this.__actions__.length, isLazy = value instanceof LazyWrapper, iteratee = args[0], useLazy = isLazy || isArray(value); + if (useLazy && checkIteratee && typeof iteratee == "function" && iteratee.length != 1) { + isLazy = useLazy = false; + } + var interceptor = function(value) { + return retUnwrapped && chainAll ? lodashFunc(value, 1)[0] : lodashFunc.apply(undefined, arrayPush([ value ], args)); + }; + var action = { + func: thru, + args: [ interceptor ], + thisArg: undefined + }, onlyLazy = isLazy && !isHybrid; + if (retUnwrapped && !chainAll) { + if (onlyLazy) { + value = value.clone(); + value.__actions__.push(action); + return func.call(value); + } + return lodashFunc.call(undefined, this.value())[0]; + } + if (!retUnwrapped && useLazy) { + value = onlyLazy ? value : new LazyWrapper(this); + var result = func.apply(value, args); + result.__actions__.push(action); + return new LodashWrapper(result, chainAll); + } + return this.thru(interceptor); + }; + }); + arrayEach([ "join", "pop", "push", "replace", "shift", "sort", "splice", "split", "unshift" ], function(methodName) { + var func = (/^(?:replace|split)$/.test(methodName) ? stringProto : arrayProto)[methodName], chainName = /^(?:push|sort|unshift)$/.test(methodName) ? "tap" : "thru", retUnwrapped = /^(?:join|pop|replace|shift)$/.test(methodName); + lodash.prototype[methodName] = function() { + var args = arguments; + if (retUnwrapped && !this.__chain__) { + return func.apply(this.value(), args); + } + return this[chainName](function(value) { + return func.apply(value, args); + }); + }; + }); + baseForOwn(LazyWrapper.prototype, function(func, methodName) { + var lodashFunc = lodash[methodName]; + if (lodashFunc) { + var key = lodashFunc.name + "", names = realNames[key] || (realNames[key] = []); + names.push({ + name: methodName, + func: lodashFunc + }); + } + }); + realNames[createHybridWrapper(undefined, BIND_KEY_FLAG).name] = [ { + name: "wrapper", + func: undefined + } ]; + LazyWrapper.prototype.clone = lazyClone; + LazyWrapper.prototype.reverse = lazyReverse; + LazyWrapper.prototype.value = lazyValue; + lodash.prototype.chain = wrapperChain; + lodash.prototype.commit = wrapperCommit; + lodash.prototype.concat = wrapperConcat; + lodash.prototype.plant = wrapperPlant; + lodash.prototype.reverse = wrapperReverse; + lodash.prototype.toString = wrapperToString; + lodash.prototype.run = lodash.prototype.toJSON = lodash.prototype.valueOf = lodash.prototype.value = wrapperValue; + lodash.prototype.collect = lodash.prototype.map; + lodash.prototype.head = lodash.prototype.first; + lodash.prototype.select = lodash.prototype.filter; + lodash.prototype.tail = lodash.prototype.rest; + return lodash; + } + var _ = runInContext(); + if (typeof define == "function" && typeof define.amd == "object" && define.amd) { + root._ = _; + define(function() { + return _; + }); + } else if (freeExports && freeModule) { + if (moduleExports) { + (freeModule.exports = _)._ = _; + } else { + freeExports._ = _; + } + } else { + root._ = _; + } +}).call(this); + (function(window, document, undefined) { "use strict"; function minErr(module, ErrorConstructor) { @@ -5391,7 +9332,7 @@ } return match; }); - message += "\nhttp://errors.angularjs.org/1.4.6/" + (module ? module + "/" : "") + code; + message += "\nhttp://errors.angularjs.org/1.4.7/" + (module ? module + "/" : "") + code; for (i = SKIP_INDEXES, paramPrefix = "?"; i < templateArgs.length; i++, paramPrefix = "&") { message += paramPrefix + "p" + (i - SKIP_INDEXES) + "=" + encodeURIComponent(toDebugString(templateArgs[i])); } @@ -6210,11 +10151,11 @@ return obj; } var version = { - full: "1.4.6", + full: "1.4.7", major: 1, minor: 4, - dot: 6, - codeName: "multiplicative-elevation" + dot: 7, + codeName: "dark-luminescence" }; function publishExternalAPI(angular) { extend(angular, { @@ -6323,6 +10264,7 @@ $httpParamSerializer: $HttpParamSerializerProvider, $httpParamSerializerJQLike: $HttpParamSerializerJQLikeProvider, $httpBackend: $HttpBackendProvider, + $xhrFactory: $xhrFactoryProvider, $location: $LocationProvider, $log: $LogProvider, $parse: $ParseProvider, @@ -6368,10 +10310,10 @@ return offset ? letter.toUpperCase() : letter; }).replace(MOZ_HACK_REGEXP, "Moz$1"); } - var SINGLE_TAG_REGEXP = /^<(\w+)\s*\/?>(?:<\/\1>|)$/; + var SINGLE_TAG_REGEXP = /^<([\w-]+)\s*\/?>(?:<\/\1>|)$/; var HTML_REGEXP = /<|&#?\w+;/; - var TAG_NAME_REGEXP = /<([\w:]+)/; - var XHTML_TAG_REGEXP = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi; + var TAG_NAME_REGEXP = /<([\w:-]+)/; + var XHTML_TAG_REGEXP = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:-]+)[^>]*)\/>/gi; var wrapMap = { option: [ 1, '" ], thead: [ 1, "", "
              " ], @@ -7614,6 +11556,9 @@ } }; return function(element, options) { + if (options.cleanupStyles) { + options.from = options.to = null; + } if (options.from) { element.css(options.from); options.from = null; @@ -8879,7 +12824,7 @@ compile: function() { return { pre: function attrInterpolatePreLinkFn(scope, element, attr) { - var $$observers = attr.$$observers || (attr.$$observers = {}); + var $$observers = attr.$$observers || (attr.$$observers = createMap()); if (EVENT_HANDLER_ATTR_REGEXP.test(name)) { throw $compileMinErr("nodomevents", "Interpolations for HTML DOM event attributes are disallowed. Please use the " + "ng- versions (such as ng-click instead of onclick) instead."); } @@ -9542,12 +13487,16 @@ } } ]; } - function createXhr() { - return new window.XMLHttpRequest(); + function $xhrFactoryProvider() { + this.$get = function() { + return function createXhr() { + return new window.XMLHttpRequest(); + }; + }; } function $HttpBackendProvider() { - this.$get = [ "$browser", "$window", "$document", function($browser, $window, $document) { - return createHttpBackend($browser, createXhr, $browser.defer, $window.angular.callbacks, $document[0]); + this.$get = [ "$browser", "$window", "$document", "$xhrFactory", function($browser, $window, $document, $xhrFactory) { + return createHttpBackend($browser, $xhrFactory, $browser.defer, $window.angular.callbacks, $document[0]); } ]; } function createHttpBackend($browser, createXhr, $browserDefer, callbacks, rawDocument) { @@ -9565,7 +13514,7 @@ callbacks[callbackId] = noop; }); } else { - var xhr = createXhr(); + var xhr = createXhr(method, url); xhr.open(method, url, true); forEach(headers, function(value, key) { if (isDefined(value)) { @@ -10273,12 +14222,18 @@ } var $parseMinErr = minErr("$parse"); function ensureSafeMemberName(name, fullExpression) { - name = isObject(name) && name.toString ? name.toString() : name; if (name === "__defineGetter__" || name === "__defineSetter__" || name === "__lookupGetter__" || name === "__lookupSetter__" || name === "__proto__") { throw $parseMinErr("isecfld", "Attempting to access a disallowed field in Angular expressions! " + "Expression: {0}", fullExpression); } return name; } + function getStringValue(name, fullExpression) { + name = name + ""; + if (!isString(name)) { + throw $parseMinErr("iseccst", "Cannot convert object to primitive value! " + "Expression: {0}", fullExpression); + } + return name; + } function ensureSafeObject(obj, fullExpression) { if (obj) { if (obj.constructor === obj) { @@ -10305,6 +14260,13 @@ } } } + function ensureSafeAssignContext(obj, fullExpression) { + if (obj) { + if (obj === 0..constructor || obj === false.constructor || obj === "".constructor || obj === {}.constructor || obj === [].constructor || obj === Function.constructor) { + throw $parseMinErr("isecaf", "Assigning to a constructor is disallowed! Expression: {0}", fullExpression); + } + } + } var OPERATORS = createMap(); forEach("+ - * / % === !== == != < > <= >= && || ! = |".split(" "), function(operator) { OPERATORS[operator] = true; @@ -11053,7 +15015,7 @@ this.stage = "main"; this.recurse(ast); var fnString = '"' + this.USE + " " + this.STRICT + '";\n' + this.filterPrefix() + "var fn=" + this.generateFunction("fn", "s,l,a,i") + extra + this.watchFns() + "return fn;"; - var fn = new Function("$filter", "ensureSafeMemberName", "ensureSafeObject", "ensureSafeFunction", "ifDefined", "plus", "text", fnString)(this.$filter, ensureSafeMemberName, ensureSafeObject, ensureSafeFunction, ifDefined, plusFn, expression); + var fn = new Function("$filter", "ensureSafeMemberName", "ensureSafeObject", "ensureSafeFunction", "getStringValue", "ensureSafeAssignContext", "ifDefined", "plus", "text", fnString)(this.$filter, ensureSafeMemberName, ensureSafeObject, ensureSafeFunction, getStringValue, ensureSafeAssignContext, ifDefined, plusFn, expression); this.state = this.stage = undefined; fn.literal = isLiteral(ast); fn.constant = isConstant(ast); @@ -11190,6 +15152,7 @@ if (ast.computed) { right = self.nextId(); self.recurse(ast.property, right); + self.getStringValue(right); self.addEnsureSafeMemberName(right); if (create && create !== 1) { self.if_(self.not(self.computedMember(left, right)), self.lazyAssign(self.computedMember(left, right), "{}")); @@ -11275,6 +15238,7 @@ self.if_(self.notNull(left.context), function() { self.recurse(ast.right, right); self.addEnsureSafeObject(self.member(left.context, left.name, left.computed)); + self.addEnsureSafeAssignContext(left.context); expression = self.member(left.context, left.name, left.computed) + ast.operator + right; self.assign(intoId, expression); recursionFn(intoId || expression); @@ -11385,6 +15349,9 @@ addEnsureSafeFunction: function(item) { this.current().body.push(this.ensureSafeFunction(item), ";"); }, + addEnsureSafeAssignContext: function(item) { + this.current().body.push(this.ensureSafeAssignContext(item), ";"); + }, ensureSafeObject: function(item) { return "ensureSafeObject(" + item + ",text)"; }, @@ -11394,6 +15361,12 @@ ensureSafeFunction: function(item) { return "ensureSafeFunction(" + item + ",text)"; }, + getStringValue: function(item) { + this.assign(item, "getStringValue(" + item + ",text)"); + }, + ensureSafeAssignContext: function(item) { + return "ensureSafeAssignContext(" + item + ",text)"; + }, lazyRecurse: function(ast, intoId, nameId, recursionFn, create, skipWatchIdCheck) { var self = this; return function() { @@ -11561,6 +15534,7 @@ var lhs = left(scope, locals, assign, inputs); var rhs = right(scope, locals, assign, inputs); ensureSafeObject(lhs.value, self.expression); + ensureSafeAssignContext(lhs.context); lhs.context[lhs.name] = rhs; return context ? { value: rhs @@ -11818,6 +15792,7 @@ var value; if (lhs != null) { rhs = right(scope, locals, assign, inputs); + rhs = getStringValue(rhs); ensureSafeMemberName(rhs, expression); if (create && create !== 1 && lhs && !lhs[rhs]) { lhs[rhs] = {}; @@ -13500,6 +17475,7 @@ if (fractionSize > 0 && number < 1) { formatedText = number.toFixed(fractionSize); number = parseFloat(formatedText); + formatedText = formatedText.replace(DECIMAL_SEP, decimalSep); } } if (number === 0) { @@ -15517,11 +19493,11 @@ function updateOptionElement(option, element) { option.element = element; element.disabled = option.disabled; - if (option.value !== element.value) element.value = option.selectValue; if (option.label !== element.label) { element.label = option.label; element.textContent = option.label; } + if (option.value !== element.value) element.value = option.selectValue; } function addOrReuseElement(parent, current, type, templateElement) { var element; @@ -15549,7 +19525,7 @@ var emptyOption_ = emptyOption && emptyOption[0]; var unknownOption_ = unknownOption && unknownOption[0]; if (emptyOption_ || unknownOption_) { - while (current && (current === emptyOption_ || current === unknownOption_)) { + while (current && (current === emptyOption_ || current === unknownOption_ || emptyOption_ && emptyOption_.nodeType === NODE_TYPE_COMMENT)) { current = current.nextSibling; } } @@ -28128,6 +32104,12 @@ var cloneObject = function(oldObject) { return JSON.parse(JSON.stringify(oldObject)); }; +var enableControls = function(controls, enabled) { + _.each(controls, function(value, key) { + controls[key] = enabled; + }); +}; + var lingvodoc = {}; lingvodoc.Object = function(clientId, objectId) { @@ -28135,10 +32117,7 @@ lingvodoc.Object = function(clientId, objectId) { this.object_id = objectId; this.type = "abstract"; this.getId = function() { - return this.client_id + "" + this.object_id; - }; - this.export = function() { - return {}; + return this.client_id + "_" + this.object_id; }; }; @@ -28199,13 +32178,33 @@ lingvodoc.Perspective = function(client_id, object_id, parent_client_id, parent_ this.is_template = is_template; this.marked_for_deletion = marked_for_deletion; this.fields = []; + this.location = null; + this.blobs = []; + this.additional_metadata = {}; this.equals = function(obj) { return lingvodoc.Object.prototype.equals.call(this, obj) && this.translation == obj.translation; }; }; lingvodoc.Perspective.fromJS = function(js) { - return new lingvodoc.Perspective(js.client_id, js.object_id, js.parent_client_id, js.parent_object_id, js.translation, js.translation_string, js.status, js.is_template, js.marked_for_deletion); + var perspective = new lingvodoc.Perspective(js.client_id, js.object_id, js.parent_client_id, js.parent_object_id, js.translation, js.translation_string, js.status, js.is_template, js.marked_for_deletion); + if (_.has(js, "location") && _.has(js.location, "content")) { + perspective["location"] = { + lat: js.location.content.lat, + lng: js.location.content.lng + }; + } + if (_.has(js, "info") && js.info.type == "list") { + if (_.isArray(js.info.content)) { + perspective["blobs"] = _.map(js.info.content, function(e) { + var blob = new lingvodoc.Blob(e.info.content.client_id, e.info.content.object_id, e.info.content.name, e.info.content.data_type); + blob.url = e.info.content.content; + return blob; + }); + } + } + perspective.additional_metadata = js.additional_metadata; + return perspective; }; lingvodoc.Perspective.prototype = new lingvodoc.Object(); @@ -28230,6 +32229,25 @@ lingvodoc.User.fromJS = function(js) { return new lingvodoc.User(js.id, js.login, js.name, js.email, js.intl_name, js.about, js.signup_date, js.organizations); }; +lingvodoc.Blob = function(clientId, objectId, name, data_type) { + lingvodoc.Object.call(this, clientId, objectId); + this.type = "blob"; + this.name = name; + this.data_type = data_type; + this.url = null; + this.equals = function(obj) { + return lingvodoc.Object.prototype.equals.call(this, obj) && this.name == obj.name; + }; +}; + +lingvodoc.Blob.fromJS = function(js) { + return new lingvodoc.Blob(js.client_id, js.object_id, js.name, js.data_type); +}; + +lingvodoc.Blob.prototype = new lingvodoc.Object(); + +lingvodoc.Blob.prototype.constructor = lingvodoc.Blob; + function lingvodocAPI($http, $q) { var addUrlParameter = function(url, key, value) { return url + (url.indexOf("?") >= 0 ? "&" : "?") + encodeURIComponent(key) + "=" + encodeURIComponent(value); @@ -28303,6 +32321,21 @@ function lingvodocAPI($http, $q) { }); return deferred.promise; }; + var getPerspectiveDictionaryFieldsNew = function(perspective) { + var deferred = $q.defer(); + var url = "/dictionary/" + perspective.parent_client_id + "/" + perspective.parent_object_id + "/perspective/" + perspective.client_id + "/" + perspective.object_id + "/fields"; + $http.get(url).success(function(data, status, headers, config) { + if (_.isArray(data.fields)) { + var fields = perspectiveToDictionaryFields(data.fields); + deferred.resolve(fields); + } else { + deferred.reject("An error occurred while fetching perspective fields"); + } + }).error(function(data, status, headers, config) { + deferred.reject("An error occurred while fetching perspective fields"); + }); + return deferred.promise; + }; var removeValue = function(entry, field, fieldValue, parent) { var deferred = $q.defer(); var url; @@ -28469,8 +32502,9 @@ function lingvodocAPI($http, $q) { }); return deferred.promise; }; - var getDictionaryProperties = function(url) { + var getDictionaryProperties = function(dictionary) { var deferred = $q.defer(); + var url = "/dictionary/" + encodeURIComponent(dictionary.client_id) + "/" + encodeURIComponent(dictionary.object_id); $http.get(url).success(function(data, status, headers, config) { deferred.resolve(data); }).error(function(data, status, headers, config) { @@ -28478,8 +32512,9 @@ function lingvodocAPI($http, $q) { }); return deferred.promise; }; - var setDictionaryProperties = function(url, properties) { + var setDictionaryProperties = function(dictionary, properties) { var deferred = $q.defer(); + var url = "/dictionary/" + encodeURIComponent(dictionary.client_id) + "/" + encodeURIComponent(dictionary.object_id); $http.put(url, properties).success(function(data, status, headers, config) { deferred.resolve(data); }).error(function(data, status, headers, config) { @@ -28487,6 +32522,16 @@ function lingvodocAPI($http, $q) { }); return deferred.promise; }; + var removeDictionary = function(dictionary) { + var deferred = $q.defer(); + var url = "/dictionary/" + encodeURIComponent(dictionary.client_id) + "/" + encodeURIComponent(dictionary.object_id); + $http.delete(url).success(function(data, status, headers, config) { + deferred.resolve(); + }).error(function(data, status, headers, config) { + deferred.reject("An error occurred while trying to delete dictionary"); + }); + return deferred.promise; + }; var getLanguages = function(url) { var deferred = $q.defer(); var flatLanguages = function(languages) { @@ -28570,6 +32615,16 @@ function lingvodocAPI($http, $q) { }); return deferred.promise; }; + var removePerspective = function(perspective) { + var deferred = $q.defer(); + var url = "/dictionary/" + perspective.parent_client_id + "/" + perspective.parent_object_id + "/perspective/" + perspective.client_id + "/" + perspective.object_id; + $http.delete(url).success(function(data, status, headers, config) { + deferred.resolve(); + }).error(function(data, status, headers, config) { + deferred.reject("An error occurred while trying to delete perspective"); + }); + return deferred.promise; + }; var getUserInfo = function(userId, clientId) { var deferred = $q.defer(); var url = "/user" + "?client_id= " + encodeURIComponent(clientId) + "&user_id= " + encodeURIComponent(userId); @@ -28650,13 +32705,14 @@ function lingvodocAPI($http, $q) { }; var getDictionaries = function(query) { var deferred = $q.defer(); - var dictionaries = []; $http.post("/dictionaries", query).success(function(data, status, headers, config) { - for (var i = 0; i < data.dictionaries.length; i++) { - var dictionary = data.dictionaries[i]; - dictionaries.push(lingvodoc.Dictionary.fromJS(dictionary)); + if (_.isArray(data.dictionaries)) { + deferred.resolve(_.map(data.dictionaries, function(d) { + return lingvodoc.Dictionary.fromJS(d); + })); + } else { + deferred.reject("Failed to fetch dictionaries list. Malformed response."); } - deferred.resolve(dictionaries); }).error(function(data, status, headers, config) { deferred.reject("Failed to fetch dictionaries list"); }); @@ -28873,8 +32929,8 @@ function lingvodocAPI($http, $q) { }; $http.post("/dictionaries", req).success(function(data, status, headers, config) { var dictionaries = []; - if (angular.isArray(data.dictionaries)) { - angular.forEach(data.dictionaries, function(jsdict) { + if (_.isArray(data.dictionaries)) { + _.forEach(data.dictionaries, function(jsdict) { var dictionary = lingvodoc.Dictionary.fromJS(jsdict); if (language.client_id == dictionary.parent_client_id && language.object_id == dictionary.parent_object_id) { dictionaries.push(dictionary); @@ -28883,7 +32939,7 @@ function lingvodocAPI($http, $q) { } deferred.resolve(dictionaries); }).error(function(data, status, headers, config) { - deferred.reject("Failed to move lexical entry"); + deferred.reject("Failed to fetch list of dictionaries"); }); return deferred.promise; }; @@ -29066,10 +33122,140 @@ function lingvodocAPI($http, $q) { }); return deferred.promise; }; + var getUserBlobs = function() { + var deferred = $q.defer(); + $http.get("/blobs").success(function(data, status, headers, config) { + var blobs = _.map(data, lingvodoc.Blob.fromJS); + deferred.resolve(blobs); + }).error(function(data, status, headers, config) { + deferred.reject("Failed to fetch list of available blobs"); + }); + return deferred.promise; + }; + var checkDictionaryBlob = function(blob, parent) { + var deferred = $q.defer(); + var query = { + blob_client_id: blob.client_id, + blob_object_id: blob.object_id, + parent_client_id: parent.client_id, + parent_object_id: parent.object_id + }; + $http.post("/convert_check", query).success(function(data, status, headers, config) { + var perspectives = _.map(data, lingvodoc.Perspective.fromJS); + deferred.resolve(perspectives); + }).error(function(data, status, headers, config) { + deferred.reject("Failed to convert dictionary"); + }); + return deferred.promise; + }; + var convertDictionary = function(req) { + var deferred = $q.defer(); + $http.post("/convert", req).success(function(data, status, headers, config) { + deferred.resolve(data); + }).error(function(data, status, headers, config) { + deferred.reject("Failed to convert dictionary"); + }); + return deferred.promise; + }; + var getPerspectiveMeta = function(dictionary, perspective) { + var deferred = $q.defer(); + var url = "/dictionary/" + encodeURIComponent(dictionary.client_id) + "/" + encodeURIComponent(dictionary.object_id) + "/perspective/" + encodeURIComponent(perspective.client_id) + "/" + encodeURIComponent(perspective.object_id) + "/meta"; + $http.get(url).success(function(data, status, headers, config) { + deferred.resolve(data); + }).error(function(data, status, headers, config) { + deferred.reject("Failed to get perspective meta data!"); + }); + return deferred.promise; + }; + var setPerspectiveMeta = function(dictionary, perspective, meta) { + var deferred = $q.defer(); + var url = "/dictionary/" + encodeURIComponent(dictionary.client_id) + "/" + encodeURIComponent(dictionary.object_id) + "/perspective/" + encodeURIComponent(perspective.client_id) + "/" + encodeURIComponent(perspective.object_id) + "/meta"; + $http.put(url, meta).success(function(data, status, headers, config) { + deferred.resolve(data); + }).error(function(data, status, headers, config) { + deferred.reject("Failed to set perspective meta data!"); + }); + return deferred.promise; + }; + var removePerspectiveMeta = function(dictionary, perspective, meta) { + var deferred = $q.defer(); + var url = "/dictionary/" + encodeURIComponent(dictionary.client_id) + "/" + encodeURIComponent(dictionary.object_id) + "/perspective/" + encodeURIComponent(perspective.client_id) + "/" + encodeURIComponent(perspective.object_id) + "/meta"; + var config = { + method: "DELETE", + url: url, + data: meta, + headers: { + "Content-Type": "application/json;charset=utf-8" + } + }; + $http(config).success(function(data, status, headers, config) { + deferred.resolve(data); + }).error(function(data, status, headers, config) { + deferred.reject("Failed to remove perspective meta data!"); + }); + return deferred.promise; + }; + var advancedSearch = function(query, where, adopted, etymology) { + var deferred = $q.defer(); + var url = "/advanced_search"; + var perspectives = where.map(function(o) { + if (o.type == "perspective") { + return { + client_id: o.client_id, + object_id: o.object_id + }; + } + }).filter(function(o) { + return typeof o !== "undefined"; + }); + var req = { + searchstrings: query, + perspectives: perspectives + }; + if (_.isBoolean(adopted)) { + req.adopted = adopted; + } + if (_.isBoolean(etymology)) { + req.with_etimology = etymology; + } + $http.post(url, req).success(function(data, status, headers, config) { + var r = data.map(function(e) { + var perspective = lingvodoc.Perspective.fromJS(e); + return getPerspectiveOriginById(perspective.client_id, perspective.object_id); + }); + $q.all(r).then(function(paths) { + var out = []; + _.each(data, function(entry, i) { + entry.lexical_entry["origin"] = paths[i]; + out.push(entry.lexical_entry); + }); + deferred.resolve(out); + }, function(reason) { + deferred.reject("An error occurred while doing basic search"); + }); + }).error(function(data, status, headers, config) { + deferred.reject("An error occurred while doing advanced search"); + }); + return deferred.promise; + }; + var convertMarkup = function(object) { + var deferred = $q.defer(); + var obj = { + client_id: object.client_id, + object_id: object.object_id + }; + $http.post("/convert/markup", obj).success(function(data, status, headers, config) { + deferred.resolve(data); + }).error(function(data, status, headers, config) { + deferred.reject("Failed to convert markup!"); + }); + return deferred.promise; + }; return { getLexicalEntries: getLexicalEntries, getLexicalEntriesCount: getLexicalEntriesCount, getPerspectiveDictionaryFields: getPerspectiveDictionaryFields, + getPerspectiveDictionaryFieldsNew: getPerspectiveDictionaryFieldsNew, addNewLexicalEntry: addNewLexicalEntry, saveValue: saveValue, removeValue: removeValue, @@ -29080,6 +33266,7 @@ function lingvodocAPI($http, $q) { approveAll: approveAll, getDictionaryProperties: getDictionaryProperties, setDictionaryProperties: setDictionaryProperties, + removeDictionary: removeDictionary, getLanguages: getLanguages, setDictionaryStatus: setDictionaryStatus, setPerspectiveStatus: setPerspectiveStatus, @@ -29087,6 +33274,7 @@ function lingvodocAPI($http, $q) { getPerspectiveFields: getPerspectiveFields, setPerspectiveFields: setPerspectiveFields, getPerspectiveFieldsNew: getPerspectiveFieldsNew, + removePerspective: removePerspective, getUserInfo: getUserInfo, setUserInfo: setUserInfo, getOrganizations: getOrganizations, @@ -29113,7 +33301,15 @@ function lingvodocAPI($http, $q) { deleteDictionaryRoles: deleteDictionaryRoles, getPerspectiveRoles: getPerspectiveRoles, addPerspectiveRoles: addPerspectiveRoles, - deletePerspectiveRoles: deletePerspectiveRoles + deletePerspectiveRoles: deletePerspectiveRoles, + getUserBlobs: getUserBlobs, + checkDictionaryBlob: checkDictionaryBlob, + convertDictionary: convertDictionary, + getPerspectiveMeta: getPerspectiveMeta, + setPerspectiveMeta: setPerspectiveMeta, + removePerspectiveMeta: removePerspectiveMeta, + advancedSearch: advancedSearch, + convertMarkup: convertMarkup }; } @@ -29145,9 +33341,34 @@ function responseHandler($timeout, $modal) { function error(message) { show("error", message, 5e3); } + function yesno(status, message, callback) { + var controller = function($scope, $modalInstance) { + $scope.status = status; + $scope.message = message; + $scope.yes = function() { + $modalInstance.close(true); + }; + $scope.no = function() { + $modalInstance.close(false); + }; + }; + $modal.open({ + animation: true, + templateUrl: "responseHandlerYesNoModal.html", + controller: controller, + size: "lg", + backdrop: "static", + keyboard: false + }).result.then(function(result) { + callback(result); + }, function() { + callback(false); + }); + } return { success: success, - error: error + error: error, + yesno: yesno }; } diff --git a/lingvodoc/static/js/organizations.js b/lingvodoc/static/js/organizations.js index 31d579e91..f67608a55 100644 --- a/lingvodoc/static/js/organizations.js +++ b/lingvodoc/static/js/organizations.js @@ -5377,6 +5377,3947 @@ return jQuery; }); +(function() { + var undefined; + var VERSION = "3.10.1"; + var BIND_FLAG = 1, BIND_KEY_FLAG = 2, CURRY_BOUND_FLAG = 4, CURRY_FLAG = 8, CURRY_RIGHT_FLAG = 16, PARTIAL_FLAG = 32, PARTIAL_RIGHT_FLAG = 64, ARY_FLAG = 128, REARG_FLAG = 256; + var DEFAULT_TRUNC_LENGTH = 30, DEFAULT_TRUNC_OMISSION = "..."; + var HOT_COUNT = 150, HOT_SPAN = 16; + var LARGE_ARRAY_SIZE = 200; + var LAZY_FILTER_FLAG = 1, LAZY_MAP_FLAG = 2; + var FUNC_ERROR_TEXT = "Expected a function"; + var PLACEHOLDER = "__lodash_placeholder__"; + var argsTag = "[object Arguments]", arrayTag = "[object Array]", boolTag = "[object Boolean]", dateTag = "[object Date]", errorTag = "[object Error]", funcTag = "[object Function]", mapTag = "[object Map]", numberTag = "[object Number]", objectTag = "[object Object]", regexpTag = "[object RegExp]", setTag = "[object Set]", stringTag = "[object String]", weakMapTag = "[object WeakMap]"; + var arrayBufferTag = "[object ArrayBuffer]", float32Tag = "[object Float32Array]", float64Tag = "[object Float64Array]", int8Tag = "[object Int8Array]", int16Tag = "[object Int16Array]", int32Tag = "[object Int32Array]", uint8Tag = "[object Uint8Array]", uint8ClampedTag = "[object Uint8ClampedArray]", uint16Tag = "[object Uint16Array]", uint32Tag = "[object Uint32Array]"; + var reEmptyStringLeading = /\b__p \+= '';/g, reEmptyStringMiddle = /\b(__p \+=) '' \+/g, reEmptyStringTrailing = /(__e\(.*?\)|\b__t\)) \+\n'';/g; + var reEscapedHtml = /&(?:amp|lt|gt|quot|#39|#96);/g, reUnescapedHtml = /[&<>"'`]/g, reHasEscapedHtml = RegExp(reEscapedHtml.source), reHasUnescapedHtml = RegExp(reUnescapedHtml.source); + var reEscape = /<%-([\s\S]+?)%>/g, reEvaluate = /<%([\s\S]+?)%>/g, reInterpolate = /<%=([\s\S]+?)%>/g; + var reIsDeepProp = /\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\n\\]|\\.)*?\1)\]/, reIsPlainProp = /^\w*$/, rePropName = /[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\n\\]|\\.)*?)\2)\]/g; + var reRegExpChars = /^[:!,]|[\\^$.*+?()[\]{}|\/]|(^[0-9a-fA-Fnrtuvx])|([\n\r\u2028\u2029])/g, reHasRegExpChars = RegExp(reRegExpChars.source); + var reComboMark = /[\u0300-\u036f\ufe20-\ufe23]/g; + var reEscapeChar = /\\(\\)?/g; + var reEsTemplate = /\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g; + var reFlags = /\w*$/; + var reHasHexPrefix = /^0[xX]/; + var reIsHostCtor = /^\[object .+?Constructor\]$/; + var reIsUint = /^\d+$/; + var reLatin1 = /[\xc0-\xd6\xd8-\xde\xdf-\xf6\xf8-\xff]/g; + var reNoMatch = /($^)/; + var reUnescapedString = /['\n\r\u2028\u2029\\]/g; + var reWords = function() { + var upper = "[A-Z\\xc0-\\xd6\\xd8-\\xde]", lower = "[a-z\\xdf-\\xf6\\xf8-\\xff]+"; + return RegExp(upper + "+(?=" + upper + lower + ")|" + upper + "?" + lower + "|" + upper + "+|[0-9]+", "g"); + }(); + var contextProps = [ "Array", "ArrayBuffer", "Date", "Error", "Float32Array", "Float64Array", "Function", "Int8Array", "Int16Array", "Int32Array", "Math", "Number", "Object", "RegExp", "Set", "String", "_", "clearTimeout", "isFinite", "parseFloat", "parseInt", "setTimeout", "TypeError", "Uint8Array", "Uint8ClampedArray", "Uint16Array", "Uint32Array", "WeakMap" ]; + var templateCounter = -1; + var typedArrayTags = {}; + typedArrayTags[float32Tag] = typedArrayTags[float64Tag] = typedArrayTags[int8Tag] = typedArrayTags[int16Tag] = typedArrayTags[int32Tag] = typedArrayTags[uint8Tag] = typedArrayTags[uint8ClampedTag] = typedArrayTags[uint16Tag] = typedArrayTags[uint32Tag] = true; + typedArrayTags[argsTag] = typedArrayTags[arrayTag] = typedArrayTags[arrayBufferTag] = typedArrayTags[boolTag] = typedArrayTags[dateTag] = typedArrayTags[errorTag] = typedArrayTags[funcTag] = typedArrayTags[mapTag] = typedArrayTags[numberTag] = typedArrayTags[objectTag] = typedArrayTags[regexpTag] = typedArrayTags[setTag] = typedArrayTags[stringTag] = typedArrayTags[weakMapTag] = false; + var cloneableTags = {}; + cloneableTags[argsTag] = cloneableTags[arrayTag] = cloneableTags[arrayBufferTag] = cloneableTags[boolTag] = cloneableTags[dateTag] = cloneableTags[float32Tag] = cloneableTags[float64Tag] = cloneableTags[int8Tag] = cloneableTags[int16Tag] = cloneableTags[int32Tag] = cloneableTags[numberTag] = cloneableTags[objectTag] = cloneableTags[regexpTag] = cloneableTags[stringTag] = cloneableTags[uint8Tag] = cloneableTags[uint8ClampedTag] = cloneableTags[uint16Tag] = cloneableTags[uint32Tag] = true; + cloneableTags[errorTag] = cloneableTags[funcTag] = cloneableTags[mapTag] = cloneableTags[setTag] = cloneableTags[weakMapTag] = false; + var deburredLetters = { + "À": "A", + "Á": "A", + "Â": "A", + "Ã": "A", + "Ä": "A", + "Å": "A", + "à": "a", + "á": "a", + "â": "a", + "ã": "a", + "ä": "a", + "å": "a", + "Ç": "C", + "ç": "c", + "Ð": "D", + "ð": "d", + "È": "E", + "É": "E", + "Ê": "E", + "Ë": "E", + "è": "e", + "é": "e", + "ê": "e", + "ë": "e", + "Ì": "I", + "Í": "I", + "Î": "I", + "Ï": "I", + "ì": "i", + "í": "i", + "î": "i", + "ï": "i", + "Ñ": "N", + "ñ": "n", + "Ò": "O", + "Ó": "O", + "Ô": "O", + "Õ": "O", + "Ö": "O", + "Ø": "O", + "ò": "o", + "ó": "o", + "ô": "o", + "õ": "o", + "ö": "o", + "ø": "o", + "Ù": "U", + "Ú": "U", + "Û": "U", + "Ü": "U", + "ù": "u", + "ú": "u", + "û": "u", + "ü": "u", + "Ý": "Y", + "ý": "y", + "ÿ": "y", + "Æ": "Ae", + "æ": "ae", + "Þ": "Th", + "þ": "th", + "ß": "ss" + }; + var htmlEscapes = { + "&": "&", + "<": "<", + ">": ">", + '"': """, + "'": "'", + "`": "`" + }; + var htmlUnescapes = { + "&": "&", + "<": "<", + ">": ">", + """: '"', + "'": "'", + "`": "`" + }; + var objectTypes = { + "function": true, + object: true + }; + var regexpEscapes = { + "0": "x30", + "1": "x31", + "2": "x32", + "3": "x33", + "4": "x34", + "5": "x35", + "6": "x36", + "7": "x37", + "8": "x38", + "9": "x39", + A: "x41", + B: "x42", + C: "x43", + D: "x44", + E: "x45", + F: "x46", + a: "x61", + b: "x62", + c: "x63", + d: "x64", + e: "x65", + f: "x66", + n: "x6e", + r: "x72", + t: "x74", + u: "x75", + v: "x76", + x: "x78" + }; + var stringEscapes = { + "\\": "\\", + "'": "'", + "\n": "n", + "\r": "r", + "\u2028": "u2028", + "\u2029": "u2029" + }; + var freeExports = objectTypes[typeof exports] && exports && !exports.nodeType && exports; + var freeModule = objectTypes[typeof module] && module && !module.nodeType && module; + var freeGlobal = freeExports && freeModule && typeof global == "object" && global && global.Object && global; + var freeSelf = objectTypes[typeof self] && self && self.Object && self; + var freeWindow = objectTypes[typeof window] && window && window.Object && window; + var moduleExports = freeModule && freeModule.exports === freeExports && freeExports; + var root = freeGlobal || freeWindow !== (this && this.window) && freeWindow || freeSelf || this; + function baseCompareAscending(value, other) { + if (value !== other) { + var valIsNull = value === null, valIsUndef = value === undefined, valIsReflexive = value === value; + var othIsNull = other === null, othIsUndef = other === undefined, othIsReflexive = other === other; + if (value > other && !othIsNull || !valIsReflexive || valIsNull && !othIsUndef && othIsReflexive || valIsUndef && othIsReflexive) { + return 1; + } + if (value < other && !valIsNull || !othIsReflexive || othIsNull && !valIsUndef && valIsReflexive || othIsUndef && valIsReflexive) { + return -1; + } + } + return 0; + } + function baseFindIndex(array, predicate, fromRight) { + var length = array.length, index = fromRight ? length : -1; + while (fromRight ? index-- : ++index < length) { + if (predicate(array[index], index, array)) { + return index; + } + } + return -1; + } + function baseIndexOf(array, value, fromIndex) { + if (value !== value) { + return indexOfNaN(array, fromIndex); + } + var index = fromIndex - 1, length = array.length; + while (++index < length) { + if (array[index] === value) { + return index; + } + } + return -1; + } + function baseIsFunction(value) { + return typeof value == "function" || false; + } + function baseToString(value) { + return value == null ? "" : value + ""; + } + function charsLeftIndex(string, chars) { + var index = -1, length = string.length; + while (++index < length && chars.indexOf(string.charAt(index)) > -1) {} + return index; + } + function charsRightIndex(string, chars) { + var index = string.length; + while (index-- && chars.indexOf(string.charAt(index)) > -1) {} + return index; + } + function compareAscending(object, other) { + return baseCompareAscending(object.criteria, other.criteria) || object.index - other.index; + } + function compareMultiple(object, other, orders) { + var index = -1, objCriteria = object.criteria, othCriteria = other.criteria, length = objCriteria.length, ordersLength = orders.length; + while (++index < length) { + var result = baseCompareAscending(objCriteria[index], othCriteria[index]); + if (result) { + if (index >= ordersLength) { + return result; + } + var order = orders[index]; + return result * (order === "asc" || order === true ? 1 : -1); + } + } + return object.index - other.index; + } + function deburrLetter(letter) { + return deburredLetters[letter]; + } + function escapeHtmlChar(chr) { + return htmlEscapes[chr]; + } + function escapeRegExpChar(chr, leadingChar, whitespaceChar) { + if (leadingChar) { + chr = regexpEscapes[chr]; + } else if (whitespaceChar) { + chr = stringEscapes[chr]; + } + return "\\" + chr; + } + function escapeStringChar(chr) { + return "\\" + stringEscapes[chr]; + } + function indexOfNaN(array, fromIndex, fromRight) { + var length = array.length, index = fromIndex + (fromRight ? 0 : -1); + while (fromRight ? index-- : ++index < length) { + var other = array[index]; + if (other !== other) { + return index; + } + } + return -1; + } + function isObjectLike(value) { + return !!value && typeof value == "object"; + } + function isSpace(charCode) { + return charCode <= 160 && (charCode >= 9 && charCode <= 13) || charCode == 32 || charCode == 160 || charCode == 5760 || charCode == 6158 || charCode >= 8192 && (charCode <= 8202 || charCode == 8232 || charCode == 8233 || charCode == 8239 || charCode == 8287 || charCode == 12288 || charCode == 65279); + } + function replaceHolders(array, placeholder) { + var index = -1, length = array.length, resIndex = -1, result = []; + while (++index < length) { + if (array[index] === placeholder) { + array[index] = PLACEHOLDER; + result[++resIndex] = index; + } + } + return result; + } + function sortedUniq(array, iteratee) { + var seen, index = -1, length = array.length, resIndex = -1, result = []; + while (++index < length) { + var value = array[index], computed = iteratee ? iteratee(value, index, array) : value; + if (!index || seen !== computed) { + seen = computed; + result[++resIndex] = value; + } + } + return result; + } + function trimmedLeftIndex(string) { + var index = -1, length = string.length; + while (++index < length && isSpace(string.charCodeAt(index))) {} + return index; + } + function trimmedRightIndex(string) { + var index = string.length; + while (index-- && isSpace(string.charCodeAt(index))) {} + return index; + } + function unescapeHtmlChar(chr) { + return htmlUnescapes[chr]; + } + function runInContext(context) { + context = context ? _.defaults(root.Object(), context, _.pick(root, contextProps)) : root; + var Array = context.Array, Date = context.Date, Error = context.Error, Function = context.Function, Math = context.Math, Number = context.Number, Object = context.Object, RegExp = context.RegExp, String = context.String, TypeError = context.TypeError; + var arrayProto = Array.prototype, objectProto = Object.prototype, stringProto = String.prototype; + var fnToString = Function.prototype.toString; + var hasOwnProperty = objectProto.hasOwnProperty; + var idCounter = 0; + var objToString = objectProto.toString; + var oldDash = root._; + var reIsNative = RegExp("^" + fnToString.call(hasOwnProperty).replace(/[\\^$.*+?()[\]{}|]/g, "\\$&").replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g, "$1.*?") + "$"); + var ArrayBuffer = context.ArrayBuffer, clearTimeout = context.clearTimeout, parseFloat = context.parseFloat, pow = Math.pow, propertyIsEnumerable = objectProto.propertyIsEnumerable, Set = getNative(context, "Set"), setTimeout = context.setTimeout, splice = arrayProto.splice, Uint8Array = context.Uint8Array, WeakMap = getNative(context, "WeakMap"); + var nativeCeil = Math.ceil, nativeCreate = getNative(Object, "create"), nativeFloor = Math.floor, nativeIsArray = getNative(Array, "isArray"), nativeIsFinite = context.isFinite, nativeKeys = getNative(Object, "keys"), nativeMax = Math.max, nativeMin = Math.min, nativeNow = getNative(Date, "now"), nativeParseInt = context.parseInt, nativeRandom = Math.random; + var NEGATIVE_INFINITY = Number.NEGATIVE_INFINITY, POSITIVE_INFINITY = Number.POSITIVE_INFINITY; + var MAX_ARRAY_LENGTH = 4294967295, MAX_ARRAY_INDEX = MAX_ARRAY_LENGTH - 1, HALF_MAX_ARRAY_LENGTH = MAX_ARRAY_LENGTH >>> 1; + var MAX_SAFE_INTEGER = 9007199254740991; + var metaMap = WeakMap && new WeakMap(); + var realNames = {}; + function lodash(value) { + if (isObjectLike(value) && !isArray(value) && !(value instanceof LazyWrapper)) { + if (value instanceof LodashWrapper) { + return value; + } + if (hasOwnProperty.call(value, "__chain__") && hasOwnProperty.call(value, "__wrapped__")) { + return wrapperClone(value); + } + } + return new LodashWrapper(value); + } + function baseLodash() {} + function LodashWrapper(value, chainAll, actions) { + this.__wrapped__ = value; + this.__actions__ = actions || []; + this.__chain__ = !!chainAll; + } + var support = lodash.support = {}; + lodash.templateSettings = { + escape: reEscape, + evaluate: reEvaluate, + interpolate: reInterpolate, + variable: "", + imports: { + _: lodash + } + }; + function LazyWrapper(value) { + this.__wrapped__ = value; + this.__actions__ = []; + this.__dir__ = 1; + this.__filtered__ = false; + this.__iteratees__ = []; + this.__takeCount__ = POSITIVE_INFINITY; + this.__views__ = []; + } + function lazyClone() { + var result = new LazyWrapper(this.__wrapped__); + result.__actions__ = arrayCopy(this.__actions__); + result.__dir__ = this.__dir__; + result.__filtered__ = this.__filtered__; + result.__iteratees__ = arrayCopy(this.__iteratees__); + result.__takeCount__ = this.__takeCount__; + result.__views__ = arrayCopy(this.__views__); + return result; + } + function lazyReverse() { + if (this.__filtered__) { + var result = new LazyWrapper(this); + result.__dir__ = -1; + result.__filtered__ = true; + } else { + result = this.clone(); + result.__dir__ *= -1; + } + return result; + } + function lazyValue() { + var array = this.__wrapped__.value(), dir = this.__dir__, isArr = isArray(array), isRight = dir < 0, arrLength = isArr ? array.length : 0, view = getView(0, arrLength, this.__views__), start = view.start, end = view.end, length = end - start, index = isRight ? end : start - 1, iteratees = this.__iteratees__, iterLength = iteratees.length, resIndex = 0, takeCount = nativeMin(length, this.__takeCount__); + if (!isArr || arrLength < LARGE_ARRAY_SIZE || arrLength == length && takeCount == length) { + return baseWrapperValue(array, this.__actions__); + } + var result = []; + outer: while (length-- && resIndex < takeCount) { + index += dir; + var iterIndex = -1, value = array[index]; + while (++iterIndex < iterLength) { + var data = iteratees[iterIndex], iteratee = data.iteratee, type = data.type, computed = iteratee(value); + if (type == LAZY_MAP_FLAG) { + value = computed; + } else if (!computed) { + if (type == LAZY_FILTER_FLAG) { + continue outer; + } else { + break outer; + } + } + } + result[resIndex++] = value; + } + return result; + } + function MapCache() { + this.__data__ = {}; + } + function mapDelete(key) { + return this.has(key) && delete this.__data__[key]; + } + function mapGet(key) { + return key == "__proto__" ? undefined : this.__data__[key]; + } + function mapHas(key) { + return key != "__proto__" && hasOwnProperty.call(this.__data__, key); + } + function mapSet(key, value) { + if (key != "__proto__") { + this.__data__[key] = value; + } + return this; + } + function SetCache(values) { + var length = values ? values.length : 0; + this.data = { + hash: nativeCreate(null), + set: new Set() + }; + while (length--) { + this.push(values[length]); + } + } + function cacheIndexOf(cache, value) { + var data = cache.data, result = typeof value == "string" || isObject(value) ? data.set.has(value) : data.hash[value]; + return result ? 0 : -1; + } + function cachePush(value) { + var data = this.data; + if (typeof value == "string" || isObject(value)) { + data.set.add(value); + } else { + data.hash[value] = true; + } + } + function arrayConcat(array, other) { + var index = -1, length = array.length, othIndex = -1, othLength = other.length, result = Array(length + othLength); + while (++index < length) { + result[index] = array[index]; + } + while (++othIndex < othLength) { + result[index++] = other[othIndex]; + } + return result; + } + function arrayCopy(source, array) { + var index = -1, length = source.length; + array || (array = Array(length)); + while (++index < length) { + array[index] = source[index]; + } + return array; + } + function arrayEach(array, iteratee) { + var index = -1, length = array.length; + while (++index < length) { + if (iteratee(array[index], index, array) === false) { + break; + } + } + return array; + } + function arrayEachRight(array, iteratee) { + var length = array.length; + while (length--) { + if (iteratee(array[length], length, array) === false) { + break; + } + } + return array; + } + function arrayEvery(array, predicate) { + var index = -1, length = array.length; + while (++index < length) { + if (!predicate(array[index], index, array)) { + return false; + } + } + return true; + } + function arrayExtremum(array, iteratee, comparator, exValue) { + var index = -1, length = array.length, computed = exValue, result = computed; + while (++index < length) { + var value = array[index], current = +iteratee(value); + if (comparator(current, computed)) { + computed = current; + result = value; + } + } + return result; + } + function arrayFilter(array, predicate) { + var index = -1, length = array.length, resIndex = -1, result = []; + while (++index < length) { + var value = array[index]; + if (predicate(value, index, array)) { + result[++resIndex] = value; + } + } + return result; + } + function arrayMap(array, iteratee) { + var index = -1, length = array.length, result = Array(length); + while (++index < length) { + result[index] = iteratee(array[index], index, array); + } + return result; + } + function arrayPush(array, values) { + var index = -1, length = values.length, offset = array.length; + while (++index < length) { + array[offset + index] = values[index]; + } + return array; + } + function arrayReduce(array, iteratee, accumulator, initFromArray) { + var index = -1, length = array.length; + if (initFromArray && length) { + accumulator = array[++index]; + } + while (++index < length) { + accumulator = iteratee(accumulator, array[index], index, array); + } + return accumulator; + } + function arrayReduceRight(array, iteratee, accumulator, initFromArray) { + var length = array.length; + if (initFromArray && length) { + accumulator = array[--length]; + } + while (length--) { + accumulator = iteratee(accumulator, array[length], length, array); + } + return accumulator; + } + function arraySome(array, predicate) { + var index = -1, length = array.length; + while (++index < length) { + if (predicate(array[index], index, array)) { + return true; + } + } + return false; + } + function arraySum(array, iteratee) { + var length = array.length, result = 0; + while (length--) { + result += +iteratee(array[length]) || 0; + } + return result; + } + function assignDefaults(objectValue, sourceValue) { + return objectValue === undefined ? sourceValue : objectValue; + } + function assignOwnDefaults(objectValue, sourceValue, key, object) { + return objectValue === undefined || !hasOwnProperty.call(object, key) ? sourceValue : objectValue; + } + function assignWith(object, source, customizer) { + var index = -1, props = keys(source), length = props.length; + while (++index < length) { + var key = props[index], value = object[key], result = customizer(value, source[key], key, object, source); + if ((result === result ? result !== value : value === value) || value === undefined && !(key in object)) { + object[key] = result; + } + } + return object; + } + function baseAssign(object, source) { + return source == null ? object : baseCopy(source, keys(source), object); + } + function baseAt(collection, props) { + var index = -1, isNil = collection == null, isArr = !isNil && isArrayLike(collection), length = isArr ? collection.length : 0, propsLength = props.length, result = Array(propsLength); + while (++index < propsLength) { + var key = props[index]; + if (isArr) { + result[index] = isIndex(key, length) ? collection[key] : undefined; + } else { + result[index] = isNil ? undefined : collection[key]; + } + } + return result; + } + function baseCopy(source, props, object) { + object || (object = {}); + var index = -1, length = props.length; + while (++index < length) { + var key = props[index]; + object[key] = source[key]; + } + return object; + } + function baseCallback(func, thisArg, argCount) { + var type = typeof func; + if (type == "function") { + return thisArg === undefined ? func : bindCallback(func, thisArg, argCount); + } + if (func == null) { + return identity; + } + if (type == "object") { + return baseMatches(func); + } + return thisArg === undefined ? property(func) : baseMatchesProperty(func, thisArg); + } + function baseClone(value, isDeep, customizer, key, object, stackA, stackB) { + var result; + if (customizer) { + result = object ? customizer(value, key, object) : customizer(value); + } + if (result !== undefined) { + return result; + } + if (!isObject(value)) { + return value; + } + var isArr = isArray(value); + if (isArr) { + result = initCloneArray(value); + if (!isDeep) { + return arrayCopy(value, result); + } + } else { + var tag = objToString.call(value), isFunc = tag == funcTag; + if (tag == objectTag || tag == argsTag || isFunc && !object) { + result = initCloneObject(isFunc ? {} : value); + if (!isDeep) { + return baseAssign(result, value); + } + } else { + return cloneableTags[tag] ? initCloneByTag(value, tag, isDeep) : object ? value : {}; + } + } + stackA || (stackA = []); + stackB || (stackB = []); + var length = stackA.length; + while (length--) { + if (stackA[length] == value) { + return stackB[length]; + } + } + stackA.push(value); + stackB.push(result); + (isArr ? arrayEach : baseForOwn)(value, function(subValue, key) { + result[key] = baseClone(subValue, isDeep, customizer, key, value, stackA, stackB); + }); + return result; + } + var baseCreate = function() { + function object() {} + return function(prototype) { + if (isObject(prototype)) { + object.prototype = prototype; + var result = new object(); + object.prototype = undefined; + } + return result || {}; + }; + }(); + function baseDelay(func, wait, args) { + if (typeof func != "function") { + throw new TypeError(FUNC_ERROR_TEXT); + } + return setTimeout(function() { + func.apply(undefined, args); + }, wait); + } + function baseDifference(array, values) { + var length = array ? array.length : 0, result = []; + if (!length) { + return result; + } + var index = -1, indexOf = getIndexOf(), isCommon = indexOf === baseIndexOf, cache = isCommon && values.length >= LARGE_ARRAY_SIZE ? createCache(values) : null, valuesLength = values.length; + if (cache) { + indexOf = cacheIndexOf; + isCommon = false; + values = cache; + } + outer: while (++index < length) { + var value = array[index]; + if (isCommon && value === value) { + var valuesIndex = valuesLength; + while (valuesIndex--) { + if (values[valuesIndex] === value) { + continue outer; + } + } + result.push(value); + } else if (indexOf(values, value, 0) < 0) { + result.push(value); + } + } + return result; + } + var baseEach = createBaseEach(baseForOwn); + var baseEachRight = createBaseEach(baseForOwnRight, true); + function baseEvery(collection, predicate) { + var result = true; + baseEach(collection, function(value, index, collection) { + result = !!predicate(value, index, collection); + return result; + }); + return result; + } + function baseExtremum(collection, iteratee, comparator, exValue) { + var computed = exValue, result = computed; + baseEach(collection, function(value, index, collection) { + var current = +iteratee(value, index, collection); + if (comparator(current, computed) || current === exValue && current === result) { + computed = current; + result = value; + } + }); + return result; + } + function baseFill(array, value, start, end) { + var length = array.length; + start = start == null ? 0 : +start || 0; + if (start < 0) { + start = -start > length ? 0 : length + start; + } + end = end === undefined || end > length ? length : +end || 0; + if (end < 0) { + end += length; + } + length = start > end ? 0 : end >>> 0; + start >>>= 0; + while (start < length) { + array[start++] = value; + } + return array; + } + function baseFilter(collection, predicate) { + var result = []; + baseEach(collection, function(value, index, collection) { + if (predicate(value, index, collection)) { + result.push(value); + } + }); + return result; + } + function baseFind(collection, predicate, eachFunc, retKey) { + var result; + eachFunc(collection, function(value, key, collection) { + if (predicate(value, key, collection)) { + result = retKey ? key : value; + return false; + } + }); + return result; + } + function baseFlatten(array, isDeep, isStrict, result) { + result || (result = []); + var index = -1, length = array.length; + while (++index < length) { + var value = array[index]; + if (isObjectLike(value) && isArrayLike(value) && (isStrict || isArray(value) || isArguments(value))) { + if (isDeep) { + baseFlatten(value, isDeep, isStrict, result); + } else { + arrayPush(result, value); + } + } else if (!isStrict) { + result[result.length] = value; + } + } + return result; + } + var baseFor = createBaseFor(); + var baseForRight = createBaseFor(true); + function baseForIn(object, iteratee) { + return baseFor(object, iteratee, keysIn); + } + function baseForOwn(object, iteratee) { + return baseFor(object, iteratee, keys); + } + function baseForOwnRight(object, iteratee) { + return baseForRight(object, iteratee, keys); + } + function baseFunctions(object, props) { + var index = -1, length = props.length, resIndex = -1, result = []; + while (++index < length) { + var key = props[index]; + if (isFunction(object[key])) { + result[++resIndex] = key; + } + } + return result; + } + function baseGet(object, path, pathKey) { + if (object == null) { + return; + } + if (pathKey !== undefined && pathKey in toObject(object)) { + path = [ pathKey ]; + } + var index = 0, length = path.length; + while (object != null && index < length) { + object = object[path[index++]]; + } + return index && index == length ? object : undefined; + } + function baseIsEqual(value, other, customizer, isLoose, stackA, stackB) { + if (value === other) { + return true; + } + if (value == null || other == null || !isObject(value) && !isObjectLike(other)) { + return value !== value && other !== other; + } + return baseIsEqualDeep(value, other, baseIsEqual, customizer, isLoose, stackA, stackB); + } + function baseIsEqualDeep(object, other, equalFunc, customizer, isLoose, stackA, stackB) { + var objIsArr = isArray(object), othIsArr = isArray(other), objTag = arrayTag, othTag = arrayTag; + if (!objIsArr) { + objTag = objToString.call(object); + if (objTag == argsTag) { + objTag = objectTag; + } else if (objTag != objectTag) { + objIsArr = isTypedArray(object); + } + } + if (!othIsArr) { + othTag = objToString.call(other); + if (othTag == argsTag) { + othTag = objectTag; + } else if (othTag != objectTag) { + othIsArr = isTypedArray(other); + } + } + var objIsObj = objTag == objectTag, othIsObj = othTag == objectTag, isSameTag = objTag == othTag; + if (isSameTag && !(objIsArr || objIsObj)) { + return equalByTag(object, other, objTag); + } + if (!isLoose) { + var objIsWrapped = objIsObj && hasOwnProperty.call(object, "__wrapped__"), othIsWrapped = othIsObj && hasOwnProperty.call(other, "__wrapped__"); + if (objIsWrapped || othIsWrapped) { + return equalFunc(objIsWrapped ? object.value() : object, othIsWrapped ? other.value() : other, customizer, isLoose, stackA, stackB); + } + } + if (!isSameTag) { + return false; + } + stackA || (stackA = []); + stackB || (stackB = []); + var length = stackA.length; + while (length--) { + if (stackA[length] == object) { + return stackB[length] == other; + } + } + stackA.push(object); + stackB.push(other); + var result = (objIsArr ? equalArrays : equalObjects)(object, other, equalFunc, customizer, isLoose, stackA, stackB); + stackA.pop(); + stackB.pop(); + return result; + } + function baseIsMatch(object, matchData, customizer) { + var index = matchData.length, length = index, noCustomizer = !customizer; + if (object == null) { + return !length; + } + object = toObject(object); + while (index--) { + var data = matchData[index]; + if (noCustomizer && data[2] ? data[1] !== object[data[0]] : !(data[0] in object)) { + return false; + } + } + while (++index < length) { + data = matchData[index]; + var key = data[0], objValue = object[key], srcValue = data[1]; + if (noCustomizer && data[2]) { + if (objValue === undefined && !(key in object)) { + return false; + } + } else { + var result = customizer ? customizer(objValue, srcValue, key) : undefined; + if (!(result === undefined ? baseIsEqual(srcValue, objValue, customizer, true) : result)) { + return false; + } + } + } + return true; + } + function baseMap(collection, iteratee) { + var index = -1, result = isArrayLike(collection) ? Array(collection.length) : []; + baseEach(collection, function(value, key, collection) { + result[++index] = iteratee(value, key, collection); + }); + return result; + } + function baseMatches(source) { + var matchData = getMatchData(source); + if (matchData.length == 1 && matchData[0][2]) { + var key = matchData[0][0], value = matchData[0][1]; + return function(object) { + if (object == null) { + return false; + } + return object[key] === value && (value !== undefined || key in toObject(object)); + }; + } + return function(object) { + return baseIsMatch(object, matchData); + }; + } + function baseMatchesProperty(path, srcValue) { + var isArr = isArray(path), isCommon = isKey(path) && isStrictComparable(srcValue), pathKey = path + ""; + path = toPath(path); + return function(object) { + if (object == null) { + return false; + } + var key = pathKey; + object = toObject(object); + if ((isArr || !isCommon) && !(key in object)) { + object = path.length == 1 ? object : baseGet(object, baseSlice(path, 0, -1)); + if (object == null) { + return false; + } + key = last(path); + object = toObject(object); + } + return object[key] === srcValue ? srcValue !== undefined || key in object : baseIsEqual(srcValue, object[key], undefined, true); + }; + } + function baseMerge(object, source, customizer, stackA, stackB) { + if (!isObject(object)) { + return object; + } + var isSrcArr = isArrayLike(source) && (isArray(source) || isTypedArray(source)), props = isSrcArr ? undefined : keys(source); + arrayEach(props || source, function(srcValue, key) { + if (props) { + key = srcValue; + srcValue = source[key]; + } + if (isObjectLike(srcValue)) { + stackA || (stackA = []); + stackB || (stackB = []); + baseMergeDeep(object, source, key, baseMerge, customizer, stackA, stackB); + } else { + var value = object[key], result = customizer ? customizer(value, srcValue, key, object, source) : undefined, isCommon = result === undefined; + if (isCommon) { + result = srcValue; + } + if ((result !== undefined || isSrcArr && !(key in object)) && (isCommon || (result === result ? result !== value : value === value))) { + object[key] = result; + } + } + }); + return object; + } + function baseMergeDeep(object, source, key, mergeFunc, customizer, stackA, stackB) { + var length = stackA.length, srcValue = source[key]; + while (length--) { + if (stackA[length] == srcValue) { + object[key] = stackB[length]; + return; + } + } + var value = object[key], result = customizer ? customizer(value, srcValue, key, object, source) : undefined, isCommon = result === undefined; + if (isCommon) { + result = srcValue; + if (isArrayLike(srcValue) && (isArray(srcValue) || isTypedArray(srcValue))) { + result = isArray(value) ? value : isArrayLike(value) ? arrayCopy(value) : []; + } else if (isPlainObject(srcValue) || isArguments(srcValue)) { + result = isArguments(value) ? toPlainObject(value) : isPlainObject(value) ? value : {}; + } else { + isCommon = false; + } + } + stackA.push(srcValue); + stackB.push(result); + if (isCommon) { + object[key] = mergeFunc(result, srcValue, customizer, stackA, stackB); + } else if (result === result ? result !== value : value === value) { + object[key] = result; + } + } + function baseProperty(key) { + return function(object) { + return object == null ? undefined : object[key]; + }; + } + function basePropertyDeep(path) { + var pathKey = path + ""; + path = toPath(path); + return function(object) { + return baseGet(object, path, pathKey); + }; + } + function basePullAt(array, indexes) { + var length = array ? indexes.length : 0; + while (length--) { + var index = indexes[length]; + if (index != previous && isIndex(index)) { + var previous = index; + splice.call(array, index, 1); + } + } + return array; + } + function baseRandom(min, max) { + return min + nativeFloor(nativeRandom() * (max - min + 1)); + } + function baseReduce(collection, iteratee, accumulator, initFromCollection, eachFunc) { + eachFunc(collection, function(value, index, collection) { + accumulator = initFromCollection ? (initFromCollection = false, value) : iteratee(accumulator, value, index, collection); + }); + return accumulator; + } + var baseSetData = !metaMap ? identity : function(func, data) { + metaMap.set(func, data); + return func; + }; + function baseSlice(array, start, end) { + var index = -1, length = array.length; + start = start == null ? 0 : +start || 0; + if (start < 0) { + start = -start > length ? 0 : length + start; + } + end = end === undefined || end > length ? length : +end || 0; + if (end < 0) { + end += length; + } + length = start > end ? 0 : end - start >>> 0; + start >>>= 0; + var result = Array(length); + while (++index < length) { + result[index] = array[index + start]; + } + return result; + } + function baseSome(collection, predicate) { + var result; + baseEach(collection, function(value, index, collection) { + result = predicate(value, index, collection); + return !result; + }); + return !!result; + } + function baseSortBy(array, comparer) { + var length = array.length; + array.sort(comparer); + while (length--) { + array[length] = array[length].value; + } + return array; + } + function baseSortByOrder(collection, iteratees, orders) { + var callback = getCallback(), index = -1; + iteratees = arrayMap(iteratees, function(iteratee) { + return callback(iteratee); + }); + var result = baseMap(collection, function(value) { + var criteria = arrayMap(iteratees, function(iteratee) { + return iteratee(value); + }); + return { + criteria: criteria, + index: ++index, + value: value + }; + }); + return baseSortBy(result, function(object, other) { + return compareMultiple(object, other, orders); + }); + } + function baseSum(collection, iteratee) { + var result = 0; + baseEach(collection, function(value, index, collection) { + result += +iteratee(value, index, collection) || 0; + }); + return result; + } + function baseUniq(array, iteratee) { + var index = -1, indexOf = getIndexOf(), length = array.length, isCommon = indexOf === baseIndexOf, isLarge = isCommon && length >= LARGE_ARRAY_SIZE, seen = isLarge ? createCache() : null, result = []; + if (seen) { + indexOf = cacheIndexOf; + isCommon = false; + } else { + isLarge = false; + seen = iteratee ? [] : result; + } + outer: while (++index < length) { + var value = array[index], computed = iteratee ? iteratee(value, index, array) : value; + if (isCommon && value === value) { + var seenIndex = seen.length; + while (seenIndex--) { + if (seen[seenIndex] === computed) { + continue outer; + } + } + if (iteratee) { + seen.push(computed); + } + result.push(value); + } else if (indexOf(seen, computed, 0) < 0) { + if (iteratee || isLarge) { + seen.push(computed); + } + result.push(value); + } + } + return result; + } + function baseValues(object, props) { + var index = -1, length = props.length, result = Array(length); + while (++index < length) { + result[index] = object[props[index]]; + } + return result; + } + function baseWhile(array, predicate, isDrop, fromRight) { + var length = array.length, index = fromRight ? length : -1; + while ((fromRight ? index-- : ++index < length) && predicate(array[index], index, array)) {} + return isDrop ? baseSlice(array, fromRight ? 0 : index, fromRight ? index + 1 : length) : baseSlice(array, fromRight ? index + 1 : 0, fromRight ? length : index); + } + function baseWrapperValue(value, actions) { + var result = value; + if (result instanceof LazyWrapper) { + result = result.value(); + } + var index = -1, length = actions.length; + while (++index < length) { + var action = actions[index]; + result = action.func.apply(action.thisArg, arrayPush([ result ], action.args)); + } + return result; + } + function binaryIndex(array, value, retHighest) { + var low = 0, high = array ? array.length : low; + if (typeof value == "number" && value === value && high <= HALF_MAX_ARRAY_LENGTH) { + while (low < high) { + var mid = low + high >>> 1, computed = array[mid]; + if ((retHighest ? computed <= value : computed < value) && computed !== null) { + low = mid + 1; + } else { + high = mid; + } + } + return high; + } + return binaryIndexBy(array, value, identity, retHighest); + } + function binaryIndexBy(array, value, iteratee, retHighest) { + value = iteratee(value); + var low = 0, high = array ? array.length : 0, valIsNaN = value !== value, valIsNull = value === null, valIsUndef = value === undefined; + while (low < high) { + var mid = nativeFloor((low + high) / 2), computed = iteratee(array[mid]), isDef = computed !== undefined, isReflexive = computed === computed; + if (valIsNaN) { + var setLow = isReflexive || retHighest; + } else if (valIsNull) { + setLow = isReflexive && isDef && (retHighest || computed != null); + } else if (valIsUndef) { + setLow = isReflexive && (retHighest || isDef); + } else if (computed == null) { + setLow = false; + } else { + setLow = retHighest ? computed <= value : computed < value; + } + if (setLow) { + low = mid + 1; + } else { + high = mid; + } + } + return nativeMin(high, MAX_ARRAY_INDEX); + } + function bindCallback(func, thisArg, argCount) { + if (typeof func != "function") { + return identity; + } + if (thisArg === undefined) { + return func; + } + switch (argCount) { + case 1: + return function(value) { + return func.call(thisArg, value); + }; + + case 3: + return function(value, index, collection) { + return func.call(thisArg, value, index, collection); + }; + + case 4: + return function(accumulator, value, index, collection) { + return func.call(thisArg, accumulator, value, index, collection); + }; + + case 5: + return function(value, other, key, object, source) { + return func.call(thisArg, value, other, key, object, source); + }; + } + return function() { + return func.apply(thisArg, arguments); + }; + } + function bufferClone(buffer) { + var result = new ArrayBuffer(buffer.byteLength), view = new Uint8Array(result); + view.set(new Uint8Array(buffer)); + return result; + } + function composeArgs(args, partials, holders) { + var holdersLength = holders.length, argsIndex = -1, argsLength = nativeMax(args.length - holdersLength, 0), leftIndex = -1, leftLength = partials.length, result = Array(leftLength + argsLength); + while (++leftIndex < leftLength) { + result[leftIndex] = partials[leftIndex]; + } + while (++argsIndex < holdersLength) { + result[holders[argsIndex]] = args[argsIndex]; + } + while (argsLength--) { + result[leftIndex++] = args[argsIndex++]; + } + return result; + } + function composeArgsRight(args, partials, holders) { + var holdersIndex = -1, holdersLength = holders.length, argsIndex = -1, argsLength = nativeMax(args.length - holdersLength, 0), rightIndex = -1, rightLength = partials.length, result = Array(argsLength + rightLength); + while (++argsIndex < argsLength) { + result[argsIndex] = args[argsIndex]; + } + var offset = argsIndex; + while (++rightIndex < rightLength) { + result[offset + rightIndex] = partials[rightIndex]; + } + while (++holdersIndex < holdersLength) { + result[offset + holders[holdersIndex]] = args[argsIndex++]; + } + return result; + } + function createAggregator(setter, initializer) { + return function(collection, iteratee, thisArg) { + var result = initializer ? initializer() : {}; + iteratee = getCallback(iteratee, thisArg, 3); + if (isArray(collection)) { + var index = -1, length = collection.length; + while (++index < length) { + var value = collection[index]; + setter(result, value, iteratee(value, index, collection), collection); + } + } else { + baseEach(collection, function(value, key, collection) { + setter(result, value, iteratee(value, key, collection), collection); + }); + } + return result; + }; + } + function createAssigner(assigner) { + return restParam(function(object, sources) { + var index = -1, length = object == null ? 0 : sources.length, customizer = length > 2 ? sources[length - 2] : undefined, guard = length > 2 ? sources[2] : undefined, thisArg = length > 1 ? sources[length - 1] : undefined; + if (typeof customizer == "function") { + customizer = bindCallback(customizer, thisArg, 5); + length -= 2; + } else { + customizer = typeof thisArg == "function" ? thisArg : undefined; + length -= customizer ? 1 : 0; + } + if (guard && isIterateeCall(sources[0], sources[1], guard)) { + customizer = length < 3 ? undefined : customizer; + length = 1; + } + while (++index < length) { + var source = sources[index]; + if (source) { + assigner(object, source, customizer); + } + } + return object; + }); + } + function createBaseEach(eachFunc, fromRight) { + return function(collection, iteratee) { + var length = collection ? getLength(collection) : 0; + if (!isLength(length)) { + return eachFunc(collection, iteratee); + } + var index = fromRight ? length : -1, iterable = toObject(collection); + while (fromRight ? index-- : ++index < length) { + if (iteratee(iterable[index], index, iterable) === false) { + break; + } + } + return collection; + }; + } + function createBaseFor(fromRight) { + return function(object, iteratee, keysFunc) { + var iterable = toObject(object), props = keysFunc(object), length = props.length, index = fromRight ? length : -1; + while (fromRight ? index-- : ++index < length) { + var key = props[index]; + if (iteratee(iterable[key], key, iterable) === false) { + break; + } + } + return object; + }; + } + function createBindWrapper(func, thisArg) { + var Ctor = createCtorWrapper(func); + function wrapper() { + var fn = this && this !== root && this instanceof wrapper ? Ctor : func; + return fn.apply(thisArg, arguments); + } + return wrapper; + } + function createCache(values) { + return nativeCreate && Set ? new SetCache(values) : null; + } + function createCompounder(callback) { + return function(string) { + var index = -1, array = words(deburr(string)), length = array.length, result = ""; + while (++index < length) { + result = callback(result, array[index], index); + } + return result; + }; + } + function createCtorWrapper(Ctor) { + return function() { + var args = arguments; + switch (args.length) { + case 0: + return new Ctor(); + + case 1: + return new Ctor(args[0]); + + case 2: + return new Ctor(args[0], args[1]); + + case 3: + return new Ctor(args[0], args[1], args[2]); + + case 4: + return new Ctor(args[0], args[1], args[2], args[3]); + + case 5: + return new Ctor(args[0], args[1], args[2], args[3], args[4]); + + case 6: + return new Ctor(args[0], args[1], args[2], args[3], args[4], args[5]); + + case 7: + return new Ctor(args[0], args[1], args[2], args[3], args[4], args[5], args[6]); + } + var thisBinding = baseCreate(Ctor.prototype), result = Ctor.apply(thisBinding, args); + return isObject(result) ? result : thisBinding; + }; + } + function createCurry(flag) { + function curryFunc(func, arity, guard) { + if (guard && isIterateeCall(func, arity, guard)) { + arity = undefined; + } + var result = createWrapper(func, flag, undefined, undefined, undefined, undefined, undefined, arity); + result.placeholder = curryFunc.placeholder; + return result; + } + return curryFunc; + } + function createDefaults(assigner, customizer) { + return restParam(function(args) { + var object = args[0]; + if (object == null) { + return object; + } + args.push(customizer); + return assigner.apply(undefined, args); + }); + } + function createExtremum(comparator, exValue) { + return function(collection, iteratee, thisArg) { + if (thisArg && isIterateeCall(collection, iteratee, thisArg)) { + iteratee = undefined; + } + iteratee = getCallback(iteratee, thisArg, 3); + if (iteratee.length == 1) { + collection = isArray(collection) ? collection : toIterable(collection); + var result = arrayExtremum(collection, iteratee, comparator, exValue); + if (!(collection.length && result === exValue)) { + return result; + } + } + return baseExtremum(collection, iteratee, comparator, exValue); + }; + } + function createFind(eachFunc, fromRight) { + return function(collection, predicate, thisArg) { + predicate = getCallback(predicate, thisArg, 3); + if (isArray(collection)) { + var index = baseFindIndex(collection, predicate, fromRight); + return index > -1 ? collection[index] : undefined; + } + return baseFind(collection, predicate, eachFunc); + }; + } + function createFindIndex(fromRight) { + return function(array, predicate, thisArg) { + if (!(array && array.length)) { + return -1; + } + predicate = getCallback(predicate, thisArg, 3); + return baseFindIndex(array, predicate, fromRight); + }; + } + function createFindKey(objectFunc) { + return function(object, predicate, thisArg) { + predicate = getCallback(predicate, thisArg, 3); + return baseFind(object, predicate, objectFunc, true); + }; + } + function createFlow(fromRight) { + return function() { + var wrapper, length = arguments.length, index = fromRight ? length : -1, leftIndex = 0, funcs = Array(length); + while (fromRight ? index-- : ++index < length) { + var func = funcs[leftIndex++] = arguments[index]; + if (typeof func != "function") { + throw new TypeError(FUNC_ERROR_TEXT); + } + if (!wrapper && LodashWrapper.prototype.thru && getFuncName(func) == "wrapper") { + wrapper = new LodashWrapper([], true); + } + } + index = wrapper ? -1 : length; + while (++index < length) { + func = funcs[index]; + var funcName = getFuncName(func), data = funcName == "wrapper" ? getData(func) : undefined; + if (data && isLaziable(data[0]) && data[1] == (ARY_FLAG | CURRY_FLAG | PARTIAL_FLAG | REARG_FLAG) && !data[4].length && data[9] == 1) { + wrapper = wrapper[getFuncName(data[0])].apply(wrapper, data[3]); + } else { + wrapper = func.length == 1 && isLaziable(func) ? wrapper[funcName]() : wrapper.thru(func); + } + } + return function() { + var args = arguments, value = args[0]; + if (wrapper && args.length == 1 && isArray(value) && value.length >= LARGE_ARRAY_SIZE) { + return wrapper.plant(value).value(); + } + var index = 0, result = length ? funcs[index].apply(this, args) : value; + while (++index < length) { + result = funcs[index].call(this, result); + } + return result; + }; + }; + } + function createForEach(arrayFunc, eachFunc) { + return function(collection, iteratee, thisArg) { + return typeof iteratee == "function" && thisArg === undefined && isArray(collection) ? arrayFunc(collection, iteratee) : eachFunc(collection, bindCallback(iteratee, thisArg, 3)); + }; + } + function createForIn(objectFunc) { + return function(object, iteratee, thisArg) { + if (typeof iteratee != "function" || thisArg !== undefined) { + iteratee = bindCallback(iteratee, thisArg, 3); + } + return objectFunc(object, iteratee, keysIn); + }; + } + function createForOwn(objectFunc) { + return function(object, iteratee, thisArg) { + if (typeof iteratee != "function" || thisArg !== undefined) { + iteratee = bindCallback(iteratee, thisArg, 3); + } + return objectFunc(object, iteratee); + }; + } + function createObjectMapper(isMapKeys) { + return function(object, iteratee, thisArg) { + var result = {}; + iteratee = getCallback(iteratee, thisArg, 3); + baseForOwn(object, function(value, key, object) { + var mapped = iteratee(value, key, object); + key = isMapKeys ? mapped : key; + value = isMapKeys ? value : mapped; + result[key] = value; + }); + return result; + }; + } + function createPadDir(fromRight) { + return function(string, length, chars) { + string = baseToString(string); + return (fromRight ? string : "") + createPadding(string, length, chars) + (fromRight ? "" : string); + }; + } + function createPartial(flag) { + var partialFunc = restParam(function(func, partials) { + var holders = replaceHolders(partials, partialFunc.placeholder); + return createWrapper(func, flag, undefined, partials, holders); + }); + return partialFunc; + } + function createReduce(arrayFunc, eachFunc) { + return function(collection, iteratee, accumulator, thisArg) { + var initFromArray = arguments.length < 3; + return typeof iteratee == "function" && thisArg === undefined && isArray(collection) ? arrayFunc(collection, iteratee, accumulator, initFromArray) : baseReduce(collection, getCallback(iteratee, thisArg, 4), accumulator, initFromArray, eachFunc); + }; + } + function createHybridWrapper(func, bitmask, thisArg, partials, holders, partialsRight, holdersRight, argPos, ary, arity) { + var isAry = bitmask & ARY_FLAG, isBind = bitmask & BIND_FLAG, isBindKey = bitmask & BIND_KEY_FLAG, isCurry = bitmask & CURRY_FLAG, isCurryBound = bitmask & CURRY_BOUND_FLAG, isCurryRight = bitmask & CURRY_RIGHT_FLAG, Ctor = isBindKey ? undefined : createCtorWrapper(func); + function wrapper() { + var length = arguments.length, index = length, args = Array(length); + while (index--) { + args[index] = arguments[index]; + } + if (partials) { + args = composeArgs(args, partials, holders); + } + if (partialsRight) { + args = composeArgsRight(args, partialsRight, holdersRight); + } + if (isCurry || isCurryRight) { + var placeholder = wrapper.placeholder, argsHolders = replaceHolders(args, placeholder); + length -= argsHolders.length; + if (length < arity) { + var newArgPos = argPos ? arrayCopy(argPos) : undefined, newArity = nativeMax(arity - length, 0), newsHolders = isCurry ? argsHolders : undefined, newHoldersRight = isCurry ? undefined : argsHolders, newPartials = isCurry ? args : undefined, newPartialsRight = isCurry ? undefined : args; + bitmask |= isCurry ? PARTIAL_FLAG : PARTIAL_RIGHT_FLAG; + bitmask &= ~(isCurry ? PARTIAL_RIGHT_FLAG : PARTIAL_FLAG); + if (!isCurryBound) { + bitmask &= ~(BIND_FLAG | BIND_KEY_FLAG); + } + var newData = [ func, bitmask, thisArg, newPartials, newsHolders, newPartialsRight, newHoldersRight, newArgPos, ary, newArity ], result = createHybridWrapper.apply(undefined, newData); + if (isLaziable(func)) { + setData(result, newData); + } + result.placeholder = placeholder; + return result; + } + } + var thisBinding = isBind ? thisArg : this, fn = isBindKey ? thisBinding[func] : func; + if (argPos) { + args = reorder(args, argPos); + } + if (isAry && ary < args.length) { + args.length = ary; + } + if (this && this !== root && this instanceof wrapper) { + fn = Ctor || createCtorWrapper(func); + } + return fn.apply(thisBinding, args); + } + return wrapper; + } + function createPadding(string, length, chars) { + var strLength = string.length; + length = +length; + if (strLength >= length || !nativeIsFinite(length)) { + return ""; + } + var padLength = length - strLength; + chars = chars == null ? " " : chars + ""; + return repeat(chars, nativeCeil(padLength / chars.length)).slice(0, padLength); + } + function createPartialWrapper(func, bitmask, thisArg, partials) { + var isBind = bitmask & BIND_FLAG, Ctor = createCtorWrapper(func); + function wrapper() { + var argsIndex = -1, argsLength = arguments.length, leftIndex = -1, leftLength = partials.length, args = Array(leftLength + argsLength); + while (++leftIndex < leftLength) { + args[leftIndex] = partials[leftIndex]; + } + while (argsLength--) { + args[leftIndex++] = arguments[++argsIndex]; + } + var fn = this && this !== root && this instanceof wrapper ? Ctor : func; + return fn.apply(isBind ? thisArg : this, args); + } + return wrapper; + } + function createRound(methodName) { + var func = Math[methodName]; + return function(number, precision) { + precision = precision === undefined ? 0 : +precision || 0; + if (precision) { + precision = pow(10, precision); + return func(number * precision) / precision; + } + return func(number); + }; + } + function createSortedIndex(retHighest) { + return function(array, value, iteratee, thisArg) { + var callback = getCallback(iteratee); + return iteratee == null && callback === baseCallback ? binaryIndex(array, value, retHighest) : binaryIndexBy(array, value, callback(iteratee, thisArg, 1), retHighest); + }; + } + function createWrapper(func, bitmask, thisArg, partials, holders, argPos, ary, arity) { + var isBindKey = bitmask & BIND_KEY_FLAG; + if (!isBindKey && typeof func != "function") { + throw new TypeError(FUNC_ERROR_TEXT); + } + var length = partials ? partials.length : 0; + if (!length) { + bitmask &= ~(PARTIAL_FLAG | PARTIAL_RIGHT_FLAG); + partials = holders = undefined; + } + length -= holders ? holders.length : 0; + if (bitmask & PARTIAL_RIGHT_FLAG) { + var partialsRight = partials, holdersRight = holders; + partials = holders = undefined; + } + var data = isBindKey ? undefined : getData(func), newData = [ func, bitmask, thisArg, partials, holders, partialsRight, holdersRight, argPos, ary, arity ]; + if (data) { + mergeData(newData, data); + bitmask = newData[1]; + arity = newData[9]; + } + newData[9] = arity == null ? isBindKey ? 0 : func.length : nativeMax(arity - length, 0) || 0; + if (bitmask == BIND_FLAG) { + var result = createBindWrapper(newData[0], newData[2]); + } else if ((bitmask == PARTIAL_FLAG || bitmask == (BIND_FLAG | PARTIAL_FLAG)) && !newData[4].length) { + result = createPartialWrapper.apply(undefined, newData); + } else { + result = createHybridWrapper.apply(undefined, newData); + } + var setter = data ? baseSetData : setData; + return setter(result, newData); + } + function equalArrays(array, other, equalFunc, customizer, isLoose, stackA, stackB) { + var index = -1, arrLength = array.length, othLength = other.length; + if (arrLength != othLength && !(isLoose && othLength > arrLength)) { + return false; + } + while (++index < arrLength) { + var arrValue = array[index], othValue = other[index], result = customizer ? customizer(isLoose ? othValue : arrValue, isLoose ? arrValue : othValue, index) : undefined; + if (result !== undefined) { + if (result) { + continue; + } + return false; + } + if (isLoose) { + if (!arraySome(other, function(othValue) { + return arrValue === othValue || equalFunc(arrValue, othValue, customizer, isLoose, stackA, stackB); + })) { + return false; + } + } else if (!(arrValue === othValue || equalFunc(arrValue, othValue, customizer, isLoose, stackA, stackB))) { + return false; + } + } + return true; + } + function equalByTag(object, other, tag) { + switch (tag) { + case boolTag: + case dateTag: + return +object == +other; + + case errorTag: + return object.name == other.name && object.message == other.message; + + case numberTag: + return object != +object ? other != +other : object == +other; + + case regexpTag: + case stringTag: + return object == other + ""; + } + return false; + } + function equalObjects(object, other, equalFunc, customizer, isLoose, stackA, stackB) { + var objProps = keys(object), objLength = objProps.length, othProps = keys(other), othLength = othProps.length; + if (objLength != othLength && !isLoose) { + return false; + } + var index = objLength; + while (index--) { + var key = objProps[index]; + if (!(isLoose ? key in other : hasOwnProperty.call(other, key))) { + return false; + } + } + var skipCtor = isLoose; + while (++index < objLength) { + key = objProps[index]; + var objValue = object[key], othValue = other[key], result = customizer ? customizer(isLoose ? othValue : objValue, isLoose ? objValue : othValue, key) : undefined; + if (!(result === undefined ? equalFunc(objValue, othValue, customizer, isLoose, stackA, stackB) : result)) { + return false; + } + skipCtor || (skipCtor = key == "constructor"); + } + if (!skipCtor) { + var objCtor = object.constructor, othCtor = other.constructor; + if (objCtor != othCtor && ("constructor" in object && "constructor" in other) && !(typeof objCtor == "function" && objCtor instanceof objCtor && typeof othCtor == "function" && othCtor instanceof othCtor)) { + return false; + } + } + return true; + } + function getCallback(func, thisArg, argCount) { + var result = lodash.callback || callback; + result = result === callback ? baseCallback : result; + return argCount ? result(func, thisArg, argCount) : result; + } + var getData = !metaMap ? noop : function(func) { + return metaMap.get(func); + }; + function getFuncName(func) { + var result = func.name + "", array = realNames[result], length = array ? array.length : 0; + while (length--) { + var data = array[length], otherFunc = data.func; + if (otherFunc == null || otherFunc == func) { + return data.name; + } + } + return result; + } + function getIndexOf(collection, target, fromIndex) { + var result = lodash.indexOf || indexOf; + result = result === indexOf ? baseIndexOf : result; + return collection ? result(collection, target, fromIndex) : result; + } + var getLength = baseProperty("length"); + function getMatchData(object) { + var result = pairs(object), length = result.length; + while (length--) { + result[length][2] = isStrictComparable(result[length][1]); + } + return result; + } + function getNative(object, key) { + var value = object == null ? undefined : object[key]; + return isNative(value) ? value : undefined; + } + function getView(start, end, transforms) { + var index = -1, length = transforms.length; + while (++index < length) { + var data = transforms[index], size = data.size; + switch (data.type) { + case "drop": + start += size; + break; + + case "dropRight": + end -= size; + break; + + case "take": + end = nativeMin(end, start + size); + break; + + case "takeRight": + start = nativeMax(start, end - size); + break; + } + } + return { + start: start, + end: end + }; + } + function initCloneArray(array) { + var length = array.length, result = new array.constructor(length); + if (length && typeof array[0] == "string" && hasOwnProperty.call(array, "index")) { + result.index = array.index; + result.input = array.input; + } + return result; + } + function initCloneObject(object) { + var Ctor = object.constructor; + if (!(typeof Ctor == "function" && Ctor instanceof Ctor)) { + Ctor = Object; + } + return new Ctor(); + } + function initCloneByTag(object, tag, isDeep) { + var Ctor = object.constructor; + switch (tag) { + case arrayBufferTag: + return bufferClone(object); + + case boolTag: + case dateTag: + return new Ctor(+object); + + case float32Tag: + case float64Tag: + case int8Tag: + case int16Tag: + case int32Tag: + case uint8Tag: + case uint8ClampedTag: + case uint16Tag: + case uint32Tag: + var buffer = object.buffer; + return new Ctor(isDeep ? bufferClone(buffer) : buffer, object.byteOffset, object.length); + + case numberTag: + case stringTag: + return new Ctor(object); + + case regexpTag: + var result = new Ctor(object.source, reFlags.exec(object)); + result.lastIndex = object.lastIndex; + } + return result; + } + function invokePath(object, path, args) { + if (object != null && !isKey(path, object)) { + path = toPath(path); + object = path.length == 1 ? object : baseGet(object, baseSlice(path, 0, -1)); + path = last(path); + } + var func = object == null ? object : object[path]; + return func == null ? undefined : func.apply(object, args); + } + function isArrayLike(value) { + return value != null && isLength(getLength(value)); + } + function isIndex(value, length) { + value = typeof value == "number" || reIsUint.test(value) ? +value : -1; + length = length == null ? MAX_SAFE_INTEGER : length; + return value > -1 && value % 1 == 0 && value < length; + } + function isIterateeCall(value, index, object) { + if (!isObject(object)) { + return false; + } + var type = typeof index; + if (type == "number" ? isArrayLike(object) && isIndex(index, object.length) : type == "string" && index in object) { + var other = object[index]; + return value === value ? value === other : other !== other; + } + return false; + } + function isKey(value, object) { + var type = typeof value; + if (type == "string" && reIsPlainProp.test(value) || type == "number") { + return true; + } + if (isArray(value)) { + return false; + } + var result = !reIsDeepProp.test(value); + return result || object != null && value in toObject(object); + } + function isLaziable(func) { + var funcName = getFuncName(func), other = lodash[funcName]; + if (typeof other != "function" || !(funcName in LazyWrapper.prototype)) { + return false; + } + if (func === other) { + return true; + } + var data = getData(other); + return !!data && func === data[0]; + } + function isLength(value) { + return typeof value == "number" && value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER; + } + function isStrictComparable(value) { + return value === value && !isObject(value); + } + function mergeData(data, source) { + var bitmask = data[1], srcBitmask = source[1], newBitmask = bitmask | srcBitmask, isCommon = newBitmask < ARY_FLAG; + var isCombo = srcBitmask == ARY_FLAG && bitmask == CURRY_FLAG || srcBitmask == ARY_FLAG && bitmask == REARG_FLAG && data[7].length <= source[8] || srcBitmask == (ARY_FLAG | REARG_FLAG) && bitmask == CURRY_FLAG; + if (!(isCommon || isCombo)) { + return data; + } + if (srcBitmask & BIND_FLAG) { + data[2] = source[2]; + newBitmask |= bitmask & BIND_FLAG ? 0 : CURRY_BOUND_FLAG; + } + var value = source[3]; + if (value) { + var partials = data[3]; + data[3] = partials ? composeArgs(partials, value, source[4]) : arrayCopy(value); + data[4] = partials ? replaceHolders(data[3], PLACEHOLDER) : arrayCopy(source[4]); + } + value = source[5]; + if (value) { + partials = data[5]; + data[5] = partials ? composeArgsRight(partials, value, source[6]) : arrayCopy(value); + data[6] = partials ? replaceHolders(data[5], PLACEHOLDER) : arrayCopy(source[6]); + } + value = source[7]; + if (value) { + data[7] = arrayCopy(value); + } + if (srcBitmask & ARY_FLAG) { + data[8] = data[8] == null ? source[8] : nativeMin(data[8], source[8]); + } + if (data[9] == null) { + data[9] = source[9]; + } + data[0] = source[0]; + data[1] = newBitmask; + return data; + } + function mergeDefaults(objectValue, sourceValue) { + return objectValue === undefined ? sourceValue : merge(objectValue, sourceValue, mergeDefaults); + } + function pickByArray(object, props) { + object = toObject(object); + var index = -1, length = props.length, result = {}; + while (++index < length) { + var key = props[index]; + if (key in object) { + result[key] = object[key]; + } + } + return result; + } + function pickByCallback(object, predicate) { + var result = {}; + baseForIn(object, function(value, key, object) { + if (predicate(value, key, object)) { + result[key] = value; + } + }); + return result; + } + function reorder(array, indexes) { + var arrLength = array.length, length = nativeMin(indexes.length, arrLength), oldArray = arrayCopy(array); + while (length--) { + var index = indexes[length]; + array[length] = isIndex(index, arrLength) ? oldArray[index] : undefined; + } + return array; + } + var setData = function() { + var count = 0, lastCalled = 0; + return function(key, value) { + var stamp = now(), remaining = HOT_SPAN - (stamp - lastCalled); + lastCalled = stamp; + if (remaining > 0) { + if (++count >= HOT_COUNT) { + return key; + } + } else { + count = 0; + } + return baseSetData(key, value); + }; + }(); + function shimKeys(object) { + var props = keysIn(object), propsLength = props.length, length = propsLength && object.length; + var allowIndexes = !!length && isLength(length) && (isArray(object) || isArguments(object)); + var index = -1, result = []; + while (++index < propsLength) { + var key = props[index]; + if (allowIndexes && isIndex(key, length) || hasOwnProperty.call(object, key)) { + result.push(key); + } + } + return result; + } + function toIterable(value) { + if (value == null) { + return []; + } + if (!isArrayLike(value)) { + return values(value); + } + return isObject(value) ? value : Object(value); + } + function toObject(value) { + return isObject(value) ? value : Object(value); + } + function toPath(value) { + if (isArray(value)) { + return value; + } + var result = []; + baseToString(value).replace(rePropName, function(match, number, quote, string) { + result.push(quote ? string.replace(reEscapeChar, "$1") : number || match); + }); + return result; + } + function wrapperClone(wrapper) { + return wrapper instanceof LazyWrapper ? wrapper.clone() : new LodashWrapper(wrapper.__wrapped__, wrapper.__chain__, arrayCopy(wrapper.__actions__)); + } + function chunk(array, size, guard) { + if (guard ? isIterateeCall(array, size, guard) : size == null) { + size = 1; + } else { + size = nativeMax(nativeFloor(size) || 1, 1); + } + var index = 0, length = array ? array.length : 0, resIndex = -1, result = Array(nativeCeil(length / size)); + while (index < length) { + result[++resIndex] = baseSlice(array, index, index += size); + } + return result; + } + function compact(array) { + var index = -1, length = array ? array.length : 0, resIndex = -1, result = []; + while (++index < length) { + var value = array[index]; + if (value) { + result[++resIndex] = value; + } + } + return result; + } + var difference = restParam(function(array, values) { + return isObjectLike(array) && isArrayLike(array) ? baseDifference(array, baseFlatten(values, false, true)) : []; + }); + function drop(array, n, guard) { + var length = array ? array.length : 0; + if (!length) { + return []; + } + if (guard ? isIterateeCall(array, n, guard) : n == null) { + n = 1; + } + return baseSlice(array, n < 0 ? 0 : n); + } + function dropRight(array, n, guard) { + var length = array ? array.length : 0; + if (!length) { + return []; + } + if (guard ? isIterateeCall(array, n, guard) : n == null) { + n = 1; + } + n = length - (+n || 0); + return baseSlice(array, 0, n < 0 ? 0 : n); + } + function dropRightWhile(array, predicate, thisArg) { + return array && array.length ? baseWhile(array, getCallback(predicate, thisArg, 3), true, true) : []; + } + function dropWhile(array, predicate, thisArg) { + return array && array.length ? baseWhile(array, getCallback(predicate, thisArg, 3), true) : []; + } + function fill(array, value, start, end) { + var length = array ? array.length : 0; + if (!length) { + return []; + } + if (start && typeof start != "number" && isIterateeCall(array, value, start)) { + start = 0; + end = length; + } + return baseFill(array, value, start, end); + } + var findIndex = createFindIndex(); + var findLastIndex = createFindIndex(true); + function first(array) { + return array ? array[0] : undefined; + } + function flatten(array, isDeep, guard) { + var length = array ? array.length : 0; + if (guard && isIterateeCall(array, isDeep, guard)) { + isDeep = false; + } + return length ? baseFlatten(array, isDeep) : []; + } + function flattenDeep(array) { + var length = array ? array.length : 0; + return length ? baseFlatten(array, true) : []; + } + function indexOf(array, value, fromIndex) { + var length = array ? array.length : 0; + if (!length) { + return -1; + } + if (typeof fromIndex == "number") { + fromIndex = fromIndex < 0 ? nativeMax(length + fromIndex, 0) : fromIndex; + } else if (fromIndex) { + var index = binaryIndex(array, value); + if (index < length && (value === value ? value === array[index] : array[index] !== array[index])) { + return index; + } + return -1; + } + return baseIndexOf(array, value, fromIndex || 0); + } + function initial(array) { + return dropRight(array, 1); + } + var intersection = restParam(function(arrays) { + var othLength = arrays.length, othIndex = othLength, caches = Array(length), indexOf = getIndexOf(), isCommon = indexOf === baseIndexOf, result = []; + while (othIndex--) { + var value = arrays[othIndex] = isArrayLike(value = arrays[othIndex]) ? value : []; + caches[othIndex] = isCommon && value.length >= 120 ? createCache(othIndex && value) : null; + } + var array = arrays[0], index = -1, length = array ? array.length : 0, seen = caches[0]; + outer: while (++index < length) { + value = array[index]; + if ((seen ? cacheIndexOf(seen, value) : indexOf(result, value, 0)) < 0) { + var othIndex = othLength; + while (--othIndex) { + var cache = caches[othIndex]; + if ((cache ? cacheIndexOf(cache, value) : indexOf(arrays[othIndex], value, 0)) < 0) { + continue outer; + } + } + if (seen) { + seen.push(value); + } + result.push(value); + } + } + return result; + }); + function last(array) { + var length = array ? array.length : 0; + return length ? array[length - 1] : undefined; + } + function lastIndexOf(array, value, fromIndex) { + var length = array ? array.length : 0; + if (!length) { + return -1; + } + var index = length; + if (typeof fromIndex == "number") { + index = (fromIndex < 0 ? nativeMax(length + fromIndex, 0) : nativeMin(fromIndex || 0, length - 1)) + 1; + } else if (fromIndex) { + index = binaryIndex(array, value, true) - 1; + var other = array[index]; + if (value === value ? value === other : other !== other) { + return index; + } + return -1; + } + if (value !== value) { + return indexOfNaN(array, index, true); + } + while (index--) { + if (array[index] === value) { + return index; + } + } + return -1; + } + function pull() { + var args = arguments, array = args[0]; + if (!(array && array.length)) { + return array; + } + var index = 0, indexOf = getIndexOf(), length = args.length; + while (++index < length) { + var fromIndex = 0, value = args[index]; + while ((fromIndex = indexOf(array, value, fromIndex)) > -1) { + splice.call(array, fromIndex, 1); + } + } + return array; + } + var pullAt = restParam(function(array, indexes) { + indexes = baseFlatten(indexes); + var result = baseAt(array, indexes); + basePullAt(array, indexes.sort(baseCompareAscending)); + return result; + }); + function remove(array, predicate, thisArg) { + var result = []; + if (!(array && array.length)) { + return result; + } + var index = -1, indexes = [], length = array.length; + predicate = getCallback(predicate, thisArg, 3); + while (++index < length) { + var value = array[index]; + if (predicate(value, index, array)) { + result.push(value); + indexes.push(index); + } + } + basePullAt(array, indexes); + return result; + } + function rest(array) { + return drop(array, 1); + } + function slice(array, start, end) { + var length = array ? array.length : 0; + if (!length) { + return []; + } + if (end && typeof end != "number" && isIterateeCall(array, start, end)) { + start = 0; + end = length; + } + return baseSlice(array, start, end); + } + var sortedIndex = createSortedIndex(); + var sortedLastIndex = createSortedIndex(true); + function take(array, n, guard) { + var length = array ? array.length : 0; + if (!length) { + return []; + } + if (guard ? isIterateeCall(array, n, guard) : n == null) { + n = 1; + } + return baseSlice(array, 0, n < 0 ? 0 : n); + } + function takeRight(array, n, guard) { + var length = array ? array.length : 0; + if (!length) { + return []; + } + if (guard ? isIterateeCall(array, n, guard) : n == null) { + n = 1; + } + n = length - (+n || 0); + return baseSlice(array, n < 0 ? 0 : n); + } + function takeRightWhile(array, predicate, thisArg) { + return array && array.length ? baseWhile(array, getCallback(predicate, thisArg, 3), false, true) : []; + } + function takeWhile(array, predicate, thisArg) { + return array && array.length ? baseWhile(array, getCallback(predicate, thisArg, 3)) : []; + } + var union = restParam(function(arrays) { + return baseUniq(baseFlatten(arrays, false, true)); + }); + function uniq(array, isSorted, iteratee, thisArg) { + var length = array ? array.length : 0; + if (!length) { + return []; + } + if (isSorted != null && typeof isSorted != "boolean") { + thisArg = iteratee; + iteratee = isIterateeCall(array, isSorted, thisArg) ? undefined : isSorted; + isSorted = false; + } + var callback = getCallback(); + if (!(iteratee == null && callback === baseCallback)) { + iteratee = callback(iteratee, thisArg, 3); + } + return isSorted && getIndexOf() === baseIndexOf ? sortedUniq(array, iteratee) : baseUniq(array, iteratee); + } + function unzip(array) { + if (!(array && array.length)) { + return []; + } + var index = -1, length = 0; + array = arrayFilter(array, function(group) { + if (isArrayLike(group)) { + length = nativeMax(group.length, length); + return true; + } + }); + var result = Array(length); + while (++index < length) { + result[index] = arrayMap(array, baseProperty(index)); + } + return result; + } + function unzipWith(array, iteratee, thisArg) { + var length = array ? array.length : 0; + if (!length) { + return []; + } + var result = unzip(array); + if (iteratee == null) { + return result; + } + iteratee = bindCallback(iteratee, thisArg, 4); + return arrayMap(result, function(group) { + return arrayReduce(group, iteratee, undefined, true); + }); + } + var without = restParam(function(array, values) { + return isArrayLike(array) ? baseDifference(array, values) : []; + }); + function xor() { + var index = -1, length = arguments.length; + while (++index < length) { + var array = arguments[index]; + if (isArrayLike(array)) { + var result = result ? arrayPush(baseDifference(result, array), baseDifference(array, result)) : array; + } + } + return result ? baseUniq(result) : []; + } + var zip = restParam(unzip); + function zipObject(props, values) { + var index = -1, length = props ? props.length : 0, result = {}; + if (length && !values && !isArray(props[0])) { + values = []; + } + while (++index < length) { + var key = props[index]; + if (values) { + result[key] = values[index]; + } else if (key) { + result[key[0]] = key[1]; + } + } + return result; + } + var zipWith = restParam(function(arrays) { + var length = arrays.length, iteratee = length > 2 ? arrays[length - 2] : undefined, thisArg = length > 1 ? arrays[length - 1] : undefined; + if (length > 2 && typeof iteratee == "function") { + length -= 2; + } else { + iteratee = length > 1 && typeof thisArg == "function" ? (--length, thisArg) : undefined; + thisArg = undefined; + } + arrays.length = length; + return unzipWith(arrays, iteratee, thisArg); + }); + function chain(value) { + var result = lodash(value); + result.__chain__ = true; + return result; + } + function tap(value, interceptor, thisArg) { + interceptor.call(thisArg, value); + return value; + } + function thru(value, interceptor, thisArg) { + return interceptor.call(thisArg, value); + } + function wrapperChain() { + return chain(this); + } + function wrapperCommit() { + return new LodashWrapper(this.value(), this.__chain__); + } + var wrapperConcat = restParam(function(values) { + values = baseFlatten(values); + return this.thru(function(array) { + return arrayConcat(isArray(array) ? array : [ toObject(array) ], values); + }); + }); + function wrapperPlant(value) { + var result, parent = this; + while (parent instanceof baseLodash) { + var clone = wrapperClone(parent); + if (result) { + previous.__wrapped__ = clone; + } else { + result = clone; + } + var previous = clone; + parent = parent.__wrapped__; + } + previous.__wrapped__ = value; + return result; + } + function wrapperReverse() { + var value = this.__wrapped__; + var interceptor = function(value) { + return value.reverse(); + }; + if (value instanceof LazyWrapper) { + var wrapped = value; + if (this.__actions__.length) { + wrapped = new LazyWrapper(this); + } + wrapped = wrapped.reverse(); + wrapped.__actions__.push({ + func: thru, + args: [ interceptor ], + thisArg: undefined + }); + return new LodashWrapper(wrapped, this.__chain__); + } + return this.thru(interceptor); + } + function wrapperToString() { + return this.value() + ""; + } + function wrapperValue() { + return baseWrapperValue(this.__wrapped__, this.__actions__); + } + var at = restParam(function(collection, props) { + return baseAt(collection, baseFlatten(props)); + }); + var countBy = createAggregator(function(result, value, key) { + hasOwnProperty.call(result, key) ? ++result[key] : result[key] = 1; + }); + function every(collection, predicate, thisArg) { + var func = isArray(collection) ? arrayEvery : baseEvery; + if (thisArg && isIterateeCall(collection, predicate, thisArg)) { + predicate = undefined; + } + if (typeof predicate != "function" || thisArg !== undefined) { + predicate = getCallback(predicate, thisArg, 3); + } + return func(collection, predicate); + } + function filter(collection, predicate, thisArg) { + var func = isArray(collection) ? arrayFilter : baseFilter; + predicate = getCallback(predicate, thisArg, 3); + return func(collection, predicate); + } + var find = createFind(baseEach); + var findLast = createFind(baseEachRight, true); + function findWhere(collection, source) { + return find(collection, baseMatches(source)); + } + var forEach = createForEach(arrayEach, baseEach); + var forEachRight = createForEach(arrayEachRight, baseEachRight); + var groupBy = createAggregator(function(result, value, key) { + if (hasOwnProperty.call(result, key)) { + result[key].push(value); + } else { + result[key] = [ value ]; + } + }); + function includes(collection, target, fromIndex, guard) { + var length = collection ? getLength(collection) : 0; + if (!isLength(length)) { + collection = values(collection); + length = collection.length; + } + if (typeof fromIndex != "number" || guard && isIterateeCall(target, fromIndex, guard)) { + fromIndex = 0; + } else { + fromIndex = fromIndex < 0 ? nativeMax(length + fromIndex, 0) : fromIndex || 0; + } + return typeof collection == "string" || !isArray(collection) && isString(collection) ? fromIndex <= length && collection.indexOf(target, fromIndex) > -1 : !!length && getIndexOf(collection, target, fromIndex) > -1; + } + var indexBy = createAggregator(function(result, value, key) { + result[key] = value; + }); + var invoke = restParam(function(collection, path, args) { + var index = -1, isFunc = typeof path == "function", isProp = isKey(path), result = isArrayLike(collection) ? Array(collection.length) : []; + baseEach(collection, function(value) { + var func = isFunc ? path : isProp && value != null ? value[path] : undefined; + result[++index] = func ? func.apply(value, args) : invokePath(value, path, args); + }); + return result; + }); + function map(collection, iteratee, thisArg) { + var func = isArray(collection) ? arrayMap : baseMap; + iteratee = getCallback(iteratee, thisArg, 3); + return func(collection, iteratee); + } + var partition = createAggregator(function(result, value, key) { + result[key ? 0 : 1].push(value); + }, function() { + return [ [], [] ]; + }); + function pluck(collection, path) { + return map(collection, property(path)); + } + var reduce = createReduce(arrayReduce, baseEach); + var reduceRight = createReduce(arrayReduceRight, baseEachRight); + function reject(collection, predicate, thisArg) { + var func = isArray(collection) ? arrayFilter : baseFilter; + predicate = getCallback(predicate, thisArg, 3); + return func(collection, function(value, index, collection) { + return !predicate(value, index, collection); + }); + } + function sample(collection, n, guard) { + if (guard ? isIterateeCall(collection, n, guard) : n == null) { + collection = toIterable(collection); + var length = collection.length; + return length > 0 ? collection[baseRandom(0, length - 1)] : undefined; + } + var index = -1, result = toArray(collection), length = result.length, lastIndex = length - 1; + n = nativeMin(n < 0 ? 0 : +n || 0, length); + while (++index < n) { + var rand = baseRandom(index, lastIndex), value = result[rand]; + result[rand] = result[index]; + result[index] = value; + } + result.length = n; + return result; + } + function shuffle(collection) { + return sample(collection, POSITIVE_INFINITY); + } + function size(collection) { + var length = collection ? getLength(collection) : 0; + return isLength(length) ? length : keys(collection).length; + } + function some(collection, predicate, thisArg) { + var func = isArray(collection) ? arraySome : baseSome; + if (thisArg && isIterateeCall(collection, predicate, thisArg)) { + predicate = undefined; + } + if (typeof predicate != "function" || thisArg !== undefined) { + predicate = getCallback(predicate, thisArg, 3); + } + return func(collection, predicate); + } + function sortBy(collection, iteratee, thisArg) { + if (collection == null) { + return []; + } + if (thisArg && isIterateeCall(collection, iteratee, thisArg)) { + iteratee = undefined; + } + var index = -1; + iteratee = getCallback(iteratee, thisArg, 3); + var result = baseMap(collection, function(value, key, collection) { + return { + criteria: iteratee(value, key, collection), + index: ++index, + value: value + }; + }); + return baseSortBy(result, compareAscending); + } + var sortByAll = restParam(function(collection, iteratees) { + if (collection == null) { + return []; + } + var guard = iteratees[2]; + if (guard && isIterateeCall(iteratees[0], iteratees[1], guard)) { + iteratees.length = 1; + } + return baseSortByOrder(collection, baseFlatten(iteratees), []); + }); + function sortByOrder(collection, iteratees, orders, guard) { + if (collection == null) { + return []; + } + if (guard && isIterateeCall(iteratees, orders, guard)) { + orders = undefined; + } + if (!isArray(iteratees)) { + iteratees = iteratees == null ? [] : [ iteratees ]; + } + if (!isArray(orders)) { + orders = orders == null ? [] : [ orders ]; + } + return baseSortByOrder(collection, iteratees, orders); + } + function where(collection, source) { + return filter(collection, baseMatches(source)); + } + var now = nativeNow || function() { + return new Date().getTime(); + }; + function after(n, func) { + if (typeof func != "function") { + if (typeof n == "function") { + var temp = n; + n = func; + func = temp; + } else { + throw new TypeError(FUNC_ERROR_TEXT); + } + } + n = nativeIsFinite(n = +n) ? n : 0; + return function() { + if (--n < 1) { + return func.apply(this, arguments); + } + }; + } + function ary(func, n, guard) { + if (guard && isIterateeCall(func, n, guard)) { + n = undefined; + } + n = func && n == null ? func.length : nativeMax(+n || 0, 0); + return createWrapper(func, ARY_FLAG, undefined, undefined, undefined, undefined, n); + } + function before(n, func) { + var result; + if (typeof func != "function") { + if (typeof n == "function") { + var temp = n; + n = func; + func = temp; + } else { + throw new TypeError(FUNC_ERROR_TEXT); + } + } + return function() { + if (--n > 0) { + result = func.apply(this, arguments); + } + if (n <= 1) { + func = undefined; + } + return result; + }; + } + var bind = restParam(function(func, thisArg, partials) { + var bitmask = BIND_FLAG; + if (partials.length) { + var holders = replaceHolders(partials, bind.placeholder); + bitmask |= PARTIAL_FLAG; + } + return createWrapper(func, bitmask, thisArg, partials, holders); + }); + var bindAll = restParam(function(object, methodNames) { + methodNames = methodNames.length ? baseFlatten(methodNames) : functions(object); + var index = -1, length = methodNames.length; + while (++index < length) { + var key = methodNames[index]; + object[key] = createWrapper(object[key], BIND_FLAG, object); + } + return object; + }); + var bindKey = restParam(function(object, key, partials) { + var bitmask = BIND_FLAG | BIND_KEY_FLAG; + if (partials.length) { + var holders = replaceHolders(partials, bindKey.placeholder); + bitmask |= PARTIAL_FLAG; + } + return createWrapper(key, bitmask, object, partials, holders); + }); + var curry = createCurry(CURRY_FLAG); + var curryRight = createCurry(CURRY_RIGHT_FLAG); + function debounce(func, wait, options) { + var args, maxTimeoutId, result, stamp, thisArg, timeoutId, trailingCall, lastCalled = 0, maxWait = false, trailing = true; + if (typeof func != "function") { + throw new TypeError(FUNC_ERROR_TEXT); + } + wait = wait < 0 ? 0 : +wait || 0; + if (options === true) { + var leading = true; + trailing = false; + } else if (isObject(options)) { + leading = !!options.leading; + maxWait = "maxWait" in options && nativeMax(+options.maxWait || 0, wait); + trailing = "trailing" in options ? !!options.trailing : trailing; + } + function cancel() { + if (timeoutId) { + clearTimeout(timeoutId); + } + if (maxTimeoutId) { + clearTimeout(maxTimeoutId); + } + lastCalled = 0; + maxTimeoutId = timeoutId = trailingCall = undefined; + } + function complete(isCalled, id) { + if (id) { + clearTimeout(id); + } + maxTimeoutId = timeoutId = trailingCall = undefined; + if (isCalled) { + lastCalled = now(); + result = func.apply(thisArg, args); + if (!timeoutId && !maxTimeoutId) { + args = thisArg = undefined; + } + } + } + function delayed() { + var remaining = wait - (now() - stamp); + if (remaining <= 0 || remaining > wait) { + complete(trailingCall, maxTimeoutId); + } else { + timeoutId = setTimeout(delayed, remaining); + } + } + function maxDelayed() { + complete(trailing, timeoutId); + } + function debounced() { + args = arguments; + stamp = now(); + thisArg = this; + trailingCall = trailing && (timeoutId || !leading); + if (maxWait === false) { + var leadingCall = leading && !timeoutId; + } else { + if (!maxTimeoutId && !leading) { + lastCalled = stamp; + } + var remaining = maxWait - (stamp - lastCalled), isCalled = remaining <= 0 || remaining > maxWait; + if (isCalled) { + if (maxTimeoutId) { + maxTimeoutId = clearTimeout(maxTimeoutId); + } + lastCalled = stamp; + result = func.apply(thisArg, args); + } else if (!maxTimeoutId) { + maxTimeoutId = setTimeout(maxDelayed, remaining); + } + } + if (isCalled && timeoutId) { + timeoutId = clearTimeout(timeoutId); + } else if (!timeoutId && wait !== maxWait) { + timeoutId = setTimeout(delayed, wait); + } + if (leadingCall) { + isCalled = true; + result = func.apply(thisArg, args); + } + if (isCalled && !timeoutId && !maxTimeoutId) { + args = thisArg = undefined; + } + return result; + } + debounced.cancel = cancel; + return debounced; + } + var defer = restParam(function(func, args) { + return baseDelay(func, 1, args); + }); + var delay = restParam(function(func, wait, args) { + return baseDelay(func, wait, args); + }); + var flow = createFlow(); + var flowRight = createFlow(true); + function memoize(func, resolver) { + if (typeof func != "function" || resolver && typeof resolver != "function") { + throw new TypeError(FUNC_ERROR_TEXT); + } + var memoized = function() { + var args = arguments, key = resolver ? resolver.apply(this, args) : args[0], cache = memoized.cache; + if (cache.has(key)) { + return cache.get(key); + } + var result = func.apply(this, args); + memoized.cache = cache.set(key, result); + return result; + }; + memoized.cache = new memoize.Cache(); + return memoized; + } + var modArgs = restParam(function(func, transforms) { + transforms = baseFlatten(transforms); + if (typeof func != "function" || !arrayEvery(transforms, baseIsFunction)) { + throw new TypeError(FUNC_ERROR_TEXT); + } + var length = transforms.length; + return restParam(function(args) { + var index = nativeMin(args.length, length); + while (index--) { + args[index] = transforms[index](args[index]); + } + return func.apply(this, args); + }); + }); + function negate(predicate) { + if (typeof predicate != "function") { + throw new TypeError(FUNC_ERROR_TEXT); + } + return function() { + return !predicate.apply(this, arguments); + }; + } + function once(func) { + return before(2, func); + } + var partial = createPartial(PARTIAL_FLAG); + var partialRight = createPartial(PARTIAL_RIGHT_FLAG); + var rearg = restParam(function(func, indexes) { + return createWrapper(func, REARG_FLAG, undefined, undefined, undefined, baseFlatten(indexes)); + }); + function restParam(func, start) { + if (typeof func != "function") { + throw new TypeError(FUNC_ERROR_TEXT); + } + start = nativeMax(start === undefined ? func.length - 1 : +start || 0, 0); + return function() { + var args = arguments, index = -1, length = nativeMax(args.length - start, 0), rest = Array(length); + while (++index < length) { + rest[index] = args[start + index]; + } + switch (start) { + case 0: + return func.call(this, rest); + + case 1: + return func.call(this, args[0], rest); + + case 2: + return func.call(this, args[0], args[1], rest); + } + var otherArgs = Array(start + 1); + index = -1; + while (++index < start) { + otherArgs[index] = args[index]; + } + otherArgs[start] = rest; + return func.apply(this, otherArgs); + }; + } + function spread(func) { + if (typeof func != "function") { + throw new TypeError(FUNC_ERROR_TEXT); + } + return function(array) { + return func.apply(this, array); + }; + } + function throttle(func, wait, options) { + var leading = true, trailing = true; + if (typeof func != "function") { + throw new TypeError(FUNC_ERROR_TEXT); + } + if (options === false) { + leading = false; + } else if (isObject(options)) { + leading = "leading" in options ? !!options.leading : leading; + trailing = "trailing" in options ? !!options.trailing : trailing; + } + return debounce(func, wait, { + leading: leading, + maxWait: +wait, + trailing: trailing + }); + } + function wrap(value, wrapper) { + wrapper = wrapper == null ? identity : wrapper; + return createWrapper(wrapper, PARTIAL_FLAG, undefined, [ value ], []); + } + function clone(value, isDeep, customizer, thisArg) { + if (isDeep && typeof isDeep != "boolean" && isIterateeCall(value, isDeep, customizer)) { + isDeep = false; + } else if (typeof isDeep == "function") { + thisArg = customizer; + customizer = isDeep; + isDeep = false; + } + return typeof customizer == "function" ? baseClone(value, isDeep, bindCallback(customizer, thisArg, 3)) : baseClone(value, isDeep); + } + function cloneDeep(value, customizer, thisArg) { + return typeof customizer == "function" ? baseClone(value, true, bindCallback(customizer, thisArg, 3)) : baseClone(value, true); + } + function gt(value, other) { + return value > other; + } + function gte(value, other) { + return value >= other; + } + function isArguments(value) { + return isObjectLike(value) && isArrayLike(value) && hasOwnProperty.call(value, "callee") && !propertyIsEnumerable.call(value, "callee"); + } + var isArray = nativeIsArray || function(value) { + return isObjectLike(value) && isLength(value.length) && objToString.call(value) == arrayTag; + }; + function isBoolean(value) { + return value === true || value === false || isObjectLike(value) && objToString.call(value) == boolTag; + } + function isDate(value) { + return isObjectLike(value) && objToString.call(value) == dateTag; + } + function isElement(value) { + return !!value && value.nodeType === 1 && isObjectLike(value) && !isPlainObject(value); + } + function isEmpty(value) { + if (value == null) { + return true; + } + if (isArrayLike(value) && (isArray(value) || isString(value) || isArguments(value) || isObjectLike(value) && isFunction(value.splice))) { + return !value.length; + } + return !keys(value).length; + } + function isEqual(value, other, customizer, thisArg) { + customizer = typeof customizer == "function" ? bindCallback(customizer, thisArg, 3) : undefined; + var result = customizer ? customizer(value, other) : undefined; + return result === undefined ? baseIsEqual(value, other, customizer) : !!result; + } + function isError(value) { + return isObjectLike(value) && typeof value.message == "string" && objToString.call(value) == errorTag; + } + function isFinite(value) { + return typeof value == "number" && nativeIsFinite(value); + } + function isFunction(value) { + return isObject(value) && objToString.call(value) == funcTag; + } + function isObject(value) { + var type = typeof value; + return !!value && (type == "object" || type == "function"); + } + function isMatch(object, source, customizer, thisArg) { + customizer = typeof customizer == "function" ? bindCallback(customizer, thisArg, 3) : undefined; + return baseIsMatch(object, getMatchData(source), customizer); + } + function isNaN(value) { + return isNumber(value) && value != +value; + } + function isNative(value) { + if (value == null) { + return false; + } + if (isFunction(value)) { + return reIsNative.test(fnToString.call(value)); + } + return isObjectLike(value) && reIsHostCtor.test(value); + } + function isNull(value) { + return value === null; + } + function isNumber(value) { + return typeof value == "number" || isObjectLike(value) && objToString.call(value) == numberTag; + } + function isPlainObject(value) { + var Ctor; + if (!(isObjectLike(value) && objToString.call(value) == objectTag && !isArguments(value)) || !hasOwnProperty.call(value, "constructor") && (Ctor = value.constructor, + typeof Ctor == "function" && !(Ctor instanceof Ctor))) { + return false; + } + var result; + baseForIn(value, function(subValue, key) { + result = key; + }); + return result === undefined || hasOwnProperty.call(value, result); + } + function isRegExp(value) { + return isObject(value) && objToString.call(value) == regexpTag; + } + function isString(value) { + return typeof value == "string" || isObjectLike(value) && objToString.call(value) == stringTag; + } + function isTypedArray(value) { + return isObjectLike(value) && isLength(value.length) && !!typedArrayTags[objToString.call(value)]; + } + function isUndefined(value) { + return value === undefined; + } + function lt(value, other) { + return value < other; + } + function lte(value, other) { + return value <= other; + } + function toArray(value) { + var length = value ? getLength(value) : 0; + if (!isLength(length)) { + return values(value); + } + if (!length) { + return []; + } + return arrayCopy(value); + } + function toPlainObject(value) { + return baseCopy(value, keysIn(value)); + } + var merge = createAssigner(baseMerge); + var assign = createAssigner(function(object, source, customizer) { + return customizer ? assignWith(object, source, customizer) : baseAssign(object, source); + }); + function create(prototype, properties, guard) { + var result = baseCreate(prototype); + if (guard && isIterateeCall(prototype, properties, guard)) { + properties = undefined; + } + return properties ? baseAssign(result, properties) : result; + } + var defaults = createDefaults(assign, assignDefaults); + var defaultsDeep = createDefaults(merge, mergeDefaults); + var findKey = createFindKey(baseForOwn); + var findLastKey = createFindKey(baseForOwnRight); + var forIn = createForIn(baseFor); + var forInRight = createForIn(baseForRight); + var forOwn = createForOwn(baseForOwn); + var forOwnRight = createForOwn(baseForOwnRight); + function functions(object) { + return baseFunctions(object, keysIn(object)); + } + function get(object, path, defaultValue) { + var result = object == null ? undefined : baseGet(object, toPath(path), path + ""); + return result === undefined ? defaultValue : result; + } + function has(object, path) { + if (object == null) { + return false; + } + var result = hasOwnProperty.call(object, path); + if (!result && !isKey(path)) { + path = toPath(path); + object = path.length == 1 ? object : baseGet(object, baseSlice(path, 0, -1)); + if (object == null) { + return false; + } + path = last(path); + result = hasOwnProperty.call(object, path); + } + return result || isLength(object.length) && isIndex(path, object.length) && (isArray(object) || isArguments(object)); + } + function invert(object, multiValue, guard) { + if (guard && isIterateeCall(object, multiValue, guard)) { + multiValue = undefined; + } + var index = -1, props = keys(object), length = props.length, result = {}; + while (++index < length) { + var key = props[index], value = object[key]; + if (multiValue) { + if (hasOwnProperty.call(result, value)) { + result[value].push(key); + } else { + result[value] = [ key ]; + } + } else { + result[value] = key; + } + } + return result; + } + var keys = !nativeKeys ? shimKeys : function(object) { + var Ctor = object == null ? undefined : object.constructor; + if (typeof Ctor == "function" && Ctor.prototype === object || typeof object != "function" && isArrayLike(object)) { + return shimKeys(object); + } + return isObject(object) ? nativeKeys(object) : []; + }; + function keysIn(object) { + if (object == null) { + return []; + } + if (!isObject(object)) { + object = Object(object); + } + var length = object.length; + length = length && isLength(length) && (isArray(object) || isArguments(object)) && length || 0; + var Ctor = object.constructor, index = -1, isProto = typeof Ctor == "function" && Ctor.prototype === object, result = Array(length), skipIndexes = length > 0; + while (++index < length) { + result[index] = index + ""; + } + for (var key in object) { + if (!(skipIndexes && isIndex(key, length)) && !(key == "constructor" && (isProto || !hasOwnProperty.call(object, key)))) { + result.push(key); + } + } + return result; + } + var mapKeys = createObjectMapper(true); + var mapValues = createObjectMapper(); + var omit = restParam(function(object, props) { + if (object == null) { + return {}; + } + if (typeof props[0] != "function") { + var props = arrayMap(baseFlatten(props), String); + return pickByArray(object, baseDifference(keysIn(object), props)); + } + var predicate = bindCallback(props[0], props[1], 3); + return pickByCallback(object, function(value, key, object) { + return !predicate(value, key, object); + }); + }); + function pairs(object) { + object = toObject(object); + var index = -1, props = keys(object), length = props.length, result = Array(length); + while (++index < length) { + var key = props[index]; + result[index] = [ key, object[key] ]; + } + return result; + } + var pick = restParam(function(object, props) { + if (object == null) { + return {}; + } + return typeof props[0] == "function" ? pickByCallback(object, bindCallback(props[0], props[1], 3)) : pickByArray(object, baseFlatten(props)); + }); + function result(object, path, defaultValue) { + var result = object == null ? undefined : object[path]; + if (result === undefined) { + if (object != null && !isKey(path, object)) { + path = toPath(path); + object = path.length == 1 ? object : baseGet(object, baseSlice(path, 0, -1)); + result = object == null ? undefined : object[last(path)]; + } + result = result === undefined ? defaultValue : result; + } + return isFunction(result) ? result.call(object) : result; + } + function set(object, path, value) { + if (object == null) { + return object; + } + var pathKey = path + ""; + path = object[pathKey] != null || isKey(path, object) ? [ pathKey ] : toPath(path); + var index = -1, length = path.length, lastIndex = length - 1, nested = object; + while (nested != null && ++index < length) { + var key = path[index]; + if (isObject(nested)) { + if (index == lastIndex) { + nested[key] = value; + } else if (nested[key] == null) { + nested[key] = isIndex(path[index + 1]) ? [] : {}; + } + } + nested = nested[key]; + } + return object; + } + function transform(object, iteratee, accumulator, thisArg) { + var isArr = isArray(object) || isTypedArray(object); + iteratee = getCallback(iteratee, thisArg, 4); + if (accumulator == null) { + if (isArr || isObject(object)) { + var Ctor = object.constructor; + if (isArr) { + accumulator = isArray(object) ? new Ctor() : []; + } else { + accumulator = baseCreate(isFunction(Ctor) ? Ctor.prototype : undefined); + } + } else { + accumulator = {}; + } + } + (isArr ? arrayEach : baseForOwn)(object, function(value, index, object) { + return iteratee(accumulator, value, index, object); + }); + return accumulator; + } + function values(object) { + return baseValues(object, keys(object)); + } + function valuesIn(object) { + return baseValues(object, keysIn(object)); + } + function inRange(value, start, end) { + start = +start || 0; + if (end === undefined) { + end = start; + start = 0; + } else { + end = +end || 0; + } + return value >= nativeMin(start, end) && value < nativeMax(start, end); + } + function random(min, max, floating) { + if (floating && isIterateeCall(min, max, floating)) { + max = floating = undefined; + } + var noMin = min == null, noMax = max == null; + if (floating == null) { + if (noMax && typeof min == "boolean") { + floating = min; + min = 1; + } else if (typeof max == "boolean") { + floating = max; + noMax = true; + } + } + if (noMin && noMax) { + max = 1; + noMax = false; + } + min = +min || 0; + if (noMax) { + max = min; + min = 0; + } else { + max = +max || 0; + } + if (floating || min % 1 || max % 1) { + var rand = nativeRandom(); + return nativeMin(min + rand * (max - min + parseFloat("1e-" + ((rand + "").length - 1))), max); + } + return baseRandom(min, max); + } + var camelCase = createCompounder(function(result, word, index) { + word = word.toLowerCase(); + return result + (index ? word.charAt(0).toUpperCase() + word.slice(1) : word); + }); + function capitalize(string) { + string = baseToString(string); + return string && string.charAt(0).toUpperCase() + string.slice(1); + } + function deburr(string) { + string = baseToString(string); + return string && string.replace(reLatin1, deburrLetter).replace(reComboMark, ""); + } + function endsWith(string, target, position) { + string = baseToString(string); + target = target + ""; + var length = string.length; + position = position === undefined ? length : nativeMin(position < 0 ? 0 : +position || 0, length); + position -= target.length; + return position >= 0 && string.indexOf(target, position) == position; + } + function escape(string) { + string = baseToString(string); + return string && reHasUnescapedHtml.test(string) ? string.replace(reUnescapedHtml, escapeHtmlChar) : string; + } + function escapeRegExp(string) { + string = baseToString(string); + return string && reHasRegExpChars.test(string) ? string.replace(reRegExpChars, escapeRegExpChar) : string || "(?:)"; + } + var kebabCase = createCompounder(function(result, word, index) { + return result + (index ? "-" : "") + word.toLowerCase(); + }); + function pad(string, length, chars) { + string = baseToString(string); + length = +length; + var strLength = string.length; + if (strLength >= length || !nativeIsFinite(length)) { + return string; + } + var mid = (length - strLength) / 2, leftLength = nativeFloor(mid), rightLength = nativeCeil(mid); + chars = createPadding("", rightLength, chars); + return chars.slice(0, leftLength) + string + chars; + } + var padLeft = createPadDir(); + var padRight = createPadDir(true); + function parseInt(string, radix, guard) { + if (guard ? isIterateeCall(string, radix, guard) : radix == null) { + radix = 0; + } else if (radix) { + radix = +radix; + } + string = trim(string); + return nativeParseInt(string, radix || (reHasHexPrefix.test(string) ? 16 : 10)); + } + function repeat(string, n) { + var result = ""; + string = baseToString(string); + n = +n; + if (n < 1 || !string || !nativeIsFinite(n)) { + return result; + } + do { + if (n % 2) { + result += string; + } + n = nativeFloor(n / 2); + string += string; + } while (n); + return result; + } + var snakeCase = createCompounder(function(result, word, index) { + return result + (index ? "_" : "") + word.toLowerCase(); + }); + var startCase = createCompounder(function(result, word, index) { + return result + (index ? " " : "") + (word.charAt(0).toUpperCase() + word.slice(1)); + }); + function startsWith(string, target, position) { + string = baseToString(string); + position = position == null ? 0 : nativeMin(position < 0 ? 0 : +position || 0, string.length); + return string.lastIndexOf(target, position) == position; + } + function template(string, options, otherOptions) { + var settings = lodash.templateSettings; + if (otherOptions && isIterateeCall(string, options, otherOptions)) { + options = otherOptions = undefined; + } + string = baseToString(string); + options = assignWith(baseAssign({}, otherOptions || options), settings, assignOwnDefaults); + var imports = assignWith(baseAssign({}, options.imports), settings.imports, assignOwnDefaults), importsKeys = keys(imports), importsValues = baseValues(imports, importsKeys); + var isEscaping, isEvaluating, index = 0, interpolate = options.interpolate || reNoMatch, source = "__p += '"; + var reDelimiters = RegExp((options.escape || reNoMatch).source + "|" + interpolate.source + "|" + (interpolate === reInterpolate ? reEsTemplate : reNoMatch).source + "|" + (options.evaluate || reNoMatch).source + "|$", "g"); + var sourceURL = "//# sourceURL=" + ("sourceURL" in options ? options.sourceURL : "lodash.templateSources[" + ++templateCounter + "]") + "\n"; + string.replace(reDelimiters, function(match, escapeValue, interpolateValue, esTemplateValue, evaluateValue, offset) { + interpolateValue || (interpolateValue = esTemplateValue); + source += string.slice(index, offset).replace(reUnescapedString, escapeStringChar); + if (escapeValue) { + isEscaping = true; + source += "' +\n__e(" + escapeValue + ") +\n'"; + } + if (evaluateValue) { + isEvaluating = true; + source += "';\n" + evaluateValue + ";\n__p += '"; + } + if (interpolateValue) { + source += "' +\n((__t = (" + interpolateValue + ")) == null ? '' : __t) +\n'"; + } + index = offset + match.length; + return match; + }); + source += "';\n"; + var variable = options.variable; + if (!variable) { + source = "with (obj) {\n" + source + "\n}\n"; + } + source = (isEvaluating ? source.replace(reEmptyStringLeading, "") : source).replace(reEmptyStringMiddle, "$1").replace(reEmptyStringTrailing, "$1;"); + source = "function(" + (variable || "obj") + ") {\n" + (variable ? "" : "obj || (obj = {});\n") + "var __t, __p = ''" + (isEscaping ? ", __e = _.escape" : "") + (isEvaluating ? ", __j = Array.prototype.join;\n" + "function print() { __p += __j.call(arguments, '') }\n" : ";\n") + source + "return __p\n}"; + var result = attempt(function() { + return Function(importsKeys, sourceURL + "return " + source).apply(undefined, importsValues); + }); + result.source = source; + if (isError(result)) { + throw result; + } + return result; + } + function trim(string, chars, guard) { + var value = string; + string = baseToString(string); + if (!string) { + return string; + } + if (guard ? isIterateeCall(value, chars, guard) : chars == null) { + return string.slice(trimmedLeftIndex(string), trimmedRightIndex(string) + 1); + } + chars = chars + ""; + return string.slice(charsLeftIndex(string, chars), charsRightIndex(string, chars) + 1); + } + function trimLeft(string, chars, guard) { + var value = string; + string = baseToString(string); + if (!string) { + return string; + } + if (guard ? isIterateeCall(value, chars, guard) : chars == null) { + return string.slice(trimmedLeftIndex(string)); + } + return string.slice(charsLeftIndex(string, chars + "")); + } + function trimRight(string, chars, guard) { + var value = string; + string = baseToString(string); + if (!string) { + return string; + } + if (guard ? isIterateeCall(value, chars, guard) : chars == null) { + return string.slice(0, trimmedRightIndex(string) + 1); + } + return string.slice(0, charsRightIndex(string, chars + "") + 1); + } + function trunc(string, options, guard) { + if (guard && isIterateeCall(string, options, guard)) { + options = undefined; + } + var length = DEFAULT_TRUNC_LENGTH, omission = DEFAULT_TRUNC_OMISSION; + if (options != null) { + if (isObject(options)) { + var separator = "separator" in options ? options.separator : separator; + length = "length" in options ? +options.length || 0 : length; + omission = "omission" in options ? baseToString(options.omission) : omission; + } else { + length = +options || 0; + } + } + string = baseToString(string); + if (length >= string.length) { + return string; + } + var end = length - omission.length; + if (end < 1) { + return omission; + } + var result = string.slice(0, end); + if (separator == null) { + return result + omission; + } + if (isRegExp(separator)) { + if (string.slice(end).search(separator)) { + var match, newEnd, substring = string.slice(0, end); + if (!separator.global) { + separator = RegExp(separator.source, (reFlags.exec(separator) || "") + "g"); + } + separator.lastIndex = 0; + while (match = separator.exec(substring)) { + newEnd = match.index; + } + result = result.slice(0, newEnd == null ? end : newEnd); + } + } else if (string.indexOf(separator, end) != end) { + var index = result.lastIndexOf(separator); + if (index > -1) { + result = result.slice(0, index); + } + } + return result + omission; + } + function unescape(string) { + string = baseToString(string); + return string && reHasEscapedHtml.test(string) ? string.replace(reEscapedHtml, unescapeHtmlChar) : string; + } + function words(string, pattern, guard) { + if (guard && isIterateeCall(string, pattern, guard)) { + pattern = undefined; + } + string = baseToString(string); + return string.match(pattern || reWords) || []; + } + var attempt = restParam(function(func, args) { + try { + return func.apply(undefined, args); + } catch (e) { + return isError(e) ? e : new Error(e); + } + }); + function callback(func, thisArg, guard) { + if (guard && isIterateeCall(func, thisArg, guard)) { + thisArg = undefined; + } + return isObjectLike(func) ? matches(func) : baseCallback(func, thisArg); + } + function constant(value) { + return function() { + return value; + }; + } + function identity(value) { + return value; + } + function matches(source) { + return baseMatches(baseClone(source, true)); + } + function matchesProperty(path, srcValue) { + return baseMatchesProperty(path, baseClone(srcValue, true)); + } + var method = restParam(function(path, args) { + return function(object) { + return invokePath(object, path, args); + }; + }); + var methodOf = restParam(function(object, args) { + return function(path) { + return invokePath(object, path, args); + }; + }); + function mixin(object, source, options) { + if (options == null) { + var isObj = isObject(source), props = isObj ? keys(source) : undefined, methodNames = props && props.length ? baseFunctions(source, props) : undefined; + if (!(methodNames ? methodNames.length : isObj)) { + methodNames = false; + options = source; + source = object; + object = this; + } + } + if (!methodNames) { + methodNames = baseFunctions(source, keys(source)); + } + var chain = true, index = -1, isFunc = isFunction(object), length = methodNames.length; + if (options === false) { + chain = false; + } else if (isObject(options) && "chain" in options) { + chain = options.chain; + } + while (++index < length) { + var methodName = methodNames[index], func = source[methodName]; + object[methodName] = func; + if (isFunc) { + object.prototype[methodName] = function(func) { + return function() { + var chainAll = this.__chain__; + if (chain || chainAll) { + var result = object(this.__wrapped__), actions = result.__actions__ = arrayCopy(this.__actions__); + actions.push({ + func: func, + args: arguments, + thisArg: object + }); + result.__chain__ = chainAll; + return result; + } + return func.apply(object, arrayPush([ this.value() ], arguments)); + }; + }(func); + } + } + return object; + } + function noConflict() { + root._ = oldDash; + return this; + } + function noop() {} + function property(path) { + return isKey(path) ? baseProperty(path) : basePropertyDeep(path); + } + function propertyOf(object) { + return function(path) { + return baseGet(object, toPath(path), path + ""); + }; + } + function range(start, end, step) { + if (step && isIterateeCall(start, end, step)) { + end = step = undefined; + } + start = +start || 0; + step = step == null ? 1 : +step || 0; + if (end == null) { + end = start; + start = 0; + } else { + end = +end || 0; + } + var index = -1, length = nativeMax(nativeCeil((end - start) / (step || 1)), 0), result = Array(length); + while (++index < length) { + result[index] = start; + start += step; + } + return result; + } + function times(n, iteratee, thisArg) { + n = nativeFloor(n); + if (n < 1 || !nativeIsFinite(n)) { + return []; + } + var index = -1, result = Array(nativeMin(n, MAX_ARRAY_LENGTH)); + iteratee = bindCallback(iteratee, thisArg, 1); + while (++index < n) { + if (index < MAX_ARRAY_LENGTH) { + result[index] = iteratee(index); + } else { + iteratee(index); + } + } + return result; + } + function uniqueId(prefix) { + var id = ++idCounter; + return baseToString(prefix) + id; + } + function add(augend, addend) { + return (+augend || 0) + (+addend || 0); + } + var ceil = createRound("ceil"); + var floor = createRound("floor"); + var max = createExtremum(gt, NEGATIVE_INFINITY); + var min = createExtremum(lt, POSITIVE_INFINITY); + var round = createRound("round"); + function sum(collection, iteratee, thisArg) { + if (thisArg && isIterateeCall(collection, iteratee, thisArg)) { + iteratee = undefined; + } + iteratee = getCallback(iteratee, thisArg, 3); + return iteratee.length == 1 ? arraySum(isArray(collection) ? collection : toIterable(collection), iteratee) : baseSum(collection, iteratee); + } + lodash.prototype = baseLodash.prototype; + LodashWrapper.prototype = baseCreate(baseLodash.prototype); + LodashWrapper.prototype.constructor = LodashWrapper; + LazyWrapper.prototype = baseCreate(baseLodash.prototype); + LazyWrapper.prototype.constructor = LazyWrapper; + MapCache.prototype["delete"] = mapDelete; + MapCache.prototype.get = mapGet; + MapCache.prototype.has = mapHas; + MapCache.prototype.set = mapSet; + SetCache.prototype.push = cachePush; + memoize.Cache = MapCache; + lodash.after = after; + lodash.ary = ary; + lodash.assign = assign; + lodash.at = at; + lodash.before = before; + lodash.bind = bind; + lodash.bindAll = bindAll; + lodash.bindKey = bindKey; + lodash.callback = callback; + lodash.chain = chain; + lodash.chunk = chunk; + lodash.compact = compact; + lodash.constant = constant; + lodash.countBy = countBy; + lodash.create = create; + lodash.curry = curry; + lodash.curryRight = curryRight; + lodash.debounce = debounce; + lodash.defaults = defaults; + lodash.defaultsDeep = defaultsDeep; + lodash.defer = defer; + lodash.delay = delay; + lodash.difference = difference; + lodash.drop = drop; + lodash.dropRight = dropRight; + lodash.dropRightWhile = dropRightWhile; + lodash.dropWhile = dropWhile; + lodash.fill = fill; + lodash.filter = filter; + lodash.flatten = flatten; + lodash.flattenDeep = flattenDeep; + lodash.flow = flow; + lodash.flowRight = flowRight; + lodash.forEach = forEach; + lodash.forEachRight = forEachRight; + lodash.forIn = forIn; + lodash.forInRight = forInRight; + lodash.forOwn = forOwn; + lodash.forOwnRight = forOwnRight; + lodash.functions = functions; + lodash.groupBy = groupBy; + lodash.indexBy = indexBy; + lodash.initial = initial; + lodash.intersection = intersection; + lodash.invert = invert; + lodash.invoke = invoke; + lodash.keys = keys; + lodash.keysIn = keysIn; + lodash.map = map; + lodash.mapKeys = mapKeys; + lodash.mapValues = mapValues; + lodash.matches = matches; + lodash.matchesProperty = matchesProperty; + lodash.memoize = memoize; + lodash.merge = merge; + lodash.method = method; + lodash.methodOf = methodOf; + lodash.mixin = mixin; + lodash.modArgs = modArgs; + lodash.negate = negate; + lodash.omit = omit; + lodash.once = once; + lodash.pairs = pairs; + lodash.partial = partial; + lodash.partialRight = partialRight; + lodash.partition = partition; + lodash.pick = pick; + lodash.pluck = pluck; + lodash.property = property; + lodash.propertyOf = propertyOf; + lodash.pull = pull; + lodash.pullAt = pullAt; + lodash.range = range; + lodash.rearg = rearg; + lodash.reject = reject; + lodash.remove = remove; + lodash.rest = rest; + lodash.restParam = restParam; + lodash.set = set; + lodash.shuffle = shuffle; + lodash.slice = slice; + lodash.sortBy = sortBy; + lodash.sortByAll = sortByAll; + lodash.sortByOrder = sortByOrder; + lodash.spread = spread; + lodash.take = take; + lodash.takeRight = takeRight; + lodash.takeRightWhile = takeRightWhile; + lodash.takeWhile = takeWhile; + lodash.tap = tap; + lodash.throttle = throttle; + lodash.thru = thru; + lodash.times = times; + lodash.toArray = toArray; + lodash.toPlainObject = toPlainObject; + lodash.transform = transform; + lodash.union = union; + lodash.uniq = uniq; + lodash.unzip = unzip; + lodash.unzipWith = unzipWith; + lodash.values = values; + lodash.valuesIn = valuesIn; + lodash.where = where; + lodash.without = without; + lodash.wrap = wrap; + lodash.xor = xor; + lodash.zip = zip; + lodash.zipObject = zipObject; + lodash.zipWith = zipWith; + lodash.backflow = flowRight; + lodash.collect = map; + lodash.compose = flowRight; + lodash.each = forEach; + lodash.eachRight = forEachRight; + lodash.extend = assign; + lodash.iteratee = callback; + lodash.methods = functions; + lodash.object = zipObject; + lodash.select = filter; + lodash.tail = rest; + lodash.unique = uniq; + mixin(lodash, lodash); + lodash.add = add; + lodash.attempt = attempt; + lodash.camelCase = camelCase; + lodash.capitalize = capitalize; + lodash.ceil = ceil; + lodash.clone = clone; + lodash.cloneDeep = cloneDeep; + lodash.deburr = deburr; + lodash.endsWith = endsWith; + lodash.escape = escape; + lodash.escapeRegExp = escapeRegExp; + lodash.every = every; + lodash.find = find; + lodash.findIndex = findIndex; + lodash.findKey = findKey; + lodash.findLast = findLast; + lodash.findLastIndex = findLastIndex; + lodash.findLastKey = findLastKey; + lodash.findWhere = findWhere; + lodash.first = first; + lodash.floor = floor; + lodash.get = get; + lodash.gt = gt; + lodash.gte = gte; + lodash.has = has; + lodash.identity = identity; + lodash.includes = includes; + lodash.indexOf = indexOf; + lodash.inRange = inRange; + lodash.isArguments = isArguments; + lodash.isArray = isArray; + lodash.isBoolean = isBoolean; + lodash.isDate = isDate; + lodash.isElement = isElement; + lodash.isEmpty = isEmpty; + lodash.isEqual = isEqual; + lodash.isError = isError; + lodash.isFinite = isFinite; + lodash.isFunction = isFunction; + lodash.isMatch = isMatch; + lodash.isNaN = isNaN; + lodash.isNative = isNative; + lodash.isNull = isNull; + lodash.isNumber = isNumber; + lodash.isObject = isObject; + lodash.isPlainObject = isPlainObject; + lodash.isRegExp = isRegExp; + lodash.isString = isString; + lodash.isTypedArray = isTypedArray; + lodash.isUndefined = isUndefined; + lodash.kebabCase = kebabCase; + lodash.last = last; + lodash.lastIndexOf = lastIndexOf; + lodash.lt = lt; + lodash.lte = lte; + lodash.max = max; + lodash.min = min; + lodash.noConflict = noConflict; + lodash.noop = noop; + lodash.now = now; + lodash.pad = pad; + lodash.padLeft = padLeft; + lodash.padRight = padRight; + lodash.parseInt = parseInt; + lodash.random = random; + lodash.reduce = reduce; + lodash.reduceRight = reduceRight; + lodash.repeat = repeat; + lodash.result = result; + lodash.round = round; + lodash.runInContext = runInContext; + lodash.size = size; + lodash.snakeCase = snakeCase; + lodash.some = some; + lodash.sortedIndex = sortedIndex; + lodash.sortedLastIndex = sortedLastIndex; + lodash.startCase = startCase; + lodash.startsWith = startsWith; + lodash.sum = sum; + lodash.template = template; + lodash.trim = trim; + lodash.trimLeft = trimLeft; + lodash.trimRight = trimRight; + lodash.trunc = trunc; + lodash.unescape = unescape; + lodash.uniqueId = uniqueId; + lodash.words = words; + lodash.all = every; + lodash.any = some; + lodash.contains = includes; + lodash.eq = isEqual; + lodash.detect = find; + lodash.foldl = reduce; + lodash.foldr = reduceRight; + lodash.head = first; + lodash.include = includes; + lodash.inject = reduce; + mixin(lodash, function() { + var source = {}; + baseForOwn(lodash, function(func, methodName) { + if (!lodash.prototype[methodName]) { + source[methodName] = func; + } + }); + return source; + }(), false); + lodash.sample = sample; + lodash.prototype.sample = function(n) { + if (!this.__chain__ && n == null) { + return sample(this.value()); + } + return this.thru(function(value) { + return sample(value, n); + }); + }; + lodash.VERSION = VERSION; + arrayEach([ "bind", "bindKey", "curry", "curryRight", "partial", "partialRight" ], function(methodName) { + lodash[methodName].placeholder = lodash; + }); + arrayEach([ "drop", "take" ], function(methodName, index) { + LazyWrapper.prototype[methodName] = function(n) { + var filtered = this.__filtered__; + if (filtered && !index) { + return new LazyWrapper(this); + } + n = n == null ? 1 : nativeMax(nativeFloor(n) || 0, 0); + var result = this.clone(); + if (filtered) { + result.__takeCount__ = nativeMin(result.__takeCount__, n); + } else { + result.__views__.push({ + size: n, + type: methodName + (result.__dir__ < 0 ? "Right" : "") + }); + } + return result; + }; + LazyWrapper.prototype[methodName + "Right"] = function(n) { + return this.reverse()[methodName](n).reverse(); + }; + }); + arrayEach([ "filter", "map", "takeWhile" ], function(methodName, index) { + var type = index + 1, isFilter = type != LAZY_MAP_FLAG; + LazyWrapper.prototype[methodName] = function(iteratee, thisArg) { + var result = this.clone(); + result.__iteratees__.push({ + iteratee: getCallback(iteratee, thisArg, 1), + type: type + }); + result.__filtered__ = result.__filtered__ || isFilter; + return result; + }; + }); + arrayEach([ "first", "last" ], function(methodName, index) { + var takeName = "take" + (index ? "Right" : ""); + LazyWrapper.prototype[methodName] = function() { + return this[takeName](1).value()[0]; + }; + }); + arrayEach([ "initial", "rest" ], function(methodName, index) { + var dropName = "drop" + (index ? "" : "Right"); + LazyWrapper.prototype[methodName] = function() { + return this.__filtered__ ? new LazyWrapper(this) : this[dropName](1); + }; + }); + arrayEach([ "pluck", "where" ], function(methodName, index) { + var operationName = index ? "filter" : "map", createCallback = index ? baseMatches : property; + LazyWrapper.prototype[methodName] = function(value) { + return this[operationName](createCallback(value)); + }; + }); + LazyWrapper.prototype.compact = function() { + return this.filter(identity); + }; + LazyWrapper.prototype.reject = function(predicate, thisArg) { + predicate = getCallback(predicate, thisArg, 1); + return this.filter(function(value) { + return !predicate(value); + }); + }; + LazyWrapper.prototype.slice = function(start, end) { + start = start == null ? 0 : +start || 0; + var result = this; + if (result.__filtered__ && (start > 0 || end < 0)) { + return new LazyWrapper(result); + } + if (start < 0) { + result = result.takeRight(-start); + } else if (start) { + result = result.drop(start); + } + if (end !== undefined) { + end = +end || 0; + result = end < 0 ? result.dropRight(-end) : result.take(end - start); + } + return result; + }; + LazyWrapper.prototype.takeRightWhile = function(predicate, thisArg) { + return this.reverse().takeWhile(predicate, thisArg).reverse(); + }; + LazyWrapper.prototype.toArray = function() { + return this.take(POSITIVE_INFINITY); + }; + baseForOwn(LazyWrapper.prototype, function(func, methodName) { + var checkIteratee = /^(?:filter|map|reject)|While$/.test(methodName), retUnwrapped = /^(?:first|last)$/.test(methodName), lodashFunc = lodash[retUnwrapped ? "take" + (methodName == "last" ? "Right" : "") : methodName]; + if (!lodashFunc) { + return; + } + lodash.prototype[methodName] = function() { + var args = retUnwrapped ? [ 1 ] : arguments, chainAll = this.__chain__, value = this.__wrapped__, isHybrid = !!this.__actions__.length, isLazy = value instanceof LazyWrapper, iteratee = args[0], useLazy = isLazy || isArray(value); + if (useLazy && checkIteratee && typeof iteratee == "function" && iteratee.length != 1) { + isLazy = useLazy = false; + } + var interceptor = function(value) { + return retUnwrapped && chainAll ? lodashFunc(value, 1)[0] : lodashFunc.apply(undefined, arrayPush([ value ], args)); + }; + var action = { + func: thru, + args: [ interceptor ], + thisArg: undefined + }, onlyLazy = isLazy && !isHybrid; + if (retUnwrapped && !chainAll) { + if (onlyLazy) { + value = value.clone(); + value.__actions__.push(action); + return func.call(value); + } + return lodashFunc.call(undefined, this.value())[0]; + } + if (!retUnwrapped && useLazy) { + value = onlyLazy ? value : new LazyWrapper(this); + var result = func.apply(value, args); + result.__actions__.push(action); + return new LodashWrapper(result, chainAll); + } + return this.thru(interceptor); + }; + }); + arrayEach([ "join", "pop", "push", "replace", "shift", "sort", "splice", "split", "unshift" ], function(methodName) { + var func = (/^(?:replace|split)$/.test(methodName) ? stringProto : arrayProto)[methodName], chainName = /^(?:push|sort|unshift)$/.test(methodName) ? "tap" : "thru", retUnwrapped = /^(?:join|pop|replace|shift)$/.test(methodName); + lodash.prototype[methodName] = function() { + var args = arguments; + if (retUnwrapped && !this.__chain__) { + return func.apply(this.value(), args); + } + return this[chainName](function(value) { + return func.apply(value, args); + }); + }; + }); + baseForOwn(LazyWrapper.prototype, function(func, methodName) { + var lodashFunc = lodash[methodName]; + if (lodashFunc) { + var key = lodashFunc.name + "", names = realNames[key] || (realNames[key] = []); + names.push({ + name: methodName, + func: lodashFunc + }); + } + }); + realNames[createHybridWrapper(undefined, BIND_KEY_FLAG).name] = [ { + name: "wrapper", + func: undefined + } ]; + LazyWrapper.prototype.clone = lazyClone; + LazyWrapper.prototype.reverse = lazyReverse; + LazyWrapper.prototype.value = lazyValue; + lodash.prototype.chain = wrapperChain; + lodash.prototype.commit = wrapperCommit; + lodash.prototype.concat = wrapperConcat; + lodash.prototype.plant = wrapperPlant; + lodash.prototype.reverse = wrapperReverse; + lodash.prototype.toString = wrapperToString; + lodash.prototype.run = lodash.prototype.toJSON = lodash.prototype.valueOf = lodash.prototype.value = wrapperValue; + lodash.prototype.collect = lodash.prototype.map; + lodash.prototype.head = lodash.prototype.first; + lodash.prototype.select = lodash.prototype.filter; + lodash.prototype.tail = lodash.prototype.rest; + return lodash; + } + var _ = runInContext(); + if (typeof define == "function" && typeof define.amd == "object" && define.amd) { + root._ = _; + define(function() { + return _; + }); + } else if (freeExports && freeModule) { + if (moduleExports) { + (freeModule.exports = _)._ = _; + } else { + freeExports._ = _; + } + } else { + root._ = _; + } +}).call(this); + (function(window, document, undefined) { "use strict"; function minErr(module, ErrorConstructor) { @@ -5391,7 +9332,7 @@ } return match; }); - message += "\nhttp://errors.angularjs.org/1.4.6/" + (module ? module + "/" : "") + code; + message += "\nhttp://errors.angularjs.org/1.4.7/" + (module ? module + "/" : "") + code; for (i = SKIP_INDEXES, paramPrefix = "?"; i < templateArgs.length; i++, paramPrefix = "&") { message += paramPrefix + "p" + (i - SKIP_INDEXES) + "=" + encodeURIComponent(toDebugString(templateArgs[i])); } @@ -6210,11 +10151,11 @@ return obj; } var version = { - full: "1.4.6", + full: "1.4.7", major: 1, minor: 4, - dot: 6, - codeName: "multiplicative-elevation" + dot: 7, + codeName: "dark-luminescence" }; function publishExternalAPI(angular) { extend(angular, { @@ -6323,6 +10264,7 @@ $httpParamSerializer: $HttpParamSerializerProvider, $httpParamSerializerJQLike: $HttpParamSerializerJQLikeProvider, $httpBackend: $HttpBackendProvider, + $xhrFactory: $xhrFactoryProvider, $location: $LocationProvider, $log: $LogProvider, $parse: $ParseProvider, @@ -6368,10 +10310,10 @@ return offset ? letter.toUpperCase() : letter; }).replace(MOZ_HACK_REGEXP, "Moz$1"); } - var SINGLE_TAG_REGEXP = /^<(\w+)\s*\/?>(?:<\/\1>|)$/; + var SINGLE_TAG_REGEXP = /^<([\w-]+)\s*\/?>(?:<\/\1>|)$/; var HTML_REGEXP = /<|&#?\w+;/; - var TAG_NAME_REGEXP = /<([\w:]+)/; - var XHTML_TAG_REGEXP = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi; + var TAG_NAME_REGEXP = /<([\w:-]+)/; + var XHTML_TAG_REGEXP = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:-]+)[^>]*)\/>/gi; var wrapMap = { option: [ 1, '" ], thead: [ 1, "", "
              " ], @@ -7614,6 +11556,9 @@ } }; return function(element, options) { + if (options.cleanupStyles) { + options.from = options.to = null; + } if (options.from) { element.css(options.from); options.from = null; @@ -8879,7 +12824,7 @@ compile: function() { return { pre: function attrInterpolatePreLinkFn(scope, element, attr) { - var $$observers = attr.$$observers || (attr.$$observers = {}); + var $$observers = attr.$$observers || (attr.$$observers = createMap()); if (EVENT_HANDLER_ATTR_REGEXP.test(name)) { throw $compileMinErr("nodomevents", "Interpolations for HTML DOM event attributes are disallowed. Please use the " + "ng- versions (such as ng-click instead of onclick) instead."); } @@ -9542,12 +13487,16 @@ } } ]; } - function createXhr() { - return new window.XMLHttpRequest(); + function $xhrFactoryProvider() { + this.$get = function() { + return function createXhr() { + return new window.XMLHttpRequest(); + }; + }; } function $HttpBackendProvider() { - this.$get = [ "$browser", "$window", "$document", function($browser, $window, $document) { - return createHttpBackend($browser, createXhr, $browser.defer, $window.angular.callbacks, $document[0]); + this.$get = [ "$browser", "$window", "$document", "$xhrFactory", function($browser, $window, $document, $xhrFactory) { + return createHttpBackend($browser, $xhrFactory, $browser.defer, $window.angular.callbacks, $document[0]); } ]; } function createHttpBackend($browser, createXhr, $browserDefer, callbacks, rawDocument) { @@ -9565,7 +13514,7 @@ callbacks[callbackId] = noop; }); } else { - var xhr = createXhr(); + var xhr = createXhr(method, url); xhr.open(method, url, true); forEach(headers, function(value, key) { if (isDefined(value)) { @@ -10273,12 +14222,18 @@ } var $parseMinErr = minErr("$parse"); function ensureSafeMemberName(name, fullExpression) { - name = isObject(name) && name.toString ? name.toString() : name; if (name === "__defineGetter__" || name === "__defineSetter__" || name === "__lookupGetter__" || name === "__lookupSetter__" || name === "__proto__") { throw $parseMinErr("isecfld", "Attempting to access a disallowed field in Angular expressions! " + "Expression: {0}", fullExpression); } return name; } + function getStringValue(name, fullExpression) { + name = name + ""; + if (!isString(name)) { + throw $parseMinErr("iseccst", "Cannot convert object to primitive value! " + "Expression: {0}", fullExpression); + } + return name; + } function ensureSafeObject(obj, fullExpression) { if (obj) { if (obj.constructor === obj) { @@ -10305,6 +14260,13 @@ } } } + function ensureSafeAssignContext(obj, fullExpression) { + if (obj) { + if (obj === 0..constructor || obj === false.constructor || obj === "".constructor || obj === {}.constructor || obj === [].constructor || obj === Function.constructor) { + throw $parseMinErr("isecaf", "Assigning to a constructor is disallowed! Expression: {0}", fullExpression); + } + } + } var OPERATORS = createMap(); forEach("+ - * / % === !== == != < > <= >= && || ! = |".split(" "), function(operator) { OPERATORS[operator] = true; @@ -11053,7 +15015,7 @@ this.stage = "main"; this.recurse(ast); var fnString = '"' + this.USE + " " + this.STRICT + '";\n' + this.filterPrefix() + "var fn=" + this.generateFunction("fn", "s,l,a,i") + extra + this.watchFns() + "return fn;"; - var fn = new Function("$filter", "ensureSafeMemberName", "ensureSafeObject", "ensureSafeFunction", "ifDefined", "plus", "text", fnString)(this.$filter, ensureSafeMemberName, ensureSafeObject, ensureSafeFunction, ifDefined, plusFn, expression); + var fn = new Function("$filter", "ensureSafeMemberName", "ensureSafeObject", "ensureSafeFunction", "getStringValue", "ensureSafeAssignContext", "ifDefined", "plus", "text", fnString)(this.$filter, ensureSafeMemberName, ensureSafeObject, ensureSafeFunction, getStringValue, ensureSafeAssignContext, ifDefined, plusFn, expression); this.state = this.stage = undefined; fn.literal = isLiteral(ast); fn.constant = isConstant(ast); @@ -11190,6 +15152,7 @@ if (ast.computed) { right = self.nextId(); self.recurse(ast.property, right); + self.getStringValue(right); self.addEnsureSafeMemberName(right); if (create && create !== 1) { self.if_(self.not(self.computedMember(left, right)), self.lazyAssign(self.computedMember(left, right), "{}")); @@ -11275,6 +15238,7 @@ self.if_(self.notNull(left.context), function() { self.recurse(ast.right, right); self.addEnsureSafeObject(self.member(left.context, left.name, left.computed)); + self.addEnsureSafeAssignContext(left.context); expression = self.member(left.context, left.name, left.computed) + ast.operator + right; self.assign(intoId, expression); recursionFn(intoId || expression); @@ -11385,6 +15349,9 @@ addEnsureSafeFunction: function(item) { this.current().body.push(this.ensureSafeFunction(item), ";"); }, + addEnsureSafeAssignContext: function(item) { + this.current().body.push(this.ensureSafeAssignContext(item), ";"); + }, ensureSafeObject: function(item) { return "ensureSafeObject(" + item + ",text)"; }, @@ -11394,6 +15361,12 @@ ensureSafeFunction: function(item) { return "ensureSafeFunction(" + item + ",text)"; }, + getStringValue: function(item) { + this.assign(item, "getStringValue(" + item + ",text)"); + }, + ensureSafeAssignContext: function(item) { + return "ensureSafeAssignContext(" + item + ",text)"; + }, lazyRecurse: function(ast, intoId, nameId, recursionFn, create, skipWatchIdCheck) { var self = this; return function() { @@ -11561,6 +15534,7 @@ var lhs = left(scope, locals, assign, inputs); var rhs = right(scope, locals, assign, inputs); ensureSafeObject(lhs.value, self.expression); + ensureSafeAssignContext(lhs.context); lhs.context[lhs.name] = rhs; return context ? { value: rhs @@ -11818,6 +15792,7 @@ var value; if (lhs != null) { rhs = right(scope, locals, assign, inputs); + rhs = getStringValue(rhs); ensureSafeMemberName(rhs, expression); if (create && create !== 1 && lhs && !lhs[rhs]) { lhs[rhs] = {}; @@ -13500,6 +17475,7 @@ if (fractionSize > 0 && number < 1) { formatedText = number.toFixed(fractionSize); number = parseFloat(formatedText); + formatedText = formatedText.replace(DECIMAL_SEP, decimalSep); } } if (number === 0) { @@ -15517,11 +19493,11 @@ function updateOptionElement(option, element) { option.element = element; element.disabled = option.disabled; - if (option.value !== element.value) element.value = option.selectValue; if (option.label !== element.label) { element.label = option.label; element.textContent = option.label; } + if (option.value !== element.value) element.value = option.selectValue; } function addOrReuseElement(parent, current, type, templateElement) { var element; @@ -15549,7 +19525,7 @@ var emptyOption_ = emptyOption && emptyOption[0]; var unknownOption_ = unknownOption && unknownOption[0]; if (emptyOption_ || unknownOption_) { - while (current && (current === emptyOption_ || current === unknownOption_)) { + while (current && (current === emptyOption_ || current === unknownOption_ || emptyOption_ && emptyOption_.nodeType === NODE_TYPE_COMMENT)) { current = current.nextSibling; } } @@ -26153,1018 +30129,77 @@ angular.module("template/modal/window.html", []).run([ "$templateCache", functio angular.module("template/pagination/pager.html", []).run([ "$templateCache", function($templateCache) { $templateCache.put("template/pagination/pager.html", '\n" + ""); -} ]); - -angular.module("template/pagination/pagination.html", []).run([ "$templateCache", function($templateCache) { - $templateCache.put("template/pagination/pagination.html", '\n" + ""); -} ]); - -angular.module("template/tooltip/tooltip-html-popup.html", []).run([ "$templateCache", function($templateCache) { - $templateCache.put("template/tooltip/tooltip-html-popup.html", '
              \n' + '
              \n' + '
              \n' + "
              \n" + ""); -} ]); - -angular.module("template/tooltip/tooltip-html-unsafe-popup.html", []).run([ "$templateCache", function($templateCache) { - $templateCache.put("template/tooltip/tooltip-html-unsafe-popup.html", '
              \n' + '
              \n' + '
              \n' + "
              \n" + ""); -} ]); - -angular.module("template/tooltip/tooltip-popup.html", []).run([ "$templateCache", function($templateCache) { - $templateCache.put("template/tooltip/tooltip-popup.html", '
              \n' + '
              \n' + '
              \n' + "
              \n" + ""); -} ]); - -angular.module("template/tooltip/tooltip-template-popup.html", []).run([ "$templateCache", function($templateCache) { - $templateCache.put("template/tooltip/tooltip-template-popup.html", '
              \n' + '
              \n' + '
              \n' + "
              \n" + ""); -} ]); - -angular.module("template/popover/popover-html.html", []).run([ "$templateCache", function($templateCache) { - $templateCache.put("template/popover/popover-html.html", '
              \n' + '
              \n' + "\n" + '
              \n' + '

              \n' + '
              \n' + "
              \n" + "
              \n" + ""); -} ]); - -angular.module("template/popover/popover-template.html", []).run([ "$templateCache", function($templateCache) { - $templateCache.put("template/popover/popover-template.html", '
              \n' + '
              \n' + "\n" + '
              \n' + '

              \n' + '
              \n' + "
              \n" + "
              \n" + ""); -} ]); - -angular.module("template/popover/popover.html", []).run([ "$templateCache", function($templateCache) { - $templateCache.put("template/popover/popover.html", '
              \n' + '
              \n' + "\n" + '
              \n' + '

              \n' + '
              \n' + "
              \n" + "
              \n" + ""); -} ]); - -angular.module("template/progressbar/bar.html", []).run([ "$templateCache", function($templateCache) { - $templateCache.put("template/progressbar/bar.html", '
              \n' + ""); -} ]); - -angular.module("template/progressbar/progress.html", []).run([ "$templateCache", function($templateCache) { - $templateCache.put("template/progressbar/progress.html", '
              '); -} ]); - -angular.module("template/progressbar/progressbar.html", []).run([ "$templateCache", function($templateCache) { - $templateCache.put("template/progressbar/progressbar.html", '
              \n' + '
              \n' + "
              \n" + ""); -} ]); - -angular.module("template/rating/rating.html", []).run([ "$templateCache", function($templateCache) { - $templateCache.put("template/rating/rating.html", '\n' + " ({{ $index < value ? '*' : ' ' }})\n" + ' \n' + "\n" + ""); -} ]); - -angular.module("template/tabs/tab.html", []).run([ "$templateCache", function($templateCache) { - $templateCache.put("template/tabs/tab.html", '
            • \n' + ' {{heading}}\n' + "
            • \n" + ""); -} ]); - -angular.module("template/tabs/tabset.html", []).run([ "$templateCache", function($templateCache) { - $templateCache.put("template/tabs/tabset.html", "
              \n" + "
                \n" + '
                \n' + '
                \n' + "
                \n" + "
                \n" + "
                \n" + ""); -} ]); - -angular.module("template/timepicker/timepicker.html", []).run([ "$templateCache", function($templateCache) { - $templateCache.put("template/timepicker/timepicker.html", "\n" + " \n" + ' \n' + ' \n' + " \n" + ' \n' + ' \n' + " \n" + " \n" + ' \n" + " \n" + ' \n" + ' \n' + " \n" + ' \n' + ' \n' + " \n" + ' \n' + ' \n' + " \n" + " \n" + "
                 
                \n' + ' \n' + " :\n' + ' \n' + "
                 
                \n" + ""); -} ]); - -angular.module("template/typeahead/typeahead-match.html", []).run([ "$templateCache", function($templateCache) { - $templateCache.put("template/typeahead/typeahead-match.html", '\n' + ""); -} ]); - -angular.module("template/typeahead/typeahead-popup.html", []).run([ "$templateCache", function($templateCache) { - $templateCache.put("template/typeahead/typeahead-popup.html", '\n" + ""); -} ]); - -!angular.$$csp() && angular.element(document).find("head").prepend(''); - -"use strict"; - -var WaveSurfer = { - defaultParams: { - height: 128, - waveColor: "#999", - progressColor: "#555", - cursorColor: "#333", - cursorWidth: 1, - skipLength: 2, - minPxPerSec: 20, - pixelRatio: window.devicePixelRatio, - fillParent: !0, - scrollParent: !1, - hideScrollbar: !1, - normalize: !1, - audioContext: null, - container: null, - dragSelection: !0, - loopSelection: !0, - audioRate: 1, - interact: !0, - splitChannels: !1, - renderer: "Canvas", - backend: "WebAudio", - mediaType: "audio" - }, - init: function(a) { - if (this.params = WaveSurfer.util.extend({}, this.defaultParams, a), this.container = "string" == typeof a.container ? document.querySelector(this.params.container) : this.params.container, - !this.container) throw new Error("Container element not found"); - if ("undefined" == typeof this.params.mediaContainer ? this.mediaContainer = this.container : "string" == typeof this.params.mediaContainer ? this.mediaContainer = document.querySelector(this.params.mediaContainer) : this.mediaContainer = this.params.mediaContainer, - !this.mediaContainer) throw new Error("Media Container element not found"); - this.savedVolume = 0, this.isMuted = !1, this.tmpEvents = [], this.createDrawer(), - this.createBackend(); - }, - createDrawer: function() { - var a = this; - this.drawer = Object.create(WaveSurfer.Drawer[this.params.renderer]), this.drawer.init(this.container, this.params), - this.drawer.on("redraw", function() { - a.drawBuffer(), a.drawer.progress(a.backend.getPlayedPercents()); - }), this.drawer.on("click", function(b, c) { - setTimeout(function() { - a.seekTo(c); - }, 0); - }), this.drawer.on("scroll", function(b) { - a.fireEvent("scroll", b); - }); - }, - createBackend: function() { - var a = this; - this.backend && this.backend.destroy(), "AudioElement" == this.params.backend && (this.params.backend = "MediaElement"), - "WebAudio" != this.params.backend || WaveSurfer.WebAudio.supportsWebAudio() || (this.params.backend = "MediaElement"), - this.backend = Object.create(WaveSurfer[this.params.backend]), this.backend.init(this.params), - this.backend.on("finish", function() { - a.fireEvent("finish"); - }), this.backend.on("play", function() { - a.fireEvent("play"); - }), this.backend.on("pause", function() { - a.fireEvent("pause"); - }), this.backend.on("audioprocess", function(b) { - a.drawer.progress(a.backend.getPlayedPercents()), a.fireEvent("audioprocess", b); - }); - }, - getDuration: function() { - return this.backend.getDuration(); - }, - getCurrentTime: function() { - return this.backend.getCurrentTime(); - }, - play: function(a, b) { - this.backend.play(a, b); - }, - pause: function() { - this.backend.pause(); - }, - playPause: function() { - this.backend.isPaused() ? this.play() : this.pause(); - }, - isPlaying: function() { - return !this.backend.isPaused(); - }, - skipBackward: function(a) { - this.skip(-a || -this.params.skipLength); - }, - skipForward: function(a) { - this.skip(a || this.params.skipLength); - }, - skip: function(a) { - var b = this.getCurrentTime() || 0, c = this.getDuration() || 1; - b = Math.max(0, Math.min(c, b + (a || 0))), this.seekAndCenter(b / c); - }, - seekAndCenter: function(a) { - this.seekTo(a), this.drawer.recenter(a); - }, - seekTo: function(a) { - var b = this.backend.isPaused(), c = this.params.scrollParent; - b && (this.params.scrollParent = !1), this.backend.seekTo(a * this.getDuration()), - this.drawer.progress(this.backend.getPlayedPercents()), b || (this.backend.pause(), - this.backend.play()), this.params.scrollParent = c, this.fireEvent("seek", a); - }, - stop: function() { - this.pause(), this.seekTo(0), this.drawer.progress(0); - }, - setVolume: function(a) { - this.backend.setVolume(a); - }, - setPlaybackRate: function(a) { - this.backend.setPlaybackRate(a); - }, - toggleMute: function() { - this.isMuted ? (this.backend.setVolume(this.savedVolume), this.isMuted = !1) : (this.savedVolume = this.backend.getVolume(), - this.backend.setVolume(0), this.isMuted = !0); - }, - toggleScroll: function() { - this.params.scrollParent = !this.params.scrollParent, this.drawBuffer(); - }, - toggleInteraction: function() { - this.params.interact = !this.params.interact; - }, - drawBuffer: function() { - var a = Math.round(this.getDuration() * this.params.minPxPerSec * this.params.pixelRatio), b = this.drawer.getWidth(), c = a; - this.params.fillParent && (!this.params.scrollParent || b > a) && (c = b); - var d = this.backend.getPeaks(c); - this.drawer.drawPeaks(d, c), this.fireEvent("redraw", d, c); - }, - zoom: function(a) { - this.params.minPxPerSec = a, this.params.scrollParent = !0, this.drawBuffer(), this.seekAndCenter(this.getCurrentTime() / this.getDuration()); - }, - loadArrayBuffer: function(a) { - this.decodeArrayBuffer(a, function(a) { - this.loadDecodedBuffer(a); - }.bind(this)); - }, - loadDecodedBuffer: function(a) { - this.backend.load(a), this.drawBuffer(), this.fireEvent("ready"); - }, - loadBlob: function(a) { - var b = this, c = new FileReader(); - c.addEventListener("progress", function(a) { - b.onProgress(a); - }), c.addEventListener("load", function(a) { - b.loadArrayBuffer(a.target.result); - }), c.addEventListener("error", function() { - b.fireEvent("error", "Error reading file"); - }), c.readAsArrayBuffer(a), this.empty(); - }, - load: function(a, b) { - switch (this.params.backend) { - case "WebAudio": - return this.loadBuffer(a); - - case "MediaElement": - return this.loadMediaElement(a, b); - } - }, - loadBuffer: function(a) { - return this.empty(), this.getArrayBuffer(a, this.loadArrayBuffer.bind(this)); - }, - loadMediaElement: function(a, b) { - this.empty(), this.backend.load(a, this.mediaContainer, b), this.tmpEvents.push(this.backend.once("canplay", function() { - this.drawBuffer(), this.fireEvent("ready"); - }.bind(this)), this.backend.once("error", function(a) { - this.fireEvent("error", a); - }.bind(this))), !b && this.backend.supportsWebAudio() && this.getArrayBuffer(a, function(a) { - this.decodeArrayBuffer(a, function(a) { - this.backend.buffer = a, this.drawBuffer(); - }.bind(this)); - }.bind(this)); - }, - decodeArrayBuffer: function(a, b) { - this.backend.decodeArrayBuffer(a, this.fireEvent.bind(this, "decoded"), this.fireEvent.bind(this, "error", "Error decoding audiobuffer")), - this.tmpEvents.push(this.once("decoded", b)); - }, - getArrayBuffer: function(a, b) { - var c = this, d = WaveSurfer.util.ajax({ - url: a, - responseType: "arraybuffer" - }); - return this.tmpEvents.push(d.on("progress", function(a) { - c.onProgress(a); - }), d.on("success", b), d.on("error", function(a) { - c.fireEvent("error", "XHR error: " + a.target.statusText); - })), d; - }, - onProgress: function(a) { - if (a.lengthComputable) var b = a.loaded / a.total; else b = a.loaded / (a.loaded + 1e6); - this.fireEvent("loading", Math.round(100 * b), a.target); - }, - exportPCM: function(a, b, c) { - a = a || 1024, b = b || 1e4, c = c || !1; - var d = this.backend.getPeaks(a, b), e = [].map.call(d, function(a) { - return Math.round(a * b) / b; - }), f = JSON.stringify(e); - return c || window.open("data:application/json;charset=utf-8," + encodeURIComponent(f)), - f; - }, - clearTmpEvents: function() { - this.tmpEvents.forEach(function(a) { - a.un(); - }); - }, - empty: function() { - this.backend.isPaused() || (this.stop(), this.backend.disconnectSource()), this.clearTmpEvents(), - this.drawer.progress(0), this.drawer.setWidth(0), this.drawer.drawPeaks({ - length: this.drawer.getWidth() - }, 0); - }, - destroy: function() { - this.fireEvent("destroy"), this.clearTmpEvents(), this.unAll(), this.backend.destroy(), - this.drawer.destroy(); - } -}; - -WaveSurfer.create = function(a) { - var b = Object.create(WaveSurfer); - return b.init(a), b; -}, WaveSurfer.util = { - extend: function(a) { - var b = Array.prototype.slice.call(arguments, 1); - return b.forEach(function(b) { - Object.keys(b).forEach(function(c) { - a[c] = b[c]; - }); - }), a; - }, - getId: function() { - return "wavesurfer_" + Math.random().toString(32).substring(2); - }, - ajax: function(a) { - var b = Object.create(WaveSurfer.Observer), c = new XMLHttpRequest(), d = !1; - return c.open(a.method || "GET", a.url, !0), c.responseType = a.responseType || "json", - c.addEventListener("progress", function(a) { - b.fireEvent("progress", a), a.lengthComputable && a.loaded == a.total && (d = !0); - }), c.addEventListener("load", function(a) { - d || b.fireEvent("progress", a), b.fireEvent("load", a), 200 == c.status || 206 == c.status ? b.fireEvent("success", c.response, a) : b.fireEvent("error", a); - }), c.addEventListener("error", function(a) { - b.fireEvent("error", a); - }), c.send(), b.xhr = c, b; - } -}, WaveSurfer.Observer = { - on: function(a, b) { - this.handlers || (this.handlers = {}); - var c = this.handlers[a]; - return c || (c = this.handlers[a] = []), c.push(b), { - name: a, - callback: b, - un: this.un.bind(this, a, b) - }; - }, - un: function(a, b) { - if (this.handlers) { - var c = this.handlers[a]; - if (c) if (b) for (var d = c.length - 1; d >= 0; d--) c[d] == b && c.splice(d, 1); else c.length = 0; - } - }, - unAll: function() { - this.handlers = null; - }, - once: function(a, b) { - var c = this, d = function() { - b.apply(this, arguments), setTimeout(function() { - c.un(a, d); - }, 0); - }; - return this.on(a, d); - }, - fireEvent: function(a) { - if (this.handlers) { - var b = this.handlers[a], c = Array.prototype.slice.call(arguments, 1); - b && b.forEach(function(a) { - a.apply(null, c); - }); - } - } -}, WaveSurfer.util.extend(WaveSurfer, WaveSurfer.Observer), WaveSurfer.WebAudio = { - scriptBufferSize: 256, - PLAYING_STATE: 0, - PAUSED_STATE: 1, - FINISHED_STATE: 2, - supportsWebAudio: function() { - return !(!window.AudioContext && !window.webkitAudioContext); - }, - getAudioContext: function() { - return WaveSurfer.WebAudio.audioContext || (WaveSurfer.WebAudio.audioContext = new (window.AudioContext || window.webkitAudioContext)()), - WaveSurfer.WebAudio.audioContext; - }, - getOfflineAudioContext: function(a) { - return WaveSurfer.WebAudio.offlineAudioContext || (WaveSurfer.WebAudio.offlineAudioContext = new (window.OfflineAudioContext || window.webkitOfflineAudioContext)(1, 2, a)), - WaveSurfer.WebAudio.offlineAudioContext; - }, - init: function(a) { - this.params = a, this.ac = a.audioContext || this.getAudioContext(), this.lastPlay = this.ac.currentTime, - this.startPosition = 0, this.scheduledPause = null, this.states = [ Object.create(WaveSurfer.WebAudio.state.playing), Object.create(WaveSurfer.WebAudio.state.paused), Object.create(WaveSurfer.WebAudio.state.finished) ], - this.createVolumeNode(), this.createScriptNode(), this.createAnalyserNode(), this.setState(this.PAUSED_STATE), - this.setPlaybackRate(this.params.audioRate); - }, - disconnectFilters: function() { - this.filters && (this.filters.forEach(function(a) { - a && a.disconnect(); - }), this.filters = null, this.analyser.connect(this.gainNode)); - }, - setState: function(a) { - this.state !== this.states[a] && (this.state = this.states[a], this.state.init.call(this)); - }, - setFilter: function() { - this.setFilters([].slice.call(arguments)); - }, - setFilters: function(a) { - this.disconnectFilters(), a && a.length && (this.filters = a, this.analyser.disconnect(), - a.reduce(function(a, b) { - return a.connect(b), b; - }, this.analyser).connect(this.gainNode)); - }, - createScriptNode: function() { - this.ac.createScriptProcessor ? this.scriptNode = this.ac.createScriptProcessor(this.scriptBufferSize) : this.scriptNode = this.ac.createJavaScriptNode(this.scriptBufferSize), - this.scriptNode.connect(this.ac.destination); - }, - addOnAudioProcess: function() { - var a = this; - this.scriptNode.onaudioprocess = function() { - var b = a.getCurrentTime(); - b >= a.getDuration() ? (a.setState(a.FINISHED_STATE), a.fireEvent("pause")) : b >= a.scheduledPause ? (a.setState(a.PAUSED_STATE), - a.fireEvent("pause")) : a.state === a.states[a.PLAYING_STATE] && a.fireEvent("audioprocess", b); - }; - }, - removeOnAudioProcess: function() { - this.scriptNode.onaudioprocess = null; - }, - createAnalyserNode: function() { - this.analyser = this.ac.createAnalyser(), this.analyser.connect(this.gainNode); - }, - createVolumeNode: function() { - this.ac.createGain ? this.gainNode = this.ac.createGain() : this.gainNode = this.ac.createGainNode(), - this.gainNode.connect(this.ac.destination); - }, - setVolume: function(a) { - this.gainNode.gain.value = a; - }, - getVolume: function() { - return this.gainNode.gain.value; - }, - decodeArrayBuffer: function(a, b, c) { - this.offlineAc || (this.offlineAc = this.getOfflineAudioContext(this.ac ? this.ac.sampleRate : 44100)), - this.offlineAc.decodeAudioData(a, function(a) { - b(a); - }.bind(this), c); - }, - getPeaks: function(a) { - for (var b = this.buffer.length / a, c = ~~(b / 10) || 1, d = this.buffer.numberOfChannels, e = [], f = [], g = 0; d > g; g++) for (var h = e[g] = [], i = this.buffer.getChannelData(g), j = 0; a > j; j++) { - for (var k = ~~(j * b), l = ~~(k + b), m = i[0], n = i[0], o = k; l > o; o += c) { - var p = i[o]; - p > n && (n = p), m > p && (m = p); - } - h[2 * j] = n, h[2 * j + 1] = m, (0 == g || n > f[2 * j]) && (f[2 * j] = n), (0 == g || m < f[2 * j + 1]) && (f[2 * j + 1] = m); - } - return this.params.splitChannels ? e : f; - }, - getPlayedPercents: function() { - return this.state.getPlayedPercents.call(this); - }, - disconnectSource: function() { - this.source && this.source.disconnect(); - }, - destroy: function() { - this.isPaused() || this.pause(), this.unAll(), this.buffer = null, this.disconnectFilters(), - this.disconnectSource(), this.gainNode.disconnect(), this.scriptNode.disconnect(), - this.analyser.disconnect(); - }, - load: function(a) { - this.startPosition = 0, this.lastPlay = this.ac.currentTime, this.buffer = a, this.createSource(); - }, - createSource: function() { - this.disconnectSource(), this.source = this.ac.createBufferSource(), this.source.start = this.source.start || this.source.noteGrainOn, - this.source.stop = this.source.stop || this.source.noteOff, this.source.playbackRate.value = this.playbackRate, - this.source.buffer = this.buffer, this.source.connect(this.analyser); - }, - isPaused: function() { - return this.state !== this.states[this.PLAYING_STATE]; - }, - getDuration: function() { - return this.buffer ? this.buffer.duration : 0; - }, - seekTo: function(a, b) { - return this.scheduledPause = null, null == a && (a = this.getCurrentTime(), a >= this.getDuration() && (a = 0)), - null == b && (b = this.getDuration()), this.startPosition = a, this.lastPlay = this.ac.currentTime, - this.state === this.states[this.FINISHED_STATE] && this.setState(this.PAUSED_STATE), - { - start: a, - end: b - }; - }, - getPlayedTime: function() { - return (this.ac.currentTime - this.lastPlay) * this.playbackRate; - }, - play: function(a, b) { - this.createSource(); - var c = this.seekTo(a, b); - a = c.start, b = c.end, this.scheduledPause = b, this.source.start(0, a, b - a), - this.setState(this.PLAYING_STATE), this.fireEvent("play"); - }, - pause: function() { - this.scheduledPause = null, this.startPosition += this.getPlayedTime(), this.source && this.source.stop(0), - this.setState(this.PAUSED_STATE), this.fireEvent("pause"); - }, - getCurrentTime: function() { - return this.state.getCurrentTime.call(this); - }, - setPlaybackRate: function(a) { - a = a || 1, this.isPaused() ? this.playbackRate = a : (this.pause(), this.playbackRate = a, - this.play()); - } -}, WaveSurfer.WebAudio.state = {}, WaveSurfer.WebAudio.state.playing = { - init: function() { - this.addOnAudioProcess(); - }, - getPlayedPercents: function() { - var a = this.getDuration(); - return this.getCurrentTime() / a || 0; - }, - getCurrentTime: function() { - return this.startPosition + this.getPlayedTime(); - } -}, WaveSurfer.WebAudio.state.paused = { - init: function() { - this.removeOnAudioProcess(); - }, - getPlayedPercents: function() { - var a = this.getDuration(); - return this.getCurrentTime() / a || 0; - }, - getCurrentTime: function() { - return this.startPosition; - } -}, WaveSurfer.WebAudio.state.finished = { - init: function() { - this.removeOnAudioProcess(), this.fireEvent("finish"); - }, - getPlayedPercents: function() { - return 1; - }, - getCurrentTime: function() { - return this.getDuration(); - } -}, WaveSurfer.util.extend(WaveSurfer.WebAudio, WaveSurfer.Observer), WaveSurfer.MediaElement = Object.create(WaveSurfer.WebAudio), -WaveSurfer.util.extend(WaveSurfer.MediaElement, { - init: function(a) { - this.params = a, this.media = { - currentTime: 0, - duration: 0, - paused: !0, - playbackRate: 1, - play: function() {}, - pause: function() {} - }, this.mediaType = a.mediaType.toLowerCase(), this.elementPosition = a.elementPosition; - }, - load: function(a, b, c) { - var d = this, e = document.createElement(this.mediaType); - e.controls = !1, e.autoplay = !1, e.preload = "auto", e.src = a, e.addEventListener("error", function() { - d.fireEvent("error", "Error loading media element"); - }), e.addEventListener("canplay", function() { - d.fireEvent("canplay"); - }), e.addEventListener("ended", function() { - d.fireEvent("finish"); - }), e.addEventListener("timeupdate", function() { - d.fireEvent("audioprocess", d.getCurrentTime()); - }); - var f = b.querySelector(this.mediaType); - f && b.removeChild(f), b.appendChild(e), this.media = e, this.peaks = c, this.onPlayEnd = null, - this.buffer = null, this.setPlaybackRate(this.playbackRate); - }, - isPaused: function() { - return !this.media || this.media.paused; - }, - getDuration: function() { - var a = this.media.duration; - return a >= 1 / 0 && (a = this.media.seekable.end()), a; - }, - getCurrentTime: function() { - return this.media && this.media.currentTime; - }, - getPlayedPercents: function() { - return this.getCurrentTime() / this.getDuration() || 0; - }, - setPlaybackRate: function(a) { - this.playbackRate = a || 1, this.media.playbackRate = this.playbackRate; - }, - seekTo: function(a) { - null != a && (this.media.currentTime = a), this.clearPlayEnd(); - }, - play: function(a, b) { - this.seekTo(a), this.media.play(), b && this.setPlayEnd(b), this.fireEvent("play"); - }, - pause: function() { - this.media && this.media.pause(), this.clearPlayEnd(), this.fireEvent("pause"); - }, - setPlayEnd: function(a) { - var b = this; - this.onPlayEnd = function(c) { - c >= a && (b.pause(), b.seekTo(a)); - }, this.on("audioprocess", this.onPlayEnd); - }, - clearPlayEnd: function() { - this.onPlayEnd && (this.un("audioprocess", this.onPlayEnd), this.onPlayEnd = null); - }, - getPeaks: function(a) { - return this.buffer ? WaveSurfer.WebAudio.getPeaks.call(this, a) : this.peaks || []; - }, - getVolume: function() { - return this.media.volume; - }, - setVolume: function(a) { - this.media.volume = a; - }, - destroy: function() { - this.pause(), this.unAll(), this.media && this.media.parentNode && this.media.parentNode.removeChild(this.media), - this.media = null; - } -}), WaveSurfer.AudioElement = WaveSurfer.MediaElement, WaveSurfer.Drawer = { - init: function(a, b) { - this.container = a, this.params = b, this.width = 0, this.height = b.height * this.params.pixelRatio, - this.lastPos = 0, this.createWrapper(), this.createElements(); - }, - createWrapper: function() { - this.wrapper = this.container.appendChild(document.createElement("wave")), this.style(this.wrapper, { - display: "block", - position: "relative", - userSelect: "none", - webkitUserSelect: "none", - height: this.params.height + "px" - }), (this.params.fillParent || this.params.scrollParent) && this.style(this.wrapper, { - width: "100%", - overflowX: this.params.hideScrollbar ? "hidden" : "auto", - overflowY: "hidden" - }), this.setupWrapperEvents(); - }, - handleEvent: function(a) { - a.preventDefault(); - var b = this.wrapper.getBoundingClientRect(); - return (a.clientX - b.left + this.wrapper.scrollLeft) / this.wrapper.scrollWidth || 0; - }, - setupWrapperEvents: function() { - var a = this; - this.wrapper.addEventListener("click", function(b) { - var c = a.wrapper.offsetHeight - a.wrapper.clientHeight; - if (0 != c) { - var d = a.wrapper.getBoundingClientRect(); - if (b.clientY >= d.bottom - c) return; - } - a.params.interact && a.fireEvent("click", b, a.handleEvent(b)); - }), this.wrapper.addEventListener("scroll", function(b) { - a.fireEvent("scroll", b); - }); - }, - drawPeaks: function(a, b) { - this.resetScroll(), this.setWidth(b), this.params.barWidth ? this.drawBars(a) : this.drawWave(a); - }, - style: function(a, b) { - return Object.keys(b).forEach(function(c) { - a.style[c] !== b[c] && (a.style[c] = b[c]); - }), a; - }, - resetScroll: function() { - null !== this.wrapper && (this.wrapper.scrollLeft = 0); - }, - recenter: function(a) { - var b = this.wrapper.scrollWidth * a; - this.recenterOnPosition(b, !0); - }, - recenterOnPosition: function(a, b) { - var c = this.wrapper.scrollLeft, d = ~~(this.wrapper.clientWidth / 2), e = a - d, f = e - c, g = this.wrapper.scrollWidth - this.wrapper.clientWidth; - if (0 != g) { - if (!b && f >= -d && d > f) { - var h = 5; - f = Math.max(-h, Math.min(h, f)), e = c + f; - } - e = Math.max(0, Math.min(g, e)), e != c && (this.wrapper.scrollLeft = e); - } - }, - getWidth: function() { - return Math.round(this.container.clientWidth * this.params.pixelRatio); - }, - setWidth: function(a) { - a != this.width && (this.width = a, this.params.fillParent || this.params.scrollParent ? this.style(this.wrapper, { - width: "" - }) : this.style(this.wrapper, { - width: ~~(this.width / this.params.pixelRatio) + "px" - }), this.updateSize()); - }, - setHeight: function(a) { - a != this.height && (this.height = a, this.style(this.wrapper, { - height: ~~(this.height / this.params.pixelRatio) + "px" - }), this.updateSize()); - }, - progress: function(a) { - var b = 1 / this.params.pixelRatio, c = Math.round(a * this.width) * b; - if (c < this.lastPos || c - this.lastPos >= b) { - if (this.lastPos = c, this.params.scrollParent) { - var d = ~~(this.wrapper.scrollWidth * a); - this.recenterOnPosition(d); - } - this.updateProgress(a); - } - }, - destroy: function() { - this.unAll(), this.wrapper && (this.container.removeChild(this.wrapper), this.wrapper = null); - }, - createElements: function() {}, - updateSize: function() {}, - drawWave: function(a, b) {}, - clearWave: function() {}, - updateProgress: function(a) {} -}, WaveSurfer.util.extend(WaveSurfer.Drawer, WaveSurfer.Observer), WaveSurfer.Drawer.Canvas = Object.create(WaveSurfer.Drawer), -WaveSurfer.util.extend(WaveSurfer.Drawer.Canvas, { - createElements: function() { - var a = this.wrapper.appendChild(this.style(document.createElement("canvas"), { - position: "absolute", - zIndex: 1, - left: 0, - top: 0, - bottom: 0 - })); - if (this.waveCc = a.getContext("2d"), this.progressWave = this.wrapper.appendChild(this.style(document.createElement("wave"), { - position: "absolute", - zIndex: 2, - left: 0, - top: 0, - bottom: 0, - overflow: "hidden", - width: "0", - display: "none", - boxSizing: "border-box", - borderRightStyle: "solid", - borderRightWidth: this.params.cursorWidth + "px", - borderRightColor: this.params.cursorColor - })), this.params.waveColor != this.params.progressColor) { - var b = this.progressWave.appendChild(document.createElement("canvas")); - this.progressCc = b.getContext("2d"); - } - }, - updateSize: function() { - var a = Math.round(this.width / this.params.pixelRatio); - this.waveCc.canvas.width = this.width, this.waveCc.canvas.height = this.height, - this.style(this.waveCc.canvas, { - width: a + "px" - }), this.style(this.progressWave, { - display: "block" - }), this.progressCc && (this.progressCc.canvas.width = this.width, this.progressCc.canvas.height = this.height, - this.style(this.progressCc.canvas, { - width: a + "px" - })), this.clearWave(); - }, - clearWave: function() { - this.waveCc.clearRect(0, 0, this.width, this.height), this.progressCc && this.progressCc.clearRect(0, 0, this.width, this.height); - }, - drawBars: function(a, b) { - if (a[0] instanceof Array) { - var c = a; - if (this.params.splitChannels) return this.setHeight(c.length * this.params.height * this.params.pixelRatio), - void c.forEach(this.drawBars, this); - a = c[0]; - } - var d = .5 / this.params.pixelRatio, e = this.width, f = this.params.height * this.params.pixelRatio, g = f * b || 0, h = f / 2, i = ~~(a.length / 2), j = this.params.barWidth * this.params.pixelRatio, k = Math.max(this.params.pixelRatio, ~~(j / 2)), l = j + k, m = 1; - if (this.params.normalize) { - var n, o; - o = Math.max.apply(Math, a), n = Math.min.apply(Math, a), m = o, -n > m && (m = -n); - } - var p = i / e; - this.waveCc.fillStyle = this.params.waveColor, this.progressCc && (this.progressCc.fillStyle = this.params.progressColor), - [ this.waveCc, this.progressCc ].forEach(function(b) { - if (b) if (this.params.reflection) for (var c = 0; e > c; c += l) { - var f = Math.round(a[2 * c * p] / m * h); - b.fillRect(c + d, h - f + g, j + d, 2 * f); - } else { - for (var c = 0; e > c; c += l) { - var f = Math.round(a[2 * c * p] / m * h); - b.fillRect(c + d, h - f + g, j + d, f); - } - for (var c = 0; e > c; c += l) { - var f = Math.round(a[2 * c * p + 1] / m * h); - b.fillRect(c + d, h - f + g, j + d, f); - } - } - }, this); - }, - drawWave: function(a, b) { - if (a[0] instanceof Array) { - var c = a; - if (this.params.splitChannels) return this.setHeight(c.length * this.params.height * this.params.pixelRatio), - void c.forEach(this.drawWave, this); - a = c[0]; - } - var d = .5 / this.params.pixelRatio, e = this.params.height * this.params.pixelRatio, f = e * b || 0, g = e / 2, h = ~~(a.length / 2), i = 1; - this.params.fillParent && this.width != h && (i = this.width / h); - var j = 1; - if (this.params.normalize) { - var k, l; - l = Math.max.apply(Math, a), k = Math.min.apply(Math, a), j = l, -k > j && (j = -k); - } - this.waveCc.fillStyle = this.params.waveColor, this.progressCc && (this.progressCc.fillStyle = this.params.progressColor), - [ this.waveCc, this.progressCc ].forEach(function(b) { - if (b) { - b.beginPath(), b.moveTo(d, g + f); - for (var c = 0; h > c; c++) { - var e = Math.round(a[2 * c] / j * g); - b.lineTo(c * i + d, g - e + f); - } - for (var c = h - 1; c >= 0; c--) { - var e = Math.round(a[2 * c + 1] / j * g); - b.lineTo(c * i + d, g - e + f); - } - b.closePath(), b.fill(), b.fillRect(0, g + f - d, this.width, d); - } - }, this); - }, - updateProgress: function(a) { - var b = Math.round(this.width * a) / this.params.pixelRatio; - this.style(this.progressWave, { - width: b + "px" - }); - } -}); +} ]); -var app = angular.module("autocomplete", []); +angular.module("template/pagination/pagination.html", []).run([ "$templateCache", function($templateCache) { + $templateCache.put("template/pagination/pagination.html", '\n" + ""); +} ]); -app.directive("autocomplete", function() { - var index = -1; - return { - restrict: "E", - scope: { - searchParam: "=ngModel", - suggestions: "=data", - onType: "=onType", - onSelect: "=onSelect", - autocompleteRequired: "=" - }, - controller: [ "$scope", function($scope) { - $scope.selectedIndex = -1; - $scope.initLock = true; - $scope.setIndex = function(i) { - $scope.selectedIndex = parseInt(i); - }; - this.setIndex = function(i) { - $scope.setIndex(i); - $scope.$apply(); - }; - $scope.getIndex = function(i) { - return $scope.selectedIndex; - }; - var watching = true; - $scope.completing = false; - $scope.$watch("searchParam", function(newValue, oldValue) { - if (oldValue === newValue || !oldValue && $scope.initLock) { - return; - } - if (watching && typeof $scope.searchParam !== "undefined" && $scope.searchParam !== null) { - $scope.completing = true; - $scope.searchFilter = $scope.searchParam; - $scope.selectedIndex = -1; - } - if ($scope.onType) $scope.onType($scope.searchParam); - }); - this.preSelect = function(suggestion) { - watching = false; - $scope.$apply(); - watching = true; - }; - $scope.preSelect = this.preSelect; - this.preSelectOff = function() { - watching = true; - }; - $scope.preSelectOff = this.preSelectOff; - $scope.select = function(suggestion) { - if (suggestion) { - $scope.searchParam = suggestion; - $scope.searchFilter = suggestion; - if ($scope.onSelect) $scope.onSelect(suggestion); - } - watching = false; - $scope.completing = false; - setTimeout(function() { - watching = true; - }, 1e3); - $scope.setIndex(-1); - }; - } ], - link: function(scope, element, attrs) { - setTimeout(function() { - scope.initLock = false; - scope.$apply(); - }, 250); - var attr = ""; - scope.attrs = { - placeholder: "start typing...", - "class": "", - id: "", - inputclass: "", - inputid: "" - }; - for (var a in attrs) { - attr = a.replace("attr", "").toLowerCase(); - if (a.indexOf("attr") === 0) { - scope.attrs[attr] = attrs[a]; - } - } - if (attrs.clickActivation) { - element[0].onclick = function(e) { - if (!scope.searchParam) { - setTimeout(function() { - scope.completing = true; - scope.$apply(); - }, 200); - } - }; - } - var key = { - left: 37, - up: 38, - right: 39, - down: 40, - enter: 13, - esc: 27, - tab: 9 - }; - document.addEventListener("keydown", function(e) { - var keycode = e.keyCode || e.which; - switch (keycode) { - case key.esc: - scope.select(); - scope.setIndex(-1); - scope.$apply(); - e.preventDefault(); - } - }, true); - document.addEventListener("blur", function(e) { - setTimeout(function() { - scope.select(); - scope.setIndex(-1); - scope.$apply(); - }, 150); - }, true); - element[0].addEventListener("keydown", function(e) { - var keycode = e.keyCode || e.which; - var l = angular.element(this).find("li").length; - if (!scope.completing || l == 0) return; - switch (keycode) { - case key.up: - index = scope.getIndex() - 1; - if (index < -1) { - index = l - 1; - } else if (index >= l) { - index = -1; - scope.setIndex(index); - scope.preSelectOff(); - break; - } - scope.setIndex(index); - if (index !== -1) scope.preSelect(angular.element(angular.element(this).find("li")[index]).text()); - scope.$apply(); - break; +angular.module("template/tooltip/tooltip-html-popup.html", []).run([ "$templateCache", function($templateCache) { + $templateCache.put("template/tooltip/tooltip-html-popup.html", '
                \n' + '
                \n' + '
                \n' + "
                \n" + ""); +} ]); - case key.down: - index = scope.getIndex() + 1; - if (index < -1) { - index = l - 1; - } else if (index >= l) { - index = -1; - scope.setIndex(index); - scope.preSelectOff(); - scope.$apply(); - break; - } - scope.setIndex(index); - if (index !== -1) scope.preSelect(angular.element(angular.element(this).find("li")[index]).text()); - break; +angular.module("template/tooltip/tooltip-html-unsafe-popup.html", []).run([ "$templateCache", function($templateCache) { + $templateCache.put("template/tooltip/tooltip-html-unsafe-popup.html", '
                \n' + '
                \n' + '
                \n' + "
                \n" + ""); +} ]); - case key.left: - break; +angular.module("template/tooltip/tooltip-popup.html", []).run([ "$templateCache", function($templateCache) { + $templateCache.put("template/tooltip/tooltip-popup.html", '
                \n' + '
                \n' + '
                \n' + "
                \n" + ""); +} ]); - case key.right: - case key.enter: - case key.tab: - index = scope.getIndex(); - if (index !== -1) { - scope.select(angular.element(angular.element(this).find("li")[index]).text()); - if (keycode == key.enter) { - e.preventDefault(); - } - } else { - if (keycode == key.enter) { - scope.select(); - } - } - scope.setIndex(-1); - scope.$apply(); - break; +angular.module("template/tooltip/tooltip-template-popup.html", []).run([ "$templateCache", function($templateCache) { + $templateCache.put("template/tooltip/tooltip-template-popup.html", '
                \n' + '
                \n' + '
                \n' + "
                \n" + ""); +} ]); - case key.esc: - scope.select(); - scope.setIndex(-1); - scope.$apply(); - e.preventDefault(); - break; +angular.module("template/popover/popover-html.html", []).run([ "$templateCache", function($templateCache) { + $templateCache.put("template/popover/popover-html.html", '
                \n' + '
                \n' + "\n" + '
                \n' + '

                \n' + '
                \n' + "
                \n" + "
                \n" + ""); +} ]); - default: - return; - } - }); - }, - template: '
                ' - }; -}); +angular.module("template/popover/popover-template.html", []).run([ "$templateCache", function($templateCache) { + $templateCache.put("template/popover/popover-template.html", '
                \n' + '
                \n' + "\n" + '
                \n' + '

                \n' + '
                \n' + "
                \n" + "
                \n" + ""); +} ]); -app.filter("highlight", [ "$sce", function($sce) { - return function(input, searchParam) { - if (typeof input === "function") return ""; - if (searchParam) { - var words = "(" + searchParam.split(/\ /).join(" |") + "|" + searchParam.split(/\ /).join("|") + ")", exp = new RegExp(words, "gi"); - if (words.length) { - input = input.replace(exp, '$1'); - } - } - return $sce.trustAsHtml(input); - }; +angular.module("template/popover/popover.html", []).run([ "$templateCache", function($templateCache) { + $templateCache.put("template/popover/popover.html", '
                \n' + '
                \n' + "\n" + '
                \n' + '

                \n' + '
                \n' + "
                \n" + "
                \n" + ""); } ]); -app.directive("suggestion", function() { - return { - restrict: "A", - require: "^autocomplete", - link: function(scope, element, attrs, autoCtrl) { - element.bind("mouseenter", function() { - autoCtrl.preSelect(attrs.val); - autoCtrl.setIndex(attrs.index); - }); - element.bind("mouseleave", function() { - autoCtrl.preSelectOff(); - }); - } - }; -}); +angular.module("template/progressbar/bar.html", []).run([ "$templateCache", function($templateCache) { + $templateCache.put("template/progressbar/bar.html", '
                \n' + ""); +} ]); + +angular.module("template/progressbar/progress.html", []).run([ "$templateCache", function($templateCache) { + $templateCache.put("template/progressbar/progress.html", '
                '); +} ]); + +angular.module("template/progressbar/progressbar.html", []).run([ "$templateCache", function($templateCache) { + $templateCache.put("template/progressbar/progressbar.html", '
                \n' + '
                \n' + "
                \n" + ""); +} ]); + +angular.module("template/rating/rating.html", []).run([ "$templateCache", function($templateCache) { + $templateCache.put("template/rating/rating.html", '\n' + " ({{ $index < value ? '*' : ' ' }})\n" + ' \n' + "\n" + ""); +} ]); + +angular.module("template/tabs/tab.html", []).run([ "$templateCache", function($templateCache) { + $templateCache.put("template/tabs/tab.html", '
              • \n' + ' {{heading}}\n' + "
              • \n" + ""); +} ]); + +angular.module("template/tabs/tabset.html", []).run([ "$templateCache", function($templateCache) { + $templateCache.put("template/tabs/tabset.html", "
                \n" + "
                  \n" + '
                  \n' + '
                  \n' + "
                  \n" + "
                  \n" + "
                  \n" + ""); +} ]); + +angular.module("template/timepicker/timepicker.html", []).run([ "$templateCache", function($templateCache) { + $templateCache.put("template/timepicker/timepicker.html", "\n" + " \n" + ' \n' + ' \n' + " \n" + ' \n' + ' \n' + " \n" + " \n" + ' \n" + " \n" + ' \n" + ' \n' + " \n" + ' \n' + ' \n' + " \n" + ' \n' + ' \n' + " \n" + " \n" + "
                   
                  \n' + ' \n' + " :\n' + ' \n' + "
                   
                  \n" + ""); +} ]); + +angular.module("template/typeahead/typeahead-match.html", []).run([ "$templateCache", function($templateCache) { + $templateCache.put("template/typeahead/typeahead-match.html", '\n' + ""); +} ]); + +angular.module("template/typeahead/typeahead-popup.html", []).run([ "$templateCache", function($templateCache) { + $templateCache.put("template/typeahead/typeahead-popup.html", '\n" + ""); +} ]); + +!angular.$$csp() && angular.element(document).find("head").prepend(''); function getCookie(name) { var nameEQ = name + "="; @@ -27228,6 +30263,12 @@ var cloneObject = function(oldObject) { return JSON.parse(JSON.stringify(oldObject)); }; +var enableControls = function(controls, enabled) { + _.each(controls, function(value, key) { + controls[key] = enabled; + }); +}; + var lingvodoc = {}; lingvodoc.Object = function(clientId, objectId) { @@ -27235,10 +30276,7 @@ lingvodoc.Object = function(clientId, objectId) { this.object_id = objectId; this.type = "abstract"; this.getId = function() { - return this.client_id + "" + this.object_id; - }; - this.export = function() { - return {}; + return this.client_id + "_" + this.object_id; }; }; @@ -27299,13 +30337,33 @@ lingvodoc.Perspective = function(client_id, object_id, parent_client_id, parent_ this.is_template = is_template; this.marked_for_deletion = marked_for_deletion; this.fields = []; + this.location = null; + this.blobs = []; + this.additional_metadata = {}; this.equals = function(obj) { return lingvodoc.Object.prototype.equals.call(this, obj) && this.translation == obj.translation; }; }; lingvodoc.Perspective.fromJS = function(js) { - return new lingvodoc.Perspective(js.client_id, js.object_id, js.parent_client_id, js.parent_object_id, js.translation, js.translation_string, js.status, js.is_template, js.marked_for_deletion); + var perspective = new lingvodoc.Perspective(js.client_id, js.object_id, js.parent_client_id, js.parent_object_id, js.translation, js.translation_string, js.status, js.is_template, js.marked_for_deletion); + if (_.has(js, "location") && _.has(js.location, "content")) { + perspective["location"] = { + lat: js.location.content.lat, + lng: js.location.content.lng + }; + } + if (_.has(js, "info") && js.info.type == "list") { + if (_.isArray(js.info.content)) { + perspective["blobs"] = _.map(js.info.content, function(e) { + var blob = new lingvodoc.Blob(e.info.content.client_id, e.info.content.object_id, e.info.content.name, e.info.content.data_type); + blob.url = e.info.content.content; + return blob; + }); + } + } + perspective.additional_metadata = js.additional_metadata; + return perspective; }; lingvodoc.Perspective.prototype = new lingvodoc.Object(); @@ -27330,6 +30388,25 @@ lingvodoc.User.fromJS = function(js) { return new lingvodoc.User(js.id, js.login, js.name, js.email, js.intl_name, js.about, js.signup_date, js.organizations); }; +lingvodoc.Blob = function(clientId, objectId, name, data_type) { + lingvodoc.Object.call(this, clientId, objectId); + this.type = "blob"; + this.name = name; + this.data_type = data_type; + this.url = null; + this.equals = function(obj) { + return lingvodoc.Object.prototype.equals.call(this, obj) && this.name == obj.name; + }; +}; + +lingvodoc.Blob.fromJS = function(js) { + return new lingvodoc.Blob(js.client_id, js.object_id, js.name, js.data_type); +}; + +lingvodoc.Blob.prototype = new lingvodoc.Object(); + +lingvodoc.Blob.prototype.constructor = lingvodoc.Blob; + function lingvodocAPI($http, $q) { var addUrlParameter = function(url, key, value) { return url + (url.indexOf("?") >= 0 ? "&" : "?") + encodeURIComponent(key) + "=" + encodeURIComponent(value); @@ -27403,6 +30480,21 @@ function lingvodocAPI($http, $q) { }); return deferred.promise; }; + var getPerspectiveDictionaryFieldsNew = function(perspective) { + var deferred = $q.defer(); + var url = "/dictionary/" + perspective.parent_client_id + "/" + perspective.parent_object_id + "/perspective/" + perspective.client_id + "/" + perspective.object_id + "/fields"; + $http.get(url).success(function(data, status, headers, config) { + if (_.isArray(data.fields)) { + var fields = perspectiveToDictionaryFields(data.fields); + deferred.resolve(fields); + } else { + deferred.reject("An error occurred while fetching perspective fields"); + } + }).error(function(data, status, headers, config) { + deferred.reject("An error occurred while fetching perspective fields"); + }); + return deferred.promise; + }; var removeValue = function(entry, field, fieldValue, parent) { var deferred = $q.defer(); var url; @@ -27569,8 +30661,9 @@ function lingvodocAPI($http, $q) { }); return deferred.promise; }; - var getDictionaryProperties = function(url) { + var getDictionaryProperties = function(dictionary) { var deferred = $q.defer(); + var url = "/dictionary/" + encodeURIComponent(dictionary.client_id) + "/" + encodeURIComponent(dictionary.object_id); $http.get(url).success(function(data, status, headers, config) { deferred.resolve(data); }).error(function(data, status, headers, config) { @@ -27578,8 +30671,9 @@ function lingvodocAPI($http, $q) { }); return deferred.promise; }; - var setDictionaryProperties = function(url, properties) { + var setDictionaryProperties = function(dictionary, properties) { var deferred = $q.defer(); + var url = "/dictionary/" + encodeURIComponent(dictionary.client_id) + "/" + encodeURIComponent(dictionary.object_id); $http.put(url, properties).success(function(data, status, headers, config) { deferred.resolve(data); }).error(function(data, status, headers, config) { @@ -27587,6 +30681,16 @@ function lingvodocAPI($http, $q) { }); return deferred.promise; }; + var removeDictionary = function(dictionary) { + var deferred = $q.defer(); + var url = "/dictionary/" + encodeURIComponent(dictionary.client_id) + "/" + encodeURIComponent(dictionary.object_id); + $http.delete(url).success(function(data, status, headers, config) { + deferred.resolve(); + }).error(function(data, status, headers, config) { + deferred.reject("An error occurred while trying to delete dictionary"); + }); + return deferred.promise; + }; var getLanguages = function(url) { var deferred = $q.defer(); var flatLanguages = function(languages) { @@ -27670,6 +30774,16 @@ function lingvodocAPI($http, $q) { }); return deferred.promise; }; + var removePerspective = function(perspective) { + var deferred = $q.defer(); + var url = "/dictionary/" + perspective.parent_client_id + "/" + perspective.parent_object_id + "/perspective/" + perspective.client_id + "/" + perspective.object_id; + $http.delete(url).success(function(data, status, headers, config) { + deferred.resolve(); + }).error(function(data, status, headers, config) { + deferred.reject("An error occurred while trying to delete perspective"); + }); + return deferred.promise; + }; var getUserInfo = function(userId, clientId) { var deferred = $q.defer(); var url = "/user" + "?client_id= " + encodeURIComponent(clientId) + "&user_id= " + encodeURIComponent(userId); @@ -27750,13 +30864,14 @@ function lingvodocAPI($http, $q) { }; var getDictionaries = function(query) { var deferred = $q.defer(); - var dictionaries = []; $http.post("/dictionaries", query).success(function(data, status, headers, config) { - for (var i = 0; i < data.dictionaries.length; i++) { - var dictionary = data.dictionaries[i]; - dictionaries.push(lingvodoc.Dictionary.fromJS(dictionary)); + if (_.isArray(data.dictionaries)) { + deferred.resolve(_.map(data.dictionaries, function(d) { + return lingvodoc.Dictionary.fromJS(d); + })); + } else { + deferred.reject("Failed to fetch dictionaries list. Malformed response."); } - deferred.resolve(dictionaries); }).error(function(data, status, headers, config) { deferred.reject("Failed to fetch dictionaries list"); }); @@ -27973,8 +31088,8 @@ function lingvodocAPI($http, $q) { }; $http.post("/dictionaries", req).success(function(data, status, headers, config) { var dictionaries = []; - if (angular.isArray(data.dictionaries)) { - angular.forEach(data.dictionaries, function(jsdict) { + if (_.isArray(data.dictionaries)) { + _.forEach(data.dictionaries, function(jsdict) { var dictionary = lingvodoc.Dictionary.fromJS(jsdict); if (language.client_id == dictionary.parent_client_id && language.object_id == dictionary.parent_object_id) { dictionaries.push(dictionary); @@ -27983,7 +31098,7 @@ function lingvodocAPI($http, $q) { } deferred.resolve(dictionaries); }).error(function(data, status, headers, config) { - deferred.reject("Failed to move lexical entry"); + deferred.reject("Failed to fetch list of dictionaries"); }); return deferred.promise; }; @@ -28166,10 +31281,140 @@ function lingvodocAPI($http, $q) { }); return deferred.promise; }; + var getUserBlobs = function() { + var deferred = $q.defer(); + $http.get("/blobs").success(function(data, status, headers, config) { + var blobs = _.map(data, lingvodoc.Blob.fromJS); + deferred.resolve(blobs); + }).error(function(data, status, headers, config) { + deferred.reject("Failed to fetch list of available blobs"); + }); + return deferred.promise; + }; + var checkDictionaryBlob = function(blob, parent) { + var deferred = $q.defer(); + var query = { + blob_client_id: blob.client_id, + blob_object_id: blob.object_id, + parent_client_id: parent.client_id, + parent_object_id: parent.object_id + }; + $http.post("/convert_check", query).success(function(data, status, headers, config) { + var perspectives = _.map(data, lingvodoc.Perspective.fromJS); + deferred.resolve(perspectives); + }).error(function(data, status, headers, config) { + deferred.reject("Failed to convert dictionary"); + }); + return deferred.promise; + }; + var convertDictionary = function(req) { + var deferred = $q.defer(); + $http.post("/convert", req).success(function(data, status, headers, config) { + deferred.resolve(data); + }).error(function(data, status, headers, config) { + deferred.reject("Failed to convert dictionary"); + }); + return deferred.promise; + }; + var getPerspectiveMeta = function(dictionary, perspective) { + var deferred = $q.defer(); + var url = "/dictionary/" + encodeURIComponent(dictionary.client_id) + "/" + encodeURIComponent(dictionary.object_id) + "/perspective/" + encodeURIComponent(perspective.client_id) + "/" + encodeURIComponent(perspective.object_id) + "/meta"; + $http.get(url).success(function(data, status, headers, config) { + deferred.resolve(data); + }).error(function(data, status, headers, config) { + deferred.reject("Failed to get perspective meta data!"); + }); + return deferred.promise; + }; + var setPerspectiveMeta = function(dictionary, perspective, meta) { + var deferred = $q.defer(); + var url = "/dictionary/" + encodeURIComponent(dictionary.client_id) + "/" + encodeURIComponent(dictionary.object_id) + "/perspective/" + encodeURIComponent(perspective.client_id) + "/" + encodeURIComponent(perspective.object_id) + "/meta"; + $http.put(url, meta).success(function(data, status, headers, config) { + deferred.resolve(data); + }).error(function(data, status, headers, config) { + deferred.reject("Failed to set perspective meta data!"); + }); + return deferred.promise; + }; + var removePerspectiveMeta = function(dictionary, perspective, meta) { + var deferred = $q.defer(); + var url = "/dictionary/" + encodeURIComponent(dictionary.client_id) + "/" + encodeURIComponent(dictionary.object_id) + "/perspective/" + encodeURIComponent(perspective.client_id) + "/" + encodeURIComponent(perspective.object_id) + "/meta"; + var config = { + method: "DELETE", + url: url, + data: meta, + headers: { + "Content-Type": "application/json;charset=utf-8" + } + }; + $http(config).success(function(data, status, headers, config) { + deferred.resolve(data); + }).error(function(data, status, headers, config) { + deferred.reject("Failed to remove perspective meta data!"); + }); + return deferred.promise; + }; + var advancedSearch = function(query, where, adopted, etymology) { + var deferred = $q.defer(); + var url = "/advanced_search"; + var perspectives = where.map(function(o) { + if (o.type == "perspective") { + return { + client_id: o.client_id, + object_id: o.object_id + }; + } + }).filter(function(o) { + return typeof o !== "undefined"; + }); + var req = { + searchstrings: query, + perspectives: perspectives + }; + if (_.isBoolean(adopted)) { + req.adopted = adopted; + } + if (_.isBoolean(etymology)) { + req.with_etimology = etymology; + } + $http.post(url, req).success(function(data, status, headers, config) { + var r = data.map(function(e) { + var perspective = lingvodoc.Perspective.fromJS(e); + return getPerspectiveOriginById(perspective.client_id, perspective.object_id); + }); + $q.all(r).then(function(paths) { + var out = []; + _.each(data, function(entry, i) { + entry.lexical_entry["origin"] = paths[i]; + out.push(entry.lexical_entry); + }); + deferred.resolve(out); + }, function(reason) { + deferred.reject("An error occurred while doing basic search"); + }); + }).error(function(data, status, headers, config) { + deferred.reject("An error occurred while doing advanced search"); + }); + return deferred.promise; + }; + var convertMarkup = function(object) { + var deferred = $q.defer(); + var obj = { + client_id: object.client_id, + object_id: object.object_id + }; + $http.post("/convert/markup", obj).success(function(data, status, headers, config) { + deferred.resolve(data); + }).error(function(data, status, headers, config) { + deferred.reject("Failed to convert markup!"); + }); + return deferred.promise; + }; return { getLexicalEntries: getLexicalEntries, getLexicalEntriesCount: getLexicalEntriesCount, getPerspectiveDictionaryFields: getPerspectiveDictionaryFields, + getPerspectiveDictionaryFieldsNew: getPerspectiveDictionaryFieldsNew, addNewLexicalEntry: addNewLexicalEntry, saveValue: saveValue, removeValue: removeValue, @@ -28180,6 +31425,7 @@ function lingvodocAPI($http, $q) { approveAll: approveAll, getDictionaryProperties: getDictionaryProperties, setDictionaryProperties: setDictionaryProperties, + removeDictionary: removeDictionary, getLanguages: getLanguages, setDictionaryStatus: setDictionaryStatus, setPerspectiveStatus: setPerspectiveStatus, @@ -28187,6 +31433,7 @@ function lingvodocAPI($http, $q) { getPerspectiveFields: getPerspectiveFields, setPerspectiveFields: setPerspectiveFields, getPerspectiveFieldsNew: getPerspectiveFieldsNew, + removePerspective: removePerspective, getUserInfo: getUserInfo, setUserInfo: setUserInfo, getOrganizations: getOrganizations, @@ -28213,7 +31460,15 @@ function lingvodocAPI($http, $q) { deleteDictionaryRoles: deleteDictionaryRoles, getPerspectiveRoles: getPerspectiveRoles, addPerspectiveRoles: addPerspectiveRoles, - deletePerspectiveRoles: deletePerspectiveRoles + deletePerspectiveRoles: deletePerspectiveRoles, + getUserBlobs: getUserBlobs, + checkDictionaryBlob: checkDictionaryBlob, + convertDictionary: convertDictionary, + getPerspectiveMeta: getPerspectiveMeta, + setPerspectiveMeta: setPerspectiveMeta, + removePerspectiveMeta: removePerspectiveMeta, + advancedSearch: advancedSearch, + convertMarkup: convertMarkup }; } @@ -28245,9 +31500,34 @@ function responseHandler($timeout, $modal) { function error(message) { show("error", message, 5e3); } + function yesno(status, message, callback) { + var controller = function($scope, $modalInstance) { + $scope.status = status; + $scope.message = message; + $scope.yes = function() { + $modalInstance.close(true); + }; + $scope.no = function() { + $modalInstance.close(false); + }; + }; + $modal.open({ + animation: true, + templateUrl: "responseHandlerYesNoModal.html", + controller: controller, + size: "lg", + backdrop: "static", + keyboard: false + }).result.then(function(result) { + callback(result); + }, function() { + callback(false); + }); + } return { success: success, - error: error + error: error, + yesno: yesno }; } diff --git a/lingvodoc/static/js/profile.js b/lingvodoc/static/js/profile.js index 80cca8839..6fca0138a 100644 --- a/lingvodoc/static/js/profile.js +++ b/lingvodoc/static/js/profile.js @@ -5377,6 +5377,3947 @@ return jQuery; }); +(function() { + var undefined; + var VERSION = "3.10.1"; + var BIND_FLAG = 1, BIND_KEY_FLAG = 2, CURRY_BOUND_FLAG = 4, CURRY_FLAG = 8, CURRY_RIGHT_FLAG = 16, PARTIAL_FLAG = 32, PARTIAL_RIGHT_FLAG = 64, ARY_FLAG = 128, REARG_FLAG = 256; + var DEFAULT_TRUNC_LENGTH = 30, DEFAULT_TRUNC_OMISSION = "..."; + var HOT_COUNT = 150, HOT_SPAN = 16; + var LARGE_ARRAY_SIZE = 200; + var LAZY_FILTER_FLAG = 1, LAZY_MAP_FLAG = 2; + var FUNC_ERROR_TEXT = "Expected a function"; + var PLACEHOLDER = "__lodash_placeholder__"; + var argsTag = "[object Arguments]", arrayTag = "[object Array]", boolTag = "[object Boolean]", dateTag = "[object Date]", errorTag = "[object Error]", funcTag = "[object Function]", mapTag = "[object Map]", numberTag = "[object Number]", objectTag = "[object Object]", regexpTag = "[object RegExp]", setTag = "[object Set]", stringTag = "[object String]", weakMapTag = "[object WeakMap]"; + var arrayBufferTag = "[object ArrayBuffer]", float32Tag = "[object Float32Array]", float64Tag = "[object Float64Array]", int8Tag = "[object Int8Array]", int16Tag = "[object Int16Array]", int32Tag = "[object Int32Array]", uint8Tag = "[object Uint8Array]", uint8ClampedTag = "[object Uint8ClampedArray]", uint16Tag = "[object Uint16Array]", uint32Tag = "[object Uint32Array]"; + var reEmptyStringLeading = /\b__p \+= '';/g, reEmptyStringMiddle = /\b(__p \+=) '' \+/g, reEmptyStringTrailing = /(__e\(.*?\)|\b__t\)) \+\n'';/g; + var reEscapedHtml = /&(?:amp|lt|gt|quot|#39|#96);/g, reUnescapedHtml = /[&<>"'`]/g, reHasEscapedHtml = RegExp(reEscapedHtml.source), reHasUnescapedHtml = RegExp(reUnescapedHtml.source); + var reEscape = /<%-([\s\S]+?)%>/g, reEvaluate = /<%([\s\S]+?)%>/g, reInterpolate = /<%=([\s\S]+?)%>/g; + var reIsDeepProp = /\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\n\\]|\\.)*?\1)\]/, reIsPlainProp = /^\w*$/, rePropName = /[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\n\\]|\\.)*?)\2)\]/g; + var reRegExpChars = /^[:!,]|[\\^$.*+?()[\]{}|\/]|(^[0-9a-fA-Fnrtuvx])|([\n\r\u2028\u2029])/g, reHasRegExpChars = RegExp(reRegExpChars.source); + var reComboMark = /[\u0300-\u036f\ufe20-\ufe23]/g; + var reEscapeChar = /\\(\\)?/g; + var reEsTemplate = /\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g; + var reFlags = /\w*$/; + var reHasHexPrefix = /^0[xX]/; + var reIsHostCtor = /^\[object .+?Constructor\]$/; + var reIsUint = /^\d+$/; + var reLatin1 = /[\xc0-\xd6\xd8-\xde\xdf-\xf6\xf8-\xff]/g; + var reNoMatch = /($^)/; + var reUnescapedString = /['\n\r\u2028\u2029\\]/g; + var reWords = function() { + var upper = "[A-Z\\xc0-\\xd6\\xd8-\\xde]", lower = "[a-z\\xdf-\\xf6\\xf8-\\xff]+"; + return RegExp(upper + "+(?=" + upper + lower + ")|" + upper + "?" + lower + "|" + upper + "+|[0-9]+", "g"); + }(); + var contextProps = [ "Array", "ArrayBuffer", "Date", "Error", "Float32Array", "Float64Array", "Function", "Int8Array", "Int16Array", "Int32Array", "Math", "Number", "Object", "RegExp", "Set", "String", "_", "clearTimeout", "isFinite", "parseFloat", "parseInt", "setTimeout", "TypeError", "Uint8Array", "Uint8ClampedArray", "Uint16Array", "Uint32Array", "WeakMap" ]; + var templateCounter = -1; + var typedArrayTags = {}; + typedArrayTags[float32Tag] = typedArrayTags[float64Tag] = typedArrayTags[int8Tag] = typedArrayTags[int16Tag] = typedArrayTags[int32Tag] = typedArrayTags[uint8Tag] = typedArrayTags[uint8ClampedTag] = typedArrayTags[uint16Tag] = typedArrayTags[uint32Tag] = true; + typedArrayTags[argsTag] = typedArrayTags[arrayTag] = typedArrayTags[arrayBufferTag] = typedArrayTags[boolTag] = typedArrayTags[dateTag] = typedArrayTags[errorTag] = typedArrayTags[funcTag] = typedArrayTags[mapTag] = typedArrayTags[numberTag] = typedArrayTags[objectTag] = typedArrayTags[regexpTag] = typedArrayTags[setTag] = typedArrayTags[stringTag] = typedArrayTags[weakMapTag] = false; + var cloneableTags = {}; + cloneableTags[argsTag] = cloneableTags[arrayTag] = cloneableTags[arrayBufferTag] = cloneableTags[boolTag] = cloneableTags[dateTag] = cloneableTags[float32Tag] = cloneableTags[float64Tag] = cloneableTags[int8Tag] = cloneableTags[int16Tag] = cloneableTags[int32Tag] = cloneableTags[numberTag] = cloneableTags[objectTag] = cloneableTags[regexpTag] = cloneableTags[stringTag] = cloneableTags[uint8Tag] = cloneableTags[uint8ClampedTag] = cloneableTags[uint16Tag] = cloneableTags[uint32Tag] = true; + cloneableTags[errorTag] = cloneableTags[funcTag] = cloneableTags[mapTag] = cloneableTags[setTag] = cloneableTags[weakMapTag] = false; + var deburredLetters = { + "À": "A", + "Á": "A", + "Â": "A", + "Ã": "A", + "Ä": "A", + "Å": "A", + "à": "a", + "á": "a", + "â": "a", + "ã": "a", + "ä": "a", + "å": "a", + "Ç": "C", + "ç": "c", + "Ð": "D", + "ð": "d", + "È": "E", + "É": "E", + "Ê": "E", + "Ë": "E", + "è": "e", + "é": "e", + "ê": "e", + "ë": "e", + "Ì": "I", + "Í": "I", + "Î": "I", + "Ï": "I", + "ì": "i", + "í": "i", + "î": "i", + "ï": "i", + "Ñ": "N", + "ñ": "n", + "Ò": "O", + "Ó": "O", + "Ô": "O", + "Õ": "O", + "Ö": "O", + "Ø": "O", + "ò": "o", + "ó": "o", + "ô": "o", + "õ": "o", + "ö": "o", + "ø": "o", + "Ù": "U", + "Ú": "U", + "Û": "U", + "Ü": "U", + "ù": "u", + "ú": "u", + "û": "u", + "ü": "u", + "Ý": "Y", + "ý": "y", + "ÿ": "y", + "Æ": "Ae", + "æ": "ae", + "Þ": "Th", + "þ": "th", + "ß": "ss" + }; + var htmlEscapes = { + "&": "&", + "<": "<", + ">": ">", + '"': """, + "'": "'", + "`": "`" + }; + var htmlUnescapes = { + "&": "&", + "<": "<", + ">": ">", + """: '"', + "'": "'", + "`": "`" + }; + var objectTypes = { + "function": true, + object: true + }; + var regexpEscapes = { + "0": "x30", + "1": "x31", + "2": "x32", + "3": "x33", + "4": "x34", + "5": "x35", + "6": "x36", + "7": "x37", + "8": "x38", + "9": "x39", + A: "x41", + B: "x42", + C: "x43", + D: "x44", + E: "x45", + F: "x46", + a: "x61", + b: "x62", + c: "x63", + d: "x64", + e: "x65", + f: "x66", + n: "x6e", + r: "x72", + t: "x74", + u: "x75", + v: "x76", + x: "x78" + }; + var stringEscapes = { + "\\": "\\", + "'": "'", + "\n": "n", + "\r": "r", + "\u2028": "u2028", + "\u2029": "u2029" + }; + var freeExports = objectTypes[typeof exports] && exports && !exports.nodeType && exports; + var freeModule = objectTypes[typeof module] && module && !module.nodeType && module; + var freeGlobal = freeExports && freeModule && typeof global == "object" && global && global.Object && global; + var freeSelf = objectTypes[typeof self] && self && self.Object && self; + var freeWindow = objectTypes[typeof window] && window && window.Object && window; + var moduleExports = freeModule && freeModule.exports === freeExports && freeExports; + var root = freeGlobal || freeWindow !== (this && this.window) && freeWindow || freeSelf || this; + function baseCompareAscending(value, other) { + if (value !== other) { + var valIsNull = value === null, valIsUndef = value === undefined, valIsReflexive = value === value; + var othIsNull = other === null, othIsUndef = other === undefined, othIsReflexive = other === other; + if (value > other && !othIsNull || !valIsReflexive || valIsNull && !othIsUndef && othIsReflexive || valIsUndef && othIsReflexive) { + return 1; + } + if (value < other && !valIsNull || !othIsReflexive || othIsNull && !valIsUndef && valIsReflexive || othIsUndef && valIsReflexive) { + return -1; + } + } + return 0; + } + function baseFindIndex(array, predicate, fromRight) { + var length = array.length, index = fromRight ? length : -1; + while (fromRight ? index-- : ++index < length) { + if (predicate(array[index], index, array)) { + return index; + } + } + return -1; + } + function baseIndexOf(array, value, fromIndex) { + if (value !== value) { + return indexOfNaN(array, fromIndex); + } + var index = fromIndex - 1, length = array.length; + while (++index < length) { + if (array[index] === value) { + return index; + } + } + return -1; + } + function baseIsFunction(value) { + return typeof value == "function" || false; + } + function baseToString(value) { + return value == null ? "" : value + ""; + } + function charsLeftIndex(string, chars) { + var index = -1, length = string.length; + while (++index < length && chars.indexOf(string.charAt(index)) > -1) {} + return index; + } + function charsRightIndex(string, chars) { + var index = string.length; + while (index-- && chars.indexOf(string.charAt(index)) > -1) {} + return index; + } + function compareAscending(object, other) { + return baseCompareAscending(object.criteria, other.criteria) || object.index - other.index; + } + function compareMultiple(object, other, orders) { + var index = -1, objCriteria = object.criteria, othCriteria = other.criteria, length = objCriteria.length, ordersLength = orders.length; + while (++index < length) { + var result = baseCompareAscending(objCriteria[index], othCriteria[index]); + if (result) { + if (index >= ordersLength) { + return result; + } + var order = orders[index]; + return result * (order === "asc" || order === true ? 1 : -1); + } + } + return object.index - other.index; + } + function deburrLetter(letter) { + return deburredLetters[letter]; + } + function escapeHtmlChar(chr) { + return htmlEscapes[chr]; + } + function escapeRegExpChar(chr, leadingChar, whitespaceChar) { + if (leadingChar) { + chr = regexpEscapes[chr]; + } else if (whitespaceChar) { + chr = stringEscapes[chr]; + } + return "\\" + chr; + } + function escapeStringChar(chr) { + return "\\" + stringEscapes[chr]; + } + function indexOfNaN(array, fromIndex, fromRight) { + var length = array.length, index = fromIndex + (fromRight ? 0 : -1); + while (fromRight ? index-- : ++index < length) { + var other = array[index]; + if (other !== other) { + return index; + } + } + return -1; + } + function isObjectLike(value) { + return !!value && typeof value == "object"; + } + function isSpace(charCode) { + return charCode <= 160 && (charCode >= 9 && charCode <= 13) || charCode == 32 || charCode == 160 || charCode == 5760 || charCode == 6158 || charCode >= 8192 && (charCode <= 8202 || charCode == 8232 || charCode == 8233 || charCode == 8239 || charCode == 8287 || charCode == 12288 || charCode == 65279); + } + function replaceHolders(array, placeholder) { + var index = -1, length = array.length, resIndex = -1, result = []; + while (++index < length) { + if (array[index] === placeholder) { + array[index] = PLACEHOLDER; + result[++resIndex] = index; + } + } + return result; + } + function sortedUniq(array, iteratee) { + var seen, index = -1, length = array.length, resIndex = -1, result = []; + while (++index < length) { + var value = array[index], computed = iteratee ? iteratee(value, index, array) : value; + if (!index || seen !== computed) { + seen = computed; + result[++resIndex] = value; + } + } + return result; + } + function trimmedLeftIndex(string) { + var index = -1, length = string.length; + while (++index < length && isSpace(string.charCodeAt(index))) {} + return index; + } + function trimmedRightIndex(string) { + var index = string.length; + while (index-- && isSpace(string.charCodeAt(index))) {} + return index; + } + function unescapeHtmlChar(chr) { + return htmlUnescapes[chr]; + } + function runInContext(context) { + context = context ? _.defaults(root.Object(), context, _.pick(root, contextProps)) : root; + var Array = context.Array, Date = context.Date, Error = context.Error, Function = context.Function, Math = context.Math, Number = context.Number, Object = context.Object, RegExp = context.RegExp, String = context.String, TypeError = context.TypeError; + var arrayProto = Array.prototype, objectProto = Object.prototype, stringProto = String.prototype; + var fnToString = Function.prototype.toString; + var hasOwnProperty = objectProto.hasOwnProperty; + var idCounter = 0; + var objToString = objectProto.toString; + var oldDash = root._; + var reIsNative = RegExp("^" + fnToString.call(hasOwnProperty).replace(/[\\^$.*+?()[\]{}|]/g, "\\$&").replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g, "$1.*?") + "$"); + var ArrayBuffer = context.ArrayBuffer, clearTimeout = context.clearTimeout, parseFloat = context.parseFloat, pow = Math.pow, propertyIsEnumerable = objectProto.propertyIsEnumerable, Set = getNative(context, "Set"), setTimeout = context.setTimeout, splice = arrayProto.splice, Uint8Array = context.Uint8Array, WeakMap = getNative(context, "WeakMap"); + var nativeCeil = Math.ceil, nativeCreate = getNative(Object, "create"), nativeFloor = Math.floor, nativeIsArray = getNative(Array, "isArray"), nativeIsFinite = context.isFinite, nativeKeys = getNative(Object, "keys"), nativeMax = Math.max, nativeMin = Math.min, nativeNow = getNative(Date, "now"), nativeParseInt = context.parseInt, nativeRandom = Math.random; + var NEGATIVE_INFINITY = Number.NEGATIVE_INFINITY, POSITIVE_INFINITY = Number.POSITIVE_INFINITY; + var MAX_ARRAY_LENGTH = 4294967295, MAX_ARRAY_INDEX = MAX_ARRAY_LENGTH - 1, HALF_MAX_ARRAY_LENGTH = MAX_ARRAY_LENGTH >>> 1; + var MAX_SAFE_INTEGER = 9007199254740991; + var metaMap = WeakMap && new WeakMap(); + var realNames = {}; + function lodash(value) { + if (isObjectLike(value) && !isArray(value) && !(value instanceof LazyWrapper)) { + if (value instanceof LodashWrapper) { + return value; + } + if (hasOwnProperty.call(value, "__chain__") && hasOwnProperty.call(value, "__wrapped__")) { + return wrapperClone(value); + } + } + return new LodashWrapper(value); + } + function baseLodash() {} + function LodashWrapper(value, chainAll, actions) { + this.__wrapped__ = value; + this.__actions__ = actions || []; + this.__chain__ = !!chainAll; + } + var support = lodash.support = {}; + lodash.templateSettings = { + escape: reEscape, + evaluate: reEvaluate, + interpolate: reInterpolate, + variable: "", + imports: { + _: lodash + } + }; + function LazyWrapper(value) { + this.__wrapped__ = value; + this.__actions__ = []; + this.__dir__ = 1; + this.__filtered__ = false; + this.__iteratees__ = []; + this.__takeCount__ = POSITIVE_INFINITY; + this.__views__ = []; + } + function lazyClone() { + var result = new LazyWrapper(this.__wrapped__); + result.__actions__ = arrayCopy(this.__actions__); + result.__dir__ = this.__dir__; + result.__filtered__ = this.__filtered__; + result.__iteratees__ = arrayCopy(this.__iteratees__); + result.__takeCount__ = this.__takeCount__; + result.__views__ = arrayCopy(this.__views__); + return result; + } + function lazyReverse() { + if (this.__filtered__) { + var result = new LazyWrapper(this); + result.__dir__ = -1; + result.__filtered__ = true; + } else { + result = this.clone(); + result.__dir__ *= -1; + } + return result; + } + function lazyValue() { + var array = this.__wrapped__.value(), dir = this.__dir__, isArr = isArray(array), isRight = dir < 0, arrLength = isArr ? array.length : 0, view = getView(0, arrLength, this.__views__), start = view.start, end = view.end, length = end - start, index = isRight ? end : start - 1, iteratees = this.__iteratees__, iterLength = iteratees.length, resIndex = 0, takeCount = nativeMin(length, this.__takeCount__); + if (!isArr || arrLength < LARGE_ARRAY_SIZE || arrLength == length && takeCount == length) { + return baseWrapperValue(array, this.__actions__); + } + var result = []; + outer: while (length-- && resIndex < takeCount) { + index += dir; + var iterIndex = -1, value = array[index]; + while (++iterIndex < iterLength) { + var data = iteratees[iterIndex], iteratee = data.iteratee, type = data.type, computed = iteratee(value); + if (type == LAZY_MAP_FLAG) { + value = computed; + } else if (!computed) { + if (type == LAZY_FILTER_FLAG) { + continue outer; + } else { + break outer; + } + } + } + result[resIndex++] = value; + } + return result; + } + function MapCache() { + this.__data__ = {}; + } + function mapDelete(key) { + return this.has(key) && delete this.__data__[key]; + } + function mapGet(key) { + return key == "__proto__" ? undefined : this.__data__[key]; + } + function mapHas(key) { + return key != "__proto__" && hasOwnProperty.call(this.__data__, key); + } + function mapSet(key, value) { + if (key != "__proto__") { + this.__data__[key] = value; + } + return this; + } + function SetCache(values) { + var length = values ? values.length : 0; + this.data = { + hash: nativeCreate(null), + set: new Set() + }; + while (length--) { + this.push(values[length]); + } + } + function cacheIndexOf(cache, value) { + var data = cache.data, result = typeof value == "string" || isObject(value) ? data.set.has(value) : data.hash[value]; + return result ? 0 : -1; + } + function cachePush(value) { + var data = this.data; + if (typeof value == "string" || isObject(value)) { + data.set.add(value); + } else { + data.hash[value] = true; + } + } + function arrayConcat(array, other) { + var index = -1, length = array.length, othIndex = -1, othLength = other.length, result = Array(length + othLength); + while (++index < length) { + result[index] = array[index]; + } + while (++othIndex < othLength) { + result[index++] = other[othIndex]; + } + return result; + } + function arrayCopy(source, array) { + var index = -1, length = source.length; + array || (array = Array(length)); + while (++index < length) { + array[index] = source[index]; + } + return array; + } + function arrayEach(array, iteratee) { + var index = -1, length = array.length; + while (++index < length) { + if (iteratee(array[index], index, array) === false) { + break; + } + } + return array; + } + function arrayEachRight(array, iteratee) { + var length = array.length; + while (length--) { + if (iteratee(array[length], length, array) === false) { + break; + } + } + return array; + } + function arrayEvery(array, predicate) { + var index = -1, length = array.length; + while (++index < length) { + if (!predicate(array[index], index, array)) { + return false; + } + } + return true; + } + function arrayExtremum(array, iteratee, comparator, exValue) { + var index = -1, length = array.length, computed = exValue, result = computed; + while (++index < length) { + var value = array[index], current = +iteratee(value); + if (comparator(current, computed)) { + computed = current; + result = value; + } + } + return result; + } + function arrayFilter(array, predicate) { + var index = -1, length = array.length, resIndex = -1, result = []; + while (++index < length) { + var value = array[index]; + if (predicate(value, index, array)) { + result[++resIndex] = value; + } + } + return result; + } + function arrayMap(array, iteratee) { + var index = -1, length = array.length, result = Array(length); + while (++index < length) { + result[index] = iteratee(array[index], index, array); + } + return result; + } + function arrayPush(array, values) { + var index = -1, length = values.length, offset = array.length; + while (++index < length) { + array[offset + index] = values[index]; + } + return array; + } + function arrayReduce(array, iteratee, accumulator, initFromArray) { + var index = -1, length = array.length; + if (initFromArray && length) { + accumulator = array[++index]; + } + while (++index < length) { + accumulator = iteratee(accumulator, array[index], index, array); + } + return accumulator; + } + function arrayReduceRight(array, iteratee, accumulator, initFromArray) { + var length = array.length; + if (initFromArray && length) { + accumulator = array[--length]; + } + while (length--) { + accumulator = iteratee(accumulator, array[length], length, array); + } + return accumulator; + } + function arraySome(array, predicate) { + var index = -1, length = array.length; + while (++index < length) { + if (predicate(array[index], index, array)) { + return true; + } + } + return false; + } + function arraySum(array, iteratee) { + var length = array.length, result = 0; + while (length--) { + result += +iteratee(array[length]) || 0; + } + return result; + } + function assignDefaults(objectValue, sourceValue) { + return objectValue === undefined ? sourceValue : objectValue; + } + function assignOwnDefaults(objectValue, sourceValue, key, object) { + return objectValue === undefined || !hasOwnProperty.call(object, key) ? sourceValue : objectValue; + } + function assignWith(object, source, customizer) { + var index = -1, props = keys(source), length = props.length; + while (++index < length) { + var key = props[index], value = object[key], result = customizer(value, source[key], key, object, source); + if ((result === result ? result !== value : value === value) || value === undefined && !(key in object)) { + object[key] = result; + } + } + return object; + } + function baseAssign(object, source) { + return source == null ? object : baseCopy(source, keys(source), object); + } + function baseAt(collection, props) { + var index = -1, isNil = collection == null, isArr = !isNil && isArrayLike(collection), length = isArr ? collection.length : 0, propsLength = props.length, result = Array(propsLength); + while (++index < propsLength) { + var key = props[index]; + if (isArr) { + result[index] = isIndex(key, length) ? collection[key] : undefined; + } else { + result[index] = isNil ? undefined : collection[key]; + } + } + return result; + } + function baseCopy(source, props, object) { + object || (object = {}); + var index = -1, length = props.length; + while (++index < length) { + var key = props[index]; + object[key] = source[key]; + } + return object; + } + function baseCallback(func, thisArg, argCount) { + var type = typeof func; + if (type == "function") { + return thisArg === undefined ? func : bindCallback(func, thisArg, argCount); + } + if (func == null) { + return identity; + } + if (type == "object") { + return baseMatches(func); + } + return thisArg === undefined ? property(func) : baseMatchesProperty(func, thisArg); + } + function baseClone(value, isDeep, customizer, key, object, stackA, stackB) { + var result; + if (customizer) { + result = object ? customizer(value, key, object) : customizer(value); + } + if (result !== undefined) { + return result; + } + if (!isObject(value)) { + return value; + } + var isArr = isArray(value); + if (isArr) { + result = initCloneArray(value); + if (!isDeep) { + return arrayCopy(value, result); + } + } else { + var tag = objToString.call(value), isFunc = tag == funcTag; + if (tag == objectTag || tag == argsTag || isFunc && !object) { + result = initCloneObject(isFunc ? {} : value); + if (!isDeep) { + return baseAssign(result, value); + } + } else { + return cloneableTags[tag] ? initCloneByTag(value, tag, isDeep) : object ? value : {}; + } + } + stackA || (stackA = []); + stackB || (stackB = []); + var length = stackA.length; + while (length--) { + if (stackA[length] == value) { + return stackB[length]; + } + } + stackA.push(value); + stackB.push(result); + (isArr ? arrayEach : baseForOwn)(value, function(subValue, key) { + result[key] = baseClone(subValue, isDeep, customizer, key, value, stackA, stackB); + }); + return result; + } + var baseCreate = function() { + function object() {} + return function(prototype) { + if (isObject(prototype)) { + object.prototype = prototype; + var result = new object(); + object.prototype = undefined; + } + return result || {}; + }; + }(); + function baseDelay(func, wait, args) { + if (typeof func != "function") { + throw new TypeError(FUNC_ERROR_TEXT); + } + return setTimeout(function() { + func.apply(undefined, args); + }, wait); + } + function baseDifference(array, values) { + var length = array ? array.length : 0, result = []; + if (!length) { + return result; + } + var index = -1, indexOf = getIndexOf(), isCommon = indexOf === baseIndexOf, cache = isCommon && values.length >= LARGE_ARRAY_SIZE ? createCache(values) : null, valuesLength = values.length; + if (cache) { + indexOf = cacheIndexOf; + isCommon = false; + values = cache; + } + outer: while (++index < length) { + var value = array[index]; + if (isCommon && value === value) { + var valuesIndex = valuesLength; + while (valuesIndex--) { + if (values[valuesIndex] === value) { + continue outer; + } + } + result.push(value); + } else if (indexOf(values, value, 0) < 0) { + result.push(value); + } + } + return result; + } + var baseEach = createBaseEach(baseForOwn); + var baseEachRight = createBaseEach(baseForOwnRight, true); + function baseEvery(collection, predicate) { + var result = true; + baseEach(collection, function(value, index, collection) { + result = !!predicate(value, index, collection); + return result; + }); + return result; + } + function baseExtremum(collection, iteratee, comparator, exValue) { + var computed = exValue, result = computed; + baseEach(collection, function(value, index, collection) { + var current = +iteratee(value, index, collection); + if (comparator(current, computed) || current === exValue && current === result) { + computed = current; + result = value; + } + }); + return result; + } + function baseFill(array, value, start, end) { + var length = array.length; + start = start == null ? 0 : +start || 0; + if (start < 0) { + start = -start > length ? 0 : length + start; + } + end = end === undefined || end > length ? length : +end || 0; + if (end < 0) { + end += length; + } + length = start > end ? 0 : end >>> 0; + start >>>= 0; + while (start < length) { + array[start++] = value; + } + return array; + } + function baseFilter(collection, predicate) { + var result = []; + baseEach(collection, function(value, index, collection) { + if (predicate(value, index, collection)) { + result.push(value); + } + }); + return result; + } + function baseFind(collection, predicate, eachFunc, retKey) { + var result; + eachFunc(collection, function(value, key, collection) { + if (predicate(value, key, collection)) { + result = retKey ? key : value; + return false; + } + }); + return result; + } + function baseFlatten(array, isDeep, isStrict, result) { + result || (result = []); + var index = -1, length = array.length; + while (++index < length) { + var value = array[index]; + if (isObjectLike(value) && isArrayLike(value) && (isStrict || isArray(value) || isArguments(value))) { + if (isDeep) { + baseFlatten(value, isDeep, isStrict, result); + } else { + arrayPush(result, value); + } + } else if (!isStrict) { + result[result.length] = value; + } + } + return result; + } + var baseFor = createBaseFor(); + var baseForRight = createBaseFor(true); + function baseForIn(object, iteratee) { + return baseFor(object, iteratee, keysIn); + } + function baseForOwn(object, iteratee) { + return baseFor(object, iteratee, keys); + } + function baseForOwnRight(object, iteratee) { + return baseForRight(object, iteratee, keys); + } + function baseFunctions(object, props) { + var index = -1, length = props.length, resIndex = -1, result = []; + while (++index < length) { + var key = props[index]; + if (isFunction(object[key])) { + result[++resIndex] = key; + } + } + return result; + } + function baseGet(object, path, pathKey) { + if (object == null) { + return; + } + if (pathKey !== undefined && pathKey in toObject(object)) { + path = [ pathKey ]; + } + var index = 0, length = path.length; + while (object != null && index < length) { + object = object[path[index++]]; + } + return index && index == length ? object : undefined; + } + function baseIsEqual(value, other, customizer, isLoose, stackA, stackB) { + if (value === other) { + return true; + } + if (value == null || other == null || !isObject(value) && !isObjectLike(other)) { + return value !== value && other !== other; + } + return baseIsEqualDeep(value, other, baseIsEqual, customizer, isLoose, stackA, stackB); + } + function baseIsEqualDeep(object, other, equalFunc, customizer, isLoose, stackA, stackB) { + var objIsArr = isArray(object), othIsArr = isArray(other), objTag = arrayTag, othTag = arrayTag; + if (!objIsArr) { + objTag = objToString.call(object); + if (objTag == argsTag) { + objTag = objectTag; + } else if (objTag != objectTag) { + objIsArr = isTypedArray(object); + } + } + if (!othIsArr) { + othTag = objToString.call(other); + if (othTag == argsTag) { + othTag = objectTag; + } else if (othTag != objectTag) { + othIsArr = isTypedArray(other); + } + } + var objIsObj = objTag == objectTag, othIsObj = othTag == objectTag, isSameTag = objTag == othTag; + if (isSameTag && !(objIsArr || objIsObj)) { + return equalByTag(object, other, objTag); + } + if (!isLoose) { + var objIsWrapped = objIsObj && hasOwnProperty.call(object, "__wrapped__"), othIsWrapped = othIsObj && hasOwnProperty.call(other, "__wrapped__"); + if (objIsWrapped || othIsWrapped) { + return equalFunc(objIsWrapped ? object.value() : object, othIsWrapped ? other.value() : other, customizer, isLoose, stackA, stackB); + } + } + if (!isSameTag) { + return false; + } + stackA || (stackA = []); + stackB || (stackB = []); + var length = stackA.length; + while (length--) { + if (stackA[length] == object) { + return stackB[length] == other; + } + } + stackA.push(object); + stackB.push(other); + var result = (objIsArr ? equalArrays : equalObjects)(object, other, equalFunc, customizer, isLoose, stackA, stackB); + stackA.pop(); + stackB.pop(); + return result; + } + function baseIsMatch(object, matchData, customizer) { + var index = matchData.length, length = index, noCustomizer = !customizer; + if (object == null) { + return !length; + } + object = toObject(object); + while (index--) { + var data = matchData[index]; + if (noCustomizer && data[2] ? data[1] !== object[data[0]] : !(data[0] in object)) { + return false; + } + } + while (++index < length) { + data = matchData[index]; + var key = data[0], objValue = object[key], srcValue = data[1]; + if (noCustomizer && data[2]) { + if (objValue === undefined && !(key in object)) { + return false; + } + } else { + var result = customizer ? customizer(objValue, srcValue, key) : undefined; + if (!(result === undefined ? baseIsEqual(srcValue, objValue, customizer, true) : result)) { + return false; + } + } + } + return true; + } + function baseMap(collection, iteratee) { + var index = -1, result = isArrayLike(collection) ? Array(collection.length) : []; + baseEach(collection, function(value, key, collection) { + result[++index] = iteratee(value, key, collection); + }); + return result; + } + function baseMatches(source) { + var matchData = getMatchData(source); + if (matchData.length == 1 && matchData[0][2]) { + var key = matchData[0][0], value = matchData[0][1]; + return function(object) { + if (object == null) { + return false; + } + return object[key] === value && (value !== undefined || key in toObject(object)); + }; + } + return function(object) { + return baseIsMatch(object, matchData); + }; + } + function baseMatchesProperty(path, srcValue) { + var isArr = isArray(path), isCommon = isKey(path) && isStrictComparable(srcValue), pathKey = path + ""; + path = toPath(path); + return function(object) { + if (object == null) { + return false; + } + var key = pathKey; + object = toObject(object); + if ((isArr || !isCommon) && !(key in object)) { + object = path.length == 1 ? object : baseGet(object, baseSlice(path, 0, -1)); + if (object == null) { + return false; + } + key = last(path); + object = toObject(object); + } + return object[key] === srcValue ? srcValue !== undefined || key in object : baseIsEqual(srcValue, object[key], undefined, true); + }; + } + function baseMerge(object, source, customizer, stackA, stackB) { + if (!isObject(object)) { + return object; + } + var isSrcArr = isArrayLike(source) && (isArray(source) || isTypedArray(source)), props = isSrcArr ? undefined : keys(source); + arrayEach(props || source, function(srcValue, key) { + if (props) { + key = srcValue; + srcValue = source[key]; + } + if (isObjectLike(srcValue)) { + stackA || (stackA = []); + stackB || (stackB = []); + baseMergeDeep(object, source, key, baseMerge, customizer, stackA, stackB); + } else { + var value = object[key], result = customizer ? customizer(value, srcValue, key, object, source) : undefined, isCommon = result === undefined; + if (isCommon) { + result = srcValue; + } + if ((result !== undefined || isSrcArr && !(key in object)) && (isCommon || (result === result ? result !== value : value === value))) { + object[key] = result; + } + } + }); + return object; + } + function baseMergeDeep(object, source, key, mergeFunc, customizer, stackA, stackB) { + var length = stackA.length, srcValue = source[key]; + while (length--) { + if (stackA[length] == srcValue) { + object[key] = stackB[length]; + return; + } + } + var value = object[key], result = customizer ? customizer(value, srcValue, key, object, source) : undefined, isCommon = result === undefined; + if (isCommon) { + result = srcValue; + if (isArrayLike(srcValue) && (isArray(srcValue) || isTypedArray(srcValue))) { + result = isArray(value) ? value : isArrayLike(value) ? arrayCopy(value) : []; + } else if (isPlainObject(srcValue) || isArguments(srcValue)) { + result = isArguments(value) ? toPlainObject(value) : isPlainObject(value) ? value : {}; + } else { + isCommon = false; + } + } + stackA.push(srcValue); + stackB.push(result); + if (isCommon) { + object[key] = mergeFunc(result, srcValue, customizer, stackA, stackB); + } else if (result === result ? result !== value : value === value) { + object[key] = result; + } + } + function baseProperty(key) { + return function(object) { + return object == null ? undefined : object[key]; + }; + } + function basePropertyDeep(path) { + var pathKey = path + ""; + path = toPath(path); + return function(object) { + return baseGet(object, path, pathKey); + }; + } + function basePullAt(array, indexes) { + var length = array ? indexes.length : 0; + while (length--) { + var index = indexes[length]; + if (index != previous && isIndex(index)) { + var previous = index; + splice.call(array, index, 1); + } + } + return array; + } + function baseRandom(min, max) { + return min + nativeFloor(nativeRandom() * (max - min + 1)); + } + function baseReduce(collection, iteratee, accumulator, initFromCollection, eachFunc) { + eachFunc(collection, function(value, index, collection) { + accumulator = initFromCollection ? (initFromCollection = false, value) : iteratee(accumulator, value, index, collection); + }); + return accumulator; + } + var baseSetData = !metaMap ? identity : function(func, data) { + metaMap.set(func, data); + return func; + }; + function baseSlice(array, start, end) { + var index = -1, length = array.length; + start = start == null ? 0 : +start || 0; + if (start < 0) { + start = -start > length ? 0 : length + start; + } + end = end === undefined || end > length ? length : +end || 0; + if (end < 0) { + end += length; + } + length = start > end ? 0 : end - start >>> 0; + start >>>= 0; + var result = Array(length); + while (++index < length) { + result[index] = array[index + start]; + } + return result; + } + function baseSome(collection, predicate) { + var result; + baseEach(collection, function(value, index, collection) { + result = predicate(value, index, collection); + return !result; + }); + return !!result; + } + function baseSortBy(array, comparer) { + var length = array.length; + array.sort(comparer); + while (length--) { + array[length] = array[length].value; + } + return array; + } + function baseSortByOrder(collection, iteratees, orders) { + var callback = getCallback(), index = -1; + iteratees = arrayMap(iteratees, function(iteratee) { + return callback(iteratee); + }); + var result = baseMap(collection, function(value) { + var criteria = arrayMap(iteratees, function(iteratee) { + return iteratee(value); + }); + return { + criteria: criteria, + index: ++index, + value: value + }; + }); + return baseSortBy(result, function(object, other) { + return compareMultiple(object, other, orders); + }); + } + function baseSum(collection, iteratee) { + var result = 0; + baseEach(collection, function(value, index, collection) { + result += +iteratee(value, index, collection) || 0; + }); + return result; + } + function baseUniq(array, iteratee) { + var index = -1, indexOf = getIndexOf(), length = array.length, isCommon = indexOf === baseIndexOf, isLarge = isCommon && length >= LARGE_ARRAY_SIZE, seen = isLarge ? createCache() : null, result = []; + if (seen) { + indexOf = cacheIndexOf; + isCommon = false; + } else { + isLarge = false; + seen = iteratee ? [] : result; + } + outer: while (++index < length) { + var value = array[index], computed = iteratee ? iteratee(value, index, array) : value; + if (isCommon && value === value) { + var seenIndex = seen.length; + while (seenIndex--) { + if (seen[seenIndex] === computed) { + continue outer; + } + } + if (iteratee) { + seen.push(computed); + } + result.push(value); + } else if (indexOf(seen, computed, 0) < 0) { + if (iteratee || isLarge) { + seen.push(computed); + } + result.push(value); + } + } + return result; + } + function baseValues(object, props) { + var index = -1, length = props.length, result = Array(length); + while (++index < length) { + result[index] = object[props[index]]; + } + return result; + } + function baseWhile(array, predicate, isDrop, fromRight) { + var length = array.length, index = fromRight ? length : -1; + while ((fromRight ? index-- : ++index < length) && predicate(array[index], index, array)) {} + return isDrop ? baseSlice(array, fromRight ? 0 : index, fromRight ? index + 1 : length) : baseSlice(array, fromRight ? index + 1 : 0, fromRight ? length : index); + } + function baseWrapperValue(value, actions) { + var result = value; + if (result instanceof LazyWrapper) { + result = result.value(); + } + var index = -1, length = actions.length; + while (++index < length) { + var action = actions[index]; + result = action.func.apply(action.thisArg, arrayPush([ result ], action.args)); + } + return result; + } + function binaryIndex(array, value, retHighest) { + var low = 0, high = array ? array.length : low; + if (typeof value == "number" && value === value && high <= HALF_MAX_ARRAY_LENGTH) { + while (low < high) { + var mid = low + high >>> 1, computed = array[mid]; + if ((retHighest ? computed <= value : computed < value) && computed !== null) { + low = mid + 1; + } else { + high = mid; + } + } + return high; + } + return binaryIndexBy(array, value, identity, retHighest); + } + function binaryIndexBy(array, value, iteratee, retHighest) { + value = iteratee(value); + var low = 0, high = array ? array.length : 0, valIsNaN = value !== value, valIsNull = value === null, valIsUndef = value === undefined; + while (low < high) { + var mid = nativeFloor((low + high) / 2), computed = iteratee(array[mid]), isDef = computed !== undefined, isReflexive = computed === computed; + if (valIsNaN) { + var setLow = isReflexive || retHighest; + } else if (valIsNull) { + setLow = isReflexive && isDef && (retHighest || computed != null); + } else if (valIsUndef) { + setLow = isReflexive && (retHighest || isDef); + } else if (computed == null) { + setLow = false; + } else { + setLow = retHighest ? computed <= value : computed < value; + } + if (setLow) { + low = mid + 1; + } else { + high = mid; + } + } + return nativeMin(high, MAX_ARRAY_INDEX); + } + function bindCallback(func, thisArg, argCount) { + if (typeof func != "function") { + return identity; + } + if (thisArg === undefined) { + return func; + } + switch (argCount) { + case 1: + return function(value) { + return func.call(thisArg, value); + }; + + case 3: + return function(value, index, collection) { + return func.call(thisArg, value, index, collection); + }; + + case 4: + return function(accumulator, value, index, collection) { + return func.call(thisArg, accumulator, value, index, collection); + }; + + case 5: + return function(value, other, key, object, source) { + return func.call(thisArg, value, other, key, object, source); + }; + } + return function() { + return func.apply(thisArg, arguments); + }; + } + function bufferClone(buffer) { + var result = new ArrayBuffer(buffer.byteLength), view = new Uint8Array(result); + view.set(new Uint8Array(buffer)); + return result; + } + function composeArgs(args, partials, holders) { + var holdersLength = holders.length, argsIndex = -1, argsLength = nativeMax(args.length - holdersLength, 0), leftIndex = -1, leftLength = partials.length, result = Array(leftLength + argsLength); + while (++leftIndex < leftLength) { + result[leftIndex] = partials[leftIndex]; + } + while (++argsIndex < holdersLength) { + result[holders[argsIndex]] = args[argsIndex]; + } + while (argsLength--) { + result[leftIndex++] = args[argsIndex++]; + } + return result; + } + function composeArgsRight(args, partials, holders) { + var holdersIndex = -1, holdersLength = holders.length, argsIndex = -1, argsLength = nativeMax(args.length - holdersLength, 0), rightIndex = -1, rightLength = partials.length, result = Array(argsLength + rightLength); + while (++argsIndex < argsLength) { + result[argsIndex] = args[argsIndex]; + } + var offset = argsIndex; + while (++rightIndex < rightLength) { + result[offset + rightIndex] = partials[rightIndex]; + } + while (++holdersIndex < holdersLength) { + result[offset + holders[holdersIndex]] = args[argsIndex++]; + } + return result; + } + function createAggregator(setter, initializer) { + return function(collection, iteratee, thisArg) { + var result = initializer ? initializer() : {}; + iteratee = getCallback(iteratee, thisArg, 3); + if (isArray(collection)) { + var index = -1, length = collection.length; + while (++index < length) { + var value = collection[index]; + setter(result, value, iteratee(value, index, collection), collection); + } + } else { + baseEach(collection, function(value, key, collection) { + setter(result, value, iteratee(value, key, collection), collection); + }); + } + return result; + }; + } + function createAssigner(assigner) { + return restParam(function(object, sources) { + var index = -1, length = object == null ? 0 : sources.length, customizer = length > 2 ? sources[length - 2] : undefined, guard = length > 2 ? sources[2] : undefined, thisArg = length > 1 ? sources[length - 1] : undefined; + if (typeof customizer == "function") { + customizer = bindCallback(customizer, thisArg, 5); + length -= 2; + } else { + customizer = typeof thisArg == "function" ? thisArg : undefined; + length -= customizer ? 1 : 0; + } + if (guard && isIterateeCall(sources[0], sources[1], guard)) { + customizer = length < 3 ? undefined : customizer; + length = 1; + } + while (++index < length) { + var source = sources[index]; + if (source) { + assigner(object, source, customizer); + } + } + return object; + }); + } + function createBaseEach(eachFunc, fromRight) { + return function(collection, iteratee) { + var length = collection ? getLength(collection) : 0; + if (!isLength(length)) { + return eachFunc(collection, iteratee); + } + var index = fromRight ? length : -1, iterable = toObject(collection); + while (fromRight ? index-- : ++index < length) { + if (iteratee(iterable[index], index, iterable) === false) { + break; + } + } + return collection; + }; + } + function createBaseFor(fromRight) { + return function(object, iteratee, keysFunc) { + var iterable = toObject(object), props = keysFunc(object), length = props.length, index = fromRight ? length : -1; + while (fromRight ? index-- : ++index < length) { + var key = props[index]; + if (iteratee(iterable[key], key, iterable) === false) { + break; + } + } + return object; + }; + } + function createBindWrapper(func, thisArg) { + var Ctor = createCtorWrapper(func); + function wrapper() { + var fn = this && this !== root && this instanceof wrapper ? Ctor : func; + return fn.apply(thisArg, arguments); + } + return wrapper; + } + function createCache(values) { + return nativeCreate && Set ? new SetCache(values) : null; + } + function createCompounder(callback) { + return function(string) { + var index = -1, array = words(deburr(string)), length = array.length, result = ""; + while (++index < length) { + result = callback(result, array[index], index); + } + return result; + }; + } + function createCtorWrapper(Ctor) { + return function() { + var args = arguments; + switch (args.length) { + case 0: + return new Ctor(); + + case 1: + return new Ctor(args[0]); + + case 2: + return new Ctor(args[0], args[1]); + + case 3: + return new Ctor(args[0], args[1], args[2]); + + case 4: + return new Ctor(args[0], args[1], args[2], args[3]); + + case 5: + return new Ctor(args[0], args[1], args[2], args[3], args[4]); + + case 6: + return new Ctor(args[0], args[1], args[2], args[3], args[4], args[5]); + + case 7: + return new Ctor(args[0], args[1], args[2], args[3], args[4], args[5], args[6]); + } + var thisBinding = baseCreate(Ctor.prototype), result = Ctor.apply(thisBinding, args); + return isObject(result) ? result : thisBinding; + }; + } + function createCurry(flag) { + function curryFunc(func, arity, guard) { + if (guard && isIterateeCall(func, arity, guard)) { + arity = undefined; + } + var result = createWrapper(func, flag, undefined, undefined, undefined, undefined, undefined, arity); + result.placeholder = curryFunc.placeholder; + return result; + } + return curryFunc; + } + function createDefaults(assigner, customizer) { + return restParam(function(args) { + var object = args[0]; + if (object == null) { + return object; + } + args.push(customizer); + return assigner.apply(undefined, args); + }); + } + function createExtremum(comparator, exValue) { + return function(collection, iteratee, thisArg) { + if (thisArg && isIterateeCall(collection, iteratee, thisArg)) { + iteratee = undefined; + } + iteratee = getCallback(iteratee, thisArg, 3); + if (iteratee.length == 1) { + collection = isArray(collection) ? collection : toIterable(collection); + var result = arrayExtremum(collection, iteratee, comparator, exValue); + if (!(collection.length && result === exValue)) { + return result; + } + } + return baseExtremum(collection, iteratee, comparator, exValue); + }; + } + function createFind(eachFunc, fromRight) { + return function(collection, predicate, thisArg) { + predicate = getCallback(predicate, thisArg, 3); + if (isArray(collection)) { + var index = baseFindIndex(collection, predicate, fromRight); + return index > -1 ? collection[index] : undefined; + } + return baseFind(collection, predicate, eachFunc); + }; + } + function createFindIndex(fromRight) { + return function(array, predicate, thisArg) { + if (!(array && array.length)) { + return -1; + } + predicate = getCallback(predicate, thisArg, 3); + return baseFindIndex(array, predicate, fromRight); + }; + } + function createFindKey(objectFunc) { + return function(object, predicate, thisArg) { + predicate = getCallback(predicate, thisArg, 3); + return baseFind(object, predicate, objectFunc, true); + }; + } + function createFlow(fromRight) { + return function() { + var wrapper, length = arguments.length, index = fromRight ? length : -1, leftIndex = 0, funcs = Array(length); + while (fromRight ? index-- : ++index < length) { + var func = funcs[leftIndex++] = arguments[index]; + if (typeof func != "function") { + throw new TypeError(FUNC_ERROR_TEXT); + } + if (!wrapper && LodashWrapper.prototype.thru && getFuncName(func) == "wrapper") { + wrapper = new LodashWrapper([], true); + } + } + index = wrapper ? -1 : length; + while (++index < length) { + func = funcs[index]; + var funcName = getFuncName(func), data = funcName == "wrapper" ? getData(func) : undefined; + if (data && isLaziable(data[0]) && data[1] == (ARY_FLAG | CURRY_FLAG | PARTIAL_FLAG | REARG_FLAG) && !data[4].length && data[9] == 1) { + wrapper = wrapper[getFuncName(data[0])].apply(wrapper, data[3]); + } else { + wrapper = func.length == 1 && isLaziable(func) ? wrapper[funcName]() : wrapper.thru(func); + } + } + return function() { + var args = arguments, value = args[0]; + if (wrapper && args.length == 1 && isArray(value) && value.length >= LARGE_ARRAY_SIZE) { + return wrapper.plant(value).value(); + } + var index = 0, result = length ? funcs[index].apply(this, args) : value; + while (++index < length) { + result = funcs[index].call(this, result); + } + return result; + }; + }; + } + function createForEach(arrayFunc, eachFunc) { + return function(collection, iteratee, thisArg) { + return typeof iteratee == "function" && thisArg === undefined && isArray(collection) ? arrayFunc(collection, iteratee) : eachFunc(collection, bindCallback(iteratee, thisArg, 3)); + }; + } + function createForIn(objectFunc) { + return function(object, iteratee, thisArg) { + if (typeof iteratee != "function" || thisArg !== undefined) { + iteratee = bindCallback(iteratee, thisArg, 3); + } + return objectFunc(object, iteratee, keysIn); + }; + } + function createForOwn(objectFunc) { + return function(object, iteratee, thisArg) { + if (typeof iteratee != "function" || thisArg !== undefined) { + iteratee = bindCallback(iteratee, thisArg, 3); + } + return objectFunc(object, iteratee); + }; + } + function createObjectMapper(isMapKeys) { + return function(object, iteratee, thisArg) { + var result = {}; + iteratee = getCallback(iteratee, thisArg, 3); + baseForOwn(object, function(value, key, object) { + var mapped = iteratee(value, key, object); + key = isMapKeys ? mapped : key; + value = isMapKeys ? value : mapped; + result[key] = value; + }); + return result; + }; + } + function createPadDir(fromRight) { + return function(string, length, chars) { + string = baseToString(string); + return (fromRight ? string : "") + createPadding(string, length, chars) + (fromRight ? "" : string); + }; + } + function createPartial(flag) { + var partialFunc = restParam(function(func, partials) { + var holders = replaceHolders(partials, partialFunc.placeholder); + return createWrapper(func, flag, undefined, partials, holders); + }); + return partialFunc; + } + function createReduce(arrayFunc, eachFunc) { + return function(collection, iteratee, accumulator, thisArg) { + var initFromArray = arguments.length < 3; + return typeof iteratee == "function" && thisArg === undefined && isArray(collection) ? arrayFunc(collection, iteratee, accumulator, initFromArray) : baseReduce(collection, getCallback(iteratee, thisArg, 4), accumulator, initFromArray, eachFunc); + }; + } + function createHybridWrapper(func, bitmask, thisArg, partials, holders, partialsRight, holdersRight, argPos, ary, arity) { + var isAry = bitmask & ARY_FLAG, isBind = bitmask & BIND_FLAG, isBindKey = bitmask & BIND_KEY_FLAG, isCurry = bitmask & CURRY_FLAG, isCurryBound = bitmask & CURRY_BOUND_FLAG, isCurryRight = bitmask & CURRY_RIGHT_FLAG, Ctor = isBindKey ? undefined : createCtorWrapper(func); + function wrapper() { + var length = arguments.length, index = length, args = Array(length); + while (index--) { + args[index] = arguments[index]; + } + if (partials) { + args = composeArgs(args, partials, holders); + } + if (partialsRight) { + args = composeArgsRight(args, partialsRight, holdersRight); + } + if (isCurry || isCurryRight) { + var placeholder = wrapper.placeholder, argsHolders = replaceHolders(args, placeholder); + length -= argsHolders.length; + if (length < arity) { + var newArgPos = argPos ? arrayCopy(argPos) : undefined, newArity = nativeMax(arity - length, 0), newsHolders = isCurry ? argsHolders : undefined, newHoldersRight = isCurry ? undefined : argsHolders, newPartials = isCurry ? args : undefined, newPartialsRight = isCurry ? undefined : args; + bitmask |= isCurry ? PARTIAL_FLAG : PARTIAL_RIGHT_FLAG; + bitmask &= ~(isCurry ? PARTIAL_RIGHT_FLAG : PARTIAL_FLAG); + if (!isCurryBound) { + bitmask &= ~(BIND_FLAG | BIND_KEY_FLAG); + } + var newData = [ func, bitmask, thisArg, newPartials, newsHolders, newPartialsRight, newHoldersRight, newArgPos, ary, newArity ], result = createHybridWrapper.apply(undefined, newData); + if (isLaziable(func)) { + setData(result, newData); + } + result.placeholder = placeholder; + return result; + } + } + var thisBinding = isBind ? thisArg : this, fn = isBindKey ? thisBinding[func] : func; + if (argPos) { + args = reorder(args, argPos); + } + if (isAry && ary < args.length) { + args.length = ary; + } + if (this && this !== root && this instanceof wrapper) { + fn = Ctor || createCtorWrapper(func); + } + return fn.apply(thisBinding, args); + } + return wrapper; + } + function createPadding(string, length, chars) { + var strLength = string.length; + length = +length; + if (strLength >= length || !nativeIsFinite(length)) { + return ""; + } + var padLength = length - strLength; + chars = chars == null ? " " : chars + ""; + return repeat(chars, nativeCeil(padLength / chars.length)).slice(0, padLength); + } + function createPartialWrapper(func, bitmask, thisArg, partials) { + var isBind = bitmask & BIND_FLAG, Ctor = createCtorWrapper(func); + function wrapper() { + var argsIndex = -1, argsLength = arguments.length, leftIndex = -1, leftLength = partials.length, args = Array(leftLength + argsLength); + while (++leftIndex < leftLength) { + args[leftIndex] = partials[leftIndex]; + } + while (argsLength--) { + args[leftIndex++] = arguments[++argsIndex]; + } + var fn = this && this !== root && this instanceof wrapper ? Ctor : func; + return fn.apply(isBind ? thisArg : this, args); + } + return wrapper; + } + function createRound(methodName) { + var func = Math[methodName]; + return function(number, precision) { + precision = precision === undefined ? 0 : +precision || 0; + if (precision) { + precision = pow(10, precision); + return func(number * precision) / precision; + } + return func(number); + }; + } + function createSortedIndex(retHighest) { + return function(array, value, iteratee, thisArg) { + var callback = getCallback(iteratee); + return iteratee == null && callback === baseCallback ? binaryIndex(array, value, retHighest) : binaryIndexBy(array, value, callback(iteratee, thisArg, 1), retHighest); + }; + } + function createWrapper(func, bitmask, thisArg, partials, holders, argPos, ary, arity) { + var isBindKey = bitmask & BIND_KEY_FLAG; + if (!isBindKey && typeof func != "function") { + throw new TypeError(FUNC_ERROR_TEXT); + } + var length = partials ? partials.length : 0; + if (!length) { + bitmask &= ~(PARTIAL_FLAG | PARTIAL_RIGHT_FLAG); + partials = holders = undefined; + } + length -= holders ? holders.length : 0; + if (bitmask & PARTIAL_RIGHT_FLAG) { + var partialsRight = partials, holdersRight = holders; + partials = holders = undefined; + } + var data = isBindKey ? undefined : getData(func), newData = [ func, bitmask, thisArg, partials, holders, partialsRight, holdersRight, argPos, ary, arity ]; + if (data) { + mergeData(newData, data); + bitmask = newData[1]; + arity = newData[9]; + } + newData[9] = arity == null ? isBindKey ? 0 : func.length : nativeMax(arity - length, 0) || 0; + if (bitmask == BIND_FLAG) { + var result = createBindWrapper(newData[0], newData[2]); + } else if ((bitmask == PARTIAL_FLAG || bitmask == (BIND_FLAG | PARTIAL_FLAG)) && !newData[4].length) { + result = createPartialWrapper.apply(undefined, newData); + } else { + result = createHybridWrapper.apply(undefined, newData); + } + var setter = data ? baseSetData : setData; + return setter(result, newData); + } + function equalArrays(array, other, equalFunc, customizer, isLoose, stackA, stackB) { + var index = -1, arrLength = array.length, othLength = other.length; + if (arrLength != othLength && !(isLoose && othLength > arrLength)) { + return false; + } + while (++index < arrLength) { + var arrValue = array[index], othValue = other[index], result = customizer ? customizer(isLoose ? othValue : arrValue, isLoose ? arrValue : othValue, index) : undefined; + if (result !== undefined) { + if (result) { + continue; + } + return false; + } + if (isLoose) { + if (!arraySome(other, function(othValue) { + return arrValue === othValue || equalFunc(arrValue, othValue, customizer, isLoose, stackA, stackB); + })) { + return false; + } + } else if (!(arrValue === othValue || equalFunc(arrValue, othValue, customizer, isLoose, stackA, stackB))) { + return false; + } + } + return true; + } + function equalByTag(object, other, tag) { + switch (tag) { + case boolTag: + case dateTag: + return +object == +other; + + case errorTag: + return object.name == other.name && object.message == other.message; + + case numberTag: + return object != +object ? other != +other : object == +other; + + case regexpTag: + case stringTag: + return object == other + ""; + } + return false; + } + function equalObjects(object, other, equalFunc, customizer, isLoose, stackA, stackB) { + var objProps = keys(object), objLength = objProps.length, othProps = keys(other), othLength = othProps.length; + if (objLength != othLength && !isLoose) { + return false; + } + var index = objLength; + while (index--) { + var key = objProps[index]; + if (!(isLoose ? key in other : hasOwnProperty.call(other, key))) { + return false; + } + } + var skipCtor = isLoose; + while (++index < objLength) { + key = objProps[index]; + var objValue = object[key], othValue = other[key], result = customizer ? customizer(isLoose ? othValue : objValue, isLoose ? objValue : othValue, key) : undefined; + if (!(result === undefined ? equalFunc(objValue, othValue, customizer, isLoose, stackA, stackB) : result)) { + return false; + } + skipCtor || (skipCtor = key == "constructor"); + } + if (!skipCtor) { + var objCtor = object.constructor, othCtor = other.constructor; + if (objCtor != othCtor && ("constructor" in object && "constructor" in other) && !(typeof objCtor == "function" && objCtor instanceof objCtor && typeof othCtor == "function" && othCtor instanceof othCtor)) { + return false; + } + } + return true; + } + function getCallback(func, thisArg, argCount) { + var result = lodash.callback || callback; + result = result === callback ? baseCallback : result; + return argCount ? result(func, thisArg, argCount) : result; + } + var getData = !metaMap ? noop : function(func) { + return metaMap.get(func); + }; + function getFuncName(func) { + var result = func.name + "", array = realNames[result], length = array ? array.length : 0; + while (length--) { + var data = array[length], otherFunc = data.func; + if (otherFunc == null || otherFunc == func) { + return data.name; + } + } + return result; + } + function getIndexOf(collection, target, fromIndex) { + var result = lodash.indexOf || indexOf; + result = result === indexOf ? baseIndexOf : result; + return collection ? result(collection, target, fromIndex) : result; + } + var getLength = baseProperty("length"); + function getMatchData(object) { + var result = pairs(object), length = result.length; + while (length--) { + result[length][2] = isStrictComparable(result[length][1]); + } + return result; + } + function getNative(object, key) { + var value = object == null ? undefined : object[key]; + return isNative(value) ? value : undefined; + } + function getView(start, end, transforms) { + var index = -1, length = transforms.length; + while (++index < length) { + var data = transforms[index], size = data.size; + switch (data.type) { + case "drop": + start += size; + break; + + case "dropRight": + end -= size; + break; + + case "take": + end = nativeMin(end, start + size); + break; + + case "takeRight": + start = nativeMax(start, end - size); + break; + } + } + return { + start: start, + end: end + }; + } + function initCloneArray(array) { + var length = array.length, result = new array.constructor(length); + if (length && typeof array[0] == "string" && hasOwnProperty.call(array, "index")) { + result.index = array.index; + result.input = array.input; + } + return result; + } + function initCloneObject(object) { + var Ctor = object.constructor; + if (!(typeof Ctor == "function" && Ctor instanceof Ctor)) { + Ctor = Object; + } + return new Ctor(); + } + function initCloneByTag(object, tag, isDeep) { + var Ctor = object.constructor; + switch (tag) { + case arrayBufferTag: + return bufferClone(object); + + case boolTag: + case dateTag: + return new Ctor(+object); + + case float32Tag: + case float64Tag: + case int8Tag: + case int16Tag: + case int32Tag: + case uint8Tag: + case uint8ClampedTag: + case uint16Tag: + case uint32Tag: + var buffer = object.buffer; + return new Ctor(isDeep ? bufferClone(buffer) : buffer, object.byteOffset, object.length); + + case numberTag: + case stringTag: + return new Ctor(object); + + case regexpTag: + var result = new Ctor(object.source, reFlags.exec(object)); + result.lastIndex = object.lastIndex; + } + return result; + } + function invokePath(object, path, args) { + if (object != null && !isKey(path, object)) { + path = toPath(path); + object = path.length == 1 ? object : baseGet(object, baseSlice(path, 0, -1)); + path = last(path); + } + var func = object == null ? object : object[path]; + return func == null ? undefined : func.apply(object, args); + } + function isArrayLike(value) { + return value != null && isLength(getLength(value)); + } + function isIndex(value, length) { + value = typeof value == "number" || reIsUint.test(value) ? +value : -1; + length = length == null ? MAX_SAFE_INTEGER : length; + return value > -1 && value % 1 == 0 && value < length; + } + function isIterateeCall(value, index, object) { + if (!isObject(object)) { + return false; + } + var type = typeof index; + if (type == "number" ? isArrayLike(object) && isIndex(index, object.length) : type == "string" && index in object) { + var other = object[index]; + return value === value ? value === other : other !== other; + } + return false; + } + function isKey(value, object) { + var type = typeof value; + if (type == "string" && reIsPlainProp.test(value) || type == "number") { + return true; + } + if (isArray(value)) { + return false; + } + var result = !reIsDeepProp.test(value); + return result || object != null && value in toObject(object); + } + function isLaziable(func) { + var funcName = getFuncName(func), other = lodash[funcName]; + if (typeof other != "function" || !(funcName in LazyWrapper.prototype)) { + return false; + } + if (func === other) { + return true; + } + var data = getData(other); + return !!data && func === data[0]; + } + function isLength(value) { + return typeof value == "number" && value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER; + } + function isStrictComparable(value) { + return value === value && !isObject(value); + } + function mergeData(data, source) { + var bitmask = data[1], srcBitmask = source[1], newBitmask = bitmask | srcBitmask, isCommon = newBitmask < ARY_FLAG; + var isCombo = srcBitmask == ARY_FLAG && bitmask == CURRY_FLAG || srcBitmask == ARY_FLAG && bitmask == REARG_FLAG && data[7].length <= source[8] || srcBitmask == (ARY_FLAG | REARG_FLAG) && bitmask == CURRY_FLAG; + if (!(isCommon || isCombo)) { + return data; + } + if (srcBitmask & BIND_FLAG) { + data[2] = source[2]; + newBitmask |= bitmask & BIND_FLAG ? 0 : CURRY_BOUND_FLAG; + } + var value = source[3]; + if (value) { + var partials = data[3]; + data[3] = partials ? composeArgs(partials, value, source[4]) : arrayCopy(value); + data[4] = partials ? replaceHolders(data[3], PLACEHOLDER) : arrayCopy(source[4]); + } + value = source[5]; + if (value) { + partials = data[5]; + data[5] = partials ? composeArgsRight(partials, value, source[6]) : arrayCopy(value); + data[6] = partials ? replaceHolders(data[5], PLACEHOLDER) : arrayCopy(source[6]); + } + value = source[7]; + if (value) { + data[7] = arrayCopy(value); + } + if (srcBitmask & ARY_FLAG) { + data[8] = data[8] == null ? source[8] : nativeMin(data[8], source[8]); + } + if (data[9] == null) { + data[9] = source[9]; + } + data[0] = source[0]; + data[1] = newBitmask; + return data; + } + function mergeDefaults(objectValue, sourceValue) { + return objectValue === undefined ? sourceValue : merge(objectValue, sourceValue, mergeDefaults); + } + function pickByArray(object, props) { + object = toObject(object); + var index = -1, length = props.length, result = {}; + while (++index < length) { + var key = props[index]; + if (key in object) { + result[key] = object[key]; + } + } + return result; + } + function pickByCallback(object, predicate) { + var result = {}; + baseForIn(object, function(value, key, object) { + if (predicate(value, key, object)) { + result[key] = value; + } + }); + return result; + } + function reorder(array, indexes) { + var arrLength = array.length, length = nativeMin(indexes.length, arrLength), oldArray = arrayCopy(array); + while (length--) { + var index = indexes[length]; + array[length] = isIndex(index, arrLength) ? oldArray[index] : undefined; + } + return array; + } + var setData = function() { + var count = 0, lastCalled = 0; + return function(key, value) { + var stamp = now(), remaining = HOT_SPAN - (stamp - lastCalled); + lastCalled = stamp; + if (remaining > 0) { + if (++count >= HOT_COUNT) { + return key; + } + } else { + count = 0; + } + return baseSetData(key, value); + }; + }(); + function shimKeys(object) { + var props = keysIn(object), propsLength = props.length, length = propsLength && object.length; + var allowIndexes = !!length && isLength(length) && (isArray(object) || isArguments(object)); + var index = -1, result = []; + while (++index < propsLength) { + var key = props[index]; + if (allowIndexes && isIndex(key, length) || hasOwnProperty.call(object, key)) { + result.push(key); + } + } + return result; + } + function toIterable(value) { + if (value == null) { + return []; + } + if (!isArrayLike(value)) { + return values(value); + } + return isObject(value) ? value : Object(value); + } + function toObject(value) { + return isObject(value) ? value : Object(value); + } + function toPath(value) { + if (isArray(value)) { + return value; + } + var result = []; + baseToString(value).replace(rePropName, function(match, number, quote, string) { + result.push(quote ? string.replace(reEscapeChar, "$1") : number || match); + }); + return result; + } + function wrapperClone(wrapper) { + return wrapper instanceof LazyWrapper ? wrapper.clone() : new LodashWrapper(wrapper.__wrapped__, wrapper.__chain__, arrayCopy(wrapper.__actions__)); + } + function chunk(array, size, guard) { + if (guard ? isIterateeCall(array, size, guard) : size == null) { + size = 1; + } else { + size = nativeMax(nativeFloor(size) || 1, 1); + } + var index = 0, length = array ? array.length : 0, resIndex = -1, result = Array(nativeCeil(length / size)); + while (index < length) { + result[++resIndex] = baseSlice(array, index, index += size); + } + return result; + } + function compact(array) { + var index = -1, length = array ? array.length : 0, resIndex = -1, result = []; + while (++index < length) { + var value = array[index]; + if (value) { + result[++resIndex] = value; + } + } + return result; + } + var difference = restParam(function(array, values) { + return isObjectLike(array) && isArrayLike(array) ? baseDifference(array, baseFlatten(values, false, true)) : []; + }); + function drop(array, n, guard) { + var length = array ? array.length : 0; + if (!length) { + return []; + } + if (guard ? isIterateeCall(array, n, guard) : n == null) { + n = 1; + } + return baseSlice(array, n < 0 ? 0 : n); + } + function dropRight(array, n, guard) { + var length = array ? array.length : 0; + if (!length) { + return []; + } + if (guard ? isIterateeCall(array, n, guard) : n == null) { + n = 1; + } + n = length - (+n || 0); + return baseSlice(array, 0, n < 0 ? 0 : n); + } + function dropRightWhile(array, predicate, thisArg) { + return array && array.length ? baseWhile(array, getCallback(predicate, thisArg, 3), true, true) : []; + } + function dropWhile(array, predicate, thisArg) { + return array && array.length ? baseWhile(array, getCallback(predicate, thisArg, 3), true) : []; + } + function fill(array, value, start, end) { + var length = array ? array.length : 0; + if (!length) { + return []; + } + if (start && typeof start != "number" && isIterateeCall(array, value, start)) { + start = 0; + end = length; + } + return baseFill(array, value, start, end); + } + var findIndex = createFindIndex(); + var findLastIndex = createFindIndex(true); + function first(array) { + return array ? array[0] : undefined; + } + function flatten(array, isDeep, guard) { + var length = array ? array.length : 0; + if (guard && isIterateeCall(array, isDeep, guard)) { + isDeep = false; + } + return length ? baseFlatten(array, isDeep) : []; + } + function flattenDeep(array) { + var length = array ? array.length : 0; + return length ? baseFlatten(array, true) : []; + } + function indexOf(array, value, fromIndex) { + var length = array ? array.length : 0; + if (!length) { + return -1; + } + if (typeof fromIndex == "number") { + fromIndex = fromIndex < 0 ? nativeMax(length + fromIndex, 0) : fromIndex; + } else if (fromIndex) { + var index = binaryIndex(array, value); + if (index < length && (value === value ? value === array[index] : array[index] !== array[index])) { + return index; + } + return -1; + } + return baseIndexOf(array, value, fromIndex || 0); + } + function initial(array) { + return dropRight(array, 1); + } + var intersection = restParam(function(arrays) { + var othLength = arrays.length, othIndex = othLength, caches = Array(length), indexOf = getIndexOf(), isCommon = indexOf === baseIndexOf, result = []; + while (othIndex--) { + var value = arrays[othIndex] = isArrayLike(value = arrays[othIndex]) ? value : []; + caches[othIndex] = isCommon && value.length >= 120 ? createCache(othIndex && value) : null; + } + var array = arrays[0], index = -1, length = array ? array.length : 0, seen = caches[0]; + outer: while (++index < length) { + value = array[index]; + if ((seen ? cacheIndexOf(seen, value) : indexOf(result, value, 0)) < 0) { + var othIndex = othLength; + while (--othIndex) { + var cache = caches[othIndex]; + if ((cache ? cacheIndexOf(cache, value) : indexOf(arrays[othIndex], value, 0)) < 0) { + continue outer; + } + } + if (seen) { + seen.push(value); + } + result.push(value); + } + } + return result; + }); + function last(array) { + var length = array ? array.length : 0; + return length ? array[length - 1] : undefined; + } + function lastIndexOf(array, value, fromIndex) { + var length = array ? array.length : 0; + if (!length) { + return -1; + } + var index = length; + if (typeof fromIndex == "number") { + index = (fromIndex < 0 ? nativeMax(length + fromIndex, 0) : nativeMin(fromIndex || 0, length - 1)) + 1; + } else if (fromIndex) { + index = binaryIndex(array, value, true) - 1; + var other = array[index]; + if (value === value ? value === other : other !== other) { + return index; + } + return -1; + } + if (value !== value) { + return indexOfNaN(array, index, true); + } + while (index--) { + if (array[index] === value) { + return index; + } + } + return -1; + } + function pull() { + var args = arguments, array = args[0]; + if (!(array && array.length)) { + return array; + } + var index = 0, indexOf = getIndexOf(), length = args.length; + while (++index < length) { + var fromIndex = 0, value = args[index]; + while ((fromIndex = indexOf(array, value, fromIndex)) > -1) { + splice.call(array, fromIndex, 1); + } + } + return array; + } + var pullAt = restParam(function(array, indexes) { + indexes = baseFlatten(indexes); + var result = baseAt(array, indexes); + basePullAt(array, indexes.sort(baseCompareAscending)); + return result; + }); + function remove(array, predicate, thisArg) { + var result = []; + if (!(array && array.length)) { + return result; + } + var index = -1, indexes = [], length = array.length; + predicate = getCallback(predicate, thisArg, 3); + while (++index < length) { + var value = array[index]; + if (predicate(value, index, array)) { + result.push(value); + indexes.push(index); + } + } + basePullAt(array, indexes); + return result; + } + function rest(array) { + return drop(array, 1); + } + function slice(array, start, end) { + var length = array ? array.length : 0; + if (!length) { + return []; + } + if (end && typeof end != "number" && isIterateeCall(array, start, end)) { + start = 0; + end = length; + } + return baseSlice(array, start, end); + } + var sortedIndex = createSortedIndex(); + var sortedLastIndex = createSortedIndex(true); + function take(array, n, guard) { + var length = array ? array.length : 0; + if (!length) { + return []; + } + if (guard ? isIterateeCall(array, n, guard) : n == null) { + n = 1; + } + return baseSlice(array, 0, n < 0 ? 0 : n); + } + function takeRight(array, n, guard) { + var length = array ? array.length : 0; + if (!length) { + return []; + } + if (guard ? isIterateeCall(array, n, guard) : n == null) { + n = 1; + } + n = length - (+n || 0); + return baseSlice(array, n < 0 ? 0 : n); + } + function takeRightWhile(array, predicate, thisArg) { + return array && array.length ? baseWhile(array, getCallback(predicate, thisArg, 3), false, true) : []; + } + function takeWhile(array, predicate, thisArg) { + return array && array.length ? baseWhile(array, getCallback(predicate, thisArg, 3)) : []; + } + var union = restParam(function(arrays) { + return baseUniq(baseFlatten(arrays, false, true)); + }); + function uniq(array, isSorted, iteratee, thisArg) { + var length = array ? array.length : 0; + if (!length) { + return []; + } + if (isSorted != null && typeof isSorted != "boolean") { + thisArg = iteratee; + iteratee = isIterateeCall(array, isSorted, thisArg) ? undefined : isSorted; + isSorted = false; + } + var callback = getCallback(); + if (!(iteratee == null && callback === baseCallback)) { + iteratee = callback(iteratee, thisArg, 3); + } + return isSorted && getIndexOf() === baseIndexOf ? sortedUniq(array, iteratee) : baseUniq(array, iteratee); + } + function unzip(array) { + if (!(array && array.length)) { + return []; + } + var index = -1, length = 0; + array = arrayFilter(array, function(group) { + if (isArrayLike(group)) { + length = nativeMax(group.length, length); + return true; + } + }); + var result = Array(length); + while (++index < length) { + result[index] = arrayMap(array, baseProperty(index)); + } + return result; + } + function unzipWith(array, iteratee, thisArg) { + var length = array ? array.length : 0; + if (!length) { + return []; + } + var result = unzip(array); + if (iteratee == null) { + return result; + } + iteratee = bindCallback(iteratee, thisArg, 4); + return arrayMap(result, function(group) { + return arrayReduce(group, iteratee, undefined, true); + }); + } + var without = restParam(function(array, values) { + return isArrayLike(array) ? baseDifference(array, values) : []; + }); + function xor() { + var index = -1, length = arguments.length; + while (++index < length) { + var array = arguments[index]; + if (isArrayLike(array)) { + var result = result ? arrayPush(baseDifference(result, array), baseDifference(array, result)) : array; + } + } + return result ? baseUniq(result) : []; + } + var zip = restParam(unzip); + function zipObject(props, values) { + var index = -1, length = props ? props.length : 0, result = {}; + if (length && !values && !isArray(props[0])) { + values = []; + } + while (++index < length) { + var key = props[index]; + if (values) { + result[key] = values[index]; + } else if (key) { + result[key[0]] = key[1]; + } + } + return result; + } + var zipWith = restParam(function(arrays) { + var length = arrays.length, iteratee = length > 2 ? arrays[length - 2] : undefined, thisArg = length > 1 ? arrays[length - 1] : undefined; + if (length > 2 && typeof iteratee == "function") { + length -= 2; + } else { + iteratee = length > 1 && typeof thisArg == "function" ? (--length, thisArg) : undefined; + thisArg = undefined; + } + arrays.length = length; + return unzipWith(arrays, iteratee, thisArg); + }); + function chain(value) { + var result = lodash(value); + result.__chain__ = true; + return result; + } + function tap(value, interceptor, thisArg) { + interceptor.call(thisArg, value); + return value; + } + function thru(value, interceptor, thisArg) { + return interceptor.call(thisArg, value); + } + function wrapperChain() { + return chain(this); + } + function wrapperCommit() { + return new LodashWrapper(this.value(), this.__chain__); + } + var wrapperConcat = restParam(function(values) { + values = baseFlatten(values); + return this.thru(function(array) { + return arrayConcat(isArray(array) ? array : [ toObject(array) ], values); + }); + }); + function wrapperPlant(value) { + var result, parent = this; + while (parent instanceof baseLodash) { + var clone = wrapperClone(parent); + if (result) { + previous.__wrapped__ = clone; + } else { + result = clone; + } + var previous = clone; + parent = parent.__wrapped__; + } + previous.__wrapped__ = value; + return result; + } + function wrapperReverse() { + var value = this.__wrapped__; + var interceptor = function(value) { + return value.reverse(); + }; + if (value instanceof LazyWrapper) { + var wrapped = value; + if (this.__actions__.length) { + wrapped = new LazyWrapper(this); + } + wrapped = wrapped.reverse(); + wrapped.__actions__.push({ + func: thru, + args: [ interceptor ], + thisArg: undefined + }); + return new LodashWrapper(wrapped, this.__chain__); + } + return this.thru(interceptor); + } + function wrapperToString() { + return this.value() + ""; + } + function wrapperValue() { + return baseWrapperValue(this.__wrapped__, this.__actions__); + } + var at = restParam(function(collection, props) { + return baseAt(collection, baseFlatten(props)); + }); + var countBy = createAggregator(function(result, value, key) { + hasOwnProperty.call(result, key) ? ++result[key] : result[key] = 1; + }); + function every(collection, predicate, thisArg) { + var func = isArray(collection) ? arrayEvery : baseEvery; + if (thisArg && isIterateeCall(collection, predicate, thisArg)) { + predicate = undefined; + } + if (typeof predicate != "function" || thisArg !== undefined) { + predicate = getCallback(predicate, thisArg, 3); + } + return func(collection, predicate); + } + function filter(collection, predicate, thisArg) { + var func = isArray(collection) ? arrayFilter : baseFilter; + predicate = getCallback(predicate, thisArg, 3); + return func(collection, predicate); + } + var find = createFind(baseEach); + var findLast = createFind(baseEachRight, true); + function findWhere(collection, source) { + return find(collection, baseMatches(source)); + } + var forEach = createForEach(arrayEach, baseEach); + var forEachRight = createForEach(arrayEachRight, baseEachRight); + var groupBy = createAggregator(function(result, value, key) { + if (hasOwnProperty.call(result, key)) { + result[key].push(value); + } else { + result[key] = [ value ]; + } + }); + function includes(collection, target, fromIndex, guard) { + var length = collection ? getLength(collection) : 0; + if (!isLength(length)) { + collection = values(collection); + length = collection.length; + } + if (typeof fromIndex != "number" || guard && isIterateeCall(target, fromIndex, guard)) { + fromIndex = 0; + } else { + fromIndex = fromIndex < 0 ? nativeMax(length + fromIndex, 0) : fromIndex || 0; + } + return typeof collection == "string" || !isArray(collection) && isString(collection) ? fromIndex <= length && collection.indexOf(target, fromIndex) > -1 : !!length && getIndexOf(collection, target, fromIndex) > -1; + } + var indexBy = createAggregator(function(result, value, key) { + result[key] = value; + }); + var invoke = restParam(function(collection, path, args) { + var index = -1, isFunc = typeof path == "function", isProp = isKey(path), result = isArrayLike(collection) ? Array(collection.length) : []; + baseEach(collection, function(value) { + var func = isFunc ? path : isProp && value != null ? value[path] : undefined; + result[++index] = func ? func.apply(value, args) : invokePath(value, path, args); + }); + return result; + }); + function map(collection, iteratee, thisArg) { + var func = isArray(collection) ? arrayMap : baseMap; + iteratee = getCallback(iteratee, thisArg, 3); + return func(collection, iteratee); + } + var partition = createAggregator(function(result, value, key) { + result[key ? 0 : 1].push(value); + }, function() { + return [ [], [] ]; + }); + function pluck(collection, path) { + return map(collection, property(path)); + } + var reduce = createReduce(arrayReduce, baseEach); + var reduceRight = createReduce(arrayReduceRight, baseEachRight); + function reject(collection, predicate, thisArg) { + var func = isArray(collection) ? arrayFilter : baseFilter; + predicate = getCallback(predicate, thisArg, 3); + return func(collection, function(value, index, collection) { + return !predicate(value, index, collection); + }); + } + function sample(collection, n, guard) { + if (guard ? isIterateeCall(collection, n, guard) : n == null) { + collection = toIterable(collection); + var length = collection.length; + return length > 0 ? collection[baseRandom(0, length - 1)] : undefined; + } + var index = -1, result = toArray(collection), length = result.length, lastIndex = length - 1; + n = nativeMin(n < 0 ? 0 : +n || 0, length); + while (++index < n) { + var rand = baseRandom(index, lastIndex), value = result[rand]; + result[rand] = result[index]; + result[index] = value; + } + result.length = n; + return result; + } + function shuffle(collection) { + return sample(collection, POSITIVE_INFINITY); + } + function size(collection) { + var length = collection ? getLength(collection) : 0; + return isLength(length) ? length : keys(collection).length; + } + function some(collection, predicate, thisArg) { + var func = isArray(collection) ? arraySome : baseSome; + if (thisArg && isIterateeCall(collection, predicate, thisArg)) { + predicate = undefined; + } + if (typeof predicate != "function" || thisArg !== undefined) { + predicate = getCallback(predicate, thisArg, 3); + } + return func(collection, predicate); + } + function sortBy(collection, iteratee, thisArg) { + if (collection == null) { + return []; + } + if (thisArg && isIterateeCall(collection, iteratee, thisArg)) { + iteratee = undefined; + } + var index = -1; + iteratee = getCallback(iteratee, thisArg, 3); + var result = baseMap(collection, function(value, key, collection) { + return { + criteria: iteratee(value, key, collection), + index: ++index, + value: value + }; + }); + return baseSortBy(result, compareAscending); + } + var sortByAll = restParam(function(collection, iteratees) { + if (collection == null) { + return []; + } + var guard = iteratees[2]; + if (guard && isIterateeCall(iteratees[0], iteratees[1], guard)) { + iteratees.length = 1; + } + return baseSortByOrder(collection, baseFlatten(iteratees), []); + }); + function sortByOrder(collection, iteratees, orders, guard) { + if (collection == null) { + return []; + } + if (guard && isIterateeCall(iteratees, orders, guard)) { + orders = undefined; + } + if (!isArray(iteratees)) { + iteratees = iteratees == null ? [] : [ iteratees ]; + } + if (!isArray(orders)) { + orders = orders == null ? [] : [ orders ]; + } + return baseSortByOrder(collection, iteratees, orders); + } + function where(collection, source) { + return filter(collection, baseMatches(source)); + } + var now = nativeNow || function() { + return new Date().getTime(); + }; + function after(n, func) { + if (typeof func != "function") { + if (typeof n == "function") { + var temp = n; + n = func; + func = temp; + } else { + throw new TypeError(FUNC_ERROR_TEXT); + } + } + n = nativeIsFinite(n = +n) ? n : 0; + return function() { + if (--n < 1) { + return func.apply(this, arguments); + } + }; + } + function ary(func, n, guard) { + if (guard && isIterateeCall(func, n, guard)) { + n = undefined; + } + n = func && n == null ? func.length : nativeMax(+n || 0, 0); + return createWrapper(func, ARY_FLAG, undefined, undefined, undefined, undefined, n); + } + function before(n, func) { + var result; + if (typeof func != "function") { + if (typeof n == "function") { + var temp = n; + n = func; + func = temp; + } else { + throw new TypeError(FUNC_ERROR_TEXT); + } + } + return function() { + if (--n > 0) { + result = func.apply(this, arguments); + } + if (n <= 1) { + func = undefined; + } + return result; + }; + } + var bind = restParam(function(func, thisArg, partials) { + var bitmask = BIND_FLAG; + if (partials.length) { + var holders = replaceHolders(partials, bind.placeholder); + bitmask |= PARTIAL_FLAG; + } + return createWrapper(func, bitmask, thisArg, partials, holders); + }); + var bindAll = restParam(function(object, methodNames) { + methodNames = methodNames.length ? baseFlatten(methodNames) : functions(object); + var index = -1, length = methodNames.length; + while (++index < length) { + var key = methodNames[index]; + object[key] = createWrapper(object[key], BIND_FLAG, object); + } + return object; + }); + var bindKey = restParam(function(object, key, partials) { + var bitmask = BIND_FLAG | BIND_KEY_FLAG; + if (partials.length) { + var holders = replaceHolders(partials, bindKey.placeholder); + bitmask |= PARTIAL_FLAG; + } + return createWrapper(key, bitmask, object, partials, holders); + }); + var curry = createCurry(CURRY_FLAG); + var curryRight = createCurry(CURRY_RIGHT_FLAG); + function debounce(func, wait, options) { + var args, maxTimeoutId, result, stamp, thisArg, timeoutId, trailingCall, lastCalled = 0, maxWait = false, trailing = true; + if (typeof func != "function") { + throw new TypeError(FUNC_ERROR_TEXT); + } + wait = wait < 0 ? 0 : +wait || 0; + if (options === true) { + var leading = true; + trailing = false; + } else if (isObject(options)) { + leading = !!options.leading; + maxWait = "maxWait" in options && nativeMax(+options.maxWait || 0, wait); + trailing = "trailing" in options ? !!options.trailing : trailing; + } + function cancel() { + if (timeoutId) { + clearTimeout(timeoutId); + } + if (maxTimeoutId) { + clearTimeout(maxTimeoutId); + } + lastCalled = 0; + maxTimeoutId = timeoutId = trailingCall = undefined; + } + function complete(isCalled, id) { + if (id) { + clearTimeout(id); + } + maxTimeoutId = timeoutId = trailingCall = undefined; + if (isCalled) { + lastCalled = now(); + result = func.apply(thisArg, args); + if (!timeoutId && !maxTimeoutId) { + args = thisArg = undefined; + } + } + } + function delayed() { + var remaining = wait - (now() - stamp); + if (remaining <= 0 || remaining > wait) { + complete(trailingCall, maxTimeoutId); + } else { + timeoutId = setTimeout(delayed, remaining); + } + } + function maxDelayed() { + complete(trailing, timeoutId); + } + function debounced() { + args = arguments; + stamp = now(); + thisArg = this; + trailingCall = trailing && (timeoutId || !leading); + if (maxWait === false) { + var leadingCall = leading && !timeoutId; + } else { + if (!maxTimeoutId && !leading) { + lastCalled = stamp; + } + var remaining = maxWait - (stamp - lastCalled), isCalled = remaining <= 0 || remaining > maxWait; + if (isCalled) { + if (maxTimeoutId) { + maxTimeoutId = clearTimeout(maxTimeoutId); + } + lastCalled = stamp; + result = func.apply(thisArg, args); + } else if (!maxTimeoutId) { + maxTimeoutId = setTimeout(maxDelayed, remaining); + } + } + if (isCalled && timeoutId) { + timeoutId = clearTimeout(timeoutId); + } else if (!timeoutId && wait !== maxWait) { + timeoutId = setTimeout(delayed, wait); + } + if (leadingCall) { + isCalled = true; + result = func.apply(thisArg, args); + } + if (isCalled && !timeoutId && !maxTimeoutId) { + args = thisArg = undefined; + } + return result; + } + debounced.cancel = cancel; + return debounced; + } + var defer = restParam(function(func, args) { + return baseDelay(func, 1, args); + }); + var delay = restParam(function(func, wait, args) { + return baseDelay(func, wait, args); + }); + var flow = createFlow(); + var flowRight = createFlow(true); + function memoize(func, resolver) { + if (typeof func != "function" || resolver && typeof resolver != "function") { + throw new TypeError(FUNC_ERROR_TEXT); + } + var memoized = function() { + var args = arguments, key = resolver ? resolver.apply(this, args) : args[0], cache = memoized.cache; + if (cache.has(key)) { + return cache.get(key); + } + var result = func.apply(this, args); + memoized.cache = cache.set(key, result); + return result; + }; + memoized.cache = new memoize.Cache(); + return memoized; + } + var modArgs = restParam(function(func, transforms) { + transforms = baseFlatten(transforms); + if (typeof func != "function" || !arrayEvery(transforms, baseIsFunction)) { + throw new TypeError(FUNC_ERROR_TEXT); + } + var length = transforms.length; + return restParam(function(args) { + var index = nativeMin(args.length, length); + while (index--) { + args[index] = transforms[index](args[index]); + } + return func.apply(this, args); + }); + }); + function negate(predicate) { + if (typeof predicate != "function") { + throw new TypeError(FUNC_ERROR_TEXT); + } + return function() { + return !predicate.apply(this, arguments); + }; + } + function once(func) { + return before(2, func); + } + var partial = createPartial(PARTIAL_FLAG); + var partialRight = createPartial(PARTIAL_RIGHT_FLAG); + var rearg = restParam(function(func, indexes) { + return createWrapper(func, REARG_FLAG, undefined, undefined, undefined, baseFlatten(indexes)); + }); + function restParam(func, start) { + if (typeof func != "function") { + throw new TypeError(FUNC_ERROR_TEXT); + } + start = nativeMax(start === undefined ? func.length - 1 : +start || 0, 0); + return function() { + var args = arguments, index = -1, length = nativeMax(args.length - start, 0), rest = Array(length); + while (++index < length) { + rest[index] = args[start + index]; + } + switch (start) { + case 0: + return func.call(this, rest); + + case 1: + return func.call(this, args[0], rest); + + case 2: + return func.call(this, args[0], args[1], rest); + } + var otherArgs = Array(start + 1); + index = -1; + while (++index < start) { + otherArgs[index] = args[index]; + } + otherArgs[start] = rest; + return func.apply(this, otherArgs); + }; + } + function spread(func) { + if (typeof func != "function") { + throw new TypeError(FUNC_ERROR_TEXT); + } + return function(array) { + return func.apply(this, array); + }; + } + function throttle(func, wait, options) { + var leading = true, trailing = true; + if (typeof func != "function") { + throw new TypeError(FUNC_ERROR_TEXT); + } + if (options === false) { + leading = false; + } else if (isObject(options)) { + leading = "leading" in options ? !!options.leading : leading; + trailing = "trailing" in options ? !!options.trailing : trailing; + } + return debounce(func, wait, { + leading: leading, + maxWait: +wait, + trailing: trailing + }); + } + function wrap(value, wrapper) { + wrapper = wrapper == null ? identity : wrapper; + return createWrapper(wrapper, PARTIAL_FLAG, undefined, [ value ], []); + } + function clone(value, isDeep, customizer, thisArg) { + if (isDeep && typeof isDeep != "boolean" && isIterateeCall(value, isDeep, customizer)) { + isDeep = false; + } else if (typeof isDeep == "function") { + thisArg = customizer; + customizer = isDeep; + isDeep = false; + } + return typeof customizer == "function" ? baseClone(value, isDeep, bindCallback(customizer, thisArg, 3)) : baseClone(value, isDeep); + } + function cloneDeep(value, customizer, thisArg) { + return typeof customizer == "function" ? baseClone(value, true, bindCallback(customizer, thisArg, 3)) : baseClone(value, true); + } + function gt(value, other) { + return value > other; + } + function gte(value, other) { + return value >= other; + } + function isArguments(value) { + return isObjectLike(value) && isArrayLike(value) && hasOwnProperty.call(value, "callee") && !propertyIsEnumerable.call(value, "callee"); + } + var isArray = nativeIsArray || function(value) { + return isObjectLike(value) && isLength(value.length) && objToString.call(value) == arrayTag; + }; + function isBoolean(value) { + return value === true || value === false || isObjectLike(value) && objToString.call(value) == boolTag; + } + function isDate(value) { + return isObjectLike(value) && objToString.call(value) == dateTag; + } + function isElement(value) { + return !!value && value.nodeType === 1 && isObjectLike(value) && !isPlainObject(value); + } + function isEmpty(value) { + if (value == null) { + return true; + } + if (isArrayLike(value) && (isArray(value) || isString(value) || isArguments(value) || isObjectLike(value) && isFunction(value.splice))) { + return !value.length; + } + return !keys(value).length; + } + function isEqual(value, other, customizer, thisArg) { + customizer = typeof customizer == "function" ? bindCallback(customizer, thisArg, 3) : undefined; + var result = customizer ? customizer(value, other) : undefined; + return result === undefined ? baseIsEqual(value, other, customizer) : !!result; + } + function isError(value) { + return isObjectLike(value) && typeof value.message == "string" && objToString.call(value) == errorTag; + } + function isFinite(value) { + return typeof value == "number" && nativeIsFinite(value); + } + function isFunction(value) { + return isObject(value) && objToString.call(value) == funcTag; + } + function isObject(value) { + var type = typeof value; + return !!value && (type == "object" || type == "function"); + } + function isMatch(object, source, customizer, thisArg) { + customizer = typeof customizer == "function" ? bindCallback(customizer, thisArg, 3) : undefined; + return baseIsMatch(object, getMatchData(source), customizer); + } + function isNaN(value) { + return isNumber(value) && value != +value; + } + function isNative(value) { + if (value == null) { + return false; + } + if (isFunction(value)) { + return reIsNative.test(fnToString.call(value)); + } + return isObjectLike(value) && reIsHostCtor.test(value); + } + function isNull(value) { + return value === null; + } + function isNumber(value) { + return typeof value == "number" || isObjectLike(value) && objToString.call(value) == numberTag; + } + function isPlainObject(value) { + var Ctor; + if (!(isObjectLike(value) && objToString.call(value) == objectTag && !isArguments(value)) || !hasOwnProperty.call(value, "constructor") && (Ctor = value.constructor, + typeof Ctor == "function" && !(Ctor instanceof Ctor))) { + return false; + } + var result; + baseForIn(value, function(subValue, key) { + result = key; + }); + return result === undefined || hasOwnProperty.call(value, result); + } + function isRegExp(value) { + return isObject(value) && objToString.call(value) == regexpTag; + } + function isString(value) { + return typeof value == "string" || isObjectLike(value) && objToString.call(value) == stringTag; + } + function isTypedArray(value) { + return isObjectLike(value) && isLength(value.length) && !!typedArrayTags[objToString.call(value)]; + } + function isUndefined(value) { + return value === undefined; + } + function lt(value, other) { + return value < other; + } + function lte(value, other) { + return value <= other; + } + function toArray(value) { + var length = value ? getLength(value) : 0; + if (!isLength(length)) { + return values(value); + } + if (!length) { + return []; + } + return arrayCopy(value); + } + function toPlainObject(value) { + return baseCopy(value, keysIn(value)); + } + var merge = createAssigner(baseMerge); + var assign = createAssigner(function(object, source, customizer) { + return customizer ? assignWith(object, source, customizer) : baseAssign(object, source); + }); + function create(prototype, properties, guard) { + var result = baseCreate(prototype); + if (guard && isIterateeCall(prototype, properties, guard)) { + properties = undefined; + } + return properties ? baseAssign(result, properties) : result; + } + var defaults = createDefaults(assign, assignDefaults); + var defaultsDeep = createDefaults(merge, mergeDefaults); + var findKey = createFindKey(baseForOwn); + var findLastKey = createFindKey(baseForOwnRight); + var forIn = createForIn(baseFor); + var forInRight = createForIn(baseForRight); + var forOwn = createForOwn(baseForOwn); + var forOwnRight = createForOwn(baseForOwnRight); + function functions(object) { + return baseFunctions(object, keysIn(object)); + } + function get(object, path, defaultValue) { + var result = object == null ? undefined : baseGet(object, toPath(path), path + ""); + return result === undefined ? defaultValue : result; + } + function has(object, path) { + if (object == null) { + return false; + } + var result = hasOwnProperty.call(object, path); + if (!result && !isKey(path)) { + path = toPath(path); + object = path.length == 1 ? object : baseGet(object, baseSlice(path, 0, -1)); + if (object == null) { + return false; + } + path = last(path); + result = hasOwnProperty.call(object, path); + } + return result || isLength(object.length) && isIndex(path, object.length) && (isArray(object) || isArguments(object)); + } + function invert(object, multiValue, guard) { + if (guard && isIterateeCall(object, multiValue, guard)) { + multiValue = undefined; + } + var index = -1, props = keys(object), length = props.length, result = {}; + while (++index < length) { + var key = props[index], value = object[key]; + if (multiValue) { + if (hasOwnProperty.call(result, value)) { + result[value].push(key); + } else { + result[value] = [ key ]; + } + } else { + result[value] = key; + } + } + return result; + } + var keys = !nativeKeys ? shimKeys : function(object) { + var Ctor = object == null ? undefined : object.constructor; + if (typeof Ctor == "function" && Ctor.prototype === object || typeof object != "function" && isArrayLike(object)) { + return shimKeys(object); + } + return isObject(object) ? nativeKeys(object) : []; + }; + function keysIn(object) { + if (object == null) { + return []; + } + if (!isObject(object)) { + object = Object(object); + } + var length = object.length; + length = length && isLength(length) && (isArray(object) || isArguments(object)) && length || 0; + var Ctor = object.constructor, index = -1, isProto = typeof Ctor == "function" && Ctor.prototype === object, result = Array(length), skipIndexes = length > 0; + while (++index < length) { + result[index] = index + ""; + } + for (var key in object) { + if (!(skipIndexes && isIndex(key, length)) && !(key == "constructor" && (isProto || !hasOwnProperty.call(object, key)))) { + result.push(key); + } + } + return result; + } + var mapKeys = createObjectMapper(true); + var mapValues = createObjectMapper(); + var omit = restParam(function(object, props) { + if (object == null) { + return {}; + } + if (typeof props[0] != "function") { + var props = arrayMap(baseFlatten(props), String); + return pickByArray(object, baseDifference(keysIn(object), props)); + } + var predicate = bindCallback(props[0], props[1], 3); + return pickByCallback(object, function(value, key, object) { + return !predicate(value, key, object); + }); + }); + function pairs(object) { + object = toObject(object); + var index = -1, props = keys(object), length = props.length, result = Array(length); + while (++index < length) { + var key = props[index]; + result[index] = [ key, object[key] ]; + } + return result; + } + var pick = restParam(function(object, props) { + if (object == null) { + return {}; + } + return typeof props[0] == "function" ? pickByCallback(object, bindCallback(props[0], props[1], 3)) : pickByArray(object, baseFlatten(props)); + }); + function result(object, path, defaultValue) { + var result = object == null ? undefined : object[path]; + if (result === undefined) { + if (object != null && !isKey(path, object)) { + path = toPath(path); + object = path.length == 1 ? object : baseGet(object, baseSlice(path, 0, -1)); + result = object == null ? undefined : object[last(path)]; + } + result = result === undefined ? defaultValue : result; + } + return isFunction(result) ? result.call(object) : result; + } + function set(object, path, value) { + if (object == null) { + return object; + } + var pathKey = path + ""; + path = object[pathKey] != null || isKey(path, object) ? [ pathKey ] : toPath(path); + var index = -1, length = path.length, lastIndex = length - 1, nested = object; + while (nested != null && ++index < length) { + var key = path[index]; + if (isObject(nested)) { + if (index == lastIndex) { + nested[key] = value; + } else if (nested[key] == null) { + nested[key] = isIndex(path[index + 1]) ? [] : {}; + } + } + nested = nested[key]; + } + return object; + } + function transform(object, iteratee, accumulator, thisArg) { + var isArr = isArray(object) || isTypedArray(object); + iteratee = getCallback(iteratee, thisArg, 4); + if (accumulator == null) { + if (isArr || isObject(object)) { + var Ctor = object.constructor; + if (isArr) { + accumulator = isArray(object) ? new Ctor() : []; + } else { + accumulator = baseCreate(isFunction(Ctor) ? Ctor.prototype : undefined); + } + } else { + accumulator = {}; + } + } + (isArr ? arrayEach : baseForOwn)(object, function(value, index, object) { + return iteratee(accumulator, value, index, object); + }); + return accumulator; + } + function values(object) { + return baseValues(object, keys(object)); + } + function valuesIn(object) { + return baseValues(object, keysIn(object)); + } + function inRange(value, start, end) { + start = +start || 0; + if (end === undefined) { + end = start; + start = 0; + } else { + end = +end || 0; + } + return value >= nativeMin(start, end) && value < nativeMax(start, end); + } + function random(min, max, floating) { + if (floating && isIterateeCall(min, max, floating)) { + max = floating = undefined; + } + var noMin = min == null, noMax = max == null; + if (floating == null) { + if (noMax && typeof min == "boolean") { + floating = min; + min = 1; + } else if (typeof max == "boolean") { + floating = max; + noMax = true; + } + } + if (noMin && noMax) { + max = 1; + noMax = false; + } + min = +min || 0; + if (noMax) { + max = min; + min = 0; + } else { + max = +max || 0; + } + if (floating || min % 1 || max % 1) { + var rand = nativeRandom(); + return nativeMin(min + rand * (max - min + parseFloat("1e-" + ((rand + "").length - 1))), max); + } + return baseRandom(min, max); + } + var camelCase = createCompounder(function(result, word, index) { + word = word.toLowerCase(); + return result + (index ? word.charAt(0).toUpperCase() + word.slice(1) : word); + }); + function capitalize(string) { + string = baseToString(string); + return string && string.charAt(0).toUpperCase() + string.slice(1); + } + function deburr(string) { + string = baseToString(string); + return string && string.replace(reLatin1, deburrLetter).replace(reComboMark, ""); + } + function endsWith(string, target, position) { + string = baseToString(string); + target = target + ""; + var length = string.length; + position = position === undefined ? length : nativeMin(position < 0 ? 0 : +position || 0, length); + position -= target.length; + return position >= 0 && string.indexOf(target, position) == position; + } + function escape(string) { + string = baseToString(string); + return string && reHasUnescapedHtml.test(string) ? string.replace(reUnescapedHtml, escapeHtmlChar) : string; + } + function escapeRegExp(string) { + string = baseToString(string); + return string && reHasRegExpChars.test(string) ? string.replace(reRegExpChars, escapeRegExpChar) : string || "(?:)"; + } + var kebabCase = createCompounder(function(result, word, index) { + return result + (index ? "-" : "") + word.toLowerCase(); + }); + function pad(string, length, chars) { + string = baseToString(string); + length = +length; + var strLength = string.length; + if (strLength >= length || !nativeIsFinite(length)) { + return string; + } + var mid = (length - strLength) / 2, leftLength = nativeFloor(mid), rightLength = nativeCeil(mid); + chars = createPadding("", rightLength, chars); + return chars.slice(0, leftLength) + string + chars; + } + var padLeft = createPadDir(); + var padRight = createPadDir(true); + function parseInt(string, radix, guard) { + if (guard ? isIterateeCall(string, radix, guard) : radix == null) { + radix = 0; + } else if (radix) { + radix = +radix; + } + string = trim(string); + return nativeParseInt(string, radix || (reHasHexPrefix.test(string) ? 16 : 10)); + } + function repeat(string, n) { + var result = ""; + string = baseToString(string); + n = +n; + if (n < 1 || !string || !nativeIsFinite(n)) { + return result; + } + do { + if (n % 2) { + result += string; + } + n = nativeFloor(n / 2); + string += string; + } while (n); + return result; + } + var snakeCase = createCompounder(function(result, word, index) { + return result + (index ? "_" : "") + word.toLowerCase(); + }); + var startCase = createCompounder(function(result, word, index) { + return result + (index ? " " : "") + (word.charAt(0).toUpperCase() + word.slice(1)); + }); + function startsWith(string, target, position) { + string = baseToString(string); + position = position == null ? 0 : nativeMin(position < 0 ? 0 : +position || 0, string.length); + return string.lastIndexOf(target, position) == position; + } + function template(string, options, otherOptions) { + var settings = lodash.templateSettings; + if (otherOptions && isIterateeCall(string, options, otherOptions)) { + options = otherOptions = undefined; + } + string = baseToString(string); + options = assignWith(baseAssign({}, otherOptions || options), settings, assignOwnDefaults); + var imports = assignWith(baseAssign({}, options.imports), settings.imports, assignOwnDefaults), importsKeys = keys(imports), importsValues = baseValues(imports, importsKeys); + var isEscaping, isEvaluating, index = 0, interpolate = options.interpolate || reNoMatch, source = "__p += '"; + var reDelimiters = RegExp((options.escape || reNoMatch).source + "|" + interpolate.source + "|" + (interpolate === reInterpolate ? reEsTemplate : reNoMatch).source + "|" + (options.evaluate || reNoMatch).source + "|$", "g"); + var sourceURL = "//# sourceURL=" + ("sourceURL" in options ? options.sourceURL : "lodash.templateSources[" + ++templateCounter + "]") + "\n"; + string.replace(reDelimiters, function(match, escapeValue, interpolateValue, esTemplateValue, evaluateValue, offset) { + interpolateValue || (interpolateValue = esTemplateValue); + source += string.slice(index, offset).replace(reUnescapedString, escapeStringChar); + if (escapeValue) { + isEscaping = true; + source += "' +\n__e(" + escapeValue + ") +\n'"; + } + if (evaluateValue) { + isEvaluating = true; + source += "';\n" + evaluateValue + ";\n__p += '"; + } + if (interpolateValue) { + source += "' +\n((__t = (" + interpolateValue + ")) == null ? '' : __t) +\n'"; + } + index = offset + match.length; + return match; + }); + source += "';\n"; + var variable = options.variable; + if (!variable) { + source = "with (obj) {\n" + source + "\n}\n"; + } + source = (isEvaluating ? source.replace(reEmptyStringLeading, "") : source).replace(reEmptyStringMiddle, "$1").replace(reEmptyStringTrailing, "$1;"); + source = "function(" + (variable || "obj") + ") {\n" + (variable ? "" : "obj || (obj = {});\n") + "var __t, __p = ''" + (isEscaping ? ", __e = _.escape" : "") + (isEvaluating ? ", __j = Array.prototype.join;\n" + "function print() { __p += __j.call(arguments, '') }\n" : ";\n") + source + "return __p\n}"; + var result = attempt(function() { + return Function(importsKeys, sourceURL + "return " + source).apply(undefined, importsValues); + }); + result.source = source; + if (isError(result)) { + throw result; + } + return result; + } + function trim(string, chars, guard) { + var value = string; + string = baseToString(string); + if (!string) { + return string; + } + if (guard ? isIterateeCall(value, chars, guard) : chars == null) { + return string.slice(trimmedLeftIndex(string), trimmedRightIndex(string) + 1); + } + chars = chars + ""; + return string.slice(charsLeftIndex(string, chars), charsRightIndex(string, chars) + 1); + } + function trimLeft(string, chars, guard) { + var value = string; + string = baseToString(string); + if (!string) { + return string; + } + if (guard ? isIterateeCall(value, chars, guard) : chars == null) { + return string.slice(trimmedLeftIndex(string)); + } + return string.slice(charsLeftIndex(string, chars + "")); + } + function trimRight(string, chars, guard) { + var value = string; + string = baseToString(string); + if (!string) { + return string; + } + if (guard ? isIterateeCall(value, chars, guard) : chars == null) { + return string.slice(0, trimmedRightIndex(string) + 1); + } + return string.slice(0, charsRightIndex(string, chars + "") + 1); + } + function trunc(string, options, guard) { + if (guard && isIterateeCall(string, options, guard)) { + options = undefined; + } + var length = DEFAULT_TRUNC_LENGTH, omission = DEFAULT_TRUNC_OMISSION; + if (options != null) { + if (isObject(options)) { + var separator = "separator" in options ? options.separator : separator; + length = "length" in options ? +options.length || 0 : length; + omission = "omission" in options ? baseToString(options.omission) : omission; + } else { + length = +options || 0; + } + } + string = baseToString(string); + if (length >= string.length) { + return string; + } + var end = length - omission.length; + if (end < 1) { + return omission; + } + var result = string.slice(0, end); + if (separator == null) { + return result + omission; + } + if (isRegExp(separator)) { + if (string.slice(end).search(separator)) { + var match, newEnd, substring = string.slice(0, end); + if (!separator.global) { + separator = RegExp(separator.source, (reFlags.exec(separator) || "") + "g"); + } + separator.lastIndex = 0; + while (match = separator.exec(substring)) { + newEnd = match.index; + } + result = result.slice(0, newEnd == null ? end : newEnd); + } + } else if (string.indexOf(separator, end) != end) { + var index = result.lastIndexOf(separator); + if (index > -1) { + result = result.slice(0, index); + } + } + return result + omission; + } + function unescape(string) { + string = baseToString(string); + return string && reHasEscapedHtml.test(string) ? string.replace(reEscapedHtml, unescapeHtmlChar) : string; + } + function words(string, pattern, guard) { + if (guard && isIterateeCall(string, pattern, guard)) { + pattern = undefined; + } + string = baseToString(string); + return string.match(pattern || reWords) || []; + } + var attempt = restParam(function(func, args) { + try { + return func.apply(undefined, args); + } catch (e) { + return isError(e) ? e : new Error(e); + } + }); + function callback(func, thisArg, guard) { + if (guard && isIterateeCall(func, thisArg, guard)) { + thisArg = undefined; + } + return isObjectLike(func) ? matches(func) : baseCallback(func, thisArg); + } + function constant(value) { + return function() { + return value; + }; + } + function identity(value) { + return value; + } + function matches(source) { + return baseMatches(baseClone(source, true)); + } + function matchesProperty(path, srcValue) { + return baseMatchesProperty(path, baseClone(srcValue, true)); + } + var method = restParam(function(path, args) { + return function(object) { + return invokePath(object, path, args); + }; + }); + var methodOf = restParam(function(object, args) { + return function(path) { + return invokePath(object, path, args); + }; + }); + function mixin(object, source, options) { + if (options == null) { + var isObj = isObject(source), props = isObj ? keys(source) : undefined, methodNames = props && props.length ? baseFunctions(source, props) : undefined; + if (!(methodNames ? methodNames.length : isObj)) { + methodNames = false; + options = source; + source = object; + object = this; + } + } + if (!methodNames) { + methodNames = baseFunctions(source, keys(source)); + } + var chain = true, index = -1, isFunc = isFunction(object), length = methodNames.length; + if (options === false) { + chain = false; + } else if (isObject(options) && "chain" in options) { + chain = options.chain; + } + while (++index < length) { + var methodName = methodNames[index], func = source[methodName]; + object[methodName] = func; + if (isFunc) { + object.prototype[methodName] = function(func) { + return function() { + var chainAll = this.__chain__; + if (chain || chainAll) { + var result = object(this.__wrapped__), actions = result.__actions__ = arrayCopy(this.__actions__); + actions.push({ + func: func, + args: arguments, + thisArg: object + }); + result.__chain__ = chainAll; + return result; + } + return func.apply(object, arrayPush([ this.value() ], arguments)); + }; + }(func); + } + } + return object; + } + function noConflict() { + root._ = oldDash; + return this; + } + function noop() {} + function property(path) { + return isKey(path) ? baseProperty(path) : basePropertyDeep(path); + } + function propertyOf(object) { + return function(path) { + return baseGet(object, toPath(path), path + ""); + }; + } + function range(start, end, step) { + if (step && isIterateeCall(start, end, step)) { + end = step = undefined; + } + start = +start || 0; + step = step == null ? 1 : +step || 0; + if (end == null) { + end = start; + start = 0; + } else { + end = +end || 0; + } + var index = -1, length = nativeMax(nativeCeil((end - start) / (step || 1)), 0), result = Array(length); + while (++index < length) { + result[index] = start; + start += step; + } + return result; + } + function times(n, iteratee, thisArg) { + n = nativeFloor(n); + if (n < 1 || !nativeIsFinite(n)) { + return []; + } + var index = -1, result = Array(nativeMin(n, MAX_ARRAY_LENGTH)); + iteratee = bindCallback(iteratee, thisArg, 1); + while (++index < n) { + if (index < MAX_ARRAY_LENGTH) { + result[index] = iteratee(index); + } else { + iteratee(index); + } + } + return result; + } + function uniqueId(prefix) { + var id = ++idCounter; + return baseToString(prefix) + id; + } + function add(augend, addend) { + return (+augend || 0) + (+addend || 0); + } + var ceil = createRound("ceil"); + var floor = createRound("floor"); + var max = createExtremum(gt, NEGATIVE_INFINITY); + var min = createExtremum(lt, POSITIVE_INFINITY); + var round = createRound("round"); + function sum(collection, iteratee, thisArg) { + if (thisArg && isIterateeCall(collection, iteratee, thisArg)) { + iteratee = undefined; + } + iteratee = getCallback(iteratee, thisArg, 3); + return iteratee.length == 1 ? arraySum(isArray(collection) ? collection : toIterable(collection), iteratee) : baseSum(collection, iteratee); + } + lodash.prototype = baseLodash.prototype; + LodashWrapper.prototype = baseCreate(baseLodash.prototype); + LodashWrapper.prototype.constructor = LodashWrapper; + LazyWrapper.prototype = baseCreate(baseLodash.prototype); + LazyWrapper.prototype.constructor = LazyWrapper; + MapCache.prototype["delete"] = mapDelete; + MapCache.prototype.get = mapGet; + MapCache.prototype.has = mapHas; + MapCache.prototype.set = mapSet; + SetCache.prototype.push = cachePush; + memoize.Cache = MapCache; + lodash.after = after; + lodash.ary = ary; + lodash.assign = assign; + lodash.at = at; + lodash.before = before; + lodash.bind = bind; + lodash.bindAll = bindAll; + lodash.bindKey = bindKey; + lodash.callback = callback; + lodash.chain = chain; + lodash.chunk = chunk; + lodash.compact = compact; + lodash.constant = constant; + lodash.countBy = countBy; + lodash.create = create; + lodash.curry = curry; + lodash.curryRight = curryRight; + lodash.debounce = debounce; + lodash.defaults = defaults; + lodash.defaultsDeep = defaultsDeep; + lodash.defer = defer; + lodash.delay = delay; + lodash.difference = difference; + lodash.drop = drop; + lodash.dropRight = dropRight; + lodash.dropRightWhile = dropRightWhile; + lodash.dropWhile = dropWhile; + lodash.fill = fill; + lodash.filter = filter; + lodash.flatten = flatten; + lodash.flattenDeep = flattenDeep; + lodash.flow = flow; + lodash.flowRight = flowRight; + lodash.forEach = forEach; + lodash.forEachRight = forEachRight; + lodash.forIn = forIn; + lodash.forInRight = forInRight; + lodash.forOwn = forOwn; + lodash.forOwnRight = forOwnRight; + lodash.functions = functions; + lodash.groupBy = groupBy; + lodash.indexBy = indexBy; + lodash.initial = initial; + lodash.intersection = intersection; + lodash.invert = invert; + lodash.invoke = invoke; + lodash.keys = keys; + lodash.keysIn = keysIn; + lodash.map = map; + lodash.mapKeys = mapKeys; + lodash.mapValues = mapValues; + lodash.matches = matches; + lodash.matchesProperty = matchesProperty; + lodash.memoize = memoize; + lodash.merge = merge; + lodash.method = method; + lodash.methodOf = methodOf; + lodash.mixin = mixin; + lodash.modArgs = modArgs; + lodash.negate = negate; + lodash.omit = omit; + lodash.once = once; + lodash.pairs = pairs; + lodash.partial = partial; + lodash.partialRight = partialRight; + lodash.partition = partition; + lodash.pick = pick; + lodash.pluck = pluck; + lodash.property = property; + lodash.propertyOf = propertyOf; + lodash.pull = pull; + lodash.pullAt = pullAt; + lodash.range = range; + lodash.rearg = rearg; + lodash.reject = reject; + lodash.remove = remove; + lodash.rest = rest; + lodash.restParam = restParam; + lodash.set = set; + lodash.shuffle = shuffle; + lodash.slice = slice; + lodash.sortBy = sortBy; + lodash.sortByAll = sortByAll; + lodash.sortByOrder = sortByOrder; + lodash.spread = spread; + lodash.take = take; + lodash.takeRight = takeRight; + lodash.takeRightWhile = takeRightWhile; + lodash.takeWhile = takeWhile; + lodash.tap = tap; + lodash.throttle = throttle; + lodash.thru = thru; + lodash.times = times; + lodash.toArray = toArray; + lodash.toPlainObject = toPlainObject; + lodash.transform = transform; + lodash.union = union; + lodash.uniq = uniq; + lodash.unzip = unzip; + lodash.unzipWith = unzipWith; + lodash.values = values; + lodash.valuesIn = valuesIn; + lodash.where = where; + lodash.without = without; + lodash.wrap = wrap; + lodash.xor = xor; + lodash.zip = zip; + lodash.zipObject = zipObject; + lodash.zipWith = zipWith; + lodash.backflow = flowRight; + lodash.collect = map; + lodash.compose = flowRight; + lodash.each = forEach; + lodash.eachRight = forEachRight; + lodash.extend = assign; + lodash.iteratee = callback; + lodash.methods = functions; + lodash.object = zipObject; + lodash.select = filter; + lodash.tail = rest; + lodash.unique = uniq; + mixin(lodash, lodash); + lodash.add = add; + lodash.attempt = attempt; + lodash.camelCase = camelCase; + lodash.capitalize = capitalize; + lodash.ceil = ceil; + lodash.clone = clone; + lodash.cloneDeep = cloneDeep; + lodash.deburr = deburr; + lodash.endsWith = endsWith; + lodash.escape = escape; + lodash.escapeRegExp = escapeRegExp; + lodash.every = every; + lodash.find = find; + lodash.findIndex = findIndex; + lodash.findKey = findKey; + lodash.findLast = findLast; + lodash.findLastIndex = findLastIndex; + lodash.findLastKey = findLastKey; + lodash.findWhere = findWhere; + lodash.first = first; + lodash.floor = floor; + lodash.get = get; + lodash.gt = gt; + lodash.gte = gte; + lodash.has = has; + lodash.identity = identity; + lodash.includes = includes; + lodash.indexOf = indexOf; + lodash.inRange = inRange; + lodash.isArguments = isArguments; + lodash.isArray = isArray; + lodash.isBoolean = isBoolean; + lodash.isDate = isDate; + lodash.isElement = isElement; + lodash.isEmpty = isEmpty; + lodash.isEqual = isEqual; + lodash.isError = isError; + lodash.isFinite = isFinite; + lodash.isFunction = isFunction; + lodash.isMatch = isMatch; + lodash.isNaN = isNaN; + lodash.isNative = isNative; + lodash.isNull = isNull; + lodash.isNumber = isNumber; + lodash.isObject = isObject; + lodash.isPlainObject = isPlainObject; + lodash.isRegExp = isRegExp; + lodash.isString = isString; + lodash.isTypedArray = isTypedArray; + lodash.isUndefined = isUndefined; + lodash.kebabCase = kebabCase; + lodash.last = last; + lodash.lastIndexOf = lastIndexOf; + lodash.lt = lt; + lodash.lte = lte; + lodash.max = max; + lodash.min = min; + lodash.noConflict = noConflict; + lodash.noop = noop; + lodash.now = now; + lodash.pad = pad; + lodash.padLeft = padLeft; + lodash.padRight = padRight; + lodash.parseInt = parseInt; + lodash.random = random; + lodash.reduce = reduce; + lodash.reduceRight = reduceRight; + lodash.repeat = repeat; + lodash.result = result; + lodash.round = round; + lodash.runInContext = runInContext; + lodash.size = size; + lodash.snakeCase = snakeCase; + lodash.some = some; + lodash.sortedIndex = sortedIndex; + lodash.sortedLastIndex = sortedLastIndex; + lodash.startCase = startCase; + lodash.startsWith = startsWith; + lodash.sum = sum; + lodash.template = template; + lodash.trim = trim; + lodash.trimLeft = trimLeft; + lodash.trimRight = trimRight; + lodash.trunc = trunc; + lodash.unescape = unescape; + lodash.uniqueId = uniqueId; + lodash.words = words; + lodash.all = every; + lodash.any = some; + lodash.contains = includes; + lodash.eq = isEqual; + lodash.detect = find; + lodash.foldl = reduce; + lodash.foldr = reduceRight; + lodash.head = first; + lodash.include = includes; + lodash.inject = reduce; + mixin(lodash, function() { + var source = {}; + baseForOwn(lodash, function(func, methodName) { + if (!lodash.prototype[methodName]) { + source[methodName] = func; + } + }); + return source; + }(), false); + lodash.sample = sample; + lodash.prototype.sample = function(n) { + if (!this.__chain__ && n == null) { + return sample(this.value()); + } + return this.thru(function(value) { + return sample(value, n); + }); + }; + lodash.VERSION = VERSION; + arrayEach([ "bind", "bindKey", "curry", "curryRight", "partial", "partialRight" ], function(methodName) { + lodash[methodName].placeholder = lodash; + }); + arrayEach([ "drop", "take" ], function(methodName, index) { + LazyWrapper.prototype[methodName] = function(n) { + var filtered = this.__filtered__; + if (filtered && !index) { + return new LazyWrapper(this); + } + n = n == null ? 1 : nativeMax(nativeFloor(n) || 0, 0); + var result = this.clone(); + if (filtered) { + result.__takeCount__ = nativeMin(result.__takeCount__, n); + } else { + result.__views__.push({ + size: n, + type: methodName + (result.__dir__ < 0 ? "Right" : "") + }); + } + return result; + }; + LazyWrapper.prototype[methodName + "Right"] = function(n) { + return this.reverse()[methodName](n).reverse(); + }; + }); + arrayEach([ "filter", "map", "takeWhile" ], function(methodName, index) { + var type = index + 1, isFilter = type != LAZY_MAP_FLAG; + LazyWrapper.prototype[methodName] = function(iteratee, thisArg) { + var result = this.clone(); + result.__iteratees__.push({ + iteratee: getCallback(iteratee, thisArg, 1), + type: type + }); + result.__filtered__ = result.__filtered__ || isFilter; + return result; + }; + }); + arrayEach([ "first", "last" ], function(methodName, index) { + var takeName = "take" + (index ? "Right" : ""); + LazyWrapper.prototype[methodName] = function() { + return this[takeName](1).value()[0]; + }; + }); + arrayEach([ "initial", "rest" ], function(methodName, index) { + var dropName = "drop" + (index ? "" : "Right"); + LazyWrapper.prototype[methodName] = function() { + return this.__filtered__ ? new LazyWrapper(this) : this[dropName](1); + }; + }); + arrayEach([ "pluck", "where" ], function(methodName, index) { + var operationName = index ? "filter" : "map", createCallback = index ? baseMatches : property; + LazyWrapper.prototype[methodName] = function(value) { + return this[operationName](createCallback(value)); + }; + }); + LazyWrapper.prototype.compact = function() { + return this.filter(identity); + }; + LazyWrapper.prototype.reject = function(predicate, thisArg) { + predicate = getCallback(predicate, thisArg, 1); + return this.filter(function(value) { + return !predicate(value); + }); + }; + LazyWrapper.prototype.slice = function(start, end) { + start = start == null ? 0 : +start || 0; + var result = this; + if (result.__filtered__ && (start > 0 || end < 0)) { + return new LazyWrapper(result); + } + if (start < 0) { + result = result.takeRight(-start); + } else if (start) { + result = result.drop(start); + } + if (end !== undefined) { + end = +end || 0; + result = end < 0 ? result.dropRight(-end) : result.take(end - start); + } + return result; + }; + LazyWrapper.prototype.takeRightWhile = function(predicate, thisArg) { + return this.reverse().takeWhile(predicate, thisArg).reverse(); + }; + LazyWrapper.prototype.toArray = function() { + return this.take(POSITIVE_INFINITY); + }; + baseForOwn(LazyWrapper.prototype, function(func, methodName) { + var checkIteratee = /^(?:filter|map|reject)|While$/.test(methodName), retUnwrapped = /^(?:first|last)$/.test(methodName), lodashFunc = lodash[retUnwrapped ? "take" + (methodName == "last" ? "Right" : "") : methodName]; + if (!lodashFunc) { + return; + } + lodash.prototype[methodName] = function() { + var args = retUnwrapped ? [ 1 ] : arguments, chainAll = this.__chain__, value = this.__wrapped__, isHybrid = !!this.__actions__.length, isLazy = value instanceof LazyWrapper, iteratee = args[0], useLazy = isLazy || isArray(value); + if (useLazy && checkIteratee && typeof iteratee == "function" && iteratee.length != 1) { + isLazy = useLazy = false; + } + var interceptor = function(value) { + return retUnwrapped && chainAll ? lodashFunc(value, 1)[0] : lodashFunc.apply(undefined, arrayPush([ value ], args)); + }; + var action = { + func: thru, + args: [ interceptor ], + thisArg: undefined + }, onlyLazy = isLazy && !isHybrid; + if (retUnwrapped && !chainAll) { + if (onlyLazy) { + value = value.clone(); + value.__actions__.push(action); + return func.call(value); + } + return lodashFunc.call(undefined, this.value())[0]; + } + if (!retUnwrapped && useLazy) { + value = onlyLazy ? value : new LazyWrapper(this); + var result = func.apply(value, args); + result.__actions__.push(action); + return new LodashWrapper(result, chainAll); + } + return this.thru(interceptor); + }; + }); + arrayEach([ "join", "pop", "push", "replace", "shift", "sort", "splice", "split", "unshift" ], function(methodName) { + var func = (/^(?:replace|split)$/.test(methodName) ? stringProto : arrayProto)[methodName], chainName = /^(?:push|sort|unshift)$/.test(methodName) ? "tap" : "thru", retUnwrapped = /^(?:join|pop|replace|shift)$/.test(methodName); + lodash.prototype[methodName] = function() { + var args = arguments; + if (retUnwrapped && !this.__chain__) { + return func.apply(this.value(), args); + } + return this[chainName](function(value) { + return func.apply(value, args); + }); + }; + }); + baseForOwn(LazyWrapper.prototype, function(func, methodName) { + var lodashFunc = lodash[methodName]; + if (lodashFunc) { + var key = lodashFunc.name + "", names = realNames[key] || (realNames[key] = []); + names.push({ + name: methodName, + func: lodashFunc + }); + } + }); + realNames[createHybridWrapper(undefined, BIND_KEY_FLAG).name] = [ { + name: "wrapper", + func: undefined + } ]; + LazyWrapper.prototype.clone = lazyClone; + LazyWrapper.prototype.reverse = lazyReverse; + LazyWrapper.prototype.value = lazyValue; + lodash.prototype.chain = wrapperChain; + lodash.prototype.commit = wrapperCommit; + lodash.prototype.concat = wrapperConcat; + lodash.prototype.plant = wrapperPlant; + lodash.prototype.reverse = wrapperReverse; + lodash.prototype.toString = wrapperToString; + lodash.prototype.run = lodash.prototype.toJSON = lodash.prototype.valueOf = lodash.prototype.value = wrapperValue; + lodash.prototype.collect = lodash.prototype.map; + lodash.prototype.head = lodash.prototype.first; + lodash.prototype.select = lodash.prototype.filter; + lodash.prototype.tail = lodash.prototype.rest; + return lodash; + } + var _ = runInContext(); + if (typeof define == "function" && typeof define.amd == "object" && define.amd) { + root._ = _; + define(function() { + return _; + }); + } else if (freeExports && freeModule) { + if (moduleExports) { + (freeModule.exports = _)._ = _; + } else { + freeExports._ = _; + } + } else { + root._ = _; + } +}).call(this); + (function(window, document, undefined) { "use strict"; function minErr(module, ErrorConstructor) { @@ -5391,7 +9332,7 @@ } return match; }); - message += "\nhttp://errors.angularjs.org/1.4.6/" + (module ? module + "/" : "") + code; + message += "\nhttp://errors.angularjs.org/1.4.7/" + (module ? module + "/" : "") + code; for (i = SKIP_INDEXES, paramPrefix = "?"; i < templateArgs.length; i++, paramPrefix = "&") { message += paramPrefix + "p" + (i - SKIP_INDEXES) + "=" + encodeURIComponent(toDebugString(templateArgs[i])); } @@ -6210,11 +10151,11 @@ return obj; } var version = { - full: "1.4.6", + full: "1.4.7", major: 1, minor: 4, - dot: 6, - codeName: "multiplicative-elevation" + dot: 7, + codeName: "dark-luminescence" }; function publishExternalAPI(angular) { extend(angular, { @@ -6323,6 +10264,7 @@ $httpParamSerializer: $HttpParamSerializerProvider, $httpParamSerializerJQLike: $HttpParamSerializerJQLikeProvider, $httpBackend: $HttpBackendProvider, + $xhrFactory: $xhrFactoryProvider, $location: $LocationProvider, $log: $LogProvider, $parse: $ParseProvider, @@ -6368,10 +10310,10 @@ return offset ? letter.toUpperCase() : letter; }).replace(MOZ_HACK_REGEXP, "Moz$1"); } - var SINGLE_TAG_REGEXP = /^<(\w+)\s*\/?>(?:<\/\1>|)$/; + var SINGLE_TAG_REGEXP = /^<([\w-]+)\s*\/?>(?:<\/\1>|)$/; var HTML_REGEXP = /<|&#?\w+;/; - var TAG_NAME_REGEXP = /<([\w:]+)/; - var XHTML_TAG_REGEXP = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi; + var TAG_NAME_REGEXP = /<([\w:-]+)/; + var XHTML_TAG_REGEXP = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:-]+)[^>]*)\/>/gi; var wrapMap = { option: [ 1, '" ], thead: [ 1, "", "
                  " ], @@ -7614,6 +11556,9 @@ } }; return function(element, options) { + if (options.cleanupStyles) { + options.from = options.to = null; + } if (options.from) { element.css(options.from); options.from = null; @@ -8879,7 +12824,7 @@ compile: function() { return { pre: function attrInterpolatePreLinkFn(scope, element, attr) { - var $$observers = attr.$$observers || (attr.$$observers = {}); + var $$observers = attr.$$observers || (attr.$$observers = createMap()); if (EVENT_HANDLER_ATTR_REGEXP.test(name)) { throw $compileMinErr("nodomevents", "Interpolations for HTML DOM event attributes are disallowed. Please use the " + "ng- versions (such as ng-click instead of onclick) instead."); } @@ -9542,12 +13487,16 @@ } } ]; } - function createXhr() { - return new window.XMLHttpRequest(); + function $xhrFactoryProvider() { + this.$get = function() { + return function createXhr() { + return new window.XMLHttpRequest(); + }; + }; } function $HttpBackendProvider() { - this.$get = [ "$browser", "$window", "$document", function($browser, $window, $document) { - return createHttpBackend($browser, createXhr, $browser.defer, $window.angular.callbacks, $document[0]); + this.$get = [ "$browser", "$window", "$document", "$xhrFactory", function($browser, $window, $document, $xhrFactory) { + return createHttpBackend($browser, $xhrFactory, $browser.defer, $window.angular.callbacks, $document[0]); } ]; } function createHttpBackend($browser, createXhr, $browserDefer, callbacks, rawDocument) { @@ -9565,7 +13514,7 @@ callbacks[callbackId] = noop; }); } else { - var xhr = createXhr(); + var xhr = createXhr(method, url); xhr.open(method, url, true); forEach(headers, function(value, key) { if (isDefined(value)) { @@ -10273,12 +14222,18 @@ } var $parseMinErr = minErr("$parse"); function ensureSafeMemberName(name, fullExpression) { - name = isObject(name) && name.toString ? name.toString() : name; if (name === "__defineGetter__" || name === "__defineSetter__" || name === "__lookupGetter__" || name === "__lookupSetter__" || name === "__proto__") { throw $parseMinErr("isecfld", "Attempting to access a disallowed field in Angular expressions! " + "Expression: {0}", fullExpression); } return name; } + function getStringValue(name, fullExpression) { + name = name + ""; + if (!isString(name)) { + throw $parseMinErr("iseccst", "Cannot convert object to primitive value! " + "Expression: {0}", fullExpression); + } + return name; + } function ensureSafeObject(obj, fullExpression) { if (obj) { if (obj.constructor === obj) { @@ -10305,6 +14260,13 @@ } } } + function ensureSafeAssignContext(obj, fullExpression) { + if (obj) { + if (obj === 0..constructor || obj === false.constructor || obj === "".constructor || obj === {}.constructor || obj === [].constructor || obj === Function.constructor) { + throw $parseMinErr("isecaf", "Assigning to a constructor is disallowed! Expression: {0}", fullExpression); + } + } + } var OPERATORS = createMap(); forEach("+ - * / % === !== == != < > <= >= && || ! = |".split(" "), function(operator) { OPERATORS[operator] = true; @@ -11053,7 +15015,7 @@ this.stage = "main"; this.recurse(ast); var fnString = '"' + this.USE + " " + this.STRICT + '";\n' + this.filterPrefix() + "var fn=" + this.generateFunction("fn", "s,l,a,i") + extra + this.watchFns() + "return fn;"; - var fn = new Function("$filter", "ensureSafeMemberName", "ensureSafeObject", "ensureSafeFunction", "ifDefined", "plus", "text", fnString)(this.$filter, ensureSafeMemberName, ensureSafeObject, ensureSafeFunction, ifDefined, plusFn, expression); + var fn = new Function("$filter", "ensureSafeMemberName", "ensureSafeObject", "ensureSafeFunction", "getStringValue", "ensureSafeAssignContext", "ifDefined", "plus", "text", fnString)(this.$filter, ensureSafeMemberName, ensureSafeObject, ensureSafeFunction, getStringValue, ensureSafeAssignContext, ifDefined, plusFn, expression); this.state = this.stage = undefined; fn.literal = isLiteral(ast); fn.constant = isConstant(ast); @@ -11190,6 +15152,7 @@ if (ast.computed) { right = self.nextId(); self.recurse(ast.property, right); + self.getStringValue(right); self.addEnsureSafeMemberName(right); if (create && create !== 1) { self.if_(self.not(self.computedMember(left, right)), self.lazyAssign(self.computedMember(left, right), "{}")); @@ -11275,6 +15238,7 @@ self.if_(self.notNull(left.context), function() { self.recurse(ast.right, right); self.addEnsureSafeObject(self.member(left.context, left.name, left.computed)); + self.addEnsureSafeAssignContext(left.context); expression = self.member(left.context, left.name, left.computed) + ast.operator + right; self.assign(intoId, expression); recursionFn(intoId || expression); @@ -11385,6 +15349,9 @@ addEnsureSafeFunction: function(item) { this.current().body.push(this.ensureSafeFunction(item), ";"); }, + addEnsureSafeAssignContext: function(item) { + this.current().body.push(this.ensureSafeAssignContext(item), ";"); + }, ensureSafeObject: function(item) { return "ensureSafeObject(" + item + ",text)"; }, @@ -11394,6 +15361,12 @@ ensureSafeFunction: function(item) { return "ensureSafeFunction(" + item + ",text)"; }, + getStringValue: function(item) { + this.assign(item, "getStringValue(" + item + ",text)"); + }, + ensureSafeAssignContext: function(item) { + return "ensureSafeAssignContext(" + item + ",text)"; + }, lazyRecurse: function(ast, intoId, nameId, recursionFn, create, skipWatchIdCheck) { var self = this; return function() { @@ -11561,6 +15534,7 @@ var lhs = left(scope, locals, assign, inputs); var rhs = right(scope, locals, assign, inputs); ensureSafeObject(lhs.value, self.expression); + ensureSafeAssignContext(lhs.context); lhs.context[lhs.name] = rhs; return context ? { value: rhs @@ -11818,6 +15792,7 @@ var value; if (lhs != null) { rhs = right(scope, locals, assign, inputs); + rhs = getStringValue(rhs); ensureSafeMemberName(rhs, expression); if (create && create !== 1 && lhs && !lhs[rhs]) { lhs[rhs] = {}; @@ -13500,6 +17475,7 @@ if (fractionSize > 0 && number < 1) { formatedText = number.toFixed(fractionSize); number = parseFloat(formatedText); + formatedText = formatedText.replace(DECIMAL_SEP, decimalSep); } } if (number === 0) { @@ -15517,11 +19493,11 @@ function updateOptionElement(option, element) { option.element = element; element.disabled = option.disabled; - if (option.value !== element.value) element.value = option.selectValue; if (option.label !== element.label) { element.label = option.label; element.textContent = option.label; } + if (option.value !== element.value) element.value = option.selectValue; } function addOrReuseElement(parent, current, type, templateElement) { var element; @@ -15549,7 +19525,7 @@ var emptyOption_ = emptyOption && emptyOption[0]; var unknownOption_ = unknownOption && unknownOption[0]; if (emptyOption_ || unknownOption_) { - while (current && (current === emptyOption_ || current === unknownOption_)) { + while (current && (current === emptyOption_ || current === unknownOption_ || emptyOption_ && emptyOption_.nodeType === NODE_TYPE_COMMENT)) { current = current.nextSibling; } } @@ -26151,1020 +30127,79 @@ angular.module("template/modal/window.html", []).run([ "$templateCache", functio $templateCache.put("template/modal/window.html", '\n" + ""); } ]); -angular.module("template/pagination/pager.html", []).run([ "$templateCache", function($templateCache) { - $templateCache.put("template/pagination/pager.html", '\n" + ""); -} ]); - -angular.module("template/pagination/pagination.html", []).run([ "$templateCache", function($templateCache) { - $templateCache.put("template/pagination/pagination.html", '\n" + ""); -} ]); - -angular.module("template/tooltip/tooltip-html-popup.html", []).run([ "$templateCache", function($templateCache) { - $templateCache.put("template/tooltip/tooltip-html-popup.html", '
                  \n' + '
                  \n' + '
                  \n' + "
                  \n" + ""); -} ]); - -angular.module("template/tooltip/tooltip-html-unsafe-popup.html", []).run([ "$templateCache", function($templateCache) { - $templateCache.put("template/tooltip/tooltip-html-unsafe-popup.html", '
                  \n' + '
                  \n' + '
                  \n' + "
                  \n" + ""); -} ]); - -angular.module("template/tooltip/tooltip-popup.html", []).run([ "$templateCache", function($templateCache) { - $templateCache.put("template/tooltip/tooltip-popup.html", '
                  \n' + '
                  \n' + '
                  \n' + "
                  \n" + ""); -} ]); - -angular.module("template/tooltip/tooltip-template-popup.html", []).run([ "$templateCache", function($templateCache) { - $templateCache.put("template/tooltip/tooltip-template-popup.html", '
                  \n' + '
                  \n' + '
                  \n' + "
                  \n" + ""); -} ]); - -angular.module("template/popover/popover-html.html", []).run([ "$templateCache", function($templateCache) { - $templateCache.put("template/popover/popover-html.html", '
                  \n' + '
                  \n' + "\n" + '
                  \n' + '

                  \n' + '
                  \n' + "
                  \n" + "
                  \n" + ""); -} ]); - -angular.module("template/popover/popover-template.html", []).run([ "$templateCache", function($templateCache) { - $templateCache.put("template/popover/popover-template.html", '
                  \n' + '
                  \n' + "\n" + '
                  \n' + '

                  \n' + '
                  \n' + "
                  \n" + "
                  \n" + ""); -} ]); - -angular.module("template/popover/popover.html", []).run([ "$templateCache", function($templateCache) { - $templateCache.put("template/popover/popover.html", '
                  \n' + '
                  \n' + "\n" + '
                  \n' + '

                  \n' + '
                  \n' + "
                  \n" + "
                  \n" + ""); -} ]); - -angular.module("template/progressbar/bar.html", []).run([ "$templateCache", function($templateCache) { - $templateCache.put("template/progressbar/bar.html", '
                  \n' + ""); -} ]); - -angular.module("template/progressbar/progress.html", []).run([ "$templateCache", function($templateCache) { - $templateCache.put("template/progressbar/progress.html", '
                  '); -} ]); - -angular.module("template/progressbar/progressbar.html", []).run([ "$templateCache", function($templateCache) { - $templateCache.put("template/progressbar/progressbar.html", '
                  \n' + '
                  \n' + "
                  \n" + ""); -} ]); - -angular.module("template/rating/rating.html", []).run([ "$templateCache", function($templateCache) { - $templateCache.put("template/rating/rating.html", '\n' + " ({{ $index < value ? '*' : ' ' }})\n" + ' \n' + "\n" + ""); -} ]); - -angular.module("template/tabs/tab.html", []).run([ "$templateCache", function($templateCache) { - $templateCache.put("template/tabs/tab.html", '
                • \n' + ' {{heading}}\n' + "
                • \n" + ""); -} ]); - -angular.module("template/tabs/tabset.html", []).run([ "$templateCache", function($templateCache) { - $templateCache.put("template/tabs/tabset.html", "
                  \n" + "
                    \n" + '
                    \n' + '
                    \n' + "
                    \n" + "
                    \n" + "
                    \n" + ""); -} ]); - -angular.module("template/timepicker/timepicker.html", []).run([ "$templateCache", function($templateCache) { - $templateCache.put("template/timepicker/timepicker.html", "\n" + " \n" + ' \n' + ' \n' + " \n" + ' \n' + ' \n' + " \n" + " \n" + ' \n" + " \n" + ' \n" + ' \n' + " \n" + ' \n' + ' \n' + " \n" + ' \n' + ' \n' + " \n" + " \n" + "
                     
                    \n' + ' \n' + " :\n' + ' \n' + "
                     
                    \n" + ""); -} ]); - -angular.module("template/typeahead/typeahead-match.html", []).run([ "$templateCache", function($templateCache) { - $templateCache.put("template/typeahead/typeahead-match.html", '\n' + ""); -} ]); - -angular.module("template/typeahead/typeahead-popup.html", []).run([ "$templateCache", function($templateCache) { - $templateCache.put("template/typeahead/typeahead-popup.html", '\n" + ""); -} ]); - -!angular.$$csp() && angular.element(document).find("head").prepend(''); - -"use strict"; - -var WaveSurfer = { - defaultParams: { - height: 128, - waveColor: "#999", - progressColor: "#555", - cursorColor: "#333", - cursorWidth: 1, - skipLength: 2, - minPxPerSec: 20, - pixelRatio: window.devicePixelRatio, - fillParent: !0, - scrollParent: !1, - hideScrollbar: !1, - normalize: !1, - audioContext: null, - container: null, - dragSelection: !0, - loopSelection: !0, - audioRate: 1, - interact: !0, - splitChannels: !1, - renderer: "Canvas", - backend: "WebAudio", - mediaType: "audio" - }, - init: function(a) { - if (this.params = WaveSurfer.util.extend({}, this.defaultParams, a), this.container = "string" == typeof a.container ? document.querySelector(this.params.container) : this.params.container, - !this.container) throw new Error("Container element not found"); - if ("undefined" == typeof this.params.mediaContainer ? this.mediaContainer = this.container : "string" == typeof this.params.mediaContainer ? this.mediaContainer = document.querySelector(this.params.mediaContainer) : this.mediaContainer = this.params.mediaContainer, - !this.mediaContainer) throw new Error("Media Container element not found"); - this.savedVolume = 0, this.isMuted = !1, this.tmpEvents = [], this.createDrawer(), - this.createBackend(); - }, - createDrawer: function() { - var a = this; - this.drawer = Object.create(WaveSurfer.Drawer[this.params.renderer]), this.drawer.init(this.container, this.params), - this.drawer.on("redraw", function() { - a.drawBuffer(), a.drawer.progress(a.backend.getPlayedPercents()); - }), this.drawer.on("click", function(b, c) { - setTimeout(function() { - a.seekTo(c); - }, 0); - }), this.drawer.on("scroll", function(b) { - a.fireEvent("scroll", b); - }); - }, - createBackend: function() { - var a = this; - this.backend && this.backend.destroy(), "AudioElement" == this.params.backend && (this.params.backend = "MediaElement"), - "WebAudio" != this.params.backend || WaveSurfer.WebAudio.supportsWebAudio() || (this.params.backend = "MediaElement"), - this.backend = Object.create(WaveSurfer[this.params.backend]), this.backend.init(this.params), - this.backend.on("finish", function() { - a.fireEvent("finish"); - }), this.backend.on("play", function() { - a.fireEvent("play"); - }), this.backend.on("pause", function() { - a.fireEvent("pause"); - }), this.backend.on("audioprocess", function(b) { - a.drawer.progress(a.backend.getPlayedPercents()), a.fireEvent("audioprocess", b); - }); - }, - getDuration: function() { - return this.backend.getDuration(); - }, - getCurrentTime: function() { - return this.backend.getCurrentTime(); - }, - play: function(a, b) { - this.backend.play(a, b); - }, - pause: function() { - this.backend.pause(); - }, - playPause: function() { - this.backend.isPaused() ? this.play() : this.pause(); - }, - isPlaying: function() { - return !this.backend.isPaused(); - }, - skipBackward: function(a) { - this.skip(-a || -this.params.skipLength); - }, - skipForward: function(a) { - this.skip(a || this.params.skipLength); - }, - skip: function(a) { - var b = this.getCurrentTime() || 0, c = this.getDuration() || 1; - b = Math.max(0, Math.min(c, b + (a || 0))), this.seekAndCenter(b / c); - }, - seekAndCenter: function(a) { - this.seekTo(a), this.drawer.recenter(a); - }, - seekTo: function(a) { - var b = this.backend.isPaused(), c = this.params.scrollParent; - b && (this.params.scrollParent = !1), this.backend.seekTo(a * this.getDuration()), - this.drawer.progress(this.backend.getPlayedPercents()), b || (this.backend.pause(), - this.backend.play()), this.params.scrollParent = c, this.fireEvent("seek", a); - }, - stop: function() { - this.pause(), this.seekTo(0), this.drawer.progress(0); - }, - setVolume: function(a) { - this.backend.setVolume(a); - }, - setPlaybackRate: function(a) { - this.backend.setPlaybackRate(a); - }, - toggleMute: function() { - this.isMuted ? (this.backend.setVolume(this.savedVolume), this.isMuted = !1) : (this.savedVolume = this.backend.getVolume(), - this.backend.setVolume(0), this.isMuted = !0); - }, - toggleScroll: function() { - this.params.scrollParent = !this.params.scrollParent, this.drawBuffer(); - }, - toggleInteraction: function() { - this.params.interact = !this.params.interact; - }, - drawBuffer: function() { - var a = Math.round(this.getDuration() * this.params.minPxPerSec * this.params.pixelRatio), b = this.drawer.getWidth(), c = a; - this.params.fillParent && (!this.params.scrollParent || b > a) && (c = b); - var d = this.backend.getPeaks(c); - this.drawer.drawPeaks(d, c), this.fireEvent("redraw", d, c); - }, - zoom: function(a) { - this.params.minPxPerSec = a, this.params.scrollParent = !0, this.drawBuffer(), this.seekAndCenter(this.getCurrentTime() / this.getDuration()); - }, - loadArrayBuffer: function(a) { - this.decodeArrayBuffer(a, function(a) { - this.loadDecodedBuffer(a); - }.bind(this)); - }, - loadDecodedBuffer: function(a) { - this.backend.load(a), this.drawBuffer(), this.fireEvent("ready"); - }, - loadBlob: function(a) { - var b = this, c = new FileReader(); - c.addEventListener("progress", function(a) { - b.onProgress(a); - }), c.addEventListener("load", function(a) { - b.loadArrayBuffer(a.target.result); - }), c.addEventListener("error", function() { - b.fireEvent("error", "Error reading file"); - }), c.readAsArrayBuffer(a), this.empty(); - }, - load: function(a, b) { - switch (this.params.backend) { - case "WebAudio": - return this.loadBuffer(a); - - case "MediaElement": - return this.loadMediaElement(a, b); - } - }, - loadBuffer: function(a) { - return this.empty(), this.getArrayBuffer(a, this.loadArrayBuffer.bind(this)); - }, - loadMediaElement: function(a, b) { - this.empty(), this.backend.load(a, this.mediaContainer, b), this.tmpEvents.push(this.backend.once("canplay", function() { - this.drawBuffer(), this.fireEvent("ready"); - }.bind(this)), this.backend.once("error", function(a) { - this.fireEvent("error", a); - }.bind(this))), !b && this.backend.supportsWebAudio() && this.getArrayBuffer(a, function(a) { - this.decodeArrayBuffer(a, function(a) { - this.backend.buffer = a, this.drawBuffer(); - }.bind(this)); - }.bind(this)); - }, - decodeArrayBuffer: function(a, b) { - this.backend.decodeArrayBuffer(a, this.fireEvent.bind(this, "decoded"), this.fireEvent.bind(this, "error", "Error decoding audiobuffer")), - this.tmpEvents.push(this.once("decoded", b)); - }, - getArrayBuffer: function(a, b) { - var c = this, d = WaveSurfer.util.ajax({ - url: a, - responseType: "arraybuffer" - }); - return this.tmpEvents.push(d.on("progress", function(a) { - c.onProgress(a); - }), d.on("success", b), d.on("error", function(a) { - c.fireEvent("error", "XHR error: " + a.target.statusText); - })), d; - }, - onProgress: function(a) { - if (a.lengthComputable) var b = a.loaded / a.total; else b = a.loaded / (a.loaded + 1e6); - this.fireEvent("loading", Math.round(100 * b), a.target); - }, - exportPCM: function(a, b, c) { - a = a || 1024, b = b || 1e4, c = c || !1; - var d = this.backend.getPeaks(a, b), e = [].map.call(d, function(a) { - return Math.round(a * b) / b; - }), f = JSON.stringify(e); - return c || window.open("data:application/json;charset=utf-8," + encodeURIComponent(f)), - f; - }, - clearTmpEvents: function() { - this.tmpEvents.forEach(function(a) { - a.un(); - }); - }, - empty: function() { - this.backend.isPaused() || (this.stop(), this.backend.disconnectSource()), this.clearTmpEvents(), - this.drawer.progress(0), this.drawer.setWidth(0), this.drawer.drawPeaks({ - length: this.drawer.getWidth() - }, 0); - }, - destroy: function() { - this.fireEvent("destroy"), this.clearTmpEvents(), this.unAll(), this.backend.destroy(), - this.drawer.destroy(); - } -}; - -WaveSurfer.create = function(a) { - var b = Object.create(WaveSurfer); - return b.init(a), b; -}, WaveSurfer.util = { - extend: function(a) { - var b = Array.prototype.slice.call(arguments, 1); - return b.forEach(function(b) { - Object.keys(b).forEach(function(c) { - a[c] = b[c]; - }); - }), a; - }, - getId: function() { - return "wavesurfer_" + Math.random().toString(32).substring(2); - }, - ajax: function(a) { - var b = Object.create(WaveSurfer.Observer), c = new XMLHttpRequest(), d = !1; - return c.open(a.method || "GET", a.url, !0), c.responseType = a.responseType || "json", - c.addEventListener("progress", function(a) { - b.fireEvent("progress", a), a.lengthComputable && a.loaded == a.total && (d = !0); - }), c.addEventListener("load", function(a) { - d || b.fireEvent("progress", a), b.fireEvent("load", a), 200 == c.status || 206 == c.status ? b.fireEvent("success", c.response, a) : b.fireEvent("error", a); - }), c.addEventListener("error", function(a) { - b.fireEvent("error", a); - }), c.send(), b.xhr = c, b; - } -}, WaveSurfer.Observer = { - on: function(a, b) { - this.handlers || (this.handlers = {}); - var c = this.handlers[a]; - return c || (c = this.handlers[a] = []), c.push(b), { - name: a, - callback: b, - un: this.un.bind(this, a, b) - }; - }, - un: function(a, b) { - if (this.handlers) { - var c = this.handlers[a]; - if (c) if (b) for (var d = c.length - 1; d >= 0; d--) c[d] == b && c.splice(d, 1); else c.length = 0; - } - }, - unAll: function() { - this.handlers = null; - }, - once: function(a, b) { - var c = this, d = function() { - b.apply(this, arguments), setTimeout(function() { - c.un(a, d); - }, 0); - }; - return this.on(a, d); - }, - fireEvent: function(a) { - if (this.handlers) { - var b = this.handlers[a], c = Array.prototype.slice.call(arguments, 1); - b && b.forEach(function(a) { - a.apply(null, c); - }); - } - } -}, WaveSurfer.util.extend(WaveSurfer, WaveSurfer.Observer), WaveSurfer.WebAudio = { - scriptBufferSize: 256, - PLAYING_STATE: 0, - PAUSED_STATE: 1, - FINISHED_STATE: 2, - supportsWebAudio: function() { - return !(!window.AudioContext && !window.webkitAudioContext); - }, - getAudioContext: function() { - return WaveSurfer.WebAudio.audioContext || (WaveSurfer.WebAudio.audioContext = new (window.AudioContext || window.webkitAudioContext)()), - WaveSurfer.WebAudio.audioContext; - }, - getOfflineAudioContext: function(a) { - return WaveSurfer.WebAudio.offlineAudioContext || (WaveSurfer.WebAudio.offlineAudioContext = new (window.OfflineAudioContext || window.webkitOfflineAudioContext)(1, 2, a)), - WaveSurfer.WebAudio.offlineAudioContext; - }, - init: function(a) { - this.params = a, this.ac = a.audioContext || this.getAudioContext(), this.lastPlay = this.ac.currentTime, - this.startPosition = 0, this.scheduledPause = null, this.states = [ Object.create(WaveSurfer.WebAudio.state.playing), Object.create(WaveSurfer.WebAudio.state.paused), Object.create(WaveSurfer.WebAudio.state.finished) ], - this.createVolumeNode(), this.createScriptNode(), this.createAnalyserNode(), this.setState(this.PAUSED_STATE), - this.setPlaybackRate(this.params.audioRate); - }, - disconnectFilters: function() { - this.filters && (this.filters.forEach(function(a) { - a && a.disconnect(); - }), this.filters = null, this.analyser.connect(this.gainNode)); - }, - setState: function(a) { - this.state !== this.states[a] && (this.state = this.states[a], this.state.init.call(this)); - }, - setFilter: function() { - this.setFilters([].slice.call(arguments)); - }, - setFilters: function(a) { - this.disconnectFilters(), a && a.length && (this.filters = a, this.analyser.disconnect(), - a.reduce(function(a, b) { - return a.connect(b), b; - }, this.analyser).connect(this.gainNode)); - }, - createScriptNode: function() { - this.ac.createScriptProcessor ? this.scriptNode = this.ac.createScriptProcessor(this.scriptBufferSize) : this.scriptNode = this.ac.createJavaScriptNode(this.scriptBufferSize), - this.scriptNode.connect(this.ac.destination); - }, - addOnAudioProcess: function() { - var a = this; - this.scriptNode.onaudioprocess = function() { - var b = a.getCurrentTime(); - b >= a.getDuration() ? (a.setState(a.FINISHED_STATE), a.fireEvent("pause")) : b >= a.scheduledPause ? (a.setState(a.PAUSED_STATE), - a.fireEvent("pause")) : a.state === a.states[a.PLAYING_STATE] && a.fireEvent("audioprocess", b); - }; - }, - removeOnAudioProcess: function() { - this.scriptNode.onaudioprocess = null; - }, - createAnalyserNode: function() { - this.analyser = this.ac.createAnalyser(), this.analyser.connect(this.gainNode); - }, - createVolumeNode: function() { - this.ac.createGain ? this.gainNode = this.ac.createGain() : this.gainNode = this.ac.createGainNode(), - this.gainNode.connect(this.ac.destination); - }, - setVolume: function(a) { - this.gainNode.gain.value = a; - }, - getVolume: function() { - return this.gainNode.gain.value; - }, - decodeArrayBuffer: function(a, b, c) { - this.offlineAc || (this.offlineAc = this.getOfflineAudioContext(this.ac ? this.ac.sampleRate : 44100)), - this.offlineAc.decodeAudioData(a, function(a) { - b(a); - }.bind(this), c); - }, - getPeaks: function(a) { - for (var b = this.buffer.length / a, c = ~~(b / 10) || 1, d = this.buffer.numberOfChannels, e = [], f = [], g = 0; d > g; g++) for (var h = e[g] = [], i = this.buffer.getChannelData(g), j = 0; a > j; j++) { - for (var k = ~~(j * b), l = ~~(k + b), m = i[0], n = i[0], o = k; l > o; o += c) { - var p = i[o]; - p > n && (n = p), m > p && (m = p); - } - h[2 * j] = n, h[2 * j + 1] = m, (0 == g || n > f[2 * j]) && (f[2 * j] = n), (0 == g || m < f[2 * j + 1]) && (f[2 * j + 1] = m); - } - return this.params.splitChannels ? e : f; - }, - getPlayedPercents: function() { - return this.state.getPlayedPercents.call(this); - }, - disconnectSource: function() { - this.source && this.source.disconnect(); - }, - destroy: function() { - this.isPaused() || this.pause(), this.unAll(), this.buffer = null, this.disconnectFilters(), - this.disconnectSource(), this.gainNode.disconnect(), this.scriptNode.disconnect(), - this.analyser.disconnect(); - }, - load: function(a) { - this.startPosition = 0, this.lastPlay = this.ac.currentTime, this.buffer = a, this.createSource(); - }, - createSource: function() { - this.disconnectSource(), this.source = this.ac.createBufferSource(), this.source.start = this.source.start || this.source.noteGrainOn, - this.source.stop = this.source.stop || this.source.noteOff, this.source.playbackRate.value = this.playbackRate, - this.source.buffer = this.buffer, this.source.connect(this.analyser); - }, - isPaused: function() { - return this.state !== this.states[this.PLAYING_STATE]; - }, - getDuration: function() { - return this.buffer ? this.buffer.duration : 0; - }, - seekTo: function(a, b) { - return this.scheduledPause = null, null == a && (a = this.getCurrentTime(), a >= this.getDuration() && (a = 0)), - null == b && (b = this.getDuration()), this.startPosition = a, this.lastPlay = this.ac.currentTime, - this.state === this.states[this.FINISHED_STATE] && this.setState(this.PAUSED_STATE), - { - start: a, - end: b - }; - }, - getPlayedTime: function() { - return (this.ac.currentTime - this.lastPlay) * this.playbackRate; - }, - play: function(a, b) { - this.createSource(); - var c = this.seekTo(a, b); - a = c.start, b = c.end, this.scheduledPause = b, this.source.start(0, a, b - a), - this.setState(this.PLAYING_STATE), this.fireEvent("play"); - }, - pause: function() { - this.scheduledPause = null, this.startPosition += this.getPlayedTime(), this.source && this.source.stop(0), - this.setState(this.PAUSED_STATE), this.fireEvent("pause"); - }, - getCurrentTime: function() { - return this.state.getCurrentTime.call(this); - }, - setPlaybackRate: function(a) { - a = a || 1, this.isPaused() ? this.playbackRate = a : (this.pause(), this.playbackRate = a, - this.play()); - } -}, WaveSurfer.WebAudio.state = {}, WaveSurfer.WebAudio.state.playing = { - init: function() { - this.addOnAudioProcess(); - }, - getPlayedPercents: function() { - var a = this.getDuration(); - return this.getCurrentTime() / a || 0; - }, - getCurrentTime: function() { - return this.startPosition + this.getPlayedTime(); - } -}, WaveSurfer.WebAudio.state.paused = { - init: function() { - this.removeOnAudioProcess(); - }, - getPlayedPercents: function() { - var a = this.getDuration(); - return this.getCurrentTime() / a || 0; - }, - getCurrentTime: function() { - return this.startPosition; - } -}, WaveSurfer.WebAudio.state.finished = { - init: function() { - this.removeOnAudioProcess(), this.fireEvent("finish"); - }, - getPlayedPercents: function() { - return 1; - }, - getCurrentTime: function() { - return this.getDuration(); - } -}, WaveSurfer.util.extend(WaveSurfer.WebAudio, WaveSurfer.Observer), WaveSurfer.MediaElement = Object.create(WaveSurfer.WebAudio), -WaveSurfer.util.extend(WaveSurfer.MediaElement, { - init: function(a) { - this.params = a, this.media = { - currentTime: 0, - duration: 0, - paused: !0, - playbackRate: 1, - play: function() {}, - pause: function() {} - }, this.mediaType = a.mediaType.toLowerCase(), this.elementPosition = a.elementPosition; - }, - load: function(a, b, c) { - var d = this, e = document.createElement(this.mediaType); - e.controls = !1, e.autoplay = !1, e.preload = "auto", e.src = a, e.addEventListener("error", function() { - d.fireEvent("error", "Error loading media element"); - }), e.addEventListener("canplay", function() { - d.fireEvent("canplay"); - }), e.addEventListener("ended", function() { - d.fireEvent("finish"); - }), e.addEventListener("timeupdate", function() { - d.fireEvent("audioprocess", d.getCurrentTime()); - }); - var f = b.querySelector(this.mediaType); - f && b.removeChild(f), b.appendChild(e), this.media = e, this.peaks = c, this.onPlayEnd = null, - this.buffer = null, this.setPlaybackRate(this.playbackRate); - }, - isPaused: function() { - return !this.media || this.media.paused; - }, - getDuration: function() { - var a = this.media.duration; - return a >= 1 / 0 && (a = this.media.seekable.end()), a; - }, - getCurrentTime: function() { - return this.media && this.media.currentTime; - }, - getPlayedPercents: function() { - return this.getCurrentTime() / this.getDuration() || 0; - }, - setPlaybackRate: function(a) { - this.playbackRate = a || 1, this.media.playbackRate = this.playbackRate; - }, - seekTo: function(a) { - null != a && (this.media.currentTime = a), this.clearPlayEnd(); - }, - play: function(a, b) { - this.seekTo(a), this.media.play(), b && this.setPlayEnd(b), this.fireEvent("play"); - }, - pause: function() { - this.media && this.media.pause(), this.clearPlayEnd(), this.fireEvent("pause"); - }, - setPlayEnd: function(a) { - var b = this; - this.onPlayEnd = function(c) { - c >= a && (b.pause(), b.seekTo(a)); - }, this.on("audioprocess", this.onPlayEnd); - }, - clearPlayEnd: function() { - this.onPlayEnd && (this.un("audioprocess", this.onPlayEnd), this.onPlayEnd = null); - }, - getPeaks: function(a) { - return this.buffer ? WaveSurfer.WebAudio.getPeaks.call(this, a) : this.peaks || []; - }, - getVolume: function() { - return this.media.volume; - }, - setVolume: function(a) { - this.media.volume = a; - }, - destroy: function() { - this.pause(), this.unAll(), this.media && this.media.parentNode && this.media.parentNode.removeChild(this.media), - this.media = null; - } -}), WaveSurfer.AudioElement = WaveSurfer.MediaElement, WaveSurfer.Drawer = { - init: function(a, b) { - this.container = a, this.params = b, this.width = 0, this.height = b.height * this.params.pixelRatio, - this.lastPos = 0, this.createWrapper(), this.createElements(); - }, - createWrapper: function() { - this.wrapper = this.container.appendChild(document.createElement("wave")), this.style(this.wrapper, { - display: "block", - position: "relative", - userSelect: "none", - webkitUserSelect: "none", - height: this.params.height + "px" - }), (this.params.fillParent || this.params.scrollParent) && this.style(this.wrapper, { - width: "100%", - overflowX: this.params.hideScrollbar ? "hidden" : "auto", - overflowY: "hidden" - }), this.setupWrapperEvents(); - }, - handleEvent: function(a) { - a.preventDefault(); - var b = this.wrapper.getBoundingClientRect(); - return (a.clientX - b.left + this.wrapper.scrollLeft) / this.wrapper.scrollWidth || 0; - }, - setupWrapperEvents: function() { - var a = this; - this.wrapper.addEventListener("click", function(b) { - var c = a.wrapper.offsetHeight - a.wrapper.clientHeight; - if (0 != c) { - var d = a.wrapper.getBoundingClientRect(); - if (b.clientY >= d.bottom - c) return; - } - a.params.interact && a.fireEvent("click", b, a.handleEvent(b)); - }), this.wrapper.addEventListener("scroll", function(b) { - a.fireEvent("scroll", b); - }); - }, - drawPeaks: function(a, b) { - this.resetScroll(), this.setWidth(b), this.params.barWidth ? this.drawBars(a) : this.drawWave(a); - }, - style: function(a, b) { - return Object.keys(b).forEach(function(c) { - a.style[c] !== b[c] && (a.style[c] = b[c]); - }), a; - }, - resetScroll: function() { - null !== this.wrapper && (this.wrapper.scrollLeft = 0); - }, - recenter: function(a) { - var b = this.wrapper.scrollWidth * a; - this.recenterOnPosition(b, !0); - }, - recenterOnPosition: function(a, b) { - var c = this.wrapper.scrollLeft, d = ~~(this.wrapper.clientWidth / 2), e = a - d, f = e - c, g = this.wrapper.scrollWidth - this.wrapper.clientWidth; - if (0 != g) { - if (!b && f >= -d && d > f) { - var h = 5; - f = Math.max(-h, Math.min(h, f)), e = c + f; - } - e = Math.max(0, Math.min(g, e)), e != c && (this.wrapper.scrollLeft = e); - } - }, - getWidth: function() { - return Math.round(this.container.clientWidth * this.params.pixelRatio); - }, - setWidth: function(a) { - a != this.width && (this.width = a, this.params.fillParent || this.params.scrollParent ? this.style(this.wrapper, { - width: "" - }) : this.style(this.wrapper, { - width: ~~(this.width / this.params.pixelRatio) + "px" - }), this.updateSize()); - }, - setHeight: function(a) { - a != this.height && (this.height = a, this.style(this.wrapper, { - height: ~~(this.height / this.params.pixelRatio) + "px" - }), this.updateSize()); - }, - progress: function(a) { - var b = 1 / this.params.pixelRatio, c = Math.round(a * this.width) * b; - if (c < this.lastPos || c - this.lastPos >= b) { - if (this.lastPos = c, this.params.scrollParent) { - var d = ~~(this.wrapper.scrollWidth * a); - this.recenterOnPosition(d); - } - this.updateProgress(a); - } - }, - destroy: function() { - this.unAll(), this.wrapper && (this.container.removeChild(this.wrapper), this.wrapper = null); - }, - createElements: function() {}, - updateSize: function() {}, - drawWave: function(a, b) {}, - clearWave: function() {}, - updateProgress: function(a) {} -}, WaveSurfer.util.extend(WaveSurfer.Drawer, WaveSurfer.Observer), WaveSurfer.Drawer.Canvas = Object.create(WaveSurfer.Drawer), -WaveSurfer.util.extend(WaveSurfer.Drawer.Canvas, { - createElements: function() { - var a = this.wrapper.appendChild(this.style(document.createElement("canvas"), { - position: "absolute", - zIndex: 1, - left: 0, - top: 0, - bottom: 0 - })); - if (this.waveCc = a.getContext("2d"), this.progressWave = this.wrapper.appendChild(this.style(document.createElement("wave"), { - position: "absolute", - zIndex: 2, - left: 0, - top: 0, - bottom: 0, - overflow: "hidden", - width: "0", - display: "none", - boxSizing: "border-box", - borderRightStyle: "solid", - borderRightWidth: this.params.cursorWidth + "px", - borderRightColor: this.params.cursorColor - })), this.params.waveColor != this.params.progressColor) { - var b = this.progressWave.appendChild(document.createElement("canvas")); - this.progressCc = b.getContext("2d"); - } - }, - updateSize: function() { - var a = Math.round(this.width / this.params.pixelRatio); - this.waveCc.canvas.width = this.width, this.waveCc.canvas.height = this.height, - this.style(this.waveCc.canvas, { - width: a + "px" - }), this.style(this.progressWave, { - display: "block" - }), this.progressCc && (this.progressCc.canvas.width = this.width, this.progressCc.canvas.height = this.height, - this.style(this.progressCc.canvas, { - width: a + "px" - })), this.clearWave(); - }, - clearWave: function() { - this.waveCc.clearRect(0, 0, this.width, this.height), this.progressCc && this.progressCc.clearRect(0, 0, this.width, this.height); - }, - drawBars: function(a, b) { - if (a[0] instanceof Array) { - var c = a; - if (this.params.splitChannels) return this.setHeight(c.length * this.params.height * this.params.pixelRatio), - void c.forEach(this.drawBars, this); - a = c[0]; - } - var d = .5 / this.params.pixelRatio, e = this.width, f = this.params.height * this.params.pixelRatio, g = f * b || 0, h = f / 2, i = ~~(a.length / 2), j = this.params.barWidth * this.params.pixelRatio, k = Math.max(this.params.pixelRatio, ~~(j / 2)), l = j + k, m = 1; - if (this.params.normalize) { - var n, o; - o = Math.max.apply(Math, a), n = Math.min.apply(Math, a), m = o, -n > m && (m = -n); - } - var p = i / e; - this.waveCc.fillStyle = this.params.waveColor, this.progressCc && (this.progressCc.fillStyle = this.params.progressColor), - [ this.waveCc, this.progressCc ].forEach(function(b) { - if (b) if (this.params.reflection) for (var c = 0; e > c; c += l) { - var f = Math.round(a[2 * c * p] / m * h); - b.fillRect(c + d, h - f + g, j + d, 2 * f); - } else { - for (var c = 0; e > c; c += l) { - var f = Math.round(a[2 * c * p] / m * h); - b.fillRect(c + d, h - f + g, j + d, f); - } - for (var c = 0; e > c; c += l) { - var f = Math.round(a[2 * c * p + 1] / m * h); - b.fillRect(c + d, h - f + g, j + d, f); - } - } - }, this); - }, - drawWave: function(a, b) { - if (a[0] instanceof Array) { - var c = a; - if (this.params.splitChannels) return this.setHeight(c.length * this.params.height * this.params.pixelRatio), - void c.forEach(this.drawWave, this); - a = c[0]; - } - var d = .5 / this.params.pixelRatio, e = this.params.height * this.params.pixelRatio, f = e * b || 0, g = e / 2, h = ~~(a.length / 2), i = 1; - this.params.fillParent && this.width != h && (i = this.width / h); - var j = 1; - if (this.params.normalize) { - var k, l; - l = Math.max.apply(Math, a), k = Math.min.apply(Math, a), j = l, -k > j && (j = -k); - } - this.waveCc.fillStyle = this.params.waveColor, this.progressCc && (this.progressCc.fillStyle = this.params.progressColor), - [ this.waveCc, this.progressCc ].forEach(function(b) { - if (b) { - b.beginPath(), b.moveTo(d, g + f); - for (var c = 0; h > c; c++) { - var e = Math.round(a[2 * c] / j * g); - b.lineTo(c * i + d, g - e + f); - } - for (var c = h - 1; c >= 0; c--) { - var e = Math.round(a[2 * c + 1] / j * g); - b.lineTo(c * i + d, g - e + f); - } - b.closePath(), b.fill(), b.fillRect(0, g + f - d, this.width, d); - } - }, this); - }, - updateProgress: function(a) { - var b = Math.round(this.width * a) / this.params.pixelRatio; - this.style(this.progressWave, { - width: b + "px" - }); - } -}); +angular.module("template/pagination/pager.html", []).run([ "$templateCache", function($templateCache) { + $templateCache.put("template/pagination/pager.html", '\n" + ""); +} ]); -var app = angular.module("autocomplete", []); +angular.module("template/pagination/pagination.html", []).run([ "$templateCache", function($templateCache) { + $templateCache.put("template/pagination/pagination.html", '\n" + ""); +} ]); -app.directive("autocomplete", function() { - var index = -1; - return { - restrict: "E", - scope: { - searchParam: "=ngModel", - suggestions: "=data", - onType: "=onType", - onSelect: "=onSelect", - autocompleteRequired: "=" - }, - controller: [ "$scope", function($scope) { - $scope.selectedIndex = -1; - $scope.initLock = true; - $scope.setIndex = function(i) { - $scope.selectedIndex = parseInt(i); - }; - this.setIndex = function(i) { - $scope.setIndex(i); - $scope.$apply(); - }; - $scope.getIndex = function(i) { - return $scope.selectedIndex; - }; - var watching = true; - $scope.completing = false; - $scope.$watch("searchParam", function(newValue, oldValue) { - if (oldValue === newValue || !oldValue && $scope.initLock) { - return; - } - if (watching && typeof $scope.searchParam !== "undefined" && $scope.searchParam !== null) { - $scope.completing = true; - $scope.searchFilter = $scope.searchParam; - $scope.selectedIndex = -1; - } - if ($scope.onType) $scope.onType($scope.searchParam); - }); - this.preSelect = function(suggestion) { - watching = false; - $scope.$apply(); - watching = true; - }; - $scope.preSelect = this.preSelect; - this.preSelectOff = function() { - watching = true; - }; - $scope.preSelectOff = this.preSelectOff; - $scope.select = function(suggestion) { - if (suggestion) { - $scope.searchParam = suggestion; - $scope.searchFilter = suggestion; - if ($scope.onSelect) $scope.onSelect(suggestion); - } - watching = false; - $scope.completing = false; - setTimeout(function() { - watching = true; - }, 1e3); - $scope.setIndex(-1); - }; - } ], - link: function(scope, element, attrs) { - setTimeout(function() { - scope.initLock = false; - scope.$apply(); - }, 250); - var attr = ""; - scope.attrs = { - placeholder: "start typing...", - "class": "", - id: "", - inputclass: "", - inputid: "" - }; - for (var a in attrs) { - attr = a.replace("attr", "").toLowerCase(); - if (a.indexOf("attr") === 0) { - scope.attrs[attr] = attrs[a]; - } - } - if (attrs.clickActivation) { - element[0].onclick = function(e) { - if (!scope.searchParam) { - setTimeout(function() { - scope.completing = true; - scope.$apply(); - }, 200); - } - }; - } - var key = { - left: 37, - up: 38, - right: 39, - down: 40, - enter: 13, - esc: 27, - tab: 9 - }; - document.addEventListener("keydown", function(e) { - var keycode = e.keyCode || e.which; - switch (keycode) { - case key.esc: - scope.select(); - scope.setIndex(-1); - scope.$apply(); - e.preventDefault(); - } - }, true); - document.addEventListener("blur", function(e) { - setTimeout(function() { - scope.select(); - scope.setIndex(-1); - scope.$apply(); - }, 150); - }, true); - element[0].addEventListener("keydown", function(e) { - var keycode = e.keyCode || e.which; - var l = angular.element(this).find("li").length; - if (!scope.completing || l == 0) return; - switch (keycode) { - case key.up: - index = scope.getIndex() - 1; - if (index < -1) { - index = l - 1; - } else if (index >= l) { - index = -1; - scope.setIndex(index); - scope.preSelectOff(); - break; - } - scope.setIndex(index); - if (index !== -1) scope.preSelect(angular.element(angular.element(this).find("li")[index]).text()); - scope.$apply(); - break; +angular.module("template/tooltip/tooltip-html-popup.html", []).run([ "$templateCache", function($templateCache) { + $templateCache.put("template/tooltip/tooltip-html-popup.html", '
                    \n' + '
                    \n' + '
                    \n' + "
                    \n" + ""); +} ]); - case key.down: - index = scope.getIndex() + 1; - if (index < -1) { - index = l - 1; - } else if (index >= l) { - index = -1; - scope.setIndex(index); - scope.preSelectOff(); - scope.$apply(); - break; - } - scope.setIndex(index); - if (index !== -1) scope.preSelect(angular.element(angular.element(this).find("li")[index]).text()); - break; +angular.module("template/tooltip/tooltip-html-unsafe-popup.html", []).run([ "$templateCache", function($templateCache) { + $templateCache.put("template/tooltip/tooltip-html-unsafe-popup.html", '
                    \n' + '
                    \n' + '
                    \n' + "
                    \n" + ""); +} ]); - case key.left: - break; +angular.module("template/tooltip/tooltip-popup.html", []).run([ "$templateCache", function($templateCache) { + $templateCache.put("template/tooltip/tooltip-popup.html", '
                    \n' + '
                    \n' + '
                    \n' + "
                    \n" + ""); +} ]); - case key.right: - case key.enter: - case key.tab: - index = scope.getIndex(); - if (index !== -1) { - scope.select(angular.element(angular.element(this).find("li")[index]).text()); - if (keycode == key.enter) { - e.preventDefault(); - } - } else { - if (keycode == key.enter) { - scope.select(); - } - } - scope.setIndex(-1); - scope.$apply(); - break; +angular.module("template/tooltip/tooltip-template-popup.html", []).run([ "$templateCache", function($templateCache) { + $templateCache.put("template/tooltip/tooltip-template-popup.html", '
                    \n' + '
                    \n' + '
                    \n' + "
                    \n" + ""); +} ]); - case key.esc: - scope.select(); - scope.setIndex(-1); - scope.$apply(); - e.preventDefault(); - break; +angular.module("template/popover/popover-html.html", []).run([ "$templateCache", function($templateCache) { + $templateCache.put("template/popover/popover-html.html", '
                    \n' + '
                    \n' + "\n" + '
                    \n' + '

                    \n' + '
                    \n' + "
                    \n" + "
                    \n" + ""); +} ]); - default: - return; - } - }); - }, - template: '
                    ' - }; -}); +angular.module("template/popover/popover-template.html", []).run([ "$templateCache", function($templateCache) { + $templateCache.put("template/popover/popover-template.html", '
                    \n' + '
                    \n' + "\n" + '
                    \n' + '

                    \n' + '
                    \n' + "
                    \n" + "
                    \n" + ""); +} ]); -app.filter("highlight", [ "$sce", function($sce) { - return function(input, searchParam) { - if (typeof input === "function") return ""; - if (searchParam) { - var words = "(" + searchParam.split(/\ /).join(" |") + "|" + searchParam.split(/\ /).join("|") + ")", exp = new RegExp(words, "gi"); - if (words.length) { - input = input.replace(exp, '$1'); - } - } - return $sce.trustAsHtml(input); - }; +angular.module("template/popover/popover.html", []).run([ "$templateCache", function($templateCache) { + $templateCache.put("template/popover/popover.html", '
                    \n' + '
                    \n' + "\n" + '
                    \n' + '

                    \n' + '
                    \n' + "
                    \n" + "
                    \n" + ""); } ]); -app.directive("suggestion", function() { - return { - restrict: "A", - require: "^autocomplete", - link: function(scope, element, attrs, autoCtrl) { - element.bind("mouseenter", function() { - autoCtrl.preSelect(attrs.val); - autoCtrl.setIndex(attrs.index); - }); - element.bind("mouseleave", function() { - autoCtrl.preSelectOff(); - }); - } - }; -}); +angular.module("template/progressbar/bar.html", []).run([ "$templateCache", function($templateCache) { + $templateCache.put("template/progressbar/bar.html", '
                    \n' + ""); +} ]); + +angular.module("template/progressbar/progress.html", []).run([ "$templateCache", function($templateCache) { + $templateCache.put("template/progressbar/progress.html", '
                    '); +} ]); + +angular.module("template/progressbar/progressbar.html", []).run([ "$templateCache", function($templateCache) { + $templateCache.put("template/progressbar/progressbar.html", '
                    \n' + '
                    \n' + "
                    \n" + ""); +} ]); + +angular.module("template/rating/rating.html", []).run([ "$templateCache", function($templateCache) { + $templateCache.put("template/rating/rating.html", '\n' + " ({{ $index < value ? '*' : ' ' }})\n" + ' \n' + "\n" + ""); +} ]); + +angular.module("template/tabs/tab.html", []).run([ "$templateCache", function($templateCache) { + $templateCache.put("template/tabs/tab.html", '
                  • \n' + ' {{heading}}\n' + "
                  • \n" + ""); +} ]); + +angular.module("template/tabs/tabset.html", []).run([ "$templateCache", function($templateCache) { + $templateCache.put("template/tabs/tabset.html", "
                    \n" + "
                      \n" + '
                      \n' + '
                      \n' + "
                      \n" + "
                      \n" + "
                      \n" + ""); +} ]); + +angular.module("template/timepicker/timepicker.html", []).run([ "$templateCache", function($templateCache) { + $templateCache.put("template/timepicker/timepicker.html", "\n" + " \n" + ' \n' + ' \n' + " \n" + ' \n' + ' \n' + " \n" + " \n" + ' \n" + " \n" + ' \n" + ' \n' + " \n" + ' \n' + ' \n' + " \n" + ' \n' + ' \n' + " \n" + " \n" + "
                       
                      \n' + ' \n' + " :\n' + ' \n' + "
                       
                      \n" + ""); +} ]); + +angular.module("template/typeahead/typeahead-match.html", []).run([ "$templateCache", function($templateCache) { + $templateCache.put("template/typeahead/typeahead-match.html", '\n' + ""); +} ]); + +angular.module("template/typeahead/typeahead-popup.html", []).run([ "$templateCache", function($templateCache) { + $templateCache.put("template/typeahead/typeahead-popup.html", '\n" + ""); +} ]); + +!angular.$$csp() && angular.element(document).find("head").prepend(''); function getCookie(name) { var nameEQ = name + "="; @@ -27228,6 +30263,12 @@ var cloneObject = function(oldObject) { return JSON.parse(JSON.stringify(oldObject)); }; +var enableControls = function(controls, enabled) { + _.each(controls, function(value, key) { + controls[key] = enabled; + }); +}; + var lingvodoc = {}; lingvodoc.Object = function(clientId, objectId) { @@ -27235,10 +30276,7 @@ lingvodoc.Object = function(clientId, objectId) { this.object_id = objectId; this.type = "abstract"; this.getId = function() { - return this.client_id + "" + this.object_id; - }; - this.export = function() { - return {}; + return this.client_id + "_" + this.object_id; }; }; @@ -27299,13 +30337,33 @@ lingvodoc.Perspective = function(client_id, object_id, parent_client_id, parent_ this.is_template = is_template; this.marked_for_deletion = marked_for_deletion; this.fields = []; + this.location = null; + this.blobs = []; + this.additional_metadata = {}; this.equals = function(obj) { return lingvodoc.Object.prototype.equals.call(this, obj) && this.translation == obj.translation; }; }; lingvodoc.Perspective.fromJS = function(js) { - return new lingvodoc.Perspective(js.client_id, js.object_id, js.parent_client_id, js.parent_object_id, js.translation, js.translation_string, js.status, js.is_template, js.marked_for_deletion); + var perspective = new lingvodoc.Perspective(js.client_id, js.object_id, js.parent_client_id, js.parent_object_id, js.translation, js.translation_string, js.status, js.is_template, js.marked_for_deletion); + if (_.has(js, "location") && _.has(js.location, "content")) { + perspective["location"] = { + lat: js.location.content.lat, + lng: js.location.content.lng + }; + } + if (_.has(js, "info") && js.info.type == "list") { + if (_.isArray(js.info.content)) { + perspective["blobs"] = _.map(js.info.content, function(e) { + var blob = new lingvodoc.Blob(e.info.content.client_id, e.info.content.object_id, e.info.content.name, e.info.content.data_type); + blob.url = e.info.content.content; + return blob; + }); + } + } + perspective.additional_metadata = js.additional_metadata; + return perspective; }; lingvodoc.Perspective.prototype = new lingvodoc.Object(); @@ -27330,6 +30388,25 @@ lingvodoc.User.fromJS = function(js) { return new lingvodoc.User(js.id, js.login, js.name, js.email, js.intl_name, js.about, js.signup_date, js.organizations); }; +lingvodoc.Blob = function(clientId, objectId, name, data_type) { + lingvodoc.Object.call(this, clientId, objectId); + this.type = "blob"; + this.name = name; + this.data_type = data_type; + this.url = null; + this.equals = function(obj) { + return lingvodoc.Object.prototype.equals.call(this, obj) && this.name == obj.name; + }; +}; + +lingvodoc.Blob.fromJS = function(js) { + return new lingvodoc.Blob(js.client_id, js.object_id, js.name, js.data_type); +}; + +lingvodoc.Blob.prototype = new lingvodoc.Object(); + +lingvodoc.Blob.prototype.constructor = lingvodoc.Blob; + function lingvodocAPI($http, $q) { var addUrlParameter = function(url, key, value) { return url + (url.indexOf("?") >= 0 ? "&" : "?") + encodeURIComponent(key) + "=" + encodeURIComponent(value); @@ -27403,6 +30480,21 @@ function lingvodocAPI($http, $q) { }); return deferred.promise; }; + var getPerspectiveDictionaryFieldsNew = function(perspective) { + var deferred = $q.defer(); + var url = "/dictionary/" + perspective.parent_client_id + "/" + perspective.parent_object_id + "/perspective/" + perspective.client_id + "/" + perspective.object_id + "/fields"; + $http.get(url).success(function(data, status, headers, config) { + if (_.isArray(data.fields)) { + var fields = perspectiveToDictionaryFields(data.fields); + deferred.resolve(fields); + } else { + deferred.reject("An error occurred while fetching perspective fields"); + } + }).error(function(data, status, headers, config) { + deferred.reject("An error occurred while fetching perspective fields"); + }); + return deferred.promise; + }; var removeValue = function(entry, field, fieldValue, parent) { var deferred = $q.defer(); var url; @@ -27569,8 +30661,9 @@ function lingvodocAPI($http, $q) { }); return deferred.promise; }; - var getDictionaryProperties = function(url) { + var getDictionaryProperties = function(dictionary) { var deferred = $q.defer(); + var url = "/dictionary/" + encodeURIComponent(dictionary.client_id) + "/" + encodeURIComponent(dictionary.object_id); $http.get(url).success(function(data, status, headers, config) { deferred.resolve(data); }).error(function(data, status, headers, config) { @@ -27578,8 +30671,9 @@ function lingvodocAPI($http, $q) { }); return deferred.promise; }; - var setDictionaryProperties = function(url, properties) { + var setDictionaryProperties = function(dictionary, properties) { var deferred = $q.defer(); + var url = "/dictionary/" + encodeURIComponent(dictionary.client_id) + "/" + encodeURIComponent(dictionary.object_id); $http.put(url, properties).success(function(data, status, headers, config) { deferred.resolve(data); }).error(function(data, status, headers, config) { @@ -27587,6 +30681,16 @@ function lingvodocAPI($http, $q) { }); return deferred.promise; }; + var removeDictionary = function(dictionary) { + var deferred = $q.defer(); + var url = "/dictionary/" + encodeURIComponent(dictionary.client_id) + "/" + encodeURIComponent(dictionary.object_id); + $http.delete(url).success(function(data, status, headers, config) { + deferred.resolve(); + }).error(function(data, status, headers, config) { + deferred.reject("An error occurred while trying to delete dictionary"); + }); + return deferred.promise; + }; var getLanguages = function(url) { var deferred = $q.defer(); var flatLanguages = function(languages) { @@ -27670,6 +30774,16 @@ function lingvodocAPI($http, $q) { }); return deferred.promise; }; + var removePerspective = function(perspective) { + var deferred = $q.defer(); + var url = "/dictionary/" + perspective.parent_client_id + "/" + perspective.parent_object_id + "/perspective/" + perspective.client_id + "/" + perspective.object_id; + $http.delete(url).success(function(data, status, headers, config) { + deferred.resolve(); + }).error(function(data, status, headers, config) { + deferred.reject("An error occurred while trying to delete perspective"); + }); + return deferred.promise; + }; var getUserInfo = function(userId, clientId) { var deferred = $q.defer(); var url = "/user" + "?client_id= " + encodeURIComponent(clientId) + "&user_id= " + encodeURIComponent(userId); @@ -27750,13 +30864,14 @@ function lingvodocAPI($http, $q) { }; var getDictionaries = function(query) { var deferred = $q.defer(); - var dictionaries = []; $http.post("/dictionaries", query).success(function(data, status, headers, config) { - for (var i = 0; i < data.dictionaries.length; i++) { - var dictionary = data.dictionaries[i]; - dictionaries.push(lingvodoc.Dictionary.fromJS(dictionary)); + if (_.isArray(data.dictionaries)) { + deferred.resolve(_.map(data.dictionaries, function(d) { + return lingvodoc.Dictionary.fromJS(d); + })); + } else { + deferred.reject("Failed to fetch dictionaries list. Malformed response."); } - deferred.resolve(dictionaries); }).error(function(data, status, headers, config) { deferred.reject("Failed to fetch dictionaries list"); }); @@ -27973,8 +31088,8 @@ function lingvodocAPI($http, $q) { }; $http.post("/dictionaries", req).success(function(data, status, headers, config) { var dictionaries = []; - if (angular.isArray(data.dictionaries)) { - angular.forEach(data.dictionaries, function(jsdict) { + if (_.isArray(data.dictionaries)) { + _.forEach(data.dictionaries, function(jsdict) { var dictionary = lingvodoc.Dictionary.fromJS(jsdict); if (language.client_id == dictionary.parent_client_id && language.object_id == dictionary.parent_object_id) { dictionaries.push(dictionary); @@ -27983,7 +31098,7 @@ function lingvodocAPI($http, $q) { } deferred.resolve(dictionaries); }).error(function(data, status, headers, config) { - deferred.reject("Failed to move lexical entry"); + deferred.reject("Failed to fetch list of dictionaries"); }); return deferred.promise; }; @@ -28166,10 +31281,140 @@ function lingvodocAPI($http, $q) { }); return deferred.promise; }; + var getUserBlobs = function() { + var deferred = $q.defer(); + $http.get("/blobs").success(function(data, status, headers, config) { + var blobs = _.map(data, lingvodoc.Blob.fromJS); + deferred.resolve(blobs); + }).error(function(data, status, headers, config) { + deferred.reject("Failed to fetch list of available blobs"); + }); + return deferred.promise; + }; + var checkDictionaryBlob = function(blob, parent) { + var deferred = $q.defer(); + var query = { + blob_client_id: blob.client_id, + blob_object_id: blob.object_id, + parent_client_id: parent.client_id, + parent_object_id: parent.object_id + }; + $http.post("/convert_check", query).success(function(data, status, headers, config) { + var perspectives = _.map(data, lingvodoc.Perspective.fromJS); + deferred.resolve(perspectives); + }).error(function(data, status, headers, config) { + deferred.reject("Failed to convert dictionary"); + }); + return deferred.promise; + }; + var convertDictionary = function(req) { + var deferred = $q.defer(); + $http.post("/convert", req).success(function(data, status, headers, config) { + deferred.resolve(data); + }).error(function(data, status, headers, config) { + deferred.reject("Failed to convert dictionary"); + }); + return deferred.promise; + }; + var getPerspectiveMeta = function(dictionary, perspective) { + var deferred = $q.defer(); + var url = "/dictionary/" + encodeURIComponent(dictionary.client_id) + "/" + encodeURIComponent(dictionary.object_id) + "/perspective/" + encodeURIComponent(perspective.client_id) + "/" + encodeURIComponent(perspective.object_id) + "/meta"; + $http.get(url).success(function(data, status, headers, config) { + deferred.resolve(data); + }).error(function(data, status, headers, config) { + deferred.reject("Failed to get perspective meta data!"); + }); + return deferred.promise; + }; + var setPerspectiveMeta = function(dictionary, perspective, meta) { + var deferred = $q.defer(); + var url = "/dictionary/" + encodeURIComponent(dictionary.client_id) + "/" + encodeURIComponent(dictionary.object_id) + "/perspective/" + encodeURIComponent(perspective.client_id) + "/" + encodeURIComponent(perspective.object_id) + "/meta"; + $http.put(url, meta).success(function(data, status, headers, config) { + deferred.resolve(data); + }).error(function(data, status, headers, config) { + deferred.reject("Failed to set perspective meta data!"); + }); + return deferred.promise; + }; + var removePerspectiveMeta = function(dictionary, perspective, meta) { + var deferred = $q.defer(); + var url = "/dictionary/" + encodeURIComponent(dictionary.client_id) + "/" + encodeURIComponent(dictionary.object_id) + "/perspective/" + encodeURIComponent(perspective.client_id) + "/" + encodeURIComponent(perspective.object_id) + "/meta"; + var config = { + method: "DELETE", + url: url, + data: meta, + headers: { + "Content-Type": "application/json;charset=utf-8" + } + }; + $http(config).success(function(data, status, headers, config) { + deferred.resolve(data); + }).error(function(data, status, headers, config) { + deferred.reject("Failed to remove perspective meta data!"); + }); + return deferred.promise; + }; + var advancedSearch = function(query, where, adopted, etymology) { + var deferred = $q.defer(); + var url = "/advanced_search"; + var perspectives = where.map(function(o) { + if (o.type == "perspective") { + return { + client_id: o.client_id, + object_id: o.object_id + }; + } + }).filter(function(o) { + return typeof o !== "undefined"; + }); + var req = { + searchstrings: query, + perspectives: perspectives + }; + if (_.isBoolean(adopted)) { + req.adopted = adopted; + } + if (_.isBoolean(etymology)) { + req.with_etimology = etymology; + } + $http.post(url, req).success(function(data, status, headers, config) { + var r = data.map(function(e) { + var perspective = lingvodoc.Perspective.fromJS(e); + return getPerspectiveOriginById(perspective.client_id, perspective.object_id); + }); + $q.all(r).then(function(paths) { + var out = []; + _.each(data, function(entry, i) { + entry.lexical_entry["origin"] = paths[i]; + out.push(entry.lexical_entry); + }); + deferred.resolve(out); + }, function(reason) { + deferred.reject("An error occurred while doing basic search"); + }); + }).error(function(data, status, headers, config) { + deferred.reject("An error occurred while doing advanced search"); + }); + return deferred.promise; + }; + var convertMarkup = function(object) { + var deferred = $q.defer(); + var obj = { + client_id: object.client_id, + object_id: object.object_id + }; + $http.post("/convert/markup", obj).success(function(data, status, headers, config) { + deferred.resolve(data); + }).error(function(data, status, headers, config) { + deferred.reject("Failed to convert markup!"); + }); + return deferred.promise; + }; return { getLexicalEntries: getLexicalEntries, getLexicalEntriesCount: getLexicalEntriesCount, getPerspectiveDictionaryFields: getPerspectiveDictionaryFields, + getPerspectiveDictionaryFieldsNew: getPerspectiveDictionaryFieldsNew, addNewLexicalEntry: addNewLexicalEntry, saveValue: saveValue, removeValue: removeValue, @@ -28180,6 +31425,7 @@ function lingvodocAPI($http, $q) { approveAll: approveAll, getDictionaryProperties: getDictionaryProperties, setDictionaryProperties: setDictionaryProperties, + removeDictionary: removeDictionary, getLanguages: getLanguages, setDictionaryStatus: setDictionaryStatus, setPerspectiveStatus: setPerspectiveStatus, @@ -28187,6 +31433,7 @@ function lingvodocAPI($http, $q) { getPerspectiveFields: getPerspectiveFields, setPerspectiveFields: setPerspectiveFields, getPerspectiveFieldsNew: getPerspectiveFieldsNew, + removePerspective: removePerspective, getUserInfo: getUserInfo, setUserInfo: setUserInfo, getOrganizations: getOrganizations, @@ -28213,7 +31460,15 @@ function lingvodocAPI($http, $q) { deleteDictionaryRoles: deleteDictionaryRoles, getPerspectiveRoles: getPerspectiveRoles, addPerspectiveRoles: addPerspectiveRoles, - deletePerspectiveRoles: deletePerspectiveRoles + deletePerspectiveRoles: deletePerspectiveRoles, + getUserBlobs: getUserBlobs, + checkDictionaryBlob: checkDictionaryBlob, + convertDictionary: convertDictionary, + getPerspectiveMeta: getPerspectiveMeta, + setPerspectiveMeta: setPerspectiveMeta, + removePerspectiveMeta: removePerspectiveMeta, + advancedSearch: advancedSearch, + convertMarkup: convertMarkup }; } @@ -28245,9 +31500,34 @@ function responseHandler($timeout, $modal) { function error(message) { show("error", message, 5e3); } + function yesno(status, message, callback) { + var controller = function($scope, $modalInstance) { + $scope.status = status; + $scope.message = message; + $scope.yes = function() { + $modalInstance.close(true); + }; + $scope.no = function() { + $modalInstance.close(false); + }; + }; + $modal.open({ + animation: true, + templateUrl: "responseHandlerYesNoModal.html", + controller: controller, + size: "lg", + backdrop: "static", + keyboard: false + }).result.then(function(result) { + callback(result); + }, function() { + callback(false); + }); + } return { success: success, - error: error + error: error, + yesno: yesno }; } diff --git a/lingvodoc/static/js/publish-dictionary.js b/lingvodoc/static/js/publish-dictionary.js index e4c99c9ee..31bde755a 100644 --- a/lingvodoc/static/js/publish-dictionary.js +++ b/lingvodoc/static/js/publish-dictionary.js @@ -5377,6 +5377,3947 @@ return jQuery; }); +(function() { + var undefined; + var VERSION = "3.10.1"; + var BIND_FLAG = 1, BIND_KEY_FLAG = 2, CURRY_BOUND_FLAG = 4, CURRY_FLAG = 8, CURRY_RIGHT_FLAG = 16, PARTIAL_FLAG = 32, PARTIAL_RIGHT_FLAG = 64, ARY_FLAG = 128, REARG_FLAG = 256; + var DEFAULT_TRUNC_LENGTH = 30, DEFAULT_TRUNC_OMISSION = "..."; + var HOT_COUNT = 150, HOT_SPAN = 16; + var LARGE_ARRAY_SIZE = 200; + var LAZY_FILTER_FLAG = 1, LAZY_MAP_FLAG = 2; + var FUNC_ERROR_TEXT = "Expected a function"; + var PLACEHOLDER = "__lodash_placeholder__"; + var argsTag = "[object Arguments]", arrayTag = "[object Array]", boolTag = "[object Boolean]", dateTag = "[object Date]", errorTag = "[object Error]", funcTag = "[object Function]", mapTag = "[object Map]", numberTag = "[object Number]", objectTag = "[object Object]", regexpTag = "[object RegExp]", setTag = "[object Set]", stringTag = "[object String]", weakMapTag = "[object WeakMap]"; + var arrayBufferTag = "[object ArrayBuffer]", float32Tag = "[object Float32Array]", float64Tag = "[object Float64Array]", int8Tag = "[object Int8Array]", int16Tag = "[object Int16Array]", int32Tag = "[object Int32Array]", uint8Tag = "[object Uint8Array]", uint8ClampedTag = "[object Uint8ClampedArray]", uint16Tag = "[object Uint16Array]", uint32Tag = "[object Uint32Array]"; + var reEmptyStringLeading = /\b__p \+= '';/g, reEmptyStringMiddle = /\b(__p \+=) '' \+/g, reEmptyStringTrailing = /(__e\(.*?\)|\b__t\)) \+\n'';/g; + var reEscapedHtml = /&(?:amp|lt|gt|quot|#39|#96);/g, reUnescapedHtml = /[&<>"'`]/g, reHasEscapedHtml = RegExp(reEscapedHtml.source), reHasUnescapedHtml = RegExp(reUnescapedHtml.source); + var reEscape = /<%-([\s\S]+?)%>/g, reEvaluate = /<%([\s\S]+?)%>/g, reInterpolate = /<%=([\s\S]+?)%>/g; + var reIsDeepProp = /\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\n\\]|\\.)*?\1)\]/, reIsPlainProp = /^\w*$/, rePropName = /[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\n\\]|\\.)*?)\2)\]/g; + var reRegExpChars = /^[:!,]|[\\^$.*+?()[\]{}|\/]|(^[0-9a-fA-Fnrtuvx])|([\n\r\u2028\u2029])/g, reHasRegExpChars = RegExp(reRegExpChars.source); + var reComboMark = /[\u0300-\u036f\ufe20-\ufe23]/g; + var reEscapeChar = /\\(\\)?/g; + var reEsTemplate = /\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g; + var reFlags = /\w*$/; + var reHasHexPrefix = /^0[xX]/; + var reIsHostCtor = /^\[object .+?Constructor\]$/; + var reIsUint = /^\d+$/; + var reLatin1 = /[\xc0-\xd6\xd8-\xde\xdf-\xf6\xf8-\xff]/g; + var reNoMatch = /($^)/; + var reUnescapedString = /['\n\r\u2028\u2029\\]/g; + var reWords = function() { + var upper = "[A-Z\\xc0-\\xd6\\xd8-\\xde]", lower = "[a-z\\xdf-\\xf6\\xf8-\\xff]+"; + return RegExp(upper + "+(?=" + upper + lower + ")|" + upper + "?" + lower + "|" + upper + "+|[0-9]+", "g"); + }(); + var contextProps = [ "Array", "ArrayBuffer", "Date", "Error", "Float32Array", "Float64Array", "Function", "Int8Array", "Int16Array", "Int32Array", "Math", "Number", "Object", "RegExp", "Set", "String", "_", "clearTimeout", "isFinite", "parseFloat", "parseInt", "setTimeout", "TypeError", "Uint8Array", "Uint8ClampedArray", "Uint16Array", "Uint32Array", "WeakMap" ]; + var templateCounter = -1; + var typedArrayTags = {}; + typedArrayTags[float32Tag] = typedArrayTags[float64Tag] = typedArrayTags[int8Tag] = typedArrayTags[int16Tag] = typedArrayTags[int32Tag] = typedArrayTags[uint8Tag] = typedArrayTags[uint8ClampedTag] = typedArrayTags[uint16Tag] = typedArrayTags[uint32Tag] = true; + typedArrayTags[argsTag] = typedArrayTags[arrayTag] = typedArrayTags[arrayBufferTag] = typedArrayTags[boolTag] = typedArrayTags[dateTag] = typedArrayTags[errorTag] = typedArrayTags[funcTag] = typedArrayTags[mapTag] = typedArrayTags[numberTag] = typedArrayTags[objectTag] = typedArrayTags[regexpTag] = typedArrayTags[setTag] = typedArrayTags[stringTag] = typedArrayTags[weakMapTag] = false; + var cloneableTags = {}; + cloneableTags[argsTag] = cloneableTags[arrayTag] = cloneableTags[arrayBufferTag] = cloneableTags[boolTag] = cloneableTags[dateTag] = cloneableTags[float32Tag] = cloneableTags[float64Tag] = cloneableTags[int8Tag] = cloneableTags[int16Tag] = cloneableTags[int32Tag] = cloneableTags[numberTag] = cloneableTags[objectTag] = cloneableTags[regexpTag] = cloneableTags[stringTag] = cloneableTags[uint8Tag] = cloneableTags[uint8ClampedTag] = cloneableTags[uint16Tag] = cloneableTags[uint32Tag] = true; + cloneableTags[errorTag] = cloneableTags[funcTag] = cloneableTags[mapTag] = cloneableTags[setTag] = cloneableTags[weakMapTag] = false; + var deburredLetters = { + "À": "A", + "Á": "A", + "Â": "A", + "Ã": "A", + "Ä": "A", + "Å": "A", + "à": "a", + "á": "a", + "â": "a", + "ã": "a", + "ä": "a", + "å": "a", + "Ç": "C", + "ç": "c", + "Ð": "D", + "ð": "d", + "È": "E", + "É": "E", + "Ê": "E", + "Ë": "E", + "è": "e", + "é": "e", + "ê": "e", + "ë": "e", + "Ì": "I", + "Í": "I", + "Î": "I", + "Ï": "I", + "ì": "i", + "í": "i", + "î": "i", + "ï": "i", + "Ñ": "N", + "ñ": "n", + "Ò": "O", + "Ó": "O", + "Ô": "O", + "Õ": "O", + "Ö": "O", + "Ø": "O", + "ò": "o", + "ó": "o", + "ô": "o", + "õ": "o", + "ö": "o", + "ø": "o", + "Ù": "U", + "Ú": "U", + "Û": "U", + "Ü": "U", + "ù": "u", + "ú": "u", + "û": "u", + "ü": "u", + "Ý": "Y", + "ý": "y", + "ÿ": "y", + "Æ": "Ae", + "æ": "ae", + "Þ": "Th", + "þ": "th", + "ß": "ss" + }; + var htmlEscapes = { + "&": "&", + "<": "<", + ">": ">", + '"': """, + "'": "'", + "`": "`" + }; + var htmlUnescapes = { + "&": "&", + "<": "<", + ">": ">", + """: '"', + "'": "'", + "`": "`" + }; + var objectTypes = { + "function": true, + object: true + }; + var regexpEscapes = { + "0": "x30", + "1": "x31", + "2": "x32", + "3": "x33", + "4": "x34", + "5": "x35", + "6": "x36", + "7": "x37", + "8": "x38", + "9": "x39", + A: "x41", + B: "x42", + C: "x43", + D: "x44", + E: "x45", + F: "x46", + a: "x61", + b: "x62", + c: "x63", + d: "x64", + e: "x65", + f: "x66", + n: "x6e", + r: "x72", + t: "x74", + u: "x75", + v: "x76", + x: "x78" + }; + var stringEscapes = { + "\\": "\\", + "'": "'", + "\n": "n", + "\r": "r", + "\u2028": "u2028", + "\u2029": "u2029" + }; + var freeExports = objectTypes[typeof exports] && exports && !exports.nodeType && exports; + var freeModule = objectTypes[typeof module] && module && !module.nodeType && module; + var freeGlobal = freeExports && freeModule && typeof global == "object" && global && global.Object && global; + var freeSelf = objectTypes[typeof self] && self && self.Object && self; + var freeWindow = objectTypes[typeof window] && window && window.Object && window; + var moduleExports = freeModule && freeModule.exports === freeExports && freeExports; + var root = freeGlobal || freeWindow !== (this && this.window) && freeWindow || freeSelf || this; + function baseCompareAscending(value, other) { + if (value !== other) { + var valIsNull = value === null, valIsUndef = value === undefined, valIsReflexive = value === value; + var othIsNull = other === null, othIsUndef = other === undefined, othIsReflexive = other === other; + if (value > other && !othIsNull || !valIsReflexive || valIsNull && !othIsUndef && othIsReflexive || valIsUndef && othIsReflexive) { + return 1; + } + if (value < other && !valIsNull || !othIsReflexive || othIsNull && !valIsUndef && valIsReflexive || othIsUndef && valIsReflexive) { + return -1; + } + } + return 0; + } + function baseFindIndex(array, predicate, fromRight) { + var length = array.length, index = fromRight ? length : -1; + while (fromRight ? index-- : ++index < length) { + if (predicate(array[index], index, array)) { + return index; + } + } + return -1; + } + function baseIndexOf(array, value, fromIndex) { + if (value !== value) { + return indexOfNaN(array, fromIndex); + } + var index = fromIndex - 1, length = array.length; + while (++index < length) { + if (array[index] === value) { + return index; + } + } + return -1; + } + function baseIsFunction(value) { + return typeof value == "function" || false; + } + function baseToString(value) { + return value == null ? "" : value + ""; + } + function charsLeftIndex(string, chars) { + var index = -1, length = string.length; + while (++index < length && chars.indexOf(string.charAt(index)) > -1) {} + return index; + } + function charsRightIndex(string, chars) { + var index = string.length; + while (index-- && chars.indexOf(string.charAt(index)) > -1) {} + return index; + } + function compareAscending(object, other) { + return baseCompareAscending(object.criteria, other.criteria) || object.index - other.index; + } + function compareMultiple(object, other, orders) { + var index = -1, objCriteria = object.criteria, othCriteria = other.criteria, length = objCriteria.length, ordersLength = orders.length; + while (++index < length) { + var result = baseCompareAscending(objCriteria[index], othCriteria[index]); + if (result) { + if (index >= ordersLength) { + return result; + } + var order = orders[index]; + return result * (order === "asc" || order === true ? 1 : -1); + } + } + return object.index - other.index; + } + function deburrLetter(letter) { + return deburredLetters[letter]; + } + function escapeHtmlChar(chr) { + return htmlEscapes[chr]; + } + function escapeRegExpChar(chr, leadingChar, whitespaceChar) { + if (leadingChar) { + chr = regexpEscapes[chr]; + } else if (whitespaceChar) { + chr = stringEscapes[chr]; + } + return "\\" + chr; + } + function escapeStringChar(chr) { + return "\\" + stringEscapes[chr]; + } + function indexOfNaN(array, fromIndex, fromRight) { + var length = array.length, index = fromIndex + (fromRight ? 0 : -1); + while (fromRight ? index-- : ++index < length) { + var other = array[index]; + if (other !== other) { + return index; + } + } + return -1; + } + function isObjectLike(value) { + return !!value && typeof value == "object"; + } + function isSpace(charCode) { + return charCode <= 160 && (charCode >= 9 && charCode <= 13) || charCode == 32 || charCode == 160 || charCode == 5760 || charCode == 6158 || charCode >= 8192 && (charCode <= 8202 || charCode == 8232 || charCode == 8233 || charCode == 8239 || charCode == 8287 || charCode == 12288 || charCode == 65279); + } + function replaceHolders(array, placeholder) { + var index = -1, length = array.length, resIndex = -1, result = []; + while (++index < length) { + if (array[index] === placeholder) { + array[index] = PLACEHOLDER; + result[++resIndex] = index; + } + } + return result; + } + function sortedUniq(array, iteratee) { + var seen, index = -1, length = array.length, resIndex = -1, result = []; + while (++index < length) { + var value = array[index], computed = iteratee ? iteratee(value, index, array) : value; + if (!index || seen !== computed) { + seen = computed; + result[++resIndex] = value; + } + } + return result; + } + function trimmedLeftIndex(string) { + var index = -1, length = string.length; + while (++index < length && isSpace(string.charCodeAt(index))) {} + return index; + } + function trimmedRightIndex(string) { + var index = string.length; + while (index-- && isSpace(string.charCodeAt(index))) {} + return index; + } + function unescapeHtmlChar(chr) { + return htmlUnescapes[chr]; + } + function runInContext(context) { + context = context ? _.defaults(root.Object(), context, _.pick(root, contextProps)) : root; + var Array = context.Array, Date = context.Date, Error = context.Error, Function = context.Function, Math = context.Math, Number = context.Number, Object = context.Object, RegExp = context.RegExp, String = context.String, TypeError = context.TypeError; + var arrayProto = Array.prototype, objectProto = Object.prototype, stringProto = String.prototype; + var fnToString = Function.prototype.toString; + var hasOwnProperty = objectProto.hasOwnProperty; + var idCounter = 0; + var objToString = objectProto.toString; + var oldDash = root._; + var reIsNative = RegExp("^" + fnToString.call(hasOwnProperty).replace(/[\\^$.*+?()[\]{}|]/g, "\\$&").replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g, "$1.*?") + "$"); + var ArrayBuffer = context.ArrayBuffer, clearTimeout = context.clearTimeout, parseFloat = context.parseFloat, pow = Math.pow, propertyIsEnumerable = objectProto.propertyIsEnumerable, Set = getNative(context, "Set"), setTimeout = context.setTimeout, splice = arrayProto.splice, Uint8Array = context.Uint8Array, WeakMap = getNative(context, "WeakMap"); + var nativeCeil = Math.ceil, nativeCreate = getNative(Object, "create"), nativeFloor = Math.floor, nativeIsArray = getNative(Array, "isArray"), nativeIsFinite = context.isFinite, nativeKeys = getNative(Object, "keys"), nativeMax = Math.max, nativeMin = Math.min, nativeNow = getNative(Date, "now"), nativeParseInt = context.parseInt, nativeRandom = Math.random; + var NEGATIVE_INFINITY = Number.NEGATIVE_INFINITY, POSITIVE_INFINITY = Number.POSITIVE_INFINITY; + var MAX_ARRAY_LENGTH = 4294967295, MAX_ARRAY_INDEX = MAX_ARRAY_LENGTH - 1, HALF_MAX_ARRAY_LENGTH = MAX_ARRAY_LENGTH >>> 1; + var MAX_SAFE_INTEGER = 9007199254740991; + var metaMap = WeakMap && new WeakMap(); + var realNames = {}; + function lodash(value) { + if (isObjectLike(value) && !isArray(value) && !(value instanceof LazyWrapper)) { + if (value instanceof LodashWrapper) { + return value; + } + if (hasOwnProperty.call(value, "__chain__") && hasOwnProperty.call(value, "__wrapped__")) { + return wrapperClone(value); + } + } + return new LodashWrapper(value); + } + function baseLodash() {} + function LodashWrapper(value, chainAll, actions) { + this.__wrapped__ = value; + this.__actions__ = actions || []; + this.__chain__ = !!chainAll; + } + var support = lodash.support = {}; + lodash.templateSettings = { + escape: reEscape, + evaluate: reEvaluate, + interpolate: reInterpolate, + variable: "", + imports: { + _: lodash + } + }; + function LazyWrapper(value) { + this.__wrapped__ = value; + this.__actions__ = []; + this.__dir__ = 1; + this.__filtered__ = false; + this.__iteratees__ = []; + this.__takeCount__ = POSITIVE_INFINITY; + this.__views__ = []; + } + function lazyClone() { + var result = new LazyWrapper(this.__wrapped__); + result.__actions__ = arrayCopy(this.__actions__); + result.__dir__ = this.__dir__; + result.__filtered__ = this.__filtered__; + result.__iteratees__ = arrayCopy(this.__iteratees__); + result.__takeCount__ = this.__takeCount__; + result.__views__ = arrayCopy(this.__views__); + return result; + } + function lazyReverse() { + if (this.__filtered__) { + var result = new LazyWrapper(this); + result.__dir__ = -1; + result.__filtered__ = true; + } else { + result = this.clone(); + result.__dir__ *= -1; + } + return result; + } + function lazyValue() { + var array = this.__wrapped__.value(), dir = this.__dir__, isArr = isArray(array), isRight = dir < 0, arrLength = isArr ? array.length : 0, view = getView(0, arrLength, this.__views__), start = view.start, end = view.end, length = end - start, index = isRight ? end : start - 1, iteratees = this.__iteratees__, iterLength = iteratees.length, resIndex = 0, takeCount = nativeMin(length, this.__takeCount__); + if (!isArr || arrLength < LARGE_ARRAY_SIZE || arrLength == length && takeCount == length) { + return baseWrapperValue(array, this.__actions__); + } + var result = []; + outer: while (length-- && resIndex < takeCount) { + index += dir; + var iterIndex = -1, value = array[index]; + while (++iterIndex < iterLength) { + var data = iteratees[iterIndex], iteratee = data.iteratee, type = data.type, computed = iteratee(value); + if (type == LAZY_MAP_FLAG) { + value = computed; + } else if (!computed) { + if (type == LAZY_FILTER_FLAG) { + continue outer; + } else { + break outer; + } + } + } + result[resIndex++] = value; + } + return result; + } + function MapCache() { + this.__data__ = {}; + } + function mapDelete(key) { + return this.has(key) && delete this.__data__[key]; + } + function mapGet(key) { + return key == "__proto__" ? undefined : this.__data__[key]; + } + function mapHas(key) { + return key != "__proto__" && hasOwnProperty.call(this.__data__, key); + } + function mapSet(key, value) { + if (key != "__proto__") { + this.__data__[key] = value; + } + return this; + } + function SetCache(values) { + var length = values ? values.length : 0; + this.data = { + hash: nativeCreate(null), + set: new Set() + }; + while (length--) { + this.push(values[length]); + } + } + function cacheIndexOf(cache, value) { + var data = cache.data, result = typeof value == "string" || isObject(value) ? data.set.has(value) : data.hash[value]; + return result ? 0 : -1; + } + function cachePush(value) { + var data = this.data; + if (typeof value == "string" || isObject(value)) { + data.set.add(value); + } else { + data.hash[value] = true; + } + } + function arrayConcat(array, other) { + var index = -1, length = array.length, othIndex = -1, othLength = other.length, result = Array(length + othLength); + while (++index < length) { + result[index] = array[index]; + } + while (++othIndex < othLength) { + result[index++] = other[othIndex]; + } + return result; + } + function arrayCopy(source, array) { + var index = -1, length = source.length; + array || (array = Array(length)); + while (++index < length) { + array[index] = source[index]; + } + return array; + } + function arrayEach(array, iteratee) { + var index = -1, length = array.length; + while (++index < length) { + if (iteratee(array[index], index, array) === false) { + break; + } + } + return array; + } + function arrayEachRight(array, iteratee) { + var length = array.length; + while (length--) { + if (iteratee(array[length], length, array) === false) { + break; + } + } + return array; + } + function arrayEvery(array, predicate) { + var index = -1, length = array.length; + while (++index < length) { + if (!predicate(array[index], index, array)) { + return false; + } + } + return true; + } + function arrayExtremum(array, iteratee, comparator, exValue) { + var index = -1, length = array.length, computed = exValue, result = computed; + while (++index < length) { + var value = array[index], current = +iteratee(value); + if (comparator(current, computed)) { + computed = current; + result = value; + } + } + return result; + } + function arrayFilter(array, predicate) { + var index = -1, length = array.length, resIndex = -1, result = []; + while (++index < length) { + var value = array[index]; + if (predicate(value, index, array)) { + result[++resIndex] = value; + } + } + return result; + } + function arrayMap(array, iteratee) { + var index = -1, length = array.length, result = Array(length); + while (++index < length) { + result[index] = iteratee(array[index], index, array); + } + return result; + } + function arrayPush(array, values) { + var index = -1, length = values.length, offset = array.length; + while (++index < length) { + array[offset + index] = values[index]; + } + return array; + } + function arrayReduce(array, iteratee, accumulator, initFromArray) { + var index = -1, length = array.length; + if (initFromArray && length) { + accumulator = array[++index]; + } + while (++index < length) { + accumulator = iteratee(accumulator, array[index], index, array); + } + return accumulator; + } + function arrayReduceRight(array, iteratee, accumulator, initFromArray) { + var length = array.length; + if (initFromArray && length) { + accumulator = array[--length]; + } + while (length--) { + accumulator = iteratee(accumulator, array[length], length, array); + } + return accumulator; + } + function arraySome(array, predicate) { + var index = -1, length = array.length; + while (++index < length) { + if (predicate(array[index], index, array)) { + return true; + } + } + return false; + } + function arraySum(array, iteratee) { + var length = array.length, result = 0; + while (length--) { + result += +iteratee(array[length]) || 0; + } + return result; + } + function assignDefaults(objectValue, sourceValue) { + return objectValue === undefined ? sourceValue : objectValue; + } + function assignOwnDefaults(objectValue, sourceValue, key, object) { + return objectValue === undefined || !hasOwnProperty.call(object, key) ? sourceValue : objectValue; + } + function assignWith(object, source, customizer) { + var index = -1, props = keys(source), length = props.length; + while (++index < length) { + var key = props[index], value = object[key], result = customizer(value, source[key], key, object, source); + if ((result === result ? result !== value : value === value) || value === undefined && !(key in object)) { + object[key] = result; + } + } + return object; + } + function baseAssign(object, source) { + return source == null ? object : baseCopy(source, keys(source), object); + } + function baseAt(collection, props) { + var index = -1, isNil = collection == null, isArr = !isNil && isArrayLike(collection), length = isArr ? collection.length : 0, propsLength = props.length, result = Array(propsLength); + while (++index < propsLength) { + var key = props[index]; + if (isArr) { + result[index] = isIndex(key, length) ? collection[key] : undefined; + } else { + result[index] = isNil ? undefined : collection[key]; + } + } + return result; + } + function baseCopy(source, props, object) { + object || (object = {}); + var index = -1, length = props.length; + while (++index < length) { + var key = props[index]; + object[key] = source[key]; + } + return object; + } + function baseCallback(func, thisArg, argCount) { + var type = typeof func; + if (type == "function") { + return thisArg === undefined ? func : bindCallback(func, thisArg, argCount); + } + if (func == null) { + return identity; + } + if (type == "object") { + return baseMatches(func); + } + return thisArg === undefined ? property(func) : baseMatchesProperty(func, thisArg); + } + function baseClone(value, isDeep, customizer, key, object, stackA, stackB) { + var result; + if (customizer) { + result = object ? customizer(value, key, object) : customizer(value); + } + if (result !== undefined) { + return result; + } + if (!isObject(value)) { + return value; + } + var isArr = isArray(value); + if (isArr) { + result = initCloneArray(value); + if (!isDeep) { + return arrayCopy(value, result); + } + } else { + var tag = objToString.call(value), isFunc = tag == funcTag; + if (tag == objectTag || tag == argsTag || isFunc && !object) { + result = initCloneObject(isFunc ? {} : value); + if (!isDeep) { + return baseAssign(result, value); + } + } else { + return cloneableTags[tag] ? initCloneByTag(value, tag, isDeep) : object ? value : {}; + } + } + stackA || (stackA = []); + stackB || (stackB = []); + var length = stackA.length; + while (length--) { + if (stackA[length] == value) { + return stackB[length]; + } + } + stackA.push(value); + stackB.push(result); + (isArr ? arrayEach : baseForOwn)(value, function(subValue, key) { + result[key] = baseClone(subValue, isDeep, customizer, key, value, stackA, stackB); + }); + return result; + } + var baseCreate = function() { + function object() {} + return function(prototype) { + if (isObject(prototype)) { + object.prototype = prototype; + var result = new object(); + object.prototype = undefined; + } + return result || {}; + }; + }(); + function baseDelay(func, wait, args) { + if (typeof func != "function") { + throw new TypeError(FUNC_ERROR_TEXT); + } + return setTimeout(function() { + func.apply(undefined, args); + }, wait); + } + function baseDifference(array, values) { + var length = array ? array.length : 0, result = []; + if (!length) { + return result; + } + var index = -1, indexOf = getIndexOf(), isCommon = indexOf === baseIndexOf, cache = isCommon && values.length >= LARGE_ARRAY_SIZE ? createCache(values) : null, valuesLength = values.length; + if (cache) { + indexOf = cacheIndexOf; + isCommon = false; + values = cache; + } + outer: while (++index < length) { + var value = array[index]; + if (isCommon && value === value) { + var valuesIndex = valuesLength; + while (valuesIndex--) { + if (values[valuesIndex] === value) { + continue outer; + } + } + result.push(value); + } else if (indexOf(values, value, 0) < 0) { + result.push(value); + } + } + return result; + } + var baseEach = createBaseEach(baseForOwn); + var baseEachRight = createBaseEach(baseForOwnRight, true); + function baseEvery(collection, predicate) { + var result = true; + baseEach(collection, function(value, index, collection) { + result = !!predicate(value, index, collection); + return result; + }); + return result; + } + function baseExtremum(collection, iteratee, comparator, exValue) { + var computed = exValue, result = computed; + baseEach(collection, function(value, index, collection) { + var current = +iteratee(value, index, collection); + if (comparator(current, computed) || current === exValue && current === result) { + computed = current; + result = value; + } + }); + return result; + } + function baseFill(array, value, start, end) { + var length = array.length; + start = start == null ? 0 : +start || 0; + if (start < 0) { + start = -start > length ? 0 : length + start; + } + end = end === undefined || end > length ? length : +end || 0; + if (end < 0) { + end += length; + } + length = start > end ? 0 : end >>> 0; + start >>>= 0; + while (start < length) { + array[start++] = value; + } + return array; + } + function baseFilter(collection, predicate) { + var result = []; + baseEach(collection, function(value, index, collection) { + if (predicate(value, index, collection)) { + result.push(value); + } + }); + return result; + } + function baseFind(collection, predicate, eachFunc, retKey) { + var result; + eachFunc(collection, function(value, key, collection) { + if (predicate(value, key, collection)) { + result = retKey ? key : value; + return false; + } + }); + return result; + } + function baseFlatten(array, isDeep, isStrict, result) { + result || (result = []); + var index = -1, length = array.length; + while (++index < length) { + var value = array[index]; + if (isObjectLike(value) && isArrayLike(value) && (isStrict || isArray(value) || isArguments(value))) { + if (isDeep) { + baseFlatten(value, isDeep, isStrict, result); + } else { + arrayPush(result, value); + } + } else if (!isStrict) { + result[result.length] = value; + } + } + return result; + } + var baseFor = createBaseFor(); + var baseForRight = createBaseFor(true); + function baseForIn(object, iteratee) { + return baseFor(object, iteratee, keysIn); + } + function baseForOwn(object, iteratee) { + return baseFor(object, iteratee, keys); + } + function baseForOwnRight(object, iteratee) { + return baseForRight(object, iteratee, keys); + } + function baseFunctions(object, props) { + var index = -1, length = props.length, resIndex = -1, result = []; + while (++index < length) { + var key = props[index]; + if (isFunction(object[key])) { + result[++resIndex] = key; + } + } + return result; + } + function baseGet(object, path, pathKey) { + if (object == null) { + return; + } + if (pathKey !== undefined && pathKey in toObject(object)) { + path = [ pathKey ]; + } + var index = 0, length = path.length; + while (object != null && index < length) { + object = object[path[index++]]; + } + return index && index == length ? object : undefined; + } + function baseIsEqual(value, other, customizer, isLoose, stackA, stackB) { + if (value === other) { + return true; + } + if (value == null || other == null || !isObject(value) && !isObjectLike(other)) { + return value !== value && other !== other; + } + return baseIsEqualDeep(value, other, baseIsEqual, customizer, isLoose, stackA, stackB); + } + function baseIsEqualDeep(object, other, equalFunc, customizer, isLoose, stackA, stackB) { + var objIsArr = isArray(object), othIsArr = isArray(other), objTag = arrayTag, othTag = arrayTag; + if (!objIsArr) { + objTag = objToString.call(object); + if (objTag == argsTag) { + objTag = objectTag; + } else if (objTag != objectTag) { + objIsArr = isTypedArray(object); + } + } + if (!othIsArr) { + othTag = objToString.call(other); + if (othTag == argsTag) { + othTag = objectTag; + } else if (othTag != objectTag) { + othIsArr = isTypedArray(other); + } + } + var objIsObj = objTag == objectTag, othIsObj = othTag == objectTag, isSameTag = objTag == othTag; + if (isSameTag && !(objIsArr || objIsObj)) { + return equalByTag(object, other, objTag); + } + if (!isLoose) { + var objIsWrapped = objIsObj && hasOwnProperty.call(object, "__wrapped__"), othIsWrapped = othIsObj && hasOwnProperty.call(other, "__wrapped__"); + if (objIsWrapped || othIsWrapped) { + return equalFunc(objIsWrapped ? object.value() : object, othIsWrapped ? other.value() : other, customizer, isLoose, stackA, stackB); + } + } + if (!isSameTag) { + return false; + } + stackA || (stackA = []); + stackB || (stackB = []); + var length = stackA.length; + while (length--) { + if (stackA[length] == object) { + return stackB[length] == other; + } + } + stackA.push(object); + stackB.push(other); + var result = (objIsArr ? equalArrays : equalObjects)(object, other, equalFunc, customizer, isLoose, stackA, stackB); + stackA.pop(); + stackB.pop(); + return result; + } + function baseIsMatch(object, matchData, customizer) { + var index = matchData.length, length = index, noCustomizer = !customizer; + if (object == null) { + return !length; + } + object = toObject(object); + while (index--) { + var data = matchData[index]; + if (noCustomizer && data[2] ? data[1] !== object[data[0]] : !(data[0] in object)) { + return false; + } + } + while (++index < length) { + data = matchData[index]; + var key = data[0], objValue = object[key], srcValue = data[1]; + if (noCustomizer && data[2]) { + if (objValue === undefined && !(key in object)) { + return false; + } + } else { + var result = customizer ? customizer(objValue, srcValue, key) : undefined; + if (!(result === undefined ? baseIsEqual(srcValue, objValue, customizer, true) : result)) { + return false; + } + } + } + return true; + } + function baseMap(collection, iteratee) { + var index = -1, result = isArrayLike(collection) ? Array(collection.length) : []; + baseEach(collection, function(value, key, collection) { + result[++index] = iteratee(value, key, collection); + }); + return result; + } + function baseMatches(source) { + var matchData = getMatchData(source); + if (matchData.length == 1 && matchData[0][2]) { + var key = matchData[0][0], value = matchData[0][1]; + return function(object) { + if (object == null) { + return false; + } + return object[key] === value && (value !== undefined || key in toObject(object)); + }; + } + return function(object) { + return baseIsMatch(object, matchData); + }; + } + function baseMatchesProperty(path, srcValue) { + var isArr = isArray(path), isCommon = isKey(path) && isStrictComparable(srcValue), pathKey = path + ""; + path = toPath(path); + return function(object) { + if (object == null) { + return false; + } + var key = pathKey; + object = toObject(object); + if ((isArr || !isCommon) && !(key in object)) { + object = path.length == 1 ? object : baseGet(object, baseSlice(path, 0, -1)); + if (object == null) { + return false; + } + key = last(path); + object = toObject(object); + } + return object[key] === srcValue ? srcValue !== undefined || key in object : baseIsEqual(srcValue, object[key], undefined, true); + }; + } + function baseMerge(object, source, customizer, stackA, stackB) { + if (!isObject(object)) { + return object; + } + var isSrcArr = isArrayLike(source) && (isArray(source) || isTypedArray(source)), props = isSrcArr ? undefined : keys(source); + arrayEach(props || source, function(srcValue, key) { + if (props) { + key = srcValue; + srcValue = source[key]; + } + if (isObjectLike(srcValue)) { + stackA || (stackA = []); + stackB || (stackB = []); + baseMergeDeep(object, source, key, baseMerge, customizer, stackA, stackB); + } else { + var value = object[key], result = customizer ? customizer(value, srcValue, key, object, source) : undefined, isCommon = result === undefined; + if (isCommon) { + result = srcValue; + } + if ((result !== undefined || isSrcArr && !(key in object)) && (isCommon || (result === result ? result !== value : value === value))) { + object[key] = result; + } + } + }); + return object; + } + function baseMergeDeep(object, source, key, mergeFunc, customizer, stackA, stackB) { + var length = stackA.length, srcValue = source[key]; + while (length--) { + if (stackA[length] == srcValue) { + object[key] = stackB[length]; + return; + } + } + var value = object[key], result = customizer ? customizer(value, srcValue, key, object, source) : undefined, isCommon = result === undefined; + if (isCommon) { + result = srcValue; + if (isArrayLike(srcValue) && (isArray(srcValue) || isTypedArray(srcValue))) { + result = isArray(value) ? value : isArrayLike(value) ? arrayCopy(value) : []; + } else if (isPlainObject(srcValue) || isArguments(srcValue)) { + result = isArguments(value) ? toPlainObject(value) : isPlainObject(value) ? value : {}; + } else { + isCommon = false; + } + } + stackA.push(srcValue); + stackB.push(result); + if (isCommon) { + object[key] = mergeFunc(result, srcValue, customizer, stackA, stackB); + } else if (result === result ? result !== value : value === value) { + object[key] = result; + } + } + function baseProperty(key) { + return function(object) { + return object == null ? undefined : object[key]; + }; + } + function basePropertyDeep(path) { + var pathKey = path + ""; + path = toPath(path); + return function(object) { + return baseGet(object, path, pathKey); + }; + } + function basePullAt(array, indexes) { + var length = array ? indexes.length : 0; + while (length--) { + var index = indexes[length]; + if (index != previous && isIndex(index)) { + var previous = index; + splice.call(array, index, 1); + } + } + return array; + } + function baseRandom(min, max) { + return min + nativeFloor(nativeRandom() * (max - min + 1)); + } + function baseReduce(collection, iteratee, accumulator, initFromCollection, eachFunc) { + eachFunc(collection, function(value, index, collection) { + accumulator = initFromCollection ? (initFromCollection = false, value) : iteratee(accumulator, value, index, collection); + }); + return accumulator; + } + var baseSetData = !metaMap ? identity : function(func, data) { + metaMap.set(func, data); + return func; + }; + function baseSlice(array, start, end) { + var index = -1, length = array.length; + start = start == null ? 0 : +start || 0; + if (start < 0) { + start = -start > length ? 0 : length + start; + } + end = end === undefined || end > length ? length : +end || 0; + if (end < 0) { + end += length; + } + length = start > end ? 0 : end - start >>> 0; + start >>>= 0; + var result = Array(length); + while (++index < length) { + result[index] = array[index + start]; + } + return result; + } + function baseSome(collection, predicate) { + var result; + baseEach(collection, function(value, index, collection) { + result = predicate(value, index, collection); + return !result; + }); + return !!result; + } + function baseSortBy(array, comparer) { + var length = array.length; + array.sort(comparer); + while (length--) { + array[length] = array[length].value; + } + return array; + } + function baseSortByOrder(collection, iteratees, orders) { + var callback = getCallback(), index = -1; + iteratees = arrayMap(iteratees, function(iteratee) { + return callback(iteratee); + }); + var result = baseMap(collection, function(value) { + var criteria = arrayMap(iteratees, function(iteratee) { + return iteratee(value); + }); + return { + criteria: criteria, + index: ++index, + value: value + }; + }); + return baseSortBy(result, function(object, other) { + return compareMultiple(object, other, orders); + }); + } + function baseSum(collection, iteratee) { + var result = 0; + baseEach(collection, function(value, index, collection) { + result += +iteratee(value, index, collection) || 0; + }); + return result; + } + function baseUniq(array, iteratee) { + var index = -1, indexOf = getIndexOf(), length = array.length, isCommon = indexOf === baseIndexOf, isLarge = isCommon && length >= LARGE_ARRAY_SIZE, seen = isLarge ? createCache() : null, result = []; + if (seen) { + indexOf = cacheIndexOf; + isCommon = false; + } else { + isLarge = false; + seen = iteratee ? [] : result; + } + outer: while (++index < length) { + var value = array[index], computed = iteratee ? iteratee(value, index, array) : value; + if (isCommon && value === value) { + var seenIndex = seen.length; + while (seenIndex--) { + if (seen[seenIndex] === computed) { + continue outer; + } + } + if (iteratee) { + seen.push(computed); + } + result.push(value); + } else if (indexOf(seen, computed, 0) < 0) { + if (iteratee || isLarge) { + seen.push(computed); + } + result.push(value); + } + } + return result; + } + function baseValues(object, props) { + var index = -1, length = props.length, result = Array(length); + while (++index < length) { + result[index] = object[props[index]]; + } + return result; + } + function baseWhile(array, predicate, isDrop, fromRight) { + var length = array.length, index = fromRight ? length : -1; + while ((fromRight ? index-- : ++index < length) && predicate(array[index], index, array)) {} + return isDrop ? baseSlice(array, fromRight ? 0 : index, fromRight ? index + 1 : length) : baseSlice(array, fromRight ? index + 1 : 0, fromRight ? length : index); + } + function baseWrapperValue(value, actions) { + var result = value; + if (result instanceof LazyWrapper) { + result = result.value(); + } + var index = -1, length = actions.length; + while (++index < length) { + var action = actions[index]; + result = action.func.apply(action.thisArg, arrayPush([ result ], action.args)); + } + return result; + } + function binaryIndex(array, value, retHighest) { + var low = 0, high = array ? array.length : low; + if (typeof value == "number" && value === value && high <= HALF_MAX_ARRAY_LENGTH) { + while (low < high) { + var mid = low + high >>> 1, computed = array[mid]; + if ((retHighest ? computed <= value : computed < value) && computed !== null) { + low = mid + 1; + } else { + high = mid; + } + } + return high; + } + return binaryIndexBy(array, value, identity, retHighest); + } + function binaryIndexBy(array, value, iteratee, retHighest) { + value = iteratee(value); + var low = 0, high = array ? array.length : 0, valIsNaN = value !== value, valIsNull = value === null, valIsUndef = value === undefined; + while (low < high) { + var mid = nativeFloor((low + high) / 2), computed = iteratee(array[mid]), isDef = computed !== undefined, isReflexive = computed === computed; + if (valIsNaN) { + var setLow = isReflexive || retHighest; + } else if (valIsNull) { + setLow = isReflexive && isDef && (retHighest || computed != null); + } else if (valIsUndef) { + setLow = isReflexive && (retHighest || isDef); + } else if (computed == null) { + setLow = false; + } else { + setLow = retHighest ? computed <= value : computed < value; + } + if (setLow) { + low = mid + 1; + } else { + high = mid; + } + } + return nativeMin(high, MAX_ARRAY_INDEX); + } + function bindCallback(func, thisArg, argCount) { + if (typeof func != "function") { + return identity; + } + if (thisArg === undefined) { + return func; + } + switch (argCount) { + case 1: + return function(value) { + return func.call(thisArg, value); + }; + + case 3: + return function(value, index, collection) { + return func.call(thisArg, value, index, collection); + }; + + case 4: + return function(accumulator, value, index, collection) { + return func.call(thisArg, accumulator, value, index, collection); + }; + + case 5: + return function(value, other, key, object, source) { + return func.call(thisArg, value, other, key, object, source); + }; + } + return function() { + return func.apply(thisArg, arguments); + }; + } + function bufferClone(buffer) { + var result = new ArrayBuffer(buffer.byteLength), view = new Uint8Array(result); + view.set(new Uint8Array(buffer)); + return result; + } + function composeArgs(args, partials, holders) { + var holdersLength = holders.length, argsIndex = -1, argsLength = nativeMax(args.length - holdersLength, 0), leftIndex = -1, leftLength = partials.length, result = Array(leftLength + argsLength); + while (++leftIndex < leftLength) { + result[leftIndex] = partials[leftIndex]; + } + while (++argsIndex < holdersLength) { + result[holders[argsIndex]] = args[argsIndex]; + } + while (argsLength--) { + result[leftIndex++] = args[argsIndex++]; + } + return result; + } + function composeArgsRight(args, partials, holders) { + var holdersIndex = -1, holdersLength = holders.length, argsIndex = -1, argsLength = nativeMax(args.length - holdersLength, 0), rightIndex = -1, rightLength = partials.length, result = Array(argsLength + rightLength); + while (++argsIndex < argsLength) { + result[argsIndex] = args[argsIndex]; + } + var offset = argsIndex; + while (++rightIndex < rightLength) { + result[offset + rightIndex] = partials[rightIndex]; + } + while (++holdersIndex < holdersLength) { + result[offset + holders[holdersIndex]] = args[argsIndex++]; + } + return result; + } + function createAggregator(setter, initializer) { + return function(collection, iteratee, thisArg) { + var result = initializer ? initializer() : {}; + iteratee = getCallback(iteratee, thisArg, 3); + if (isArray(collection)) { + var index = -1, length = collection.length; + while (++index < length) { + var value = collection[index]; + setter(result, value, iteratee(value, index, collection), collection); + } + } else { + baseEach(collection, function(value, key, collection) { + setter(result, value, iteratee(value, key, collection), collection); + }); + } + return result; + }; + } + function createAssigner(assigner) { + return restParam(function(object, sources) { + var index = -1, length = object == null ? 0 : sources.length, customizer = length > 2 ? sources[length - 2] : undefined, guard = length > 2 ? sources[2] : undefined, thisArg = length > 1 ? sources[length - 1] : undefined; + if (typeof customizer == "function") { + customizer = bindCallback(customizer, thisArg, 5); + length -= 2; + } else { + customizer = typeof thisArg == "function" ? thisArg : undefined; + length -= customizer ? 1 : 0; + } + if (guard && isIterateeCall(sources[0], sources[1], guard)) { + customizer = length < 3 ? undefined : customizer; + length = 1; + } + while (++index < length) { + var source = sources[index]; + if (source) { + assigner(object, source, customizer); + } + } + return object; + }); + } + function createBaseEach(eachFunc, fromRight) { + return function(collection, iteratee) { + var length = collection ? getLength(collection) : 0; + if (!isLength(length)) { + return eachFunc(collection, iteratee); + } + var index = fromRight ? length : -1, iterable = toObject(collection); + while (fromRight ? index-- : ++index < length) { + if (iteratee(iterable[index], index, iterable) === false) { + break; + } + } + return collection; + }; + } + function createBaseFor(fromRight) { + return function(object, iteratee, keysFunc) { + var iterable = toObject(object), props = keysFunc(object), length = props.length, index = fromRight ? length : -1; + while (fromRight ? index-- : ++index < length) { + var key = props[index]; + if (iteratee(iterable[key], key, iterable) === false) { + break; + } + } + return object; + }; + } + function createBindWrapper(func, thisArg) { + var Ctor = createCtorWrapper(func); + function wrapper() { + var fn = this && this !== root && this instanceof wrapper ? Ctor : func; + return fn.apply(thisArg, arguments); + } + return wrapper; + } + function createCache(values) { + return nativeCreate && Set ? new SetCache(values) : null; + } + function createCompounder(callback) { + return function(string) { + var index = -1, array = words(deburr(string)), length = array.length, result = ""; + while (++index < length) { + result = callback(result, array[index], index); + } + return result; + }; + } + function createCtorWrapper(Ctor) { + return function() { + var args = arguments; + switch (args.length) { + case 0: + return new Ctor(); + + case 1: + return new Ctor(args[0]); + + case 2: + return new Ctor(args[0], args[1]); + + case 3: + return new Ctor(args[0], args[1], args[2]); + + case 4: + return new Ctor(args[0], args[1], args[2], args[3]); + + case 5: + return new Ctor(args[0], args[1], args[2], args[3], args[4]); + + case 6: + return new Ctor(args[0], args[1], args[2], args[3], args[4], args[5]); + + case 7: + return new Ctor(args[0], args[1], args[2], args[3], args[4], args[5], args[6]); + } + var thisBinding = baseCreate(Ctor.prototype), result = Ctor.apply(thisBinding, args); + return isObject(result) ? result : thisBinding; + }; + } + function createCurry(flag) { + function curryFunc(func, arity, guard) { + if (guard && isIterateeCall(func, arity, guard)) { + arity = undefined; + } + var result = createWrapper(func, flag, undefined, undefined, undefined, undefined, undefined, arity); + result.placeholder = curryFunc.placeholder; + return result; + } + return curryFunc; + } + function createDefaults(assigner, customizer) { + return restParam(function(args) { + var object = args[0]; + if (object == null) { + return object; + } + args.push(customizer); + return assigner.apply(undefined, args); + }); + } + function createExtremum(comparator, exValue) { + return function(collection, iteratee, thisArg) { + if (thisArg && isIterateeCall(collection, iteratee, thisArg)) { + iteratee = undefined; + } + iteratee = getCallback(iteratee, thisArg, 3); + if (iteratee.length == 1) { + collection = isArray(collection) ? collection : toIterable(collection); + var result = arrayExtremum(collection, iteratee, comparator, exValue); + if (!(collection.length && result === exValue)) { + return result; + } + } + return baseExtremum(collection, iteratee, comparator, exValue); + }; + } + function createFind(eachFunc, fromRight) { + return function(collection, predicate, thisArg) { + predicate = getCallback(predicate, thisArg, 3); + if (isArray(collection)) { + var index = baseFindIndex(collection, predicate, fromRight); + return index > -1 ? collection[index] : undefined; + } + return baseFind(collection, predicate, eachFunc); + }; + } + function createFindIndex(fromRight) { + return function(array, predicate, thisArg) { + if (!(array && array.length)) { + return -1; + } + predicate = getCallback(predicate, thisArg, 3); + return baseFindIndex(array, predicate, fromRight); + }; + } + function createFindKey(objectFunc) { + return function(object, predicate, thisArg) { + predicate = getCallback(predicate, thisArg, 3); + return baseFind(object, predicate, objectFunc, true); + }; + } + function createFlow(fromRight) { + return function() { + var wrapper, length = arguments.length, index = fromRight ? length : -1, leftIndex = 0, funcs = Array(length); + while (fromRight ? index-- : ++index < length) { + var func = funcs[leftIndex++] = arguments[index]; + if (typeof func != "function") { + throw new TypeError(FUNC_ERROR_TEXT); + } + if (!wrapper && LodashWrapper.prototype.thru && getFuncName(func) == "wrapper") { + wrapper = new LodashWrapper([], true); + } + } + index = wrapper ? -1 : length; + while (++index < length) { + func = funcs[index]; + var funcName = getFuncName(func), data = funcName == "wrapper" ? getData(func) : undefined; + if (data && isLaziable(data[0]) && data[1] == (ARY_FLAG | CURRY_FLAG | PARTIAL_FLAG | REARG_FLAG) && !data[4].length && data[9] == 1) { + wrapper = wrapper[getFuncName(data[0])].apply(wrapper, data[3]); + } else { + wrapper = func.length == 1 && isLaziable(func) ? wrapper[funcName]() : wrapper.thru(func); + } + } + return function() { + var args = arguments, value = args[0]; + if (wrapper && args.length == 1 && isArray(value) && value.length >= LARGE_ARRAY_SIZE) { + return wrapper.plant(value).value(); + } + var index = 0, result = length ? funcs[index].apply(this, args) : value; + while (++index < length) { + result = funcs[index].call(this, result); + } + return result; + }; + }; + } + function createForEach(arrayFunc, eachFunc) { + return function(collection, iteratee, thisArg) { + return typeof iteratee == "function" && thisArg === undefined && isArray(collection) ? arrayFunc(collection, iteratee) : eachFunc(collection, bindCallback(iteratee, thisArg, 3)); + }; + } + function createForIn(objectFunc) { + return function(object, iteratee, thisArg) { + if (typeof iteratee != "function" || thisArg !== undefined) { + iteratee = bindCallback(iteratee, thisArg, 3); + } + return objectFunc(object, iteratee, keysIn); + }; + } + function createForOwn(objectFunc) { + return function(object, iteratee, thisArg) { + if (typeof iteratee != "function" || thisArg !== undefined) { + iteratee = bindCallback(iteratee, thisArg, 3); + } + return objectFunc(object, iteratee); + }; + } + function createObjectMapper(isMapKeys) { + return function(object, iteratee, thisArg) { + var result = {}; + iteratee = getCallback(iteratee, thisArg, 3); + baseForOwn(object, function(value, key, object) { + var mapped = iteratee(value, key, object); + key = isMapKeys ? mapped : key; + value = isMapKeys ? value : mapped; + result[key] = value; + }); + return result; + }; + } + function createPadDir(fromRight) { + return function(string, length, chars) { + string = baseToString(string); + return (fromRight ? string : "") + createPadding(string, length, chars) + (fromRight ? "" : string); + }; + } + function createPartial(flag) { + var partialFunc = restParam(function(func, partials) { + var holders = replaceHolders(partials, partialFunc.placeholder); + return createWrapper(func, flag, undefined, partials, holders); + }); + return partialFunc; + } + function createReduce(arrayFunc, eachFunc) { + return function(collection, iteratee, accumulator, thisArg) { + var initFromArray = arguments.length < 3; + return typeof iteratee == "function" && thisArg === undefined && isArray(collection) ? arrayFunc(collection, iteratee, accumulator, initFromArray) : baseReduce(collection, getCallback(iteratee, thisArg, 4), accumulator, initFromArray, eachFunc); + }; + } + function createHybridWrapper(func, bitmask, thisArg, partials, holders, partialsRight, holdersRight, argPos, ary, arity) { + var isAry = bitmask & ARY_FLAG, isBind = bitmask & BIND_FLAG, isBindKey = bitmask & BIND_KEY_FLAG, isCurry = bitmask & CURRY_FLAG, isCurryBound = bitmask & CURRY_BOUND_FLAG, isCurryRight = bitmask & CURRY_RIGHT_FLAG, Ctor = isBindKey ? undefined : createCtorWrapper(func); + function wrapper() { + var length = arguments.length, index = length, args = Array(length); + while (index--) { + args[index] = arguments[index]; + } + if (partials) { + args = composeArgs(args, partials, holders); + } + if (partialsRight) { + args = composeArgsRight(args, partialsRight, holdersRight); + } + if (isCurry || isCurryRight) { + var placeholder = wrapper.placeholder, argsHolders = replaceHolders(args, placeholder); + length -= argsHolders.length; + if (length < arity) { + var newArgPos = argPos ? arrayCopy(argPos) : undefined, newArity = nativeMax(arity - length, 0), newsHolders = isCurry ? argsHolders : undefined, newHoldersRight = isCurry ? undefined : argsHolders, newPartials = isCurry ? args : undefined, newPartialsRight = isCurry ? undefined : args; + bitmask |= isCurry ? PARTIAL_FLAG : PARTIAL_RIGHT_FLAG; + bitmask &= ~(isCurry ? PARTIAL_RIGHT_FLAG : PARTIAL_FLAG); + if (!isCurryBound) { + bitmask &= ~(BIND_FLAG | BIND_KEY_FLAG); + } + var newData = [ func, bitmask, thisArg, newPartials, newsHolders, newPartialsRight, newHoldersRight, newArgPos, ary, newArity ], result = createHybridWrapper.apply(undefined, newData); + if (isLaziable(func)) { + setData(result, newData); + } + result.placeholder = placeholder; + return result; + } + } + var thisBinding = isBind ? thisArg : this, fn = isBindKey ? thisBinding[func] : func; + if (argPos) { + args = reorder(args, argPos); + } + if (isAry && ary < args.length) { + args.length = ary; + } + if (this && this !== root && this instanceof wrapper) { + fn = Ctor || createCtorWrapper(func); + } + return fn.apply(thisBinding, args); + } + return wrapper; + } + function createPadding(string, length, chars) { + var strLength = string.length; + length = +length; + if (strLength >= length || !nativeIsFinite(length)) { + return ""; + } + var padLength = length - strLength; + chars = chars == null ? " " : chars + ""; + return repeat(chars, nativeCeil(padLength / chars.length)).slice(0, padLength); + } + function createPartialWrapper(func, bitmask, thisArg, partials) { + var isBind = bitmask & BIND_FLAG, Ctor = createCtorWrapper(func); + function wrapper() { + var argsIndex = -1, argsLength = arguments.length, leftIndex = -1, leftLength = partials.length, args = Array(leftLength + argsLength); + while (++leftIndex < leftLength) { + args[leftIndex] = partials[leftIndex]; + } + while (argsLength--) { + args[leftIndex++] = arguments[++argsIndex]; + } + var fn = this && this !== root && this instanceof wrapper ? Ctor : func; + return fn.apply(isBind ? thisArg : this, args); + } + return wrapper; + } + function createRound(methodName) { + var func = Math[methodName]; + return function(number, precision) { + precision = precision === undefined ? 0 : +precision || 0; + if (precision) { + precision = pow(10, precision); + return func(number * precision) / precision; + } + return func(number); + }; + } + function createSortedIndex(retHighest) { + return function(array, value, iteratee, thisArg) { + var callback = getCallback(iteratee); + return iteratee == null && callback === baseCallback ? binaryIndex(array, value, retHighest) : binaryIndexBy(array, value, callback(iteratee, thisArg, 1), retHighest); + }; + } + function createWrapper(func, bitmask, thisArg, partials, holders, argPos, ary, arity) { + var isBindKey = bitmask & BIND_KEY_FLAG; + if (!isBindKey && typeof func != "function") { + throw new TypeError(FUNC_ERROR_TEXT); + } + var length = partials ? partials.length : 0; + if (!length) { + bitmask &= ~(PARTIAL_FLAG | PARTIAL_RIGHT_FLAG); + partials = holders = undefined; + } + length -= holders ? holders.length : 0; + if (bitmask & PARTIAL_RIGHT_FLAG) { + var partialsRight = partials, holdersRight = holders; + partials = holders = undefined; + } + var data = isBindKey ? undefined : getData(func), newData = [ func, bitmask, thisArg, partials, holders, partialsRight, holdersRight, argPos, ary, arity ]; + if (data) { + mergeData(newData, data); + bitmask = newData[1]; + arity = newData[9]; + } + newData[9] = arity == null ? isBindKey ? 0 : func.length : nativeMax(arity - length, 0) || 0; + if (bitmask == BIND_FLAG) { + var result = createBindWrapper(newData[0], newData[2]); + } else if ((bitmask == PARTIAL_FLAG || bitmask == (BIND_FLAG | PARTIAL_FLAG)) && !newData[4].length) { + result = createPartialWrapper.apply(undefined, newData); + } else { + result = createHybridWrapper.apply(undefined, newData); + } + var setter = data ? baseSetData : setData; + return setter(result, newData); + } + function equalArrays(array, other, equalFunc, customizer, isLoose, stackA, stackB) { + var index = -1, arrLength = array.length, othLength = other.length; + if (arrLength != othLength && !(isLoose && othLength > arrLength)) { + return false; + } + while (++index < arrLength) { + var arrValue = array[index], othValue = other[index], result = customizer ? customizer(isLoose ? othValue : arrValue, isLoose ? arrValue : othValue, index) : undefined; + if (result !== undefined) { + if (result) { + continue; + } + return false; + } + if (isLoose) { + if (!arraySome(other, function(othValue) { + return arrValue === othValue || equalFunc(arrValue, othValue, customizer, isLoose, stackA, stackB); + })) { + return false; + } + } else if (!(arrValue === othValue || equalFunc(arrValue, othValue, customizer, isLoose, stackA, stackB))) { + return false; + } + } + return true; + } + function equalByTag(object, other, tag) { + switch (tag) { + case boolTag: + case dateTag: + return +object == +other; + + case errorTag: + return object.name == other.name && object.message == other.message; + + case numberTag: + return object != +object ? other != +other : object == +other; + + case regexpTag: + case stringTag: + return object == other + ""; + } + return false; + } + function equalObjects(object, other, equalFunc, customizer, isLoose, stackA, stackB) { + var objProps = keys(object), objLength = objProps.length, othProps = keys(other), othLength = othProps.length; + if (objLength != othLength && !isLoose) { + return false; + } + var index = objLength; + while (index--) { + var key = objProps[index]; + if (!(isLoose ? key in other : hasOwnProperty.call(other, key))) { + return false; + } + } + var skipCtor = isLoose; + while (++index < objLength) { + key = objProps[index]; + var objValue = object[key], othValue = other[key], result = customizer ? customizer(isLoose ? othValue : objValue, isLoose ? objValue : othValue, key) : undefined; + if (!(result === undefined ? equalFunc(objValue, othValue, customizer, isLoose, stackA, stackB) : result)) { + return false; + } + skipCtor || (skipCtor = key == "constructor"); + } + if (!skipCtor) { + var objCtor = object.constructor, othCtor = other.constructor; + if (objCtor != othCtor && ("constructor" in object && "constructor" in other) && !(typeof objCtor == "function" && objCtor instanceof objCtor && typeof othCtor == "function" && othCtor instanceof othCtor)) { + return false; + } + } + return true; + } + function getCallback(func, thisArg, argCount) { + var result = lodash.callback || callback; + result = result === callback ? baseCallback : result; + return argCount ? result(func, thisArg, argCount) : result; + } + var getData = !metaMap ? noop : function(func) { + return metaMap.get(func); + }; + function getFuncName(func) { + var result = func.name + "", array = realNames[result], length = array ? array.length : 0; + while (length--) { + var data = array[length], otherFunc = data.func; + if (otherFunc == null || otherFunc == func) { + return data.name; + } + } + return result; + } + function getIndexOf(collection, target, fromIndex) { + var result = lodash.indexOf || indexOf; + result = result === indexOf ? baseIndexOf : result; + return collection ? result(collection, target, fromIndex) : result; + } + var getLength = baseProperty("length"); + function getMatchData(object) { + var result = pairs(object), length = result.length; + while (length--) { + result[length][2] = isStrictComparable(result[length][1]); + } + return result; + } + function getNative(object, key) { + var value = object == null ? undefined : object[key]; + return isNative(value) ? value : undefined; + } + function getView(start, end, transforms) { + var index = -1, length = transforms.length; + while (++index < length) { + var data = transforms[index], size = data.size; + switch (data.type) { + case "drop": + start += size; + break; + + case "dropRight": + end -= size; + break; + + case "take": + end = nativeMin(end, start + size); + break; + + case "takeRight": + start = nativeMax(start, end - size); + break; + } + } + return { + start: start, + end: end + }; + } + function initCloneArray(array) { + var length = array.length, result = new array.constructor(length); + if (length && typeof array[0] == "string" && hasOwnProperty.call(array, "index")) { + result.index = array.index; + result.input = array.input; + } + return result; + } + function initCloneObject(object) { + var Ctor = object.constructor; + if (!(typeof Ctor == "function" && Ctor instanceof Ctor)) { + Ctor = Object; + } + return new Ctor(); + } + function initCloneByTag(object, tag, isDeep) { + var Ctor = object.constructor; + switch (tag) { + case arrayBufferTag: + return bufferClone(object); + + case boolTag: + case dateTag: + return new Ctor(+object); + + case float32Tag: + case float64Tag: + case int8Tag: + case int16Tag: + case int32Tag: + case uint8Tag: + case uint8ClampedTag: + case uint16Tag: + case uint32Tag: + var buffer = object.buffer; + return new Ctor(isDeep ? bufferClone(buffer) : buffer, object.byteOffset, object.length); + + case numberTag: + case stringTag: + return new Ctor(object); + + case regexpTag: + var result = new Ctor(object.source, reFlags.exec(object)); + result.lastIndex = object.lastIndex; + } + return result; + } + function invokePath(object, path, args) { + if (object != null && !isKey(path, object)) { + path = toPath(path); + object = path.length == 1 ? object : baseGet(object, baseSlice(path, 0, -1)); + path = last(path); + } + var func = object == null ? object : object[path]; + return func == null ? undefined : func.apply(object, args); + } + function isArrayLike(value) { + return value != null && isLength(getLength(value)); + } + function isIndex(value, length) { + value = typeof value == "number" || reIsUint.test(value) ? +value : -1; + length = length == null ? MAX_SAFE_INTEGER : length; + return value > -1 && value % 1 == 0 && value < length; + } + function isIterateeCall(value, index, object) { + if (!isObject(object)) { + return false; + } + var type = typeof index; + if (type == "number" ? isArrayLike(object) && isIndex(index, object.length) : type == "string" && index in object) { + var other = object[index]; + return value === value ? value === other : other !== other; + } + return false; + } + function isKey(value, object) { + var type = typeof value; + if (type == "string" && reIsPlainProp.test(value) || type == "number") { + return true; + } + if (isArray(value)) { + return false; + } + var result = !reIsDeepProp.test(value); + return result || object != null && value in toObject(object); + } + function isLaziable(func) { + var funcName = getFuncName(func), other = lodash[funcName]; + if (typeof other != "function" || !(funcName in LazyWrapper.prototype)) { + return false; + } + if (func === other) { + return true; + } + var data = getData(other); + return !!data && func === data[0]; + } + function isLength(value) { + return typeof value == "number" && value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER; + } + function isStrictComparable(value) { + return value === value && !isObject(value); + } + function mergeData(data, source) { + var bitmask = data[1], srcBitmask = source[1], newBitmask = bitmask | srcBitmask, isCommon = newBitmask < ARY_FLAG; + var isCombo = srcBitmask == ARY_FLAG && bitmask == CURRY_FLAG || srcBitmask == ARY_FLAG && bitmask == REARG_FLAG && data[7].length <= source[8] || srcBitmask == (ARY_FLAG | REARG_FLAG) && bitmask == CURRY_FLAG; + if (!(isCommon || isCombo)) { + return data; + } + if (srcBitmask & BIND_FLAG) { + data[2] = source[2]; + newBitmask |= bitmask & BIND_FLAG ? 0 : CURRY_BOUND_FLAG; + } + var value = source[3]; + if (value) { + var partials = data[3]; + data[3] = partials ? composeArgs(partials, value, source[4]) : arrayCopy(value); + data[4] = partials ? replaceHolders(data[3], PLACEHOLDER) : arrayCopy(source[4]); + } + value = source[5]; + if (value) { + partials = data[5]; + data[5] = partials ? composeArgsRight(partials, value, source[6]) : arrayCopy(value); + data[6] = partials ? replaceHolders(data[5], PLACEHOLDER) : arrayCopy(source[6]); + } + value = source[7]; + if (value) { + data[7] = arrayCopy(value); + } + if (srcBitmask & ARY_FLAG) { + data[8] = data[8] == null ? source[8] : nativeMin(data[8], source[8]); + } + if (data[9] == null) { + data[9] = source[9]; + } + data[0] = source[0]; + data[1] = newBitmask; + return data; + } + function mergeDefaults(objectValue, sourceValue) { + return objectValue === undefined ? sourceValue : merge(objectValue, sourceValue, mergeDefaults); + } + function pickByArray(object, props) { + object = toObject(object); + var index = -1, length = props.length, result = {}; + while (++index < length) { + var key = props[index]; + if (key in object) { + result[key] = object[key]; + } + } + return result; + } + function pickByCallback(object, predicate) { + var result = {}; + baseForIn(object, function(value, key, object) { + if (predicate(value, key, object)) { + result[key] = value; + } + }); + return result; + } + function reorder(array, indexes) { + var arrLength = array.length, length = nativeMin(indexes.length, arrLength), oldArray = arrayCopy(array); + while (length--) { + var index = indexes[length]; + array[length] = isIndex(index, arrLength) ? oldArray[index] : undefined; + } + return array; + } + var setData = function() { + var count = 0, lastCalled = 0; + return function(key, value) { + var stamp = now(), remaining = HOT_SPAN - (stamp - lastCalled); + lastCalled = stamp; + if (remaining > 0) { + if (++count >= HOT_COUNT) { + return key; + } + } else { + count = 0; + } + return baseSetData(key, value); + }; + }(); + function shimKeys(object) { + var props = keysIn(object), propsLength = props.length, length = propsLength && object.length; + var allowIndexes = !!length && isLength(length) && (isArray(object) || isArguments(object)); + var index = -1, result = []; + while (++index < propsLength) { + var key = props[index]; + if (allowIndexes && isIndex(key, length) || hasOwnProperty.call(object, key)) { + result.push(key); + } + } + return result; + } + function toIterable(value) { + if (value == null) { + return []; + } + if (!isArrayLike(value)) { + return values(value); + } + return isObject(value) ? value : Object(value); + } + function toObject(value) { + return isObject(value) ? value : Object(value); + } + function toPath(value) { + if (isArray(value)) { + return value; + } + var result = []; + baseToString(value).replace(rePropName, function(match, number, quote, string) { + result.push(quote ? string.replace(reEscapeChar, "$1") : number || match); + }); + return result; + } + function wrapperClone(wrapper) { + return wrapper instanceof LazyWrapper ? wrapper.clone() : new LodashWrapper(wrapper.__wrapped__, wrapper.__chain__, arrayCopy(wrapper.__actions__)); + } + function chunk(array, size, guard) { + if (guard ? isIterateeCall(array, size, guard) : size == null) { + size = 1; + } else { + size = nativeMax(nativeFloor(size) || 1, 1); + } + var index = 0, length = array ? array.length : 0, resIndex = -1, result = Array(nativeCeil(length / size)); + while (index < length) { + result[++resIndex] = baseSlice(array, index, index += size); + } + return result; + } + function compact(array) { + var index = -1, length = array ? array.length : 0, resIndex = -1, result = []; + while (++index < length) { + var value = array[index]; + if (value) { + result[++resIndex] = value; + } + } + return result; + } + var difference = restParam(function(array, values) { + return isObjectLike(array) && isArrayLike(array) ? baseDifference(array, baseFlatten(values, false, true)) : []; + }); + function drop(array, n, guard) { + var length = array ? array.length : 0; + if (!length) { + return []; + } + if (guard ? isIterateeCall(array, n, guard) : n == null) { + n = 1; + } + return baseSlice(array, n < 0 ? 0 : n); + } + function dropRight(array, n, guard) { + var length = array ? array.length : 0; + if (!length) { + return []; + } + if (guard ? isIterateeCall(array, n, guard) : n == null) { + n = 1; + } + n = length - (+n || 0); + return baseSlice(array, 0, n < 0 ? 0 : n); + } + function dropRightWhile(array, predicate, thisArg) { + return array && array.length ? baseWhile(array, getCallback(predicate, thisArg, 3), true, true) : []; + } + function dropWhile(array, predicate, thisArg) { + return array && array.length ? baseWhile(array, getCallback(predicate, thisArg, 3), true) : []; + } + function fill(array, value, start, end) { + var length = array ? array.length : 0; + if (!length) { + return []; + } + if (start && typeof start != "number" && isIterateeCall(array, value, start)) { + start = 0; + end = length; + } + return baseFill(array, value, start, end); + } + var findIndex = createFindIndex(); + var findLastIndex = createFindIndex(true); + function first(array) { + return array ? array[0] : undefined; + } + function flatten(array, isDeep, guard) { + var length = array ? array.length : 0; + if (guard && isIterateeCall(array, isDeep, guard)) { + isDeep = false; + } + return length ? baseFlatten(array, isDeep) : []; + } + function flattenDeep(array) { + var length = array ? array.length : 0; + return length ? baseFlatten(array, true) : []; + } + function indexOf(array, value, fromIndex) { + var length = array ? array.length : 0; + if (!length) { + return -1; + } + if (typeof fromIndex == "number") { + fromIndex = fromIndex < 0 ? nativeMax(length + fromIndex, 0) : fromIndex; + } else if (fromIndex) { + var index = binaryIndex(array, value); + if (index < length && (value === value ? value === array[index] : array[index] !== array[index])) { + return index; + } + return -1; + } + return baseIndexOf(array, value, fromIndex || 0); + } + function initial(array) { + return dropRight(array, 1); + } + var intersection = restParam(function(arrays) { + var othLength = arrays.length, othIndex = othLength, caches = Array(length), indexOf = getIndexOf(), isCommon = indexOf === baseIndexOf, result = []; + while (othIndex--) { + var value = arrays[othIndex] = isArrayLike(value = arrays[othIndex]) ? value : []; + caches[othIndex] = isCommon && value.length >= 120 ? createCache(othIndex && value) : null; + } + var array = arrays[0], index = -1, length = array ? array.length : 0, seen = caches[0]; + outer: while (++index < length) { + value = array[index]; + if ((seen ? cacheIndexOf(seen, value) : indexOf(result, value, 0)) < 0) { + var othIndex = othLength; + while (--othIndex) { + var cache = caches[othIndex]; + if ((cache ? cacheIndexOf(cache, value) : indexOf(arrays[othIndex], value, 0)) < 0) { + continue outer; + } + } + if (seen) { + seen.push(value); + } + result.push(value); + } + } + return result; + }); + function last(array) { + var length = array ? array.length : 0; + return length ? array[length - 1] : undefined; + } + function lastIndexOf(array, value, fromIndex) { + var length = array ? array.length : 0; + if (!length) { + return -1; + } + var index = length; + if (typeof fromIndex == "number") { + index = (fromIndex < 0 ? nativeMax(length + fromIndex, 0) : nativeMin(fromIndex || 0, length - 1)) + 1; + } else if (fromIndex) { + index = binaryIndex(array, value, true) - 1; + var other = array[index]; + if (value === value ? value === other : other !== other) { + return index; + } + return -1; + } + if (value !== value) { + return indexOfNaN(array, index, true); + } + while (index--) { + if (array[index] === value) { + return index; + } + } + return -1; + } + function pull() { + var args = arguments, array = args[0]; + if (!(array && array.length)) { + return array; + } + var index = 0, indexOf = getIndexOf(), length = args.length; + while (++index < length) { + var fromIndex = 0, value = args[index]; + while ((fromIndex = indexOf(array, value, fromIndex)) > -1) { + splice.call(array, fromIndex, 1); + } + } + return array; + } + var pullAt = restParam(function(array, indexes) { + indexes = baseFlatten(indexes); + var result = baseAt(array, indexes); + basePullAt(array, indexes.sort(baseCompareAscending)); + return result; + }); + function remove(array, predicate, thisArg) { + var result = []; + if (!(array && array.length)) { + return result; + } + var index = -1, indexes = [], length = array.length; + predicate = getCallback(predicate, thisArg, 3); + while (++index < length) { + var value = array[index]; + if (predicate(value, index, array)) { + result.push(value); + indexes.push(index); + } + } + basePullAt(array, indexes); + return result; + } + function rest(array) { + return drop(array, 1); + } + function slice(array, start, end) { + var length = array ? array.length : 0; + if (!length) { + return []; + } + if (end && typeof end != "number" && isIterateeCall(array, start, end)) { + start = 0; + end = length; + } + return baseSlice(array, start, end); + } + var sortedIndex = createSortedIndex(); + var sortedLastIndex = createSortedIndex(true); + function take(array, n, guard) { + var length = array ? array.length : 0; + if (!length) { + return []; + } + if (guard ? isIterateeCall(array, n, guard) : n == null) { + n = 1; + } + return baseSlice(array, 0, n < 0 ? 0 : n); + } + function takeRight(array, n, guard) { + var length = array ? array.length : 0; + if (!length) { + return []; + } + if (guard ? isIterateeCall(array, n, guard) : n == null) { + n = 1; + } + n = length - (+n || 0); + return baseSlice(array, n < 0 ? 0 : n); + } + function takeRightWhile(array, predicate, thisArg) { + return array && array.length ? baseWhile(array, getCallback(predicate, thisArg, 3), false, true) : []; + } + function takeWhile(array, predicate, thisArg) { + return array && array.length ? baseWhile(array, getCallback(predicate, thisArg, 3)) : []; + } + var union = restParam(function(arrays) { + return baseUniq(baseFlatten(arrays, false, true)); + }); + function uniq(array, isSorted, iteratee, thisArg) { + var length = array ? array.length : 0; + if (!length) { + return []; + } + if (isSorted != null && typeof isSorted != "boolean") { + thisArg = iteratee; + iteratee = isIterateeCall(array, isSorted, thisArg) ? undefined : isSorted; + isSorted = false; + } + var callback = getCallback(); + if (!(iteratee == null && callback === baseCallback)) { + iteratee = callback(iteratee, thisArg, 3); + } + return isSorted && getIndexOf() === baseIndexOf ? sortedUniq(array, iteratee) : baseUniq(array, iteratee); + } + function unzip(array) { + if (!(array && array.length)) { + return []; + } + var index = -1, length = 0; + array = arrayFilter(array, function(group) { + if (isArrayLike(group)) { + length = nativeMax(group.length, length); + return true; + } + }); + var result = Array(length); + while (++index < length) { + result[index] = arrayMap(array, baseProperty(index)); + } + return result; + } + function unzipWith(array, iteratee, thisArg) { + var length = array ? array.length : 0; + if (!length) { + return []; + } + var result = unzip(array); + if (iteratee == null) { + return result; + } + iteratee = bindCallback(iteratee, thisArg, 4); + return arrayMap(result, function(group) { + return arrayReduce(group, iteratee, undefined, true); + }); + } + var without = restParam(function(array, values) { + return isArrayLike(array) ? baseDifference(array, values) : []; + }); + function xor() { + var index = -1, length = arguments.length; + while (++index < length) { + var array = arguments[index]; + if (isArrayLike(array)) { + var result = result ? arrayPush(baseDifference(result, array), baseDifference(array, result)) : array; + } + } + return result ? baseUniq(result) : []; + } + var zip = restParam(unzip); + function zipObject(props, values) { + var index = -1, length = props ? props.length : 0, result = {}; + if (length && !values && !isArray(props[0])) { + values = []; + } + while (++index < length) { + var key = props[index]; + if (values) { + result[key] = values[index]; + } else if (key) { + result[key[0]] = key[1]; + } + } + return result; + } + var zipWith = restParam(function(arrays) { + var length = arrays.length, iteratee = length > 2 ? arrays[length - 2] : undefined, thisArg = length > 1 ? arrays[length - 1] : undefined; + if (length > 2 && typeof iteratee == "function") { + length -= 2; + } else { + iteratee = length > 1 && typeof thisArg == "function" ? (--length, thisArg) : undefined; + thisArg = undefined; + } + arrays.length = length; + return unzipWith(arrays, iteratee, thisArg); + }); + function chain(value) { + var result = lodash(value); + result.__chain__ = true; + return result; + } + function tap(value, interceptor, thisArg) { + interceptor.call(thisArg, value); + return value; + } + function thru(value, interceptor, thisArg) { + return interceptor.call(thisArg, value); + } + function wrapperChain() { + return chain(this); + } + function wrapperCommit() { + return new LodashWrapper(this.value(), this.__chain__); + } + var wrapperConcat = restParam(function(values) { + values = baseFlatten(values); + return this.thru(function(array) { + return arrayConcat(isArray(array) ? array : [ toObject(array) ], values); + }); + }); + function wrapperPlant(value) { + var result, parent = this; + while (parent instanceof baseLodash) { + var clone = wrapperClone(parent); + if (result) { + previous.__wrapped__ = clone; + } else { + result = clone; + } + var previous = clone; + parent = parent.__wrapped__; + } + previous.__wrapped__ = value; + return result; + } + function wrapperReverse() { + var value = this.__wrapped__; + var interceptor = function(value) { + return value.reverse(); + }; + if (value instanceof LazyWrapper) { + var wrapped = value; + if (this.__actions__.length) { + wrapped = new LazyWrapper(this); + } + wrapped = wrapped.reverse(); + wrapped.__actions__.push({ + func: thru, + args: [ interceptor ], + thisArg: undefined + }); + return new LodashWrapper(wrapped, this.__chain__); + } + return this.thru(interceptor); + } + function wrapperToString() { + return this.value() + ""; + } + function wrapperValue() { + return baseWrapperValue(this.__wrapped__, this.__actions__); + } + var at = restParam(function(collection, props) { + return baseAt(collection, baseFlatten(props)); + }); + var countBy = createAggregator(function(result, value, key) { + hasOwnProperty.call(result, key) ? ++result[key] : result[key] = 1; + }); + function every(collection, predicate, thisArg) { + var func = isArray(collection) ? arrayEvery : baseEvery; + if (thisArg && isIterateeCall(collection, predicate, thisArg)) { + predicate = undefined; + } + if (typeof predicate != "function" || thisArg !== undefined) { + predicate = getCallback(predicate, thisArg, 3); + } + return func(collection, predicate); + } + function filter(collection, predicate, thisArg) { + var func = isArray(collection) ? arrayFilter : baseFilter; + predicate = getCallback(predicate, thisArg, 3); + return func(collection, predicate); + } + var find = createFind(baseEach); + var findLast = createFind(baseEachRight, true); + function findWhere(collection, source) { + return find(collection, baseMatches(source)); + } + var forEach = createForEach(arrayEach, baseEach); + var forEachRight = createForEach(arrayEachRight, baseEachRight); + var groupBy = createAggregator(function(result, value, key) { + if (hasOwnProperty.call(result, key)) { + result[key].push(value); + } else { + result[key] = [ value ]; + } + }); + function includes(collection, target, fromIndex, guard) { + var length = collection ? getLength(collection) : 0; + if (!isLength(length)) { + collection = values(collection); + length = collection.length; + } + if (typeof fromIndex != "number" || guard && isIterateeCall(target, fromIndex, guard)) { + fromIndex = 0; + } else { + fromIndex = fromIndex < 0 ? nativeMax(length + fromIndex, 0) : fromIndex || 0; + } + return typeof collection == "string" || !isArray(collection) && isString(collection) ? fromIndex <= length && collection.indexOf(target, fromIndex) > -1 : !!length && getIndexOf(collection, target, fromIndex) > -1; + } + var indexBy = createAggregator(function(result, value, key) { + result[key] = value; + }); + var invoke = restParam(function(collection, path, args) { + var index = -1, isFunc = typeof path == "function", isProp = isKey(path), result = isArrayLike(collection) ? Array(collection.length) : []; + baseEach(collection, function(value) { + var func = isFunc ? path : isProp && value != null ? value[path] : undefined; + result[++index] = func ? func.apply(value, args) : invokePath(value, path, args); + }); + return result; + }); + function map(collection, iteratee, thisArg) { + var func = isArray(collection) ? arrayMap : baseMap; + iteratee = getCallback(iteratee, thisArg, 3); + return func(collection, iteratee); + } + var partition = createAggregator(function(result, value, key) { + result[key ? 0 : 1].push(value); + }, function() { + return [ [], [] ]; + }); + function pluck(collection, path) { + return map(collection, property(path)); + } + var reduce = createReduce(arrayReduce, baseEach); + var reduceRight = createReduce(arrayReduceRight, baseEachRight); + function reject(collection, predicate, thisArg) { + var func = isArray(collection) ? arrayFilter : baseFilter; + predicate = getCallback(predicate, thisArg, 3); + return func(collection, function(value, index, collection) { + return !predicate(value, index, collection); + }); + } + function sample(collection, n, guard) { + if (guard ? isIterateeCall(collection, n, guard) : n == null) { + collection = toIterable(collection); + var length = collection.length; + return length > 0 ? collection[baseRandom(0, length - 1)] : undefined; + } + var index = -1, result = toArray(collection), length = result.length, lastIndex = length - 1; + n = nativeMin(n < 0 ? 0 : +n || 0, length); + while (++index < n) { + var rand = baseRandom(index, lastIndex), value = result[rand]; + result[rand] = result[index]; + result[index] = value; + } + result.length = n; + return result; + } + function shuffle(collection) { + return sample(collection, POSITIVE_INFINITY); + } + function size(collection) { + var length = collection ? getLength(collection) : 0; + return isLength(length) ? length : keys(collection).length; + } + function some(collection, predicate, thisArg) { + var func = isArray(collection) ? arraySome : baseSome; + if (thisArg && isIterateeCall(collection, predicate, thisArg)) { + predicate = undefined; + } + if (typeof predicate != "function" || thisArg !== undefined) { + predicate = getCallback(predicate, thisArg, 3); + } + return func(collection, predicate); + } + function sortBy(collection, iteratee, thisArg) { + if (collection == null) { + return []; + } + if (thisArg && isIterateeCall(collection, iteratee, thisArg)) { + iteratee = undefined; + } + var index = -1; + iteratee = getCallback(iteratee, thisArg, 3); + var result = baseMap(collection, function(value, key, collection) { + return { + criteria: iteratee(value, key, collection), + index: ++index, + value: value + }; + }); + return baseSortBy(result, compareAscending); + } + var sortByAll = restParam(function(collection, iteratees) { + if (collection == null) { + return []; + } + var guard = iteratees[2]; + if (guard && isIterateeCall(iteratees[0], iteratees[1], guard)) { + iteratees.length = 1; + } + return baseSortByOrder(collection, baseFlatten(iteratees), []); + }); + function sortByOrder(collection, iteratees, orders, guard) { + if (collection == null) { + return []; + } + if (guard && isIterateeCall(iteratees, orders, guard)) { + orders = undefined; + } + if (!isArray(iteratees)) { + iteratees = iteratees == null ? [] : [ iteratees ]; + } + if (!isArray(orders)) { + orders = orders == null ? [] : [ orders ]; + } + return baseSortByOrder(collection, iteratees, orders); + } + function where(collection, source) { + return filter(collection, baseMatches(source)); + } + var now = nativeNow || function() { + return new Date().getTime(); + }; + function after(n, func) { + if (typeof func != "function") { + if (typeof n == "function") { + var temp = n; + n = func; + func = temp; + } else { + throw new TypeError(FUNC_ERROR_TEXT); + } + } + n = nativeIsFinite(n = +n) ? n : 0; + return function() { + if (--n < 1) { + return func.apply(this, arguments); + } + }; + } + function ary(func, n, guard) { + if (guard && isIterateeCall(func, n, guard)) { + n = undefined; + } + n = func && n == null ? func.length : nativeMax(+n || 0, 0); + return createWrapper(func, ARY_FLAG, undefined, undefined, undefined, undefined, n); + } + function before(n, func) { + var result; + if (typeof func != "function") { + if (typeof n == "function") { + var temp = n; + n = func; + func = temp; + } else { + throw new TypeError(FUNC_ERROR_TEXT); + } + } + return function() { + if (--n > 0) { + result = func.apply(this, arguments); + } + if (n <= 1) { + func = undefined; + } + return result; + }; + } + var bind = restParam(function(func, thisArg, partials) { + var bitmask = BIND_FLAG; + if (partials.length) { + var holders = replaceHolders(partials, bind.placeholder); + bitmask |= PARTIAL_FLAG; + } + return createWrapper(func, bitmask, thisArg, partials, holders); + }); + var bindAll = restParam(function(object, methodNames) { + methodNames = methodNames.length ? baseFlatten(methodNames) : functions(object); + var index = -1, length = methodNames.length; + while (++index < length) { + var key = methodNames[index]; + object[key] = createWrapper(object[key], BIND_FLAG, object); + } + return object; + }); + var bindKey = restParam(function(object, key, partials) { + var bitmask = BIND_FLAG | BIND_KEY_FLAG; + if (partials.length) { + var holders = replaceHolders(partials, bindKey.placeholder); + bitmask |= PARTIAL_FLAG; + } + return createWrapper(key, bitmask, object, partials, holders); + }); + var curry = createCurry(CURRY_FLAG); + var curryRight = createCurry(CURRY_RIGHT_FLAG); + function debounce(func, wait, options) { + var args, maxTimeoutId, result, stamp, thisArg, timeoutId, trailingCall, lastCalled = 0, maxWait = false, trailing = true; + if (typeof func != "function") { + throw new TypeError(FUNC_ERROR_TEXT); + } + wait = wait < 0 ? 0 : +wait || 0; + if (options === true) { + var leading = true; + trailing = false; + } else if (isObject(options)) { + leading = !!options.leading; + maxWait = "maxWait" in options && nativeMax(+options.maxWait || 0, wait); + trailing = "trailing" in options ? !!options.trailing : trailing; + } + function cancel() { + if (timeoutId) { + clearTimeout(timeoutId); + } + if (maxTimeoutId) { + clearTimeout(maxTimeoutId); + } + lastCalled = 0; + maxTimeoutId = timeoutId = trailingCall = undefined; + } + function complete(isCalled, id) { + if (id) { + clearTimeout(id); + } + maxTimeoutId = timeoutId = trailingCall = undefined; + if (isCalled) { + lastCalled = now(); + result = func.apply(thisArg, args); + if (!timeoutId && !maxTimeoutId) { + args = thisArg = undefined; + } + } + } + function delayed() { + var remaining = wait - (now() - stamp); + if (remaining <= 0 || remaining > wait) { + complete(trailingCall, maxTimeoutId); + } else { + timeoutId = setTimeout(delayed, remaining); + } + } + function maxDelayed() { + complete(trailing, timeoutId); + } + function debounced() { + args = arguments; + stamp = now(); + thisArg = this; + trailingCall = trailing && (timeoutId || !leading); + if (maxWait === false) { + var leadingCall = leading && !timeoutId; + } else { + if (!maxTimeoutId && !leading) { + lastCalled = stamp; + } + var remaining = maxWait - (stamp - lastCalled), isCalled = remaining <= 0 || remaining > maxWait; + if (isCalled) { + if (maxTimeoutId) { + maxTimeoutId = clearTimeout(maxTimeoutId); + } + lastCalled = stamp; + result = func.apply(thisArg, args); + } else if (!maxTimeoutId) { + maxTimeoutId = setTimeout(maxDelayed, remaining); + } + } + if (isCalled && timeoutId) { + timeoutId = clearTimeout(timeoutId); + } else if (!timeoutId && wait !== maxWait) { + timeoutId = setTimeout(delayed, wait); + } + if (leadingCall) { + isCalled = true; + result = func.apply(thisArg, args); + } + if (isCalled && !timeoutId && !maxTimeoutId) { + args = thisArg = undefined; + } + return result; + } + debounced.cancel = cancel; + return debounced; + } + var defer = restParam(function(func, args) { + return baseDelay(func, 1, args); + }); + var delay = restParam(function(func, wait, args) { + return baseDelay(func, wait, args); + }); + var flow = createFlow(); + var flowRight = createFlow(true); + function memoize(func, resolver) { + if (typeof func != "function" || resolver && typeof resolver != "function") { + throw new TypeError(FUNC_ERROR_TEXT); + } + var memoized = function() { + var args = arguments, key = resolver ? resolver.apply(this, args) : args[0], cache = memoized.cache; + if (cache.has(key)) { + return cache.get(key); + } + var result = func.apply(this, args); + memoized.cache = cache.set(key, result); + return result; + }; + memoized.cache = new memoize.Cache(); + return memoized; + } + var modArgs = restParam(function(func, transforms) { + transforms = baseFlatten(transforms); + if (typeof func != "function" || !arrayEvery(transforms, baseIsFunction)) { + throw new TypeError(FUNC_ERROR_TEXT); + } + var length = transforms.length; + return restParam(function(args) { + var index = nativeMin(args.length, length); + while (index--) { + args[index] = transforms[index](args[index]); + } + return func.apply(this, args); + }); + }); + function negate(predicate) { + if (typeof predicate != "function") { + throw new TypeError(FUNC_ERROR_TEXT); + } + return function() { + return !predicate.apply(this, arguments); + }; + } + function once(func) { + return before(2, func); + } + var partial = createPartial(PARTIAL_FLAG); + var partialRight = createPartial(PARTIAL_RIGHT_FLAG); + var rearg = restParam(function(func, indexes) { + return createWrapper(func, REARG_FLAG, undefined, undefined, undefined, baseFlatten(indexes)); + }); + function restParam(func, start) { + if (typeof func != "function") { + throw new TypeError(FUNC_ERROR_TEXT); + } + start = nativeMax(start === undefined ? func.length - 1 : +start || 0, 0); + return function() { + var args = arguments, index = -1, length = nativeMax(args.length - start, 0), rest = Array(length); + while (++index < length) { + rest[index] = args[start + index]; + } + switch (start) { + case 0: + return func.call(this, rest); + + case 1: + return func.call(this, args[0], rest); + + case 2: + return func.call(this, args[0], args[1], rest); + } + var otherArgs = Array(start + 1); + index = -1; + while (++index < start) { + otherArgs[index] = args[index]; + } + otherArgs[start] = rest; + return func.apply(this, otherArgs); + }; + } + function spread(func) { + if (typeof func != "function") { + throw new TypeError(FUNC_ERROR_TEXT); + } + return function(array) { + return func.apply(this, array); + }; + } + function throttle(func, wait, options) { + var leading = true, trailing = true; + if (typeof func != "function") { + throw new TypeError(FUNC_ERROR_TEXT); + } + if (options === false) { + leading = false; + } else if (isObject(options)) { + leading = "leading" in options ? !!options.leading : leading; + trailing = "trailing" in options ? !!options.trailing : trailing; + } + return debounce(func, wait, { + leading: leading, + maxWait: +wait, + trailing: trailing + }); + } + function wrap(value, wrapper) { + wrapper = wrapper == null ? identity : wrapper; + return createWrapper(wrapper, PARTIAL_FLAG, undefined, [ value ], []); + } + function clone(value, isDeep, customizer, thisArg) { + if (isDeep && typeof isDeep != "boolean" && isIterateeCall(value, isDeep, customizer)) { + isDeep = false; + } else if (typeof isDeep == "function") { + thisArg = customizer; + customizer = isDeep; + isDeep = false; + } + return typeof customizer == "function" ? baseClone(value, isDeep, bindCallback(customizer, thisArg, 3)) : baseClone(value, isDeep); + } + function cloneDeep(value, customizer, thisArg) { + return typeof customizer == "function" ? baseClone(value, true, bindCallback(customizer, thisArg, 3)) : baseClone(value, true); + } + function gt(value, other) { + return value > other; + } + function gte(value, other) { + return value >= other; + } + function isArguments(value) { + return isObjectLike(value) && isArrayLike(value) && hasOwnProperty.call(value, "callee") && !propertyIsEnumerable.call(value, "callee"); + } + var isArray = nativeIsArray || function(value) { + return isObjectLike(value) && isLength(value.length) && objToString.call(value) == arrayTag; + }; + function isBoolean(value) { + return value === true || value === false || isObjectLike(value) && objToString.call(value) == boolTag; + } + function isDate(value) { + return isObjectLike(value) && objToString.call(value) == dateTag; + } + function isElement(value) { + return !!value && value.nodeType === 1 && isObjectLike(value) && !isPlainObject(value); + } + function isEmpty(value) { + if (value == null) { + return true; + } + if (isArrayLike(value) && (isArray(value) || isString(value) || isArguments(value) || isObjectLike(value) && isFunction(value.splice))) { + return !value.length; + } + return !keys(value).length; + } + function isEqual(value, other, customizer, thisArg) { + customizer = typeof customizer == "function" ? bindCallback(customizer, thisArg, 3) : undefined; + var result = customizer ? customizer(value, other) : undefined; + return result === undefined ? baseIsEqual(value, other, customizer) : !!result; + } + function isError(value) { + return isObjectLike(value) && typeof value.message == "string" && objToString.call(value) == errorTag; + } + function isFinite(value) { + return typeof value == "number" && nativeIsFinite(value); + } + function isFunction(value) { + return isObject(value) && objToString.call(value) == funcTag; + } + function isObject(value) { + var type = typeof value; + return !!value && (type == "object" || type == "function"); + } + function isMatch(object, source, customizer, thisArg) { + customizer = typeof customizer == "function" ? bindCallback(customizer, thisArg, 3) : undefined; + return baseIsMatch(object, getMatchData(source), customizer); + } + function isNaN(value) { + return isNumber(value) && value != +value; + } + function isNative(value) { + if (value == null) { + return false; + } + if (isFunction(value)) { + return reIsNative.test(fnToString.call(value)); + } + return isObjectLike(value) && reIsHostCtor.test(value); + } + function isNull(value) { + return value === null; + } + function isNumber(value) { + return typeof value == "number" || isObjectLike(value) && objToString.call(value) == numberTag; + } + function isPlainObject(value) { + var Ctor; + if (!(isObjectLike(value) && objToString.call(value) == objectTag && !isArguments(value)) || !hasOwnProperty.call(value, "constructor") && (Ctor = value.constructor, + typeof Ctor == "function" && !(Ctor instanceof Ctor))) { + return false; + } + var result; + baseForIn(value, function(subValue, key) { + result = key; + }); + return result === undefined || hasOwnProperty.call(value, result); + } + function isRegExp(value) { + return isObject(value) && objToString.call(value) == regexpTag; + } + function isString(value) { + return typeof value == "string" || isObjectLike(value) && objToString.call(value) == stringTag; + } + function isTypedArray(value) { + return isObjectLike(value) && isLength(value.length) && !!typedArrayTags[objToString.call(value)]; + } + function isUndefined(value) { + return value === undefined; + } + function lt(value, other) { + return value < other; + } + function lte(value, other) { + return value <= other; + } + function toArray(value) { + var length = value ? getLength(value) : 0; + if (!isLength(length)) { + return values(value); + } + if (!length) { + return []; + } + return arrayCopy(value); + } + function toPlainObject(value) { + return baseCopy(value, keysIn(value)); + } + var merge = createAssigner(baseMerge); + var assign = createAssigner(function(object, source, customizer) { + return customizer ? assignWith(object, source, customizer) : baseAssign(object, source); + }); + function create(prototype, properties, guard) { + var result = baseCreate(prototype); + if (guard && isIterateeCall(prototype, properties, guard)) { + properties = undefined; + } + return properties ? baseAssign(result, properties) : result; + } + var defaults = createDefaults(assign, assignDefaults); + var defaultsDeep = createDefaults(merge, mergeDefaults); + var findKey = createFindKey(baseForOwn); + var findLastKey = createFindKey(baseForOwnRight); + var forIn = createForIn(baseFor); + var forInRight = createForIn(baseForRight); + var forOwn = createForOwn(baseForOwn); + var forOwnRight = createForOwn(baseForOwnRight); + function functions(object) { + return baseFunctions(object, keysIn(object)); + } + function get(object, path, defaultValue) { + var result = object == null ? undefined : baseGet(object, toPath(path), path + ""); + return result === undefined ? defaultValue : result; + } + function has(object, path) { + if (object == null) { + return false; + } + var result = hasOwnProperty.call(object, path); + if (!result && !isKey(path)) { + path = toPath(path); + object = path.length == 1 ? object : baseGet(object, baseSlice(path, 0, -1)); + if (object == null) { + return false; + } + path = last(path); + result = hasOwnProperty.call(object, path); + } + return result || isLength(object.length) && isIndex(path, object.length) && (isArray(object) || isArguments(object)); + } + function invert(object, multiValue, guard) { + if (guard && isIterateeCall(object, multiValue, guard)) { + multiValue = undefined; + } + var index = -1, props = keys(object), length = props.length, result = {}; + while (++index < length) { + var key = props[index], value = object[key]; + if (multiValue) { + if (hasOwnProperty.call(result, value)) { + result[value].push(key); + } else { + result[value] = [ key ]; + } + } else { + result[value] = key; + } + } + return result; + } + var keys = !nativeKeys ? shimKeys : function(object) { + var Ctor = object == null ? undefined : object.constructor; + if (typeof Ctor == "function" && Ctor.prototype === object || typeof object != "function" && isArrayLike(object)) { + return shimKeys(object); + } + return isObject(object) ? nativeKeys(object) : []; + }; + function keysIn(object) { + if (object == null) { + return []; + } + if (!isObject(object)) { + object = Object(object); + } + var length = object.length; + length = length && isLength(length) && (isArray(object) || isArguments(object)) && length || 0; + var Ctor = object.constructor, index = -1, isProto = typeof Ctor == "function" && Ctor.prototype === object, result = Array(length), skipIndexes = length > 0; + while (++index < length) { + result[index] = index + ""; + } + for (var key in object) { + if (!(skipIndexes && isIndex(key, length)) && !(key == "constructor" && (isProto || !hasOwnProperty.call(object, key)))) { + result.push(key); + } + } + return result; + } + var mapKeys = createObjectMapper(true); + var mapValues = createObjectMapper(); + var omit = restParam(function(object, props) { + if (object == null) { + return {}; + } + if (typeof props[0] != "function") { + var props = arrayMap(baseFlatten(props), String); + return pickByArray(object, baseDifference(keysIn(object), props)); + } + var predicate = bindCallback(props[0], props[1], 3); + return pickByCallback(object, function(value, key, object) { + return !predicate(value, key, object); + }); + }); + function pairs(object) { + object = toObject(object); + var index = -1, props = keys(object), length = props.length, result = Array(length); + while (++index < length) { + var key = props[index]; + result[index] = [ key, object[key] ]; + } + return result; + } + var pick = restParam(function(object, props) { + if (object == null) { + return {}; + } + return typeof props[0] == "function" ? pickByCallback(object, bindCallback(props[0], props[1], 3)) : pickByArray(object, baseFlatten(props)); + }); + function result(object, path, defaultValue) { + var result = object == null ? undefined : object[path]; + if (result === undefined) { + if (object != null && !isKey(path, object)) { + path = toPath(path); + object = path.length == 1 ? object : baseGet(object, baseSlice(path, 0, -1)); + result = object == null ? undefined : object[last(path)]; + } + result = result === undefined ? defaultValue : result; + } + return isFunction(result) ? result.call(object) : result; + } + function set(object, path, value) { + if (object == null) { + return object; + } + var pathKey = path + ""; + path = object[pathKey] != null || isKey(path, object) ? [ pathKey ] : toPath(path); + var index = -1, length = path.length, lastIndex = length - 1, nested = object; + while (nested != null && ++index < length) { + var key = path[index]; + if (isObject(nested)) { + if (index == lastIndex) { + nested[key] = value; + } else if (nested[key] == null) { + nested[key] = isIndex(path[index + 1]) ? [] : {}; + } + } + nested = nested[key]; + } + return object; + } + function transform(object, iteratee, accumulator, thisArg) { + var isArr = isArray(object) || isTypedArray(object); + iteratee = getCallback(iteratee, thisArg, 4); + if (accumulator == null) { + if (isArr || isObject(object)) { + var Ctor = object.constructor; + if (isArr) { + accumulator = isArray(object) ? new Ctor() : []; + } else { + accumulator = baseCreate(isFunction(Ctor) ? Ctor.prototype : undefined); + } + } else { + accumulator = {}; + } + } + (isArr ? arrayEach : baseForOwn)(object, function(value, index, object) { + return iteratee(accumulator, value, index, object); + }); + return accumulator; + } + function values(object) { + return baseValues(object, keys(object)); + } + function valuesIn(object) { + return baseValues(object, keysIn(object)); + } + function inRange(value, start, end) { + start = +start || 0; + if (end === undefined) { + end = start; + start = 0; + } else { + end = +end || 0; + } + return value >= nativeMin(start, end) && value < nativeMax(start, end); + } + function random(min, max, floating) { + if (floating && isIterateeCall(min, max, floating)) { + max = floating = undefined; + } + var noMin = min == null, noMax = max == null; + if (floating == null) { + if (noMax && typeof min == "boolean") { + floating = min; + min = 1; + } else if (typeof max == "boolean") { + floating = max; + noMax = true; + } + } + if (noMin && noMax) { + max = 1; + noMax = false; + } + min = +min || 0; + if (noMax) { + max = min; + min = 0; + } else { + max = +max || 0; + } + if (floating || min % 1 || max % 1) { + var rand = nativeRandom(); + return nativeMin(min + rand * (max - min + parseFloat("1e-" + ((rand + "").length - 1))), max); + } + return baseRandom(min, max); + } + var camelCase = createCompounder(function(result, word, index) { + word = word.toLowerCase(); + return result + (index ? word.charAt(0).toUpperCase() + word.slice(1) : word); + }); + function capitalize(string) { + string = baseToString(string); + return string && string.charAt(0).toUpperCase() + string.slice(1); + } + function deburr(string) { + string = baseToString(string); + return string && string.replace(reLatin1, deburrLetter).replace(reComboMark, ""); + } + function endsWith(string, target, position) { + string = baseToString(string); + target = target + ""; + var length = string.length; + position = position === undefined ? length : nativeMin(position < 0 ? 0 : +position || 0, length); + position -= target.length; + return position >= 0 && string.indexOf(target, position) == position; + } + function escape(string) { + string = baseToString(string); + return string && reHasUnescapedHtml.test(string) ? string.replace(reUnescapedHtml, escapeHtmlChar) : string; + } + function escapeRegExp(string) { + string = baseToString(string); + return string && reHasRegExpChars.test(string) ? string.replace(reRegExpChars, escapeRegExpChar) : string || "(?:)"; + } + var kebabCase = createCompounder(function(result, word, index) { + return result + (index ? "-" : "") + word.toLowerCase(); + }); + function pad(string, length, chars) { + string = baseToString(string); + length = +length; + var strLength = string.length; + if (strLength >= length || !nativeIsFinite(length)) { + return string; + } + var mid = (length - strLength) / 2, leftLength = nativeFloor(mid), rightLength = nativeCeil(mid); + chars = createPadding("", rightLength, chars); + return chars.slice(0, leftLength) + string + chars; + } + var padLeft = createPadDir(); + var padRight = createPadDir(true); + function parseInt(string, radix, guard) { + if (guard ? isIterateeCall(string, radix, guard) : radix == null) { + radix = 0; + } else if (radix) { + radix = +radix; + } + string = trim(string); + return nativeParseInt(string, radix || (reHasHexPrefix.test(string) ? 16 : 10)); + } + function repeat(string, n) { + var result = ""; + string = baseToString(string); + n = +n; + if (n < 1 || !string || !nativeIsFinite(n)) { + return result; + } + do { + if (n % 2) { + result += string; + } + n = nativeFloor(n / 2); + string += string; + } while (n); + return result; + } + var snakeCase = createCompounder(function(result, word, index) { + return result + (index ? "_" : "") + word.toLowerCase(); + }); + var startCase = createCompounder(function(result, word, index) { + return result + (index ? " " : "") + (word.charAt(0).toUpperCase() + word.slice(1)); + }); + function startsWith(string, target, position) { + string = baseToString(string); + position = position == null ? 0 : nativeMin(position < 0 ? 0 : +position || 0, string.length); + return string.lastIndexOf(target, position) == position; + } + function template(string, options, otherOptions) { + var settings = lodash.templateSettings; + if (otherOptions && isIterateeCall(string, options, otherOptions)) { + options = otherOptions = undefined; + } + string = baseToString(string); + options = assignWith(baseAssign({}, otherOptions || options), settings, assignOwnDefaults); + var imports = assignWith(baseAssign({}, options.imports), settings.imports, assignOwnDefaults), importsKeys = keys(imports), importsValues = baseValues(imports, importsKeys); + var isEscaping, isEvaluating, index = 0, interpolate = options.interpolate || reNoMatch, source = "__p += '"; + var reDelimiters = RegExp((options.escape || reNoMatch).source + "|" + interpolate.source + "|" + (interpolate === reInterpolate ? reEsTemplate : reNoMatch).source + "|" + (options.evaluate || reNoMatch).source + "|$", "g"); + var sourceURL = "//# sourceURL=" + ("sourceURL" in options ? options.sourceURL : "lodash.templateSources[" + ++templateCounter + "]") + "\n"; + string.replace(reDelimiters, function(match, escapeValue, interpolateValue, esTemplateValue, evaluateValue, offset) { + interpolateValue || (interpolateValue = esTemplateValue); + source += string.slice(index, offset).replace(reUnescapedString, escapeStringChar); + if (escapeValue) { + isEscaping = true; + source += "' +\n__e(" + escapeValue + ") +\n'"; + } + if (evaluateValue) { + isEvaluating = true; + source += "';\n" + evaluateValue + ";\n__p += '"; + } + if (interpolateValue) { + source += "' +\n((__t = (" + interpolateValue + ")) == null ? '' : __t) +\n'"; + } + index = offset + match.length; + return match; + }); + source += "';\n"; + var variable = options.variable; + if (!variable) { + source = "with (obj) {\n" + source + "\n}\n"; + } + source = (isEvaluating ? source.replace(reEmptyStringLeading, "") : source).replace(reEmptyStringMiddle, "$1").replace(reEmptyStringTrailing, "$1;"); + source = "function(" + (variable || "obj") + ") {\n" + (variable ? "" : "obj || (obj = {});\n") + "var __t, __p = ''" + (isEscaping ? ", __e = _.escape" : "") + (isEvaluating ? ", __j = Array.prototype.join;\n" + "function print() { __p += __j.call(arguments, '') }\n" : ";\n") + source + "return __p\n}"; + var result = attempt(function() { + return Function(importsKeys, sourceURL + "return " + source).apply(undefined, importsValues); + }); + result.source = source; + if (isError(result)) { + throw result; + } + return result; + } + function trim(string, chars, guard) { + var value = string; + string = baseToString(string); + if (!string) { + return string; + } + if (guard ? isIterateeCall(value, chars, guard) : chars == null) { + return string.slice(trimmedLeftIndex(string), trimmedRightIndex(string) + 1); + } + chars = chars + ""; + return string.slice(charsLeftIndex(string, chars), charsRightIndex(string, chars) + 1); + } + function trimLeft(string, chars, guard) { + var value = string; + string = baseToString(string); + if (!string) { + return string; + } + if (guard ? isIterateeCall(value, chars, guard) : chars == null) { + return string.slice(trimmedLeftIndex(string)); + } + return string.slice(charsLeftIndex(string, chars + "")); + } + function trimRight(string, chars, guard) { + var value = string; + string = baseToString(string); + if (!string) { + return string; + } + if (guard ? isIterateeCall(value, chars, guard) : chars == null) { + return string.slice(0, trimmedRightIndex(string) + 1); + } + return string.slice(0, charsRightIndex(string, chars + "") + 1); + } + function trunc(string, options, guard) { + if (guard && isIterateeCall(string, options, guard)) { + options = undefined; + } + var length = DEFAULT_TRUNC_LENGTH, omission = DEFAULT_TRUNC_OMISSION; + if (options != null) { + if (isObject(options)) { + var separator = "separator" in options ? options.separator : separator; + length = "length" in options ? +options.length || 0 : length; + omission = "omission" in options ? baseToString(options.omission) : omission; + } else { + length = +options || 0; + } + } + string = baseToString(string); + if (length >= string.length) { + return string; + } + var end = length - omission.length; + if (end < 1) { + return omission; + } + var result = string.slice(0, end); + if (separator == null) { + return result + omission; + } + if (isRegExp(separator)) { + if (string.slice(end).search(separator)) { + var match, newEnd, substring = string.slice(0, end); + if (!separator.global) { + separator = RegExp(separator.source, (reFlags.exec(separator) || "") + "g"); + } + separator.lastIndex = 0; + while (match = separator.exec(substring)) { + newEnd = match.index; + } + result = result.slice(0, newEnd == null ? end : newEnd); + } + } else if (string.indexOf(separator, end) != end) { + var index = result.lastIndexOf(separator); + if (index > -1) { + result = result.slice(0, index); + } + } + return result + omission; + } + function unescape(string) { + string = baseToString(string); + return string && reHasEscapedHtml.test(string) ? string.replace(reEscapedHtml, unescapeHtmlChar) : string; + } + function words(string, pattern, guard) { + if (guard && isIterateeCall(string, pattern, guard)) { + pattern = undefined; + } + string = baseToString(string); + return string.match(pattern || reWords) || []; + } + var attempt = restParam(function(func, args) { + try { + return func.apply(undefined, args); + } catch (e) { + return isError(e) ? e : new Error(e); + } + }); + function callback(func, thisArg, guard) { + if (guard && isIterateeCall(func, thisArg, guard)) { + thisArg = undefined; + } + return isObjectLike(func) ? matches(func) : baseCallback(func, thisArg); + } + function constant(value) { + return function() { + return value; + }; + } + function identity(value) { + return value; + } + function matches(source) { + return baseMatches(baseClone(source, true)); + } + function matchesProperty(path, srcValue) { + return baseMatchesProperty(path, baseClone(srcValue, true)); + } + var method = restParam(function(path, args) { + return function(object) { + return invokePath(object, path, args); + }; + }); + var methodOf = restParam(function(object, args) { + return function(path) { + return invokePath(object, path, args); + }; + }); + function mixin(object, source, options) { + if (options == null) { + var isObj = isObject(source), props = isObj ? keys(source) : undefined, methodNames = props && props.length ? baseFunctions(source, props) : undefined; + if (!(methodNames ? methodNames.length : isObj)) { + methodNames = false; + options = source; + source = object; + object = this; + } + } + if (!methodNames) { + methodNames = baseFunctions(source, keys(source)); + } + var chain = true, index = -1, isFunc = isFunction(object), length = methodNames.length; + if (options === false) { + chain = false; + } else if (isObject(options) && "chain" in options) { + chain = options.chain; + } + while (++index < length) { + var methodName = methodNames[index], func = source[methodName]; + object[methodName] = func; + if (isFunc) { + object.prototype[methodName] = function(func) { + return function() { + var chainAll = this.__chain__; + if (chain || chainAll) { + var result = object(this.__wrapped__), actions = result.__actions__ = arrayCopy(this.__actions__); + actions.push({ + func: func, + args: arguments, + thisArg: object + }); + result.__chain__ = chainAll; + return result; + } + return func.apply(object, arrayPush([ this.value() ], arguments)); + }; + }(func); + } + } + return object; + } + function noConflict() { + root._ = oldDash; + return this; + } + function noop() {} + function property(path) { + return isKey(path) ? baseProperty(path) : basePropertyDeep(path); + } + function propertyOf(object) { + return function(path) { + return baseGet(object, toPath(path), path + ""); + }; + } + function range(start, end, step) { + if (step && isIterateeCall(start, end, step)) { + end = step = undefined; + } + start = +start || 0; + step = step == null ? 1 : +step || 0; + if (end == null) { + end = start; + start = 0; + } else { + end = +end || 0; + } + var index = -1, length = nativeMax(nativeCeil((end - start) / (step || 1)), 0), result = Array(length); + while (++index < length) { + result[index] = start; + start += step; + } + return result; + } + function times(n, iteratee, thisArg) { + n = nativeFloor(n); + if (n < 1 || !nativeIsFinite(n)) { + return []; + } + var index = -1, result = Array(nativeMin(n, MAX_ARRAY_LENGTH)); + iteratee = bindCallback(iteratee, thisArg, 1); + while (++index < n) { + if (index < MAX_ARRAY_LENGTH) { + result[index] = iteratee(index); + } else { + iteratee(index); + } + } + return result; + } + function uniqueId(prefix) { + var id = ++idCounter; + return baseToString(prefix) + id; + } + function add(augend, addend) { + return (+augend || 0) + (+addend || 0); + } + var ceil = createRound("ceil"); + var floor = createRound("floor"); + var max = createExtremum(gt, NEGATIVE_INFINITY); + var min = createExtremum(lt, POSITIVE_INFINITY); + var round = createRound("round"); + function sum(collection, iteratee, thisArg) { + if (thisArg && isIterateeCall(collection, iteratee, thisArg)) { + iteratee = undefined; + } + iteratee = getCallback(iteratee, thisArg, 3); + return iteratee.length == 1 ? arraySum(isArray(collection) ? collection : toIterable(collection), iteratee) : baseSum(collection, iteratee); + } + lodash.prototype = baseLodash.prototype; + LodashWrapper.prototype = baseCreate(baseLodash.prototype); + LodashWrapper.prototype.constructor = LodashWrapper; + LazyWrapper.prototype = baseCreate(baseLodash.prototype); + LazyWrapper.prototype.constructor = LazyWrapper; + MapCache.prototype["delete"] = mapDelete; + MapCache.prototype.get = mapGet; + MapCache.prototype.has = mapHas; + MapCache.prototype.set = mapSet; + SetCache.prototype.push = cachePush; + memoize.Cache = MapCache; + lodash.after = after; + lodash.ary = ary; + lodash.assign = assign; + lodash.at = at; + lodash.before = before; + lodash.bind = bind; + lodash.bindAll = bindAll; + lodash.bindKey = bindKey; + lodash.callback = callback; + lodash.chain = chain; + lodash.chunk = chunk; + lodash.compact = compact; + lodash.constant = constant; + lodash.countBy = countBy; + lodash.create = create; + lodash.curry = curry; + lodash.curryRight = curryRight; + lodash.debounce = debounce; + lodash.defaults = defaults; + lodash.defaultsDeep = defaultsDeep; + lodash.defer = defer; + lodash.delay = delay; + lodash.difference = difference; + lodash.drop = drop; + lodash.dropRight = dropRight; + lodash.dropRightWhile = dropRightWhile; + lodash.dropWhile = dropWhile; + lodash.fill = fill; + lodash.filter = filter; + lodash.flatten = flatten; + lodash.flattenDeep = flattenDeep; + lodash.flow = flow; + lodash.flowRight = flowRight; + lodash.forEach = forEach; + lodash.forEachRight = forEachRight; + lodash.forIn = forIn; + lodash.forInRight = forInRight; + lodash.forOwn = forOwn; + lodash.forOwnRight = forOwnRight; + lodash.functions = functions; + lodash.groupBy = groupBy; + lodash.indexBy = indexBy; + lodash.initial = initial; + lodash.intersection = intersection; + lodash.invert = invert; + lodash.invoke = invoke; + lodash.keys = keys; + lodash.keysIn = keysIn; + lodash.map = map; + lodash.mapKeys = mapKeys; + lodash.mapValues = mapValues; + lodash.matches = matches; + lodash.matchesProperty = matchesProperty; + lodash.memoize = memoize; + lodash.merge = merge; + lodash.method = method; + lodash.methodOf = methodOf; + lodash.mixin = mixin; + lodash.modArgs = modArgs; + lodash.negate = negate; + lodash.omit = omit; + lodash.once = once; + lodash.pairs = pairs; + lodash.partial = partial; + lodash.partialRight = partialRight; + lodash.partition = partition; + lodash.pick = pick; + lodash.pluck = pluck; + lodash.property = property; + lodash.propertyOf = propertyOf; + lodash.pull = pull; + lodash.pullAt = pullAt; + lodash.range = range; + lodash.rearg = rearg; + lodash.reject = reject; + lodash.remove = remove; + lodash.rest = rest; + lodash.restParam = restParam; + lodash.set = set; + lodash.shuffle = shuffle; + lodash.slice = slice; + lodash.sortBy = sortBy; + lodash.sortByAll = sortByAll; + lodash.sortByOrder = sortByOrder; + lodash.spread = spread; + lodash.take = take; + lodash.takeRight = takeRight; + lodash.takeRightWhile = takeRightWhile; + lodash.takeWhile = takeWhile; + lodash.tap = tap; + lodash.throttle = throttle; + lodash.thru = thru; + lodash.times = times; + lodash.toArray = toArray; + lodash.toPlainObject = toPlainObject; + lodash.transform = transform; + lodash.union = union; + lodash.uniq = uniq; + lodash.unzip = unzip; + lodash.unzipWith = unzipWith; + lodash.values = values; + lodash.valuesIn = valuesIn; + lodash.where = where; + lodash.without = without; + lodash.wrap = wrap; + lodash.xor = xor; + lodash.zip = zip; + lodash.zipObject = zipObject; + lodash.zipWith = zipWith; + lodash.backflow = flowRight; + lodash.collect = map; + lodash.compose = flowRight; + lodash.each = forEach; + lodash.eachRight = forEachRight; + lodash.extend = assign; + lodash.iteratee = callback; + lodash.methods = functions; + lodash.object = zipObject; + lodash.select = filter; + lodash.tail = rest; + lodash.unique = uniq; + mixin(lodash, lodash); + lodash.add = add; + lodash.attempt = attempt; + lodash.camelCase = camelCase; + lodash.capitalize = capitalize; + lodash.ceil = ceil; + lodash.clone = clone; + lodash.cloneDeep = cloneDeep; + lodash.deburr = deburr; + lodash.endsWith = endsWith; + lodash.escape = escape; + lodash.escapeRegExp = escapeRegExp; + lodash.every = every; + lodash.find = find; + lodash.findIndex = findIndex; + lodash.findKey = findKey; + lodash.findLast = findLast; + lodash.findLastIndex = findLastIndex; + lodash.findLastKey = findLastKey; + lodash.findWhere = findWhere; + lodash.first = first; + lodash.floor = floor; + lodash.get = get; + lodash.gt = gt; + lodash.gte = gte; + lodash.has = has; + lodash.identity = identity; + lodash.includes = includes; + lodash.indexOf = indexOf; + lodash.inRange = inRange; + lodash.isArguments = isArguments; + lodash.isArray = isArray; + lodash.isBoolean = isBoolean; + lodash.isDate = isDate; + lodash.isElement = isElement; + lodash.isEmpty = isEmpty; + lodash.isEqual = isEqual; + lodash.isError = isError; + lodash.isFinite = isFinite; + lodash.isFunction = isFunction; + lodash.isMatch = isMatch; + lodash.isNaN = isNaN; + lodash.isNative = isNative; + lodash.isNull = isNull; + lodash.isNumber = isNumber; + lodash.isObject = isObject; + lodash.isPlainObject = isPlainObject; + lodash.isRegExp = isRegExp; + lodash.isString = isString; + lodash.isTypedArray = isTypedArray; + lodash.isUndefined = isUndefined; + lodash.kebabCase = kebabCase; + lodash.last = last; + lodash.lastIndexOf = lastIndexOf; + lodash.lt = lt; + lodash.lte = lte; + lodash.max = max; + lodash.min = min; + lodash.noConflict = noConflict; + lodash.noop = noop; + lodash.now = now; + lodash.pad = pad; + lodash.padLeft = padLeft; + lodash.padRight = padRight; + lodash.parseInt = parseInt; + lodash.random = random; + lodash.reduce = reduce; + lodash.reduceRight = reduceRight; + lodash.repeat = repeat; + lodash.result = result; + lodash.round = round; + lodash.runInContext = runInContext; + lodash.size = size; + lodash.snakeCase = snakeCase; + lodash.some = some; + lodash.sortedIndex = sortedIndex; + lodash.sortedLastIndex = sortedLastIndex; + lodash.startCase = startCase; + lodash.startsWith = startsWith; + lodash.sum = sum; + lodash.template = template; + lodash.trim = trim; + lodash.trimLeft = trimLeft; + lodash.trimRight = trimRight; + lodash.trunc = trunc; + lodash.unescape = unescape; + lodash.uniqueId = uniqueId; + lodash.words = words; + lodash.all = every; + lodash.any = some; + lodash.contains = includes; + lodash.eq = isEqual; + lodash.detect = find; + lodash.foldl = reduce; + lodash.foldr = reduceRight; + lodash.head = first; + lodash.include = includes; + lodash.inject = reduce; + mixin(lodash, function() { + var source = {}; + baseForOwn(lodash, function(func, methodName) { + if (!lodash.prototype[methodName]) { + source[methodName] = func; + } + }); + return source; + }(), false); + lodash.sample = sample; + lodash.prototype.sample = function(n) { + if (!this.__chain__ && n == null) { + return sample(this.value()); + } + return this.thru(function(value) { + return sample(value, n); + }); + }; + lodash.VERSION = VERSION; + arrayEach([ "bind", "bindKey", "curry", "curryRight", "partial", "partialRight" ], function(methodName) { + lodash[methodName].placeholder = lodash; + }); + arrayEach([ "drop", "take" ], function(methodName, index) { + LazyWrapper.prototype[methodName] = function(n) { + var filtered = this.__filtered__; + if (filtered && !index) { + return new LazyWrapper(this); + } + n = n == null ? 1 : nativeMax(nativeFloor(n) || 0, 0); + var result = this.clone(); + if (filtered) { + result.__takeCount__ = nativeMin(result.__takeCount__, n); + } else { + result.__views__.push({ + size: n, + type: methodName + (result.__dir__ < 0 ? "Right" : "") + }); + } + return result; + }; + LazyWrapper.prototype[methodName + "Right"] = function(n) { + return this.reverse()[methodName](n).reverse(); + }; + }); + arrayEach([ "filter", "map", "takeWhile" ], function(methodName, index) { + var type = index + 1, isFilter = type != LAZY_MAP_FLAG; + LazyWrapper.prototype[methodName] = function(iteratee, thisArg) { + var result = this.clone(); + result.__iteratees__.push({ + iteratee: getCallback(iteratee, thisArg, 1), + type: type + }); + result.__filtered__ = result.__filtered__ || isFilter; + return result; + }; + }); + arrayEach([ "first", "last" ], function(methodName, index) { + var takeName = "take" + (index ? "Right" : ""); + LazyWrapper.prototype[methodName] = function() { + return this[takeName](1).value()[0]; + }; + }); + arrayEach([ "initial", "rest" ], function(methodName, index) { + var dropName = "drop" + (index ? "" : "Right"); + LazyWrapper.prototype[methodName] = function() { + return this.__filtered__ ? new LazyWrapper(this) : this[dropName](1); + }; + }); + arrayEach([ "pluck", "where" ], function(methodName, index) { + var operationName = index ? "filter" : "map", createCallback = index ? baseMatches : property; + LazyWrapper.prototype[methodName] = function(value) { + return this[operationName](createCallback(value)); + }; + }); + LazyWrapper.prototype.compact = function() { + return this.filter(identity); + }; + LazyWrapper.prototype.reject = function(predicate, thisArg) { + predicate = getCallback(predicate, thisArg, 1); + return this.filter(function(value) { + return !predicate(value); + }); + }; + LazyWrapper.prototype.slice = function(start, end) { + start = start == null ? 0 : +start || 0; + var result = this; + if (result.__filtered__ && (start > 0 || end < 0)) { + return new LazyWrapper(result); + } + if (start < 0) { + result = result.takeRight(-start); + } else if (start) { + result = result.drop(start); + } + if (end !== undefined) { + end = +end || 0; + result = end < 0 ? result.dropRight(-end) : result.take(end - start); + } + return result; + }; + LazyWrapper.prototype.takeRightWhile = function(predicate, thisArg) { + return this.reverse().takeWhile(predicate, thisArg).reverse(); + }; + LazyWrapper.prototype.toArray = function() { + return this.take(POSITIVE_INFINITY); + }; + baseForOwn(LazyWrapper.prototype, function(func, methodName) { + var checkIteratee = /^(?:filter|map|reject)|While$/.test(methodName), retUnwrapped = /^(?:first|last)$/.test(methodName), lodashFunc = lodash[retUnwrapped ? "take" + (methodName == "last" ? "Right" : "") : methodName]; + if (!lodashFunc) { + return; + } + lodash.prototype[methodName] = function() { + var args = retUnwrapped ? [ 1 ] : arguments, chainAll = this.__chain__, value = this.__wrapped__, isHybrid = !!this.__actions__.length, isLazy = value instanceof LazyWrapper, iteratee = args[0], useLazy = isLazy || isArray(value); + if (useLazy && checkIteratee && typeof iteratee == "function" && iteratee.length != 1) { + isLazy = useLazy = false; + } + var interceptor = function(value) { + return retUnwrapped && chainAll ? lodashFunc(value, 1)[0] : lodashFunc.apply(undefined, arrayPush([ value ], args)); + }; + var action = { + func: thru, + args: [ interceptor ], + thisArg: undefined + }, onlyLazy = isLazy && !isHybrid; + if (retUnwrapped && !chainAll) { + if (onlyLazy) { + value = value.clone(); + value.__actions__.push(action); + return func.call(value); + } + return lodashFunc.call(undefined, this.value())[0]; + } + if (!retUnwrapped && useLazy) { + value = onlyLazy ? value : new LazyWrapper(this); + var result = func.apply(value, args); + result.__actions__.push(action); + return new LodashWrapper(result, chainAll); + } + return this.thru(interceptor); + }; + }); + arrayEach([ "join", "pop", "push", "replace", "shift", "sort", "splice", "split", "unshift" ], function(methodName) { + var func = (/^(?:replace|split)$/.test(methodName) ? stringProto : arrayProto)[methodName], chainName = /^(?:push|sort|unshift)$/.test(methodName) ? "tap" : "thru", retUnwrapped = /^(?:join|pop|replace|shift)$/.test(methodName); + lodash.prototype[methodName] = function() { + var args = arguments; + if (retUnwrapped && !this.__chain__) { + return func.apply(this.value(), args); + } + return this[chainName](function(value) { + return func.apply(value, args); + }); + }; + }); + baseForOwn(LazyWrapper.prototype, function(func, methodName) { + var lodashFunc = lodash[methodName]; + if (lodashFunc) { + var key = lodashFunc.name + "", names = realNames[key] || (realNames[key] = []); + names.push({ + name: methodName, + func: lodashFunc + }); + } + }); + realNames[createHybridWrapper(undefined, BIND_KEY_FLAG).name] = [ { + name: "wrapper", + func: undefined + } ]; + LazyWrapper.prototype.clone = lazyClone; + LazyWrapper.prototype.reverse = lazyReverse; + LazyWrapper.prototype.value = lazyValue; + lodash.prototype.chain = wrapperChain; + lodash.prototype.commit = wrapperCommit; + lodash.prototype.concat = wrapperConcat; + lodash.prototype.plant = wrapperPlant; + lodash.prototype.reverse = wrapperReverse; + lodash.prototype.toString = wrapperToString; + lodash.prototype.run = lodash.prototype.toJSON = lodash.prototype.valueOf = lodash.prototype.value = wrapperValue; + lodash.prototype.collect = lodash.prototype.map; + lodash.prototype.head = lodash.prototype.first; + lodash.prototype.select = lodash.prototype.filter; + lodash.prototype.tail = lodash.prototype.rest; + return lodash; + } + var _ = runInContext(); + if (typeof define == "function" && typeof define.amd == "object" && define.amd) { + root._ = _; + define(function() { + return _; + }); + } else if (freeExports && freeModule) { + if (moduleExports) { + (freeModule.exports = _)._ = _; + } else { + freeExports._ = _; + } + } else { + root._ = _; + } +}).call(this); + (function(window, document, undefined) { "use strict"; function minErr(module, ErrorConstructor) { @@ -5391,7 +9332,7 @@ } return match; }); - message += "\nhttp://errors.angularjs.org/1.4.6/" + (module ? module + "/" : "") + code; + message += "\nhttp://errors.angularjs.org/1.4.7/" + (module ? module + "/" : "") + code; for (i = SKIP_INDEXES, paramPrefix = "?"; i < templateArgs.length; i++, paramPrefix = "&") { message += paramPrefix + "p" + (i - SKIP_INDEXES) + "=" + encodeURIComponent(toDebugString(templateArgs[i])); } @@ -6210,11 +10151,11 @@ return obj; } var version = { - full: "1.4.6", + full: "1.4.7", major: 1, minor: 4, - dot: 6, - codeName: "multiplicative-elevation" + dot: 7, + codeName: "dark-luminescence" }; function publishExternalAPI(angular) { extend(angular, { @@ -6323,6 +10264,7 @@ $httpParamSerializer: $HttpParamSerializerProvider, $httpParamSerializerJQLike: $HttpParamSerializerJQLikeProvider, $httpBackend: $HttpBackendProvider, + $xhrFactory: $xhrFactoryProvider, $location: $LocationProvider, $log: $LogProvider, $parse: $ParseProvider, @@ -6368,10 +10310,10 @@ return offset ? letter.toUpperCase() : letter; }).replace(MOZ_HACK_REGEXP, "Moz$1"); } - var SINGLE_TAG_REGEXP = /^<(\w+)\s*\/?>(?:<\/\1>|)$/; + var SINGLE_TAG_REGEXP = /^<([\w-]+)\s*\/?>(?:<\/\1>|)$/; var HTML_REGEXP = /<|&#?\w+;/; - var TAG_NAME_REGEXP = /<([\w:]+)/; - var XHTML_TAG_REGEXP = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi; + var TAG_NAME_REGEXP = /<([\w:-]+)/; + var XHTML_TAG_REGEXP = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:-]+)[^>]*)\/>/gi; var wrapMap = { option: [ 1, '" ], thead: [ 1, "", "
                      " ], @@ -7614,6 +11556,9 @@ } }; return function(element, options) { + if (options.cleanupStyles) { + options.from = options.to = null; + } if (options.from) { element.css(options.from); options.from = null; @@ -8879,7 +12824,7 @@ compile: function() { return { pre: function attrInterpolatePreLinkFn(scope, element, attr) { - var $$observers = attr.$$observers || (attr.$$observers = {}); + var $$observers = attr.$$observers || (attr.$$observers = createMap()); if (EVENT_HANDLER_ATTR_REGEXP.test(name)) { throw $compileMinErr("nodomevents", "Interpolations for HTML DOM event attributes are disallowed. Please use the " + "ng- versions (such as ng-click instead of onclick) instead."); } @@ -9542,12 +13487,16 @@ } } ]; } - function createXhr() { - return new window.XMLHttpRequest(); + function $xhrFactoryProvider() { + this.$get = function() { + return function createXhr() { + return new window.XMLHttpRequest(); + }; + }; } function $HttpBackendProvider() { - this.$get = [ "$browser", "$window", "$document", function($browser, $window, $document) { - return createHttpBackend($browser, createXhr, $browser.defer, $window.angular.callbacks, $document[0]); + this.$get = [ "$browser", "$window", "$document", "$xhrFactory", function($browser, $window, $document, $xhrFactory) { + return createHttpBackend($browser, $xhrFactory, $browser.defer, $window.angular.callbacks, $document[0]); } ]; } function createHttpBackend($browser, createXhr, $browserDefer, callbacks, rawDocument) { @@ -9565,7 +13514,7 @@ callbacks[callbackId] = noop; }); } else { - var xhr = createXhr(); + var xhr = createXhr(method, url); xhr.open(method, url, true); forEach(headers, function(value, key) { if (isDefined(value)) { @@ -10273,12 +14222,18 @@ } var $parseMinErr = minErr("$parse"); function ensureSafeMemberName(name, fullExpression) { - name = isObject(name) && name.toString ? name.toString() : name; if (name === "__defineGetter__" || name === "__defineSetter__" || name === "__lookupGetter__" || name === "__lookupSetter__" || name === "__proto__") { throw $parseMinErr("isecfld", "Attempting to access a disallowed field in Angular expressions! " + "Expression: {0}", fullExpression); } return name; } + function getStringValue(name, fullExpression) { + name = name + ""; + if (!isString(name)) { + throw $parseMinErr("iseccst", "Cannot convert object to primitive value! " + "Expression: {0}", fullExpression); + } + return name; + } function ensureSafeObject(obj, fullExpression) { if (obj) { if (obj.constructor === obj) { @@ -10305,6 +14260,13 @@ } } } + function ensureSafeAssignContext(obj, fullExpression) { + if (obj) { + if (obj === 0..constructor || obj === false.constructor || obj === "".constructor || obj === {}.constructor || obj === [].constructor || obj === Function.constructor) { + throw $parseMinErr("isecaf", "Assigning to a constructor is disallowed! Expression: {0}", fullExpression); + } + } + } var OPERATORS = createMap(); forEach("+ - * / % === !== == != < > <= >= && || ! = |".split(" "), function(operator) { OPERATORS[operator] = true; @@ -11053,7 +15015,7 @@ this.stage = "main"; this.recurse(ast); var fnString = '"' + this.USE + " " + this.STRICT + '";\n' + this.filterPrefix() + "var fn=" + this.generateFunction("fn", "s,l,a,i") + extra + this.watchFns() + "return fn;"; - var fn = new Function("$filter", "ensureSafeMemberName", "ensureSafeObject", "ensureSafeFunction", "ifDefined", "plus", "text", fnString)(this.$filter, ensureSafeMemberName, ensureSafeObject, ensureSafeFunction, ifDefined, plusFn, expression); + var fn = new Function("$filter", "ensureSafeMemberName", "ensureSafeObject", "ensureSafeFunction", "getStringValue", "ensureSafeAssignContext", "ifDefined", "plus", "text", fnString)(this.$filter, ensureSafeMemberName, ensureSafeObject, ensureSafeFunction, getStringValue, ensureSafeAssignContext, ifDefined, plusFn, expression); this.state = this.stage = undefined; fn.literal = isLiteral(ast); fn.constant = isConstant(ast); @@ -11190,6 +15152,7 @@ if (ast.computed) { right = self.nextId(); self.recurse(ast.property, right); + self.getStringValue(right); self.addEnsureSafeMemberName(right); if (create && create !== 1) { self.if_(self.not(self.computedMember(left, right)), self.lazyAssign(self.computedMember(left, right), "{}")); @@ -11275,6 +15238,7 @@ self.if_(self.notNull(left.context), function() { self.recurse(ast.right, right); self.addEnsureSafeObject(self.member(left.context, left.name, left.computed)); + self.addEnsureSafeAssignContext(left.context); expression = self.member(left.context, left.name, left.computed) + ast.operator + right; self.assign(intoId, expression); recursionFn(intoId || expression); @@ -11385,6 +15349,9 @@ addEnsureSafeFunction: function(item) { this.current().body.push(this.ensureSafeFunction(item), ";"); }, + addEnsureSafeAssignContext: function(item) { + this.current().body.push(this.ensureSafeAssignContext(item), ";"); + }, ensureSafeObject: function(item) { return "ensureSafeObject(" + item + ",text)"; }, @@ -11394,6 +15361,12 @@ ensureSafeFunction: function(item) { return "ensureSafeFunction(" + item + ",text)"; }, + getStringValue: function(item) { + this.assign(item, "getStringValue(" + item + ",text)"); + }, + ensureSafeAssignContext: function(item) { + return "ensureSafeAssignContext(" + item + ",text)"; + }, lazyRecurse: function(ast, intoId, nameId, recursionFn, create, skipWatchIdCheck) { var self = this; return function() { @@ -11561,6 +15534,7 @@ var lhs = left(scope, locals, assign, inputs); var rhs = right(scope, locals, assign, inputs); ensureSafeObject(lhs.value, self.expression); + ensureSafeAssignContext(lhs.context); lhs.context[lhs.name] = rhs; return context ? { value: rhs @@ -11818,6 +15792,7 @@ var value; if (lhs != null) { rhs = right(scope, locals, assign, inputs); + rhs = getStringValue(rhs); ensureSafeMemberName(rhs, expression); if (create && create !== 1 && lhs && !lhs[rhs]) { lhs[rhs] = {}; @@ -13500,6 +17475,7 @@ if (fractionSize > 0 && number < 1) { formatedText = number.toFixed(fractionSize); number = parseFloat(formatedText); + formatedText = formatedText.replace(DECIMAL_SEP, decimalSep); } } if (number === 0) { @@ -15517,11 +19493,11 @@ function updateOptionElement(option, element) { option.element = element; element.disabled = option.disabled; - if (option.value !== element.value) element.value = option.selectValue; if (option.label !== element.label) { element.label = option.label; element.textContent = option.label; } + if (option.value !== element.value) element.value = option.selectValue; } function addOrReuseElement(parent, current, type, templateElement) { var element; @@ -15549,7 +19525,7 @@ var emptyOption_ = emptyOption && emptyOption[0]; var unknownOption_ = unknownOption && unknownOption[0]; if (emptyOption_ || unknownOption_) { - while (current && (current === emptyOption_ || current === unknownOption_)) { + while (current && (current === emptyOption_ || current === unknownOption_ || emptyOption_ && emptyOption_.nodeType === NODE_TYPE_COMMENT)) { current = current.nextSibling; } } @@ -26949,6 +30925,284 @@ WaveSurfer.util.extend(WaveSurfer.Drawer.Canvas, { "use strict"; +WaveSurfer.Regions = { + init: function(a) { + this.wavesurfer = a, this.wrapper = this.wavesurfer.drawer.wrapper, this.list = {}; + }, + add: function(a) { + var b = Object.create(WaveSurfer.Region); + return b.init(a, this.wavesurfer), this.list[b.id] = b, b.on("remove", function() { + delete this.list[b.id]; + }.bind(this)), b; + }, + clear: function() { + Object.keys(this.list).forEach(function(a) { + this.list[a].remove(); + }, this); + }, + enableDragSelection: function(a) { + var b, c, d, e = this; + this.wrapper.addEventListener("mousedown", function(a) { + b = !0, c = e.wavesurfer.drawer.handleEvent(a), d = null; + }), this.wrapper.addEventListener("mouseup", function(a) { + b = !1, d && (d.fireEvent("update-end", a), e.wavesurfer.fireEvent("region-update-end", d, a)), + d = null; + }), this.wrapper.addEventListener("mousemove", function(f) { + if (b) { + d || (d = e.add(a || {})); + var g = e.wavesurfer.getDuration(), h = e.wavesurfer.drawer.handleEvent(f); + d.update({ + start: Math.min(h * g, c * g), + end: Math.max(h * g, c * g) + }); + } + }); + } +}, WaveSurfer.Region = { + style: WaveSurfer.Drawer.style, + init: function(a, b) { + this.wavesurfer = b, this.wrapper = b.drawer.wrapper, this.id = null == a.id ? WaveSurfer.util.getId() : a.id, + this.start = Number(a.start) || 0, this.end = null == a.end ? this.start + 4 / this.wrapper.scrollWidth * this.wavesurfer.getDuration() : Number(a.end), + this.resize = void 0 === a.resize ? !0 : Boolean(a.resize), this.drag = void 0 === a.drag ? !0 : Boolean(a.drag), + this.loop = Boolean(a.loop), this.color = a.color || "rgba(0, 0, 0, 0.1)", this.data = a.data || {}, + this.maxLength = a.maxLength, this.minLength = a.minLength, this.bindInOut(), this.render(), + this.wavesurfer.fireEvent("region-created", this); + }, + update: function(a) { + null != a.start && (this.start = Number(a.start)), null != a.end && (this.end = Number(a.end)), + null != a.loop && (this.loop = Boolean(a.loop)), null != a.color && (this.color = a.color), + null != a.data && (this.data = a.data), null != a.resize && (this.resize = Boolean(a.resize)), + null != a.drag && (this.drag = Boolean(a.drag)), null != a.maxLength && (this.maxLength = Number(a.maxLength)), + null != a.minLength && (this.minLength = Number(a.minLength)), this.updateRender(), + this.fireEvent("update"), this.wavesurfer.fireEvent("region-updated", this); + }, + remove: function(a) { + this.element && (this.wrapper.removeChild(this.element), this.element = null, this.fireEvent("remove"), + this.wavesurfer.fireEvent("region-removed", this)); + }, + play: function() { + this.wavesurfer.play(this.start, this.end), this.fireEvent("play"), this.wavesurfer.fireEvent("region-play", this); + }, + playLoop: function() { + this.play(), this.once("out", this.playLoop.bind(this)); + }, + render: function() { + var a = document.createElement("region"); + a.className = "wavesurfer-region", a.title = this.formatTime(this.start, this.end), + a.setAttribute("data-id", this.id); + this.wrapper.scrollWidth; + if (this.style(a, { + position: "absolute", + zIndex: 2, + height: "100%", + top: "0px" + }), this.resize) { + var b = a.appendChild(document.createElement("handle")), c = a.appendChild(document.createElement("handle")); + b.className = "wavesurfer-handle wavesurfer-handle-start", c.className = "wavesurfer-handle wavesurfer-handle-end"; + var d = { + cursor: "col-resize", + position: "absolute", + left: "0px", + top: "0px", + width: "1%", + maxWidth: "4px", + height: "100%" + }; + this.style(b, d), this.style(c, d), this.style(c, { + left: "100%" + }); + } + this.element = this.wrapper.appendChild(a), this.updateRender(), this.bindEvents(a); + }, + formatTime: function(a, b) { + return (a == b ? [ a ] : [ a, b ]).map(function(a) { + return [ Math.floor(a % 3600 / 60), ("00" + Math.floor(a % 60)).slice(-2) ].join(":"); + }).join("–"); + }, + updateRender: function() { + var a = this.wavesurfer.getDuration(), b = this.wrapper.scrollWidth; + this.start < 0 && (this.start = 0, this.end = this.end - this.start), this.end > a && (this.end = a, + this.start = a - (this.end - this.start)), null != this.minLength && (this.end = Math.max(this.start + this.minLength, this.end)), + null != this.maxLength && (this.end = Math.min(this.start + this.maxLength, this.end)), + this.style(this.element, { + left: ~~(this.start / a * b) + "px", + width: ~~((this.end - this.start) / a * b) + "px", + backgroundColor: this.color, + cursor: this.drag ? "move" : "default" + }), this.element.title = this.formatTime(this.start, this.end); + }, + bindInOut: function() { + var a = this, b = function() { + a.firedIn = !1, a.firedOut = !1; + }, c = function(b) { + !a.firedIn && a.start <= b && a.end > b && (a.firedIn = !0, a.fireEvent("in"), a.wavesurfer.fireEvent("region-in", a)), + !a.firedOut && a.firedIn && a.end <= Math.round(100 * b) / 100 && (a.firedOut = !0, + a.fireEvent("out"), a.wavesurfer.fireEvent("region-out", a)); + }; + this.wavesurfer.on("play", b), this.wavesurfer.backend.on("audioprocess", c), this.on("remove", function() { + a.wavesurfer.un("play", b), a.wavesurfer.backend.un("audioprocess", c); + }), this.on("out", function() { + a.loop && a.wavesurfer.play(a.start); + }); + }, + bindEvents: function() { + var a = this; + this.element.addEventListener("mouseenter", function(b) { + a.fireEvent("mouseenter", b), a.wavesurfer.fireEvent("region-mouseenter", a, b); + }), this.element.addEventListener("mouseleave", function(b) { + a.fireEvent("mouseleave", b), a.wavesurfer.fireEvent("region-mouseleave", a, b); + }), this.element.addEventListener("click", function(b) { + b.preventDefault(), a.fireEvent("click", b), a.wavesurfer.fireEvent("region-click", a, b); + }), this.element.addEventListener("dblclick", function(b) { + b.stopPropagation(), b.preventDefault(), a.fireEvent("dblclick", b), a.wavesurfer.fireEvent("region-dblclick", a, b); + }), (this.drag || this.resize) && function() { + var b, c, d, e = a.wavesurfer.getDuration(), f = function(f) { + f.stopPropagation(), d = a.wavesurfer.drawer.handleEvent(f) * e, "handle" == f.target.tagName.toLowerCase() ? c = f.target.classList.contains("wavesurfer-handle-start") ? "start" : "end" : b = !0; + }, g = function(d) { + (b || c) && (b = !1, c = !1, d.stopPropagation(), d.preventDefault(), a.fireEvent("update-end", d), + a.wavesurfer.fireEvent("region-update-end", a, d)); + }, h = function(f) { + if (b || c) { + var g = a.wavesurfer.drawer.handleEvent(f) * e, h = g - d; + d = g, a.drag && b && a.onDrag(h), a.resize && c && a.onResize(h, c); + } + }; + a.element.addEventListener("mousedown", f), a.wrapper.addEventListener("mousemove", h), + document.body.addEventListener("mouseup", g), a.on("remove", function() { + document.body.removeEventListener("mouseup", g), a.wrapper.removeEventListener("mousemove", h); + }), a.wavesurfer.on("destroy", function() { + document.body.removeEventListener("mouseup", g); + }); + }(); + }, + onDrag: function(a) { + this.update({ + start: this.start + a, + end: this.end + a + }); + }, + onResize: function(a, b) { + "start" == b ? this.update({ + start: Math.min(this.start + a, this.end), + end: Math.max(this.start + a, this.end) + }) : this.update({ + start: Math.min(this.end + a, this.start), + end: Math.max(this.end + a, this.start) + }); + } +}, WaveSurfer.util.extend(WaveSurfer.Region, WaveSurfer.Observer), WaveSurfer.initRegions = function() { + this.regions || (this.regions = Object.create(WaveSurfer.Regions), this.regions.init(this)); +}, WaveSurfer.addRegion = function(a) { + return this.initRegions(), this.regions.add(a); +}, WaveSurfer.clearRegions = function() { + this.regions && this.regions.clear(); +}, WaveSurfer.enableDragSelection = function(a) { + this.initRegions(), this.regions.enableDragSelection(a); +}; + +"use strict"; + +WaveSurfer.Spectrogram = { + init: function(a) { + this.params = a; + var b = this.wavesurfer = a.wavesurfer; + if (!this.wavesurfer) throw Error("No WaveSurfer instance provided"); + this.frequenciesDataUrl = a.frequenciesDataUrl; + var c = this.drawer = this.wavesurfer.drawer; + if (this.buffer = this.wavesurfer.backend.buffer, this.container = "string" == typeof a.container ? document.querySelector(a.container) : a.container, + !this.container) throw Error("No container for WaveSurfer spectrogram"); + this.width = c.width, this.pixelRatio = this.params.pixelRatio || b.params.pixelRatio, + this.fftSamples = this.params.fftSamples || b.params.fftSamples || 512, this.height = this.fftSamples / 2, + this.createWrapper(), this.createCanvas(), this.render(), b.drawer.wrapper.onscroll = this.updateScroll.bind(this), + b.on("destroy", this.destroy.bind(this)); + }, + destroy: function() { + this.unAll(), this.wrapper && (this.wrapper.parentNode.removeChild(this.wrapper), + this.wrapper = null); + }, + createWrapper: function() { + var a = this.container.querySelector("spectrogram"); + a && this.container.removeChild(a); + var b = this.wavesurfer.params; + this.wrapper = this.container.appendChild(document.createElement("spectrogram")), + this.drawer.style(this.wrapper, { + display: "block", + position: "relative", + userSelect: "none", + webkitUserSelect: "none", + height: this.height + "px" + }), (b.fillParent || b.scrollParent) && this.drawer.style(this.wrapper, { + width: "100%", + overflowX: "hidden", + overflowY: "hidden" + }); + var c = this; + this.wrapper.addEventListener("click", function(a) { + a.preventDefault(); + var b = "offsetX" in a ? a.offsetX : a.layerX; + c.fireEvent("click", b / c.scrollWidth || 0); + }); + }, + createCanvas: function() { + var a = this.canvas = this.wrapper.appendChild(document.createElement("canvas")); + this.spectrCc = a.getContext("2d"), this.wavesurfer.drawer.style(a, { + position: "absolute", + zIndex: 4 + }); + }, + render: function() { + this.updateCanvasStyle(), this.frequenciesDataUrl ? this.loadFrequenciesData(this.frequenciesDataUrl) : this.getFrequencies(this.drawSpectrogram); + }, + updateCanvasStyle: function() { + var a = Math.round(this.width / this.pixelRatio) + "px"; + this.canvas.width = this.width, this.canvas.height = this.height, this.canvas.style.width = a; + }, + drawSpectrogram: function(a, b) { + for (var c = (b.spectrCc, b.wavesurfer.backend.getDuration(), b.height), d = b.resample(a), e = 2 / b.buffer.numberOfChannels, f = 0; f < d.length; f++) for (var g = 0; g < d[f].length; g++) { + var h = 255 - d[f][g]; + b.spectrCc.fillStyle = "rgb(" + h + ", " + h + ", " + h + ")", b.spectrCc.fillRect(f, c - g * e, 1, 1 * e); + } + }, + getFrequencies: function(a) { + var b = this.fftSamples, c = this.buffer, d = [], e = new window.OfflineAudioContext(1, c.length, c.sampleRate), f = e.createBufferSource(), g = e.createScriptProcessor(0, 1, 1), h = e.createAnalyser(); + h.fftSize = b, h.smoothingTimeConstant = this.width / c.duration < 10 ? .75 : .25, + f.buffer = c, f.connect(h), h.connect(g), g.connect(e.destination), g.onaudioprocess = function() { + var a = new Uint8Array(h.frequencyBinCount); + h.getByteFrequencyData(a), d.push(a); + }, f.start(0), e.startRendering(); + var i = this; + e.oncomplete = function() { + a(d, i); + }; + }, + loadFrequenciesData: function(a) { + var b = this, c = WaveSurfer.util.ajax({ + url: a + }); + return c.on("success", function(a) { + b.drawSpectrogram(JSON.parse(a), b); + }), c.on("error", function(a) { + b.fireEvent("error", "XHR error: " + a.target.statusText); + }), c; + }, + updateScroll: function(a) { + this.wrapper.scrollLeft = a.target.scrollLeft; + }, + resample: function(a, b) { + for (var b = this.width, c = [], d = 1 / a.length, e = 1 / b, f = 0; b > f; f++) { + for (var g = new Array(a[0].length), h = 0; h < a.length; h++) { + var i = h * d, j = i + d, k = f * e, l = k + e, m = k >= j || i >= l ? 0 : Math.min(Math.max(j, k), Math.max(l, i)) - Math.max(Math.min(j, k), Math.min(l, i)); + if (m > 0) for (var n = 0; n < a[0].length; n++) null == g[n] && (g[n] = 0), g[n] += m / e * a[h][n]; + } + for (var o = new Uint8Array(a[0].length), n = 0; n < a[0].length; n++) o[n] = g[n]; + c.push(o); + } + return c; + } +}, WaveSurfer.util.extend(WaveSurfer.Spectrogram, WaveSurfer.Observer); + +"use strict"; + var model = {}; model.Value = function() { @@ -27120,8 +31374,10 @@ var elan = function() { var header = xml.querySelector("HEADER"); var inMilliseconds = header.getAttribute("TIME_UNITS") == "milliseconds"; var media = header.querySelector("MEDIA_DESCRIPTOR"); - this.mediaUrl = media.getAttribute("MEDIA_URL"); - this.mediaType = media.getAttribute("MIME_TYPE"); + if (media) { + this.mediaUrl = media.getAttribute("MEDIA_URL"); + this.mediaType = media.getAttribute("MIME_TYPE"); + } var properties = xml.querySelectorAll("PROPERTY"); _forEach.call(properties, function(prop) { var name = prop.getAttribute("NAME"); @@ -27301,6 +31557,12 @@ var cloneObject = function(oldObject) { return JSON.parse(JSON.stringify(oldObject)); }; +var enableControls = function(controls, enabled) { + _.each(controls, function(value, key) { + controls[key] = enabled; + }); +}; + var lingvodoc = {}; lingvodoc.Object = function(clientId, objectId) { @@ -27308,10 +31570,7 @@ lingvodoc.Object = function(clientId, objectId) { this.object_id = objectId; this.type = "abstract"; this.getId = function() { - return this.client_id + "" + this.object_id; - }; - this.export = function() { - return {}; + return this.client_id + "_" + this.object_id; }; }; @@ -27372,13 +31631,33 @@ lingvodoc.Perspective = function(client_id, object_id, parent_client_id, parent_ this.is_template = is_template; this.marked_for_deletion = marked_for_deletion; this.fields = []; + this.location = null; + this.blobs = []; + this.additional_metadata = {}; this.equals = function(obj) { return lingvodoc.Object.prototype.equals.call(this, obj) && this.translation == obj.translation; }; }; lingvodoc.Perspective.fromJS = function(js) { - return new lingvodoc.Perspective(js.client_id, js.object_id, js.parent_client_id, js.parent_object_id, js.translation, js.translation_string, js.status, js.is_template, js.marked_for_deletion); + var perspective = new lingvodoc.Perspective(js.client_id, js.object_id, js.parent_client_id, js.parent_object_id, js.translation, js.translation_string, js.status, js.is_template, js.marked_for_deletion); + if (_.has(js, "location") && _.has(js.location, "content")) { + perspective["location"] = { + lat: js.location.content.lat, + lng: js.location.content.lng + }; + } + if (_.has(js, "info") && js.info.type == "list") { + if (_.isArray(js.info.content)) { + perspective["blobs"] = _.map(js.info.content, function(e) { + var blob = new lingvodoc.Blob(e.info.content.client_id, e.info.content.object_id, e.info.content.name, e.info.content.data_type); + blob.url = e.info.content.content; + return blob; + }); + } + } + perspective.additional_metadata = js.additional_metadata; + return perspective; }; lingvodoc.Perspective.prototype = new lingvodoc.Object(); @@ -27403,6 +31682,25 @@ lingvodoc.User.fromJS = function(js) { return new lingvodoc.User(js.id, js.login, js.name, js.email, js.intl_name, js.about, js.signup_date, js.organizations); }; +lingvodoc.Blob = function(clientId, objectId, name, data_type) { + lingvodoc.Object.call(this, clientId, objectId); + this.type = "blob"; + this.name = name; + this.data_type = data_type; + this.url = null; + this.equals = function(obj) { + return lingvodoc.Object.prototype.equals.call(this, obj) && this.name == obj.name; + }; +}; + +lingvodoc.Blob.fromJS = function(js) { + return new lingvodoc.Blob(js.client_id, js.object_id, js.name, js.data_type); +}; + +lingvodoc.Blob.prototype = new lingvodoc.Object(); + +lingvodoc.Blob.prototype.constructor = lingvodoc.Blob; + function lingvodocAPI($http, $q) { var addUrlParameter = function(url, key, value) { return url + (url.indexOf("?") >= 0 ? "&" : "?") + encodeURIComponent(key) + "=" + encodeURIComponent(value); @@ -27476,6 +31774,21 @@ function lingvodocAPI($http, $q) { }); return deferred.promise; }; + var getPerspectiveDictionaryFieldsNew = function(perspective) { + var deferred = $q.defer(); + var url = "/dictionary/" + perspective.parent_client_id + "/" + perspective.parent_object_id + "/perspective/" + perspective.client_id + "/" + perspective.object_id + "/fields"; + $http.get(url).success(function(data, status, headers, config) { + if (_.isArray(data.fields)) { + var fields = perspectiveToDictionaryFields(data.fields); + deferred.resolve(fields); + } else { + deferred.reject("An error occurred while fetching perspective fields"); + } + }).error(function(data, status, headers, config) { + deferred.reject("An error occurred while fetching perspective fields"); + }); + return deferred.promise; + }; var removeValue = function(entry, field, fieldValue, parent) { var deferred = $q.defer(); var url; @@ -27642,8 +31955,9 @@ function lingvodocAPI($http, $q) { }); return deferred.promise; }; - var getDictionaryProperties = function(url) { + var getDictionaryProperties = function(dictionary) { var deferred = $q.defer(); + var url = "/dictionary/" + encodeURIComponent(dictionary.client_id) + "/" + encodeURIComponent(dictionary.object_id); $http.get(url).success(function(data, status, headers, config) { deferred.resolve(data); }).error(function(data, status, headers, config) { @@ -27651,8 +31965,9 @@ function lingvodocAPI($http, $q) { }); return deferred.promise; }; - var setDictionaryProperties = function(url, properties) { + var setDictionaryProperties = function(dictionary, properties) { var deferred = $q.defer(); + var url = "/dictionary/" + encodeURIComponent(dictionary.client_id) + "/" + encodeURIComponent(dictionary.object_id); $http.put(url, properties).success(function(data, status, headers, config) { deferred.resolve(data); }).error(function(data, status, headers, config) { @@ -27660,6 +31975,16 @@ function lingvodocAPI($http, $q) { }); return deferred.promise; }; + var removeDictionary = function(dictionary) { + var deferred = $q.defer(); + var url = "/dictionary/" + encodeURIComponent(dictionary.client_id) + "/" + encodeURIComponent(dictionary.object_id); + $http.delete(url).success(function(data, status, headers, config) { + deferred.resolve(); + }).error(function(data, status, headers, config) { + deferred.reject("An error occurred while trying to delete dictionary"); + }); + return deferred.promise; + }; var getLanguages = function(url) { var deferred = $q.defer(); var flatLanguages = function(languages) { @@ -27743,6 +32068,16 @@ function lingvodocAPI($http, $q) { }); return deferred.promise; }; + var removePerspective = function(perspective) { + var deferred = $q.defer(); + var url = "/dictionary/" + perspective.parent_client_id + "/" + perspective.parent_object_id + "/perspective/" + perspective.client_id + "/" + perspective.object_id; + $http.delete(url).success(function(data, status, headers, config) { + deferred.resolve(); + }).error(function(data, status, headers, config) { + deferred.reject("An error occurred while trying to delete perspective"); + }); + return deferred.promise; + }; var getUserInfo = function(userId, clientId) { var deferred = $q.defer(); var url = "/user" + "?client_id= " + encodeURIComponent(clientId) + "&user_id= " + encodeURIComponent(userId); @@ -27823,13 +32158,14 @@ function lingvodocAPI($http, $q) { }; var getDictionaries = function(query) { var deferred = $q.defer(); - var dictionaries = []; $http.post("/dictionaries", query).success(function(data, status, headers, config) { - for (var i = 0; i < data.dictionaries.length; i++) { - var dictionary = data.dictionaries[i]; - dictionaries.push(lingvodoc.Dictionary.fromJS(dictionary)); + if (_.isArray(data.dictionaries)) { + deferred.resolve(_.map(data.dictionaries, function(d) { + return lingvodoc.Dictionary.fromJS(d); + })); + } else { + deferred.reject("Failed to fetch dictionaries list. Malformed response."); } - deferred.resolve(dictionaries); }).error(function(data, status, headers, config) { deferred.reject("Failed to fetch dictionaries list"); }); @@ -28046,8 +32382,8 @@ function lingvodocAPI($http, $q) { }; $http.post("/dictionaries", req).success(function(data, status, headers, config) { var dictionaries = []; - if (angular.isArray(data.dictionaries)) { - angular.forEach(data.dictionaries, function(jsdict) { + if (_.isArray(data.dictionaries)) { + _.forEach(data.dictionaries, function(jsdict) { var dictionary = lingvodoc.Dictionary.fromJS(jsdict); if (language.client_id == dictionary.parent_client_id && language.object_id == dictionary.parent_object_id) { dictionaries.push(dictionary); @@ -28056,7 +32392,7 @@ function lingvodocAPI($http, $q) { } deferred.resolve(dictionaries); }).error(function(data, status, headers, config) { - deferred.reject("Failed to move lexical entry"); + deferred.reject("Failed to fetch list of dictionaries"); }); return deferred.promise; }; @@ -28239,10 +32575,140 @@ function lingvodocAPI($http, $q) { }); return deferred.promise; }; + var getUserBlobs = function() { + var deferred = $q.defer(); + $http.get("/blobs").success(function(data, status, headers, config) { + var blobs = _.map(data, lingvodoc.Blob.fromJS); + deferred.resolve(blobs); + }).error(function(data, status, headers, config) { + deferred.reject("Failed to fetch list of available blobs"); + }); + return deferred.promise; + }; + var checkDictionaryBlob = function(blob, parent) { + var deferred = $q.defer(); + var query = { + blob_client_id: blob.client_id, + blob_object_id: blob.object_id, + parent_client_id: parent.client_id, + parent_object_id: parent.object_id + }; + $http.post("/convert_check", query).success(function(data, status, headers, config) { + var perspectives = _.map(data, lingvodoc.Perspective.fromJS); + deferred.resolve(perspectives); + }).error(function(data, status, headers, config) { + deferred.reject("Failed to convert dictionary"); + }); + return deferred.promise; + }; + var convertDictionary = function(req) { + var deferred = $q.defer(); + $http.post("/convert", req).success(function(data, status, headers, config) { + deferred.resolve(data); + }).error(function(data, status, headers, config) { + deferred.reject("Failed to convert dictionary"); + }); + return deferred.promise; + }; + var getPerspectiveMeta = function(dictionary, perspective) { + var deferred = $q.defer(); + var url = "/dictionary/" + encodeURIComponent(dictionary.client_id) + "/" + encodeURIComponent(dictionary.object_id) + "/perspective/" + encodeURIComponent(perspective.client_id) + "/" + encodeURIComponent(perspective.object_id) + "/meta"; + $http.get(url).success(function(data, status, headers, config) { + deferred.resolve(data); + }).error(function(data, status, headers, config) { + deferred.reject("Failed to get perspective meta data!"); + }); + return deferred.promise; + }; + var setPerspectiveMeta = function(dictionary, perspective, meta) { + var deferred = $q.defer(); + var url = "/dictionary/" + encodeURIComponent(dictionary.client_id) + "/" + encodeURIComponent(dictionary.object_id) + "/perspective/" + encodeURIComponent(perspective.client_id) + "/" + encodeURIComponent(perspective.object_id) + "/meta"; + $http.put(url, meta).success(function(data, status, headers, config) { + deferred.resolve(data); + }).error(function(data, status, headers, config) { + deferred.reject("Failed to set perspective meta data!"); + }); + return deferred.promise; + }; + var removePerspectiveMeta = function(dictionary, perspective, meta) { + var deferred = $q.defer(); + var url = "/dictionary/" + encodeURIComponent(dictionary.client_id) + "/" + encodeURIComponent(dictionary.object_id) + "/perspective/" + encodeURIComponent(perspective.client_id) + "/" + encodeURIComponent(perspective.object_id) + "/meta"; + var config = { + method: "DELETE", + url: url, + data: meta, + headers: { + "Content-Type": "application/json;charset=utf-8" + } + }; + $http(config).success(function(data, status, headers, config) { + deferred.resolve(data); + }).error(function(data, status, headers, config) { + deferred.reject("Failed to remove perspective meta data!"); + }); + return deferred.promise; + }; + var advancedSearch = function(query, where, adopted, etymology) { + var deferred = $q.defer(); + var url = "/advanced_search"; + var perspectives = where.map(function(o) { + if (o.type == "perspective") { + return { + client_id: o.client_id, + object_id: o.object_id + }; + } + }).filter(function(o) { + return typeof o !== "undefined"; + }); + var req = { + searchstrings: query, + perspectives: perspectives + }; + if (_.isBoolean(adopted)) { + req.adopted = adopted; + } + if (_.isBoolean(etymology)) { + req.with_etimology = etymology; + } + $http.post(url, req).success(function(data, status, headers, config) { + var r = data.map(function(e) { + var perspective = lingvodoc.Perspective.fromJS(e); + return getPerspectiveOriginById(perspective.client_id, perspective.object_id); + }); + $q.all(r).then(function(paths) { + var out = []; + _.each(data, function(entry, i) { + entry.lexical_entry["origin"] = paths[i]; + out.push(entry.lexical_entry); + }); + deferred.resolve(out); + }, function(reason) { + deferred.reject("An error occurred while doing basic search"); + }); + }).error(function(data, status, headers, config) { + deferred.reject("An error occurred while doing advanced search"); + }); + return deferred.promise; + }; + var convertMarkup = function(object) { + var deferred = $q.defer(); + var obj = { + client_id: object.client_id, + object_id: object.object_id + }; + $http.post("/convert/markup", obj).success(function(data, status, headers, config) { + deferred.resolve(data); + }).error(function(data, status, headers, config) { + deferred.reject("Failed to convert markup!"); + }); + return deferred.promise; + }; return { getLexicalEntries: getLexicalEntries, getLexicalEntriesCount: getLexicalEntriesCount, getPerspectiveDictionaryFields: getPerspectiveDictionaryFields, + getPerspectiveDictionaryFieldsNew: getPerspectiveDictionaryFieldsNew, addNewLexicalEntry: addNewLexicalEntry, saveValue: saveValue, removeValue: removeValue, @@ -28253,6 +32719,7 @@ function lingvodocAPI($http, $q) { approveAll: approveAll, getDictionaryProperties: getDictionaryProperties, setDictionaryProperties: setDictionaryProperties, + removeDictionary: removeDictionary, getLanguages: getLanguages, setDictionaryStatus: setDictionaryStatus, setPerspectiveStatus: setPerspectiveStatus, @@ -28260,6 +32727,7 @@ function lingvodocAPI($http, $q) { getPerspectiveFields: getPerspectiveFields, setPerspectiveFields: setPerspectiveFields, getPerspectiveFieldsNew: getPerspectiveFieldsNew, + removePerspective: removePerspective, getUserInfo: getUserInfo, setUserInfo: setUserInfo, getOrganizations: getOrganizations, @@ -28286,7 +32754,15 @@ function lingvodocAPI($http, $q) { deleteDictionaryRoles: deleteDictionaryRoles, getPerspectiveRoles: getPerspectiveRoles, addPerspectiveRoles: addPerspectiveRoles, - deletePerspectiveRoles: deletePerspectiveRoles + deletePerspectiveRoles: deletePerspectiveRoles, + getUserBlobs: getUserBlobs, + checkDictionaryBlob: checkDictionaryBlob, + convertDictionary: convertDictionary, + getPerspectiveMeta: getPerspectiveMeta, + setPerspectiveMeta: setPerspectiveMeta, + removePerspectiveMeta: removePerspectiveMeta, + advancedSearch: advancedSearch, + convertMarkup: convertMarkup }; } @@ -28318,9 +32794,34 @@ function responseHandler($timeout, $modal) { function error(message) { show("error", message, 5e3); } + function yesno(status, message, callback) { + var controller = function($scope, $modalInstance) { + $scope.status = status; + $scope.message = message; + $scope.yes = function() { + $modalInstance.close(true); + }; + $scope.no = function() { + $modalInstance.close(false); + }; + }; + $modal.open({ + animation: true, + templateUrl: "responseHandlerYesNoModal.html", + controller: controller, + size: "lg", + backdrop: "static", + keyboard: false + }).result.then(function(result) { + callback(result); + }, function() { + callback(false); + }); + } return { success: success, - error: error + error: error, + yesno: yesno }; } @@ -28336,7 +32837,7 @@ angular.module("PublishDictionaryModule", [ "ui.bootstrap" ]).service("dictionar if ($attrs.url) { wavesurfer.load($attrs.url, $attrs.data || null); } - $scope.$emit("wavesurferInit", wavesurfer); + $scope.$emit("wavesurferInit", wavesurfer, $element); } }; }).directive("onReadFile", function($parse) { @@ -28487,18 +32988,18 @@ angular.module("PublishDictionaryModule", [ "ui.bootstrap" ]).service("dictionar } }); }; - $scope.annotate = function(soundEntity, markupEntity) { + $scope.annotate = function(sound, markup) { var modalInstance = $modal.open({ animation: true, templateUrl: "annotationModal.html", controller: "AnnotationController", size: "lg", resolve: { - soundUrl: function() { - return soundEntity.content; - }, - annotationUrl: function() { - return markupEntity.content; + params: function() { + return { + sound: sound, + markup: markup + }; } } }); @@ -28562,7 +33063,7 @@ angular.module("PublishDictionaryModule", [ "ui.bootstrap" ]).service("dictionar }, function(reason) { responseHandler.error(reason); }); -} ]).controller("AnnotationController", [ "$scope", "$http", "soundUrl", "responseHandler", "annotationUrl", function($scope, $http, soundUrl, responseHandler, annotationUrl) { +} ]).controller("AnnotationController", [ "$scope", "$http", "dictionaryService", "responseHandler", "params", function($scope, $http, dictionaryService, responseHandler, params) { var activeUrl = null; var createRegions = function(annotaion) { if (annotaion instanceof elan.Document) { @@ -28580,19 +33081,6 @@ angular.module("PublishDictionaryModule", [ "ui.bootstrap" ]).service("dictionar }); } }; - var loadAnnotation = function(url) { - $http.get(url).success(function(data, status, headers, config) { - try { - var xml = new DOMParser().parseFromString(data, "application/xml"); - var annotation = new elan.Document(); - annotation.importXML(xml); - $scope.annotation = annotation; - createRegions(annotation); - } catch (e) { - alert("Failed to parse ELAN annotation: " + e); - } - }).error(function(data, status, headers, config) {}); - }; $scope.paused = true; $scope.annotation = null; $scope.playPause = function() { @@ -28631,10 +33119,23 @@ angular.module("PublishDictionaryModule", [ "ui.bootstrap" ]).service("dictionar region.remove(region); }); $scope.wavesurfer.once("ready", function() { - loadAnnotation(annotationUrl); + dictionaryService.convertMarkup(params.markup).then(function(data) { + try { + console.log(data.content); + var xml = new DOMParser().parseFromString(data.content, "application/xml"); + var annotation = new elan.Document(); + annotation.importXML(xml); + $scope.annotation = annotation; + createRegions(annotation); + } catch (e) { + responseHandler.error("Failed to parse ELAN annotation: " + e); + } + }, function(reason) { + responseHandler.error(reason); + }); $scope.$apply(); }); - $scope.wavesurfer.load(soundUrl); + $scope.wavesurfer.load(params.sound.content); }); $scope.$on("modal.closing", function(e) { $scope.wavesurfer.stop(); @@ -28840,7 +33341,7 @@ function WaveSurferController($scope) { $scope.isMediaFileAvailable = function() { return activeUrl != null; }; - $scope.$on("wavesurferInit", function(e, wavesurfer) { + $scope.$on("wavesurferInit", function(e, wavesurfer, container) { $scope.wavesurfer = wavesurfer; $scope.wavesurfer.on("play", function() { $scope.paused = false; diff --git a/lingvodoc/static/js/user-upload.js b/lingvodoc/static/js/user-upload.js index 8e77fadd9..03a2a93e5 100644 --- a/lingvodoc/static/js/user-upload.js +++ b/lingvodoc/static/js/user-upload.js @@ -5377,6 +5377,3947 @@ return jQuery; }); +(function() { + var undefined; + var VERSION = "3.10.1"; + var BIND_FLAG = 1, BIND_KEY_FLAG = 2, CURRY_BOUND_FLAG = 4, CURRY_FLAG = 8, CURRY_RIGHT_FLAG = 16, PARTIAL_FLAG = 32, PARTIAL_RIGHT_FLAG = 64, ARY_FLAG = 128, REARG_FLAG = 256; + var DEFAULT_TRUNC_LENGTH = 30, DEFAULT_TRUNC_OMISSION = "..."; + var HOT_COUNT = 150, HOT_SPAN = 16; + var LARGE_ARRAY_SIZE = 200; + var LAZY_FILTER_FLAG = 1, LAZY_MAP_FLAG = 2; + var FUNC_ERROR_TEXT = "Expected a function"; + var PLACEHOLDER = "__lodash_placeholder__"; + var argsTag = "[object Arguments]", arrayTag = "[object Array]", boolTag = "[object Boolean]", dateTag = "[object Date]", errorTag = "[object Error]", funcTag = "[object Function]", mapTag = "[object Map]", numberTag = "[object Number]", objectTag = "[object Object]", regexpTag = "[object RegExp]", setTag = "[object Set]", stringTag = "[object String]", weakMapTag = "[object WeakMap]"; + var arrayBufferTag = "[object ArrayBuffer]", float32Tag = "[object Float32Array]", float64Tag = "[object Float64Array]", int8Tag = "[object Int8Array]", int16Tag = "[object Int16Array]", int32Tag = "[object Int32Array]", uint8Tag = "[object Uint8Array]", uint8ClampedTag = "[object Uint8ClampedArray]", uint16Tag = "[object Uint16Array]", uint32Tag = "[object Uint32Array]"; + var reEmptyStringLeading = /\b__p \+= '';/g, reEmptyStringMiddle = /\b(__p \+=) '' \+/g, reEmptyStringTrailing = /(__e\(.*?\)|\b__t\)) \+\n'';/g; + var reEscapedHtml = /&(?:amp|lt|gt|quot|#39|#96);/g, reUnescapedHtml = /[&<>"'`]/g, reHasEscapedHtml = RegExp(reEscapedHtml.source), reHasUnescapedHtml = RegExp(reUnescapedHtml.source); + var reEscape = /<%-([\s\S]+?)%>/g, reEvaluate = /<%([\s\S]+?)%>/g, reInterpolate = /<%=([\s\S]+?)%>/g; + var reIsDeepProp = /\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\n\\]|\\.)*?\1)\]/, reIsPlainProp = /^\w*$/, rePropName = /[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\n\\]|\\.)*?)\2)\]/g; + var reRegExpChars = /^[:!,]|[\\^$.*+?()[\]{}|\/]|(^[0-9a-fA-Fnrtuvx])|([\n\r\u2028\u2029])/g, reHasRegExpChars = RegExp(reRegExpChars.source); + var reComboMark = /[\u0300-\u036f\ufe20-\ufe23]/g; + var reEscapeChar = /\\(\\)?/g; + var reEsTemplate = /\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g; + var reFlags = /\w*$/; + var reHasHexPrefix = /^0[xX]/; + var reIsHostCtor = /^\[object .+?Constructor\]$/; + var reIsUint = /^\d+$/; + var reLatin1 = /[\xc0-\xd6\xd8-\xde\xdf-\xf6\xf8-\xff]/g; + var reNoMatch = /($^)/; + var reUnescapedString = /['\n\r\u2028\u2029\\]/g; + var reWords = function() { + var upper = "[A-Z\\xc0-\\xd6\\xd8-\\xde]", lower = "[a-z\\xdf-\\xf6\\xf8-\\xff]+"; + return RegExp(upper + "+(?=" + upper + lower + ")|" + upper + "?" + lower + "|" + upper + "+|[0-9]+", "g"); + }(); + var contextProps = [ "Array", "ArrayBuffer", "Date", "Error", "Float32Array", "Float64Array", "Function", "Int8Array", "Int16Array", "Int32Array", "Math", "Number", "Object", "RegExp", "Set", "String", "_", "clearTimeout", "isFinite", "parseFloat", "parseInt", "setTimeout", "TypeError", "Uint8Array", "Uint8ClampedArray", "Uint16Array", "Uint32Array", "WeakMap" ]; + var templateCounter = -1; + var typedArrayTags = {}; + typedArrayTags[float32Tag] = typedArrayTags[float64Tag] = typedArrayTags[int8Tag] = typedArrayTags[int16Tag] = typedArrayTags[int32Tag] = typedArrayTags[uint8Tag] = typedArrayTags[uint8ClampedTag] = typedArrayTags[uint16Tag] = typedArrayTags[uint32Tag] = true; + typedArrayTags[argsTag] = typedArrayTags[arrayTag] = typedArrayTags[arrayBufferTag] = typedArrayTags[boolTag] = typedArrayTags[dateTag] = typedArrayTags[errorTag] = typedArrayTags[funcTag] = typedArrayTags[mapTag] = typedArrayTags[numberTag] = typedArrayTags[objectTag] = typedArrayTags[regexpTag] = typedArrayTags[setTag] = typedArrayTags[stringTag] = typedArrayTags[weakMapTag] = false; + var cloneableTags = {}; + cloneableTags[argsTag] = cloneableTags[arrayTag] = cloneableTags[arrayBufferTag] = cloneableTags[boolTag] = cloneableTags[dateTag] = cloneableTags[float32Tag] = cloneableTags[float64Tag] = cloneableTags[int8Tag] = cloneableTags[int16Tag] = cloneableTags[int32Tag] = cloneableTags[numberTag] = cloneableTags[objectTag] = cloneableTags[regexpTag] = cloneableTags[stringTag] = cloneableTags[uint8Tag] = cloneableTags[uint8ClampedTag] = cloneableTags[uint16Tag] = cloneableTags[uint32Tag] = true; + cloneableTags[errorTag] = cloneableTags[funcTag] = cloneableTags[mapTag] = cloneableTags[setTag] = cloneableTags[weakMapTag] = false; + var deburredLetters = { + "À": "A", + "Á": "A", + "Â": "A", + "Ã": "A", + "Ä": "A", + "Å": "A", + "à": "a", + "á": "a", + "â": "a", + "ã": "a", + "ä": "a", + "å": "a", + "Ç": "C", + "ç": "c", + "Ð": "D", + "ð": "d", + "È": "E", + "É": "E", + "Ê": "E", + "Ë": "E", + "è": "e", + "é": "e", + "ê": "e", + "ë": "e", + "Ì": "I", + "Í": "I", + "Î": "I", + "Ï": "I", + "ì": "i", + "í": "i", + "î": "i", + "ï": "i", + "Ñ": "N", + "ñ": "n", + "Ò": "O", + "Ó": "O", + "Ô": "O", + "Õ": "O", + "Ö": "O", + "Ø": "O", + "ò": "o", + "ó": "o", + "ô": "o", + "õ": "o", + "ö": "o", + "ø": "o", + "Ù": "U", + "Ú": "U", + "Û": "U", + "Ü": "U", + "ù": "u", + "ú": "u", + "û": "u", + "ü": "u", + "Ý": "Y", + "ý": "y", + "ÿ": "y", + "Æ": "Ae", + "æ": "ae", + "Þ": "Th", + "þ": "th", + "ß": "ss" + }; + var htmlEscapes = { + "&": "&", + "<": "<", + ">": ">", + '"': """, + "'": "'", + "`": "`" + }; + var htmlUnescapes = { + "&": "&", + "<": "<", + ">": ">", + """: '"', + "'": "'", + "`": "`" + }; + var objectTypes = { + "function": true, + object: true + }; + var regexpEscapes = { + "0": "x30", + "1": "x31", + "2": "x32", + "3": "x33", + "4": "x34", + "5": "x35", + "6": "x36", + "7": "x37", + "8": "x38", + "9": "x39", + A: "x41", + B: "x42", + C: "x43", + D: "x44", + E: "x45", + F: "x46", + a: "x61", + b: "x62", + c: "x63", + d: "x64", + e: "x65", + f: "x66", + n: "x6e", + r: "x72", + t: "x74", + u: "x75", + v: "x76", + x: "x78" + }; + var stringEscapes = { + "\\": "\\", + "'": "'", + "\n": "n", + "\r": "r", + "\u2028": "u2028", + "\u2029": "u2029" + }; + var freeExports = objectTypes[typeof exports] && exports && !exports.nodeType && exports; + var freeModule = objectTypes[typeof module] && module && !module.nodeType && module; + var freeGlobal = freeExports && freeModule && typeof global == "object" && global && global.Object && global; + var freeSelf = objectTypes[typeof self] && self && self.Object && self; + var freeWindow = objectTypes[typeof window] && window && window.Object && window; + var moduleExports = freeModule && freeModule.exports === freeExports && freeExports; + var root = freeGlobal || freeWindow !== (this && this.window) && freeWindow || freeSelf || this; + function baseCompareAscending(value, other) { + if (value !== other) { + var valIsNull = value === null, valIsUndef = value === undefined, valIsReflexive = value === value; + var othIsNull = other === null, othIsUndef = other === undefined, othIsReflexive = other === other; + if (value > other && !othIsNull || !valIsReflexive || valIsNull && !othIsUndef && othIsReflexive || valIsUndef && othIsReflexive) { + return 1; + } + if (value < other && !valIsNull || !othIsReflexive || othIsNull && !valIsUndef && valIsReflexive || othIsUndef && valIsReflexive) { + return -1; + } + } + return 0; + } + function baseFindIndex(array, predicate, fromRight) { + var length = array.length, index = fromRight ? length : -1; + while (fromRight ? index-- : ++index < length) { + if (predicate(array[index], index, array)) { + return index; + } + } + return -1; + } + function baseIndexOf(array, value, fromIndex) { + if (value !== value) { + return indexOfNaN(array, fromIndex); + } + var index = fromIndex - 1, length = array.length; + while (++index < length) { + if (array[index] === value) { + return index; + } + } + return -1; + } + function baseIsFunction(value) { + return typeof value == "function" || false; + } + function baseToString(value) { + return value == null ? "" : value + ""; + } + function charsLeftIndex(string, chars) { + var index = -1, length = string.length; + while (++index < length && chars.indexOf(string.charAt(index)) > -1) {} + return index; + } + function charsRightIndex(string, chars) { + var index = string.length; + while (index-- && chars.indexOf(string.charAt(index)) > -1) {} + return index; + } + function compareAscending(object, other) { + return baseCompareAscending(object.criteria, other.criteria) || object.index - other.index; + } + function compareMultiple(object, other, orders) { + var index = -1, objCriteria = object.criteria, othCriteria = other.criteria, length = objCriteria.length, ordersLength = orders.length; + while (++index < length) { + var result = baseCompareAscending(objCriteria[index], othCriteria[index]); + if (result) { + if (index >= ordersLength) { + return result; + } + var order = orders[index]; + return result * (order === "asc" || order === true ? 1 : -1); + } + } + return object.index - other.index; + } + function deburrLetter(letter) { + return deburredLetters[letter]; + } + function escapeHtmlChar(chr) { + return htmlEscapes[chr]; + } + function escapeRegExpChar(chr, leadingChar, whitespaceChar) { + if (leadingChar) { + chr = regexpEscapes[chr]; + } else if (whitespaceChar) { + chr = stringEscapes[chr]; + } + return "\\" + chr; + } + function escapeStringChar(chr) { + return "\\" + stringEscapes[chr]; + } + function indexOfNaN(array, fromIndex, fromRight) { + var length = array.length, index = fromIndex + (fromRight ? 0 : -1); + while (fromRight ? index-- : ++index < length) { + var other = array[index]; + if (other !== other) { + return index; + } + } + return -1; + } + function isObjectLike(value) { + return !!value && typeof value == "object"; + } + function isSpace(charCode) { + return charCode <= 160 && (charCode >= 9 && charCode <= 13) || charCode == 32 || charCode == 160 || charCode == 5760 || charCode == 6158 || charCode >= 8192 && (charCode <= 8202 || charCode == 8232 || charCode == 8233 || charCode == 8239 || charCode == 8287 || charCode == 12288 || charCode == 65279); + } + function replaceHolders(array, placeholder) { + var index = -1, length = array.length, resIndex = -1, result = []; + while (++index < length) { + if (array[index] === placeholder) { + array[index] = PLACEHOLDER; + result[++resIndex] = index; + } + } + return result; + } + function sortedUniq(array, iteratee) { + var seen, index = -1, length = array.length, resIndex = -1, result = []; + while (++index < length) { + var value = array[index], computed = iteratee ? iteratee(value, index, array) : value; + if (!index || seen !== computed) { + seen = computed; + result[++resIndex] = value; + } + } + return result; + } + function trimmedLeftIndex(string) { + var index = -1, length = string.length; + while (++index < length && isSpace(string.charCodeAt(index))) {} + return index; + } + function trimmedRightIndex(string) { + var index = string.length; + while (index-- && isSpace(string.charCodeAt(index))) {} + return index; + } + function unescapeHtmlChar(chr) { + return htmlUnescapes[chr]; + } + function runInContext(context) { + context = context ? _.defaults(root.Object(), context, _.pick(root, contextProps)) : root; + var Array = context.Array, Date = context.Date, Error = context.Error, Function = context.Function, Math = context.Math, Number = context.Number, Object = context.Object, RegExp = context.RegExp, String = context.String, TypeError = context.TypeError; + var arrayProto = Array.prototype, objectProto = Object.prototype, stringProto = String.prototype; + var fnToString = Function.prototype.toString; + var hasOwnProperty = objectProto.hasOwnProperty; + var idCounter = 0; + var objToString = objectProto.toString; + var oldDash = root._; + var reIsNative = RegExp("^" + fnToString.call(hasOwnProperty).replace(/[\\^$.*+?()[\]{}|]/g, "\\$&").replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g, "$1.*?") + "$"); + var ArrayBuffer = context.ArrayBuffer, clearTimeout = context.clearTimeout, parseFloat = context.parseFloat, pow = Math.pow, propertyIsEnumerable = objectProto.propertyIsEnumerable, Set = getNative(context, "Set"), setTimeout = context.setTimeout, splice = arrayProto.splice, Uint8Array = context.Uint8Array, WeakMap = getNative(context, "WeakMap"); + var nativeCeil = Math.ceil, nativeCreate = getNative(Object, "create"), nativeFloor = Math.floor, nativeIsArray = getNative(Array, "isArray"), nativeIsFinite = context.isFinite, nativeKeys = getNative(Object, "keys"), nativeMax = Math.max, nativeMin = Math.min, nativeNow = getNative(Date, "now"), nativeParseInt = context.parseInt, nativeRandom = Math.random; + var NEGATIVE_INFINITY = Number.NEGATIVE_INFINITY, POSITIVE_INFINITY = Number.POSITIVE_INFINITY; + var MAX_ARRAY_LENGTH = 4294967295, MAX_ARRAY_INDEX = MAX_ARRAY_LENGTH - 1, HALF_MAX_ARRAY_LENGTH = MAX_ARRAY_LENGTH >>> 1; + var MAX_SAFE_INTEGER = 9007199254740991; + var metaMap = WeakMap && new WeakMap(); + var realNames = {}; + function lodash(value) { + if (isObjectLike(value) && !isArray(value) && !(value instanceof LazyWrapper)) { + if (value instanceof LodashWrapper) { + return value; + } + if (hasOwnProperty.call(value, "__chain__") && hasOwnProperty.call(value, "__wrapped__")) { + return wrapperClone(value); + } + } + return new LodashWrapper(value); + } + function baseLodash() {} + function LodashWrapper(value, chainAll, actions) { + this.__wrapped__ = value; + this.__actions__ = actions || []; + this.__chain__ = !!chainAll; + } + var support = lodash.support = {}; + lodash.templateSettings = { + escape: reEscape, + evaluate: reEvaluate, + interpolate: reInterpolate, + variable: "", + imports: { + _: lodash + } + }; + function LazyWrapper(value) { + this.__wrapped__ = value; + this.__actions__ = []; + this.__dir__ = 1; + this.__filtered__ = false; + this.__iteratees__ = []; + this.__takeCount__ = POSITIVE_INFINITY; + this.__views__ = []; + } + function lazyClone() { + var result = new LazyWrapper(this.__wrapped__); + result.__actions__ = arrayCopy(this.__actions__); + result.__dir__ = this.__dir__; + result.__filtered__ = this.__filtered__; + result.__iteratees__ = arrayCopy(this.__iteratees__); + result.__takeCount__ = this.__takeCount__; + result.__views__ = arrayCopy(this.__views__); + return result; + } + function lazyReverse() { + if (this.__filtered__) { + var result = new LazyWrapper(this); + result.__dir__ = -1; + result.__filtered__ = true; + } else { + result = this.clone(); + result.__dir__ *= -1; + } + return result; + } + function lazyValue() { + var array = this.__wrapped__.value(), dir = this.__dir__, isArr = isArray(array), isRight = dir < 0, arrLength = isArr ? array.length : 0, view = getView(0, arrLength, this.__views__), start = view.start, end = view.end, length = end - start, index = isRight ? end : start - 1, iteratees = this.__iteratees__, iterLength = iteratees.length, resIndex = 0, takeCount = nativeMin(length, this.__takeCount__); + if (!isArr || arrLength < LARGE_ARRAY_SIZE || arrLength == length && takeCount == length) { + return baseWrapperValue(array, this.__actions__); + } + var result = []; + outer: while (length-- && resIndex < takeCount) { + index += dir; + var iterIndex = -1, value = array[index]; + while (++iterIndex < iterLength) { + var data = iteratees[iterIndex], iteratee = data.iteratee, type = data.type, computed = iteratee(value); + if (type == LAZY_MAP_FLAG) { + value = computed; + } else if (!computed) { + if (type == LAZY_FILTER_FLAG) { + continue outer; + } else { + break outer; + } + } + } + result[resIndex++] = value; + } + return result; + } + function MapCache() { + this.__data__ = {}; + } + function mapDelete(key) { + return this.has(key) && delete this.__data__[key]; + } + function mapGet(key) { + return key == "__proto__" ? undefined : this.__data__[key]; + } + function mapHas(key) { + return key != "__proto__" && hasOwnProperty.call(this.__data__, key); + } + function mapSet(key, value) { + if (key != "__proto__") { + this.__data__[key] = value; + } + return this; + } + function SetCache(values) { + var length = values ? values.length : 0; + this.data = { + hash: nativeCreate(null), + set: new Set() + }; + while (length--) { + this.push(values[length]); + } + } + function cacheIndexOf(cache, value) { + var data = cache.data, result = typeof value == "string" || isObject(value) ? data.set.has(value) : data.hash[value]; + return result ? 0 : -1; + } + function cachePush(value) { + var data = this.data; + if (typeof value == "string" || isObject(value)) { + data.set.add(value); + } else { + data.hash[value] = true; + } + } + function arrayConcat(array, other) { + var index = -1, length = array.length, othIndex = -1, othLength = other.length, result = Array(length + othLength); + while (++index < length) { + result[index] = array[index]; + } + while (++othIndex < othLength) { + result[index++] = other[othIndex]; + } + return result; + } + function arrayCopy(source, array) { + var index = -1, length = source.length; + array || (array = Array(length)); + while (++index < length) { + array[index] = source[index]; + } + return array; + } + function arrayEach(array, iteratee) { + var index = -1, length = array.length; + while (++index < length) { + if (iteratee(array[index], index, array) === false) { + break; + } + } + return array; + } + function arrayEachRight(array, iteratee) { + var length = array.length; + while (length--) { + if (iteratee(array[length], length, array) === false) { + break; + } + } + return array; + } + function arrayEvery(array, predicate) { + var index = -1, length = array.length; + while (++index < length) { + if (!predicate(array[index], index, array)) { + return false; + } + } + return true; + } + function arrayExtremum(array, iteratee, comparator, exValue) { + var index = -1, length = array.length, computed = exValue, result = computed; + while (++index < length) { + var value = array[index], current = +iteratee(value); + if (comparator(current, computed)) { + computed = current; + result = value; + } + } + return result; + } + function arrayFilter(array, predicate) { + var index = -1, length = array.length, resIndex = -1, result = []; + while (++index < length) { + var value = array[index]; + if (predicate(value, index, array)) { + result[++resIndex] = value; + } + } + return result; + } + function arrayMap(array, iteratee) { + var index = -1, length = array.length, result = Array(length); + while (++index < length) { + result[index] = iteratee(array[index], index, array); + } + return result; + } + function arrayPush(array, values) { + var index = -1, length = values.length, offset = array.length; + while (++index < length) { + array[offset + index] = values[index]; + } + return array; + } + function arrayReduce(array, iteratee, accumulator, initFromArray) { + var index = -1, length = array.length; + if (initFromArray && length) { + accumulator = array[++index]; + } + while (++index < length) { + accumulator = iteratee(accumulator, array[index], index, array); + } + return accumulator; + } + function arrayReduceRight(array, iteratee, accumulator, initFromArray) { + var length = array.length; + if (initFromArray && length) { + accumulator = array[--length]; + } + while (length--) { + accumulator = iteratee(accumulator, array[length], length, array); + } + return accumulator; + } + function arraySome(array, predicate) { + var index = -1, length = array.length; + while (++index < length) { + if (predicate(array[index], index, array)) { + return true; + } + } + return false; + } + function arraySum(array, iteratee) { + var length = array.length, result = 0; + while (length--) { + result += +iteratee(array[length]) || 0; + } + return result; + } + function assignDefaults(objectValue, sourceValue) { + return objectValue === undefined ? sourceValue : objectValue; + } + function assignOwnDefaults(objectValue, sourceValue, key, object) { + return objectValue === undefined || !hasOwnProperty.call(object, key) ? sourceValue : objectValue; + } + function assignWith(object, source, customizer) { + var index = -1, props = keys(source), length = props.length; + while (++index < length) { + var key = props[index], value = object[key], result = customizer(value, source[key], key, object, source); + if ((result === result ? result !== value : value === value) || value === undefined && !(key in object)) { + object[key] = result; + } + } + return object; + } + function baseAssign(object, source) { + return source == null ? object : baseCopy(source, keys(source), object); + } + function baseAt(collection, props) { + var index = -1, isNil = collection == null, isArr = !isNil && isArrayLike(collection), length = isArr ? collection.length : 0, propsLength = props.length, result = Array(propsLength); + while (++index < propsLength) { + var key = props[index]; + if (isArr) { + result[index] = isIndex(key, length) ? collection[key] : undefined; + } else { + result[index] = isNil ? undefined : collection[key]; + } + } + return result; + } + function baseCopy(source, props, object) { + object || (object = {}); + var index = -1, length = props.length; + while (++index < length) { + var key = props[index]; + object[key] = source[key]; + } + return object; + } + function baseCallback(func, thisArg, argCount) { + var type = typeof func; + if (type == "function") { + return thisArg === undefined ? func : bindCallback(func, thisArg, argCount); + } + if (func == null) { + return identity; + } + if (type == "object") { + return baseMatches(func); + } + return thisArg === undefined ? property(func) : baseMatchesProperty(func, thisArg); + } + function baseClone(value, isDeep, customizer, key, object, stackA, stackB) { + var result; + if (customizer) { + result = object ? customizer(value, key, object) : customizer(value); + } + if (result !== undefined) { + return result; + } + if (!isObject(value)) { + return value; + } + var isArr = isArray(value); + if (isArr) { + result = initCloneArray(value); + if (!isDeep) { + return arrayCopy(value, result); + } + } else { + var tag = objToString.call(value), isFunc = tag == funcTag; + if (tag == objectTag || tag == argsTag || isFunc && !object) { + result = initCloneObject(isFunc ? {} : value); + if (!isDeep) { + return baseAssign(result, value); + } + } else { + return cloneableTags[tag] ? initCloneByTag(value, tag, isDeep) : object ? value : {}; + } + } + stackA || (stackA = []); + stackB || (stackB = []); + var length = stackA.length; + while (length--) { + if (stackA[length] == value) { + return stackB[length]; + } + } + stackA.push(value); + stackB.push(result); + (isArr ? arrayEach : baseForOwn)(value, function(subValue, key) { + result[key] = baseClone(subValue, isDeep, customizer, key, value, stackA, stackB); + }); + return result; + } + var baseCreate = function() { + function object() {} + return function(prototype) { + if (isObject(prototype)) { + object.prototype = prototype; + var result = new object(); + object.prototype = undefined; + } + return result || {}; + }; + }(); + function baseDelay(func, wait, args) { + if (typeof func != "function") { + throw new TypeError(FUNC_ERROR_TEXT); + } + return setTimeout(function() { + func.apply(undefined, args); + }, wait); + } + function baseDifference(array, values) { + var length = array ? array.length : 0, result = []; + if (!length) { + return result; + } + var index = -1, indexOf = getIndexOf(), isCommon = indexOf === baseIndexOf, cache = isCommon && values.length >= LARGE_ARRAY_SIZE ? createCache(values) : null, valuesLength = values.length; + if (cache) { + indexOf = cacheIndexOf; + isCommon = false; + values = cache; + } + outer: while (++index < length) { + var value = array[index]; + if (isCommon && value === value) { + var valuesIndex = valuesLength; + while (valuesIndex--) { + if (values[valuesIndex] === value) { + continue outer; + } + } + result.push(value); + } else if (indexOf(values, value, 0) < 0) { + result.push(value); + } + } + return result; + } + var baseEach = createBaseEach(baseForOwn); + var baseEachRight = createBaseEach(baseForOwnRight, true); + function baseEvery(collection, predicate) { + var result = true; + baseEach(collection, function(value, index, collection) { + result = !!predicate(value, index, collection); + return result; + }); + return result; + } + function baseExtremum(collection, iteratee, comparator, exValue) { + var computed = exValue, result = computed; + baseEach(collection, function(value, index, collection) { + var current = +iteratee(value, index, collection); + if (comparator(current, computed) || current === exValue && current === result) { + computed = current; + result = value; + } + }); + return result; + } + function baseFill(array, value, start, end) { + var length = array.length; + start = start == null ? 0 : +start || 0; + if (start < 0) { + start = -start > length ? 0 : length + start; + } + end = end === undefined || end > length ? length : +end || 0; + if (end < 0) { + end += length; + } + length = start > end ? 0 : end >>> 0; + start >>>= 0; + while (start < length) { + array[start++] = value; + } + return array; + } + function baseFilter(collection, predicate) { + var result = []; + baseEach(collection, function(value, index, collection) { + if (predicate(value, index, collection)) { + result.push(value); + } + }); + return result; + } + function baseFind(collection, predicate, eachFunc, retKey) { + var result; + eachFunc(collection, function(value, key, collection) { + if (predicate(value, key, collection)) { + result = retKey ? key : value; + return false; + } + }); + return result; + } + function baseFlatten(array, isDeep, isStrict, result) { + result || (result = []); + var index = -1, length = array.length; + while (++index < length) { + var value = array[index]; + if (isObjectLike(value) && isArrayLike(value) && (isStrict || isArray(value) || isArguments(value))) { + if (isDeep) { + baseFlatten(value, isDeep, isStrict, result); + } else { + arrayPush(result, value); + } + } else if (!isStrict) { + result[result.length] = value; + } + } + return result; + } + var baseFor = createBaseFor(); + var baseForRight = createBaseFor(true); + function baseForIn(object, iteratee) { + return baseFor(object, iteratee, keysIn); + } + function baseForOwn(object, iteratee) { + return baseFor(object, iteratee, keys); + } + function baseForOwnRight(object, iteratee) { + return baseForRight(object, iteratee, keys); + } + function baseFunctions(object, props) { + var index = -1, length = props.length, resIndex = -1, result = []; + while (++index < length) { + var key = props[index]; + if (isFunction(object[key])) { + result[++resIndex] = key; + } + } + return result; + } + function baseGet(object, path, pathKey) { + if (object == null) { + return; + } + if (pathKey !== undefined && pathKey in toObject(object)) { + path = [ pathKey ]; + } + var index = 0, length = path.length; + while (object != null && index < length) { + object = object[path[index++]]; + } + return index && index == length ? object : undefined; + } + function baseIsEqual(value, other, customizer, isLoose, stackA, stackB) { + if (value === other) { + return true; + } + if (value == null || other == null || !isObject(value) && !isObjectLike(other)) { + return value !== value && other !== other; + } + return baseIsEqualDeep(value, other, baseIsEqual, customizer, isLoose, stackA, stackB); + } + function baseIsEqualDeep(object, other, equalFunc, customizer, isLoose, stackA, stackB) { + var objIsArr = isArray(object), othIsArr = isArray(other), objTag = arrayTag, othTag = arrayTag; + if (!objIsArr) { + objTag = objToString.call(object); + if (objTag == argsTag) { + objTag = objectTag; + } else if (objTag != objectTag) { + objIsArr = isTypedArray(object); + } + } + if (!othIsArr) { + othTag = objToString.call(other); + if (othTag == argsTag) { + othTag = objectTag; + } else if (othTag != objectTag) { + othIsArr = isTypedArray(other); + } + } + var objIsObj = objTag == objectTag, othIsObj = othTag == objectTag, isSameTag = objTag == othTag; + if (isSameTag && !(objIsArr || objIsObj)) { + return equalByTag(object, other, objTag); + } + if (!isLoose) { + var objIsWrapped = objIsObj && hasOwnProperty.call(object, "__wrapped__"), othIsWrapped = othIsObj && hasOwnProperty.call(other, "__wrapped__"); + if (objIsWrapped || othIsWrapped) { + return equalFunc(objIsWrapped ? object.value() : object, othIsWrapped ? other.value() : other, customizer, isLoose, stackA, stackB); + } + } + if (!isSameTag) { + return false; + } + stackA || (stackA = []); + stackB || (stackB = []); + var length = stackA.length; + while (length--) { + if (stackA[length] == object) { + return stackB[length] == other; + } + } + stackA.push(object); + stackB.push(other); + var result = (objIsArr ? equalArrays : equalObjects)(object, other, equalFunc, customizer, isLoose, stackA, stackB); + stackA.pop(); + stackB.pop(); + return result; + } + function baseIsMatch(object, matchData, customizer) { + var index = matchData.length, length = index, noCustomizer = !customizer; + if (object == null) { + return !length; + } + object = toObject(object); + while (index--) { + var data = matchData[index]; + if (noCustomizer && data[2] ? data[1] !== object[data[0]] : !(data[0] in object)) { + return false; + } + } + while (++index < length) { + data = matchData[index]; + var key = data[0], objValue = object[key], srcValue = data[1]; + if (noCustomizer && data[2]) { + if (objValue === undefined && !(key in object)) { + return false; + } + } else { + var result = customizer ? customizer(objValue, srcValue, key) : undefined; + if (!(result === undefined ? baseIsEqual(srcValue, objValue, customizer, true) : result)) { + return false; + } + } + } + return true; + } + function baseMap(collection, iteratee) { + var index = -1, result = isArrayLike(collection) ? Array(collection.length) : []; + baseEach(collection, function(value, key, collection) { + result[++index] = iteratee(value, key, collection); + }); + return result; + } + function baseMatches(source) { + var matchData = getMatchData(source); + if (matchData.length == 1 && matchData[0][2]) { + var key = matchData[0][0], value = matchData[0][1]; + return function(object) { + if (object == null) { + return false; + } + return object[key] === value && (value !== undefined || key in toObject(object)); + }; + } + return function(object) { + return baseIsMatch(object, matchData); + }; + } + function baseMatchesProperty(path, srcValue) { + var isArr = isArray(path), isCommon = isKey(path) && isStrictComparable(srcValue), pathKey = path + ""; + path = toPath(path); + return function(object) { + if (object == null) { + return false; + } + var key = pathKey; + object = toObject(object); + if ((isArr || !isCommon) && !(key in object)) { + object = path.length == 1 ? object : baseGet(object, baseSlice(path, 0, -1)); + if (object == null) { + return false; + } + key = last(path); + object = toObject(object); + } + return object[key] === srcValue ? srcValue !== undefined || key in object : baseIsEqual(srcValue, object[key], undefined, true); + }; + } + function baseMerge(object, source, customizer, stackA, stackB) { + if (!isObject(object)) { + return object; + } + var isSrcArr = isArrayLike(source) && (isArray(source) || isTypedArray(source)), props = isSrcArr ? undefined : keys(source); + arrayEach(props || source, function(srcValue, key) { + if (props) { + key = srcValue; + srcValue = source[key]; + } + if (isObjectLike(srcValue)) { + stackA || (stackA = []); + stackB || (stackB = []); + baseMergeDeep(object, source, key, baseMerge, customizer, stackA, stackB); + } else { + var value = object[key], result = customizer ? customizer(value, srcValue, key, object, source) : undefined, isCommon = result === undefined; + if (isCommon) { + result = srcValue; + } + if ((result !== undefined || isSrcArr && !(key in object)) && (isCommon || (result === result ? result !== value : value === value))) { + object[key] = result; + } + } + }); + return object; + } + function baseMergeDeep(object, source, key, mergeFunc, customizer, stackA, stackB) { + var length = stackA.length, srcValue = source[key]; + while (length--) { + if (stackA[length] == srcValue) { + object[key] = stackB[length]; + return; + } + } + var value = object[key], result = customizer ? customizer(value, srcValue, key, object, source) : undefined, isCommon = result === undefined; + if (isCommon) { + result = srcValue; + if (isArrayLike(srcValue) && (isArray(srcValue) || isTypedArray(srcValue))) { + result = isArray(value) ? value : isArrayLike(value) ? arrayCopy(value) : []; + } else if (isPlainObject(srcValue) || isArguments(srcValue)) { + result = isArguments(value) ? toPlainObject(value) : isPlainObject(value) ? value : {}; + } else { + isCommon = false; + } + } + stackA.push(srcValue); + stackB.push(result); + if (isCommon) { + object[key] = mergeFunc(result, srcValue, customizer, stackA, stackB); + } else if (result === result ? result !== value : value === value) { + object[key] = result; + } + } + function baseProperty(key) { + return function(object) { + return object == null ? undefined : object[key]; + }; + } + function basePropertyDeep(path) { + var pathKey = path + ""; + path = toPath(path); + return function(object) { + return baseGet(object, path, pathKey); + }; + } + function basePullAt(array, indexes) { + var length = array ? indexes.length : 0; + while (length--) { + var index = indexes[length]; + if (index != previous && isIndex(index)) { + var previous = index; + splice.call(array, index, 1); + } + } + return array; + } + function baseRandom(min, max) { + return min + nativeFloor(nativeRandom() * (max - min + 1)); + } + function baseReduce(collection, iteratee, accumulator, initFromCollection, eachFunc) { + eachFunc(collection, function(value, index, collection) { + accumulator = initFromCollection ? (initFromCollection = false, value) : iteratee(accumulator, value, index, collection); + }); + return accumulator; + } + var baseSetData = !metaMap ? identity : function(func, data) { + metaMap.set(func, data); + return func; + }; + function baseSlice(array, start, end) { + var index = -1, length = array.length; + start = start == null ? 0 : +start || 0; + if (start < 0) { + start = -start > length ? 0 : length + start; + } + end = end === undefined || end > length ? length : +end || 0; + if (end < 0) { + end += length; + } + length = start > end ? 0 : end - start >>> 0; + start >>>= 0; + var result = Array(length); + while (++index < length) { + result[index] = array[index + start]; + } + return result; + } + function baseSome(collection, predicate) { + var result; + baseEach(collection, function(value, index, collection) { + result = predicate(value, index, collection); + return !result; + }); + return !!result; + } + function baseSortBy(array, comparer) { + var length = array.length; + array.sort(comparer); + while (length--) { + array[length] = array[length].value; + } + return array; + } + function baseSortByOrder(collection, iteratees, orders) { + var callback = getCallback(), index = -1; + iteratees = arrayMap(iteratees, function(iteratee) { + return callback(iteratee); + }); + var result = baseMap(collection, function(value) { + var criteria = arrayMap(iteratees, function(iteratee) { + return iteratee(value); + }); + return { + criteria: criteria, + index: ++index, + value: value + }; + }); + return baseSortBy(result, function(object, other) { + return compareMultiple(object, other, orders); + }); + } + function baseSum(collection, iteratee) { + var result = 0; + baseEach(collection, function(value, index, collection) { + result += +iteratee(value, index, collection) || 0; + }); + return result; + } + function baseUniq(array, iteratee) { + var index = -1, indexOf = getIndexOf(), length = array.length, isCommon = indexOf === baseIndexOf, isLarge = isCommon && length >= LARGE_ARRAY_SIZE, seen = isLarge ? createCache() : null, result = []; + if (seen) { + indexOf = cacheIndexOf; + isCommon = false; + } else { + isLarge = false; + seen = iteratee ? [] : result; + } + outer: while (++index < length) { + var value = array[index], computed = iteratee ? iteratee(value, index, array) : value; + if (isCommon && value === value) { + var seenIndex = seen.length; + while (seenIndex--) { + if (seen[seenIndex] === computed) { + continue outer; + } + } + if (iteratee) { + seen.push(computed); + } + result.push(value); + } else if (indexOf(seen, computed, 0) < 0) { + if (iteratee || isLarge) { + seen.push(computed); + } + result.push(value); + } + } + return result; + } + function baseValues(object, props) { + var index = -1, length = props.length, result = Array(length); + while (++index < length) { + result[index] = object[props[index]]; + } + return result; + } + function baseWhile(array, predicate, isDrop, fromRight) { + var length = array.length, index = fromRight ? length : -1; + while ((fromRight ? index-- : ++index < length) && predicate(array[index], index, array)) {} + return isDrop ? baseSlice(array, fromRight ? 0 : index, fromRight ? index + 1 : length) : baseSlice(array, fromRight ? index + 1 : 0, fromRight ? length : index); + } + function baseWrapperValue(value, actions) { + var result = value; + if (result instanceof LazyWrapper) { + result = result.value(); + } + var index = -1, length = actions.length; + while (++index < length) { + var action = actions[index]; + result = action.func.apply(action.thisArg, arrayPush([ result ], action.args)); + } + return result; + } + function binaryIndex(array, value, retHighest) { + var low = 0, high = array ? array.length : low; + if (typeof value == "number" && value === value && high <= HALF_MAX_ARRAY_LENGTH) { + while (low < high) { + var mid = low + high >>> 1, computed = array[mid]; + if ((retHighest ? computed <= value : computed < value) && computed !== null) { + low = mid + 1; + } else { + high = mid; + } + } + return high; + } + return binaryIndexBy(array, value, identity, retHighest); + } + function binaryIndexBy(array, value, iteratee, retHighest) { + value = iteratee(value); + var low = 0, high = array ? array.length : 0, valIsNaN = value !== value, valIsNull = value === null, valIsUndef = value === undefined; + while (low < high) { + var mid = nativeFloor((low + high) / 2), computed = iteratee(array[mid]), isDef = computed !== undefined, isReflexive = computed === computed; + if (valIsNaN) { + var setLow = isReflexive || retHighest; + } else if (valIsNull) { + setLow = isReflexive && isDef && (retHighest || computed != null); + } else if (valIsUndef) { + setLow = isReflexive && (retHighest || isDef); + } else if (computed == null) { + setLow = false; + } else { + setLow = retHighest ? computed <= value : computed < value; + } + if (setLow) { + low = mid + 1; + } else { + high = mid; + } + } + return nativeMin(high, MAX_ARRAY_INDEX); + } + function bindCallback(func, thisArg, argCount) { + if (typeof func != "function") { + return identity; + } + if (thisArg === undefined) { + return func; + } + switch (argCount) { + case 1: + return function(value) { + return func.call(thisArg, value); + }; + + case 3: + return function(value, index, collection) { + return func.call(thisArg, value, index, collection); + }; + + case 4: + return function(accumulator, value, index, collection) { + return func.call(thisArg, accumulator, value, index, collection); + }; + + case 5: + return function(value, other, key, object, source) { + return func.call(thisArg, value, other, key, object, source); + }; + } + return function() { + return func.apply(thisArg, arguments); + }; + } + function bufferClone(buffer) { + var result = new ArrayBuffer(buffer.byteLength), view = new Uint8Array(result); + view.set(new Uint8Array(buffer)); + return result; + } + function composeArgs(args, partials, holders) { + var holdersLength = holders.length, argsIndex = -1, argsLength = nativeMax(args.length - holdersLength, 0), leftIndex = -1, leftLength = partials.length, result = Array(leftLength + argsLength); + while (++leftIndex < leftLength) { + result[leftIndex] = partials[leftIndex]; + } + while (++argsIndex < holdersLength) { + result[holders[argsIndex]] = args[argsIndex]; + } + while (argsLength--) { + result[leftIndex++] = args[argsIndex++]; + } + return result; + } + function composeArgsRight(args, partials, holders) { + var holdersIndex = -1, holdersLength = holders.length, argsIndex = -1, argsLength = nativeMax(args.length - holdersLength, 0), rightIndex = -1, rightLength = partials.length, result = Array(argsLength + rightLength); + while (++argsIndex < argsLength) { + result[argsIndex] = args[argsIndex]; + } + var offset = argsIndex; + while (++rightIndex < rightLength) { + result[offset + rightIndex] = partials[rightIndex]; + } + while (++holdersIndex < holdersLength) { + result[offset + holders[holdersIndex]] = args[argsIndex++]; + } + return result; + } + function createAggregator(setter, initializer) { + return function(collection, iteratee, thisArg) { + var result = initializer ? initializer() : {}; + iteratee = getCallback(iteratee, thisArg, 3); + if (isArray(collection)) { + var index = -1, length = collection.length; + while (++index < length) { + var value = collection[index]; + setter(result, value, iteratee(value, index, collection), collection); + } + } else { + baseEach(collection, function(value, key, collection) { + setter(result, value, iteratee(value, key, collection), collection); + }); + } + return result; + }; + } + function createAssigner(assigner) { + return restParam(function(object, sources) { + var index = -1, length = object == null ? 0 : sources.length, customizer = length > 2 ? sources[length - 2] : undefined, guard = length > 2 ? sources[2] : undefined, thisArg = length > 1 ? sources[length - 1] : undefined; + if (typeof customizer == "function") { + customizer = bindCallback(customizer, thisArg, 5); + length -= 2; + } else { + customizer = typeof thisArg == "function" ? thisArg : undefined; + length -= customizer ? 1 : 0; + } + if (guard && isIterateeCall(sources[0], sources[1], guard)) { + customizer = length < 3 ? undefined : customizer; + length = 1; + } + while (++index < length) { + var source = sources[index]; + if (source) { + assigner(object, source, customizer); + } + } + return object; + }); + } + function createBaseEach(eachFunc, fromRight) { + return function(collection, iteratee) { + var length = collection ? getLength(collection) : 0; + if (!isLength(length)) { + return eachFunc(collection, iteratee); + } + var index = fromRight ? length : -1, iterable = toObject(collection); + while (fromRight ? index-- : ++index < length) { + if (iteratee(iterable[index], index, iterable) === false) { + break; + } + } + return collection; + }; + } + function createBaseFor(fromRight) { + return function(object, iteratee, keysFunc) { + var iterable = toObject(object), props = keysFunc(object), length = props.length, index = fromRight ? length : -1; + while (fromRight ? index-- : ++index < length) { + var key = props[index]; + if (iteratee(iterable[key], key, iterable) === false) { + break; + } + } + return object; + }; + } + function createBindWrapper(func, thisArg) { + var Ctor = createCtorWrapper(func); + function wrapper() { + var fn = this && this !== root && this instanceof wrapper ? Ctor : func; + return fn.apply(thisArg, arguments); + } + return wrapper; + } + function createCache(values) { + return nativeCreate && Set ? new SetCache(values) : null; + } + function createCompounder(callback) { + return function(string) { + var index = -1, array = words(deburr(string)), length = array.length, result = ""; + while (++index < length) { + result = callback(result, array[index], index); + } + return result; + }; + } + function createCtorWrapper(Ctor) { + return function() { + var args = arguments; + switch (args.length) { + case 0: + return new Ctor(); + + case 1: + return new Ctor(args[0]); + + case 2: + return new Ctor(args[0], args[1]); + + case 3: + return new Ctor(args[0], args[1], args[2]); + + case 4: + return new Ctor(args[0], args[1], args[2], args[3]); + + case 5: + return new Ctor(args[0], args[1], args[2], args[3], args[4]); + + case 6: + return new Ctor(args[0], args[1], args[2], args[3], args[4], args[5]); + + case 7: + return new Ctor(args[0], args[1], args[2], args[3], args[4], args[5], args[6]); + } + var thisBinding = baseCreate(Ctor.prototype), result = Ctor.apply(thisBinding, args); + return isObject(result) ? result : thisBinding; + }; + } + function createCurry(flag) { + function curryFunc(func, arity, guard) { + if (guard && isIterateeCall(func, arity, guard)) { + arity = undefined; + } + var result = createWrapper(func, flag, undefined, undefined, undefined, undefined, undefined, arity); + result.placeholder = curryFunc.placeholder; + return result; + } + return curryFunc; + } + function createDefaults(assigner, customizer) { + return restParam(function(args) { + var object = args[0]; + if (object == null) { + return object; + } + args.push(customizer); + return assigner.apply(undefined, args); + }); + } + function createExtremum(comparator, exValue) { + return function(collection, iteratee, thisArg) { + if (thisArg && isIterateeCall(collection, iteratee, thisArg)) { + iteratee = undefined; + } + iteratee = getCallback(iteratee, thisArg, 3); + if (iteratee.length == 1) { + collection = isArray(collection) ? collection : toIterable(collection); + var result = arrayExtremum(collection, iteratee, comparator, exValue); + if (!(collection.length && result === exValue)) { + return result; + } + } + return baseExtremum(collection, iteratee, comparator, exValue); + }; + } + function createFind(eachFunc, fromRight) { + return function(collection, predicate, thisArg) { + predicate = getCallback(predicate, thisArg, 3); + if (isArray(collection)) { + var index = baseFindIndex(collection, predicate, fromRight); + return index > -1 ? collection[index] : undefined; + } + return baseFind(collection, predicate, eachFunc); + }; + } + function createFindIndex(fromRight) { + return function(array, predicate, thisArg) { + if (!(array && array.length)) { + return -1; + } + predicate = getCallback(predicate, thisArg, 3); + return baseFindIndex(array, predicate, fromRight); + }; + } + function createFindKey(objectFunc) { + return function(object, predicate, thisArg) { + predicate = getCallback(predicate, thisArg, 3); + return baseFind(object, predicate, objectFunc, true); + }; + } + function createFlow(fromRight) { + return function() { + var wrapper, length = arguments.length, index = fromRight ? length : -1, leftIndex = 0, funcs = Array(length); + while (fromRight ? index-- : ++index < length) { + var func = funcs[leftIndex++] = arguments[index]; + if (typeof func != "function") { + throw new TypeError(FUNC_ERROR_TEXT); + } + if (!wrapper && LodashWrapper.prototype.thru && getFuncName(func) == "wrapper") { + wrapper = new LodashWrapper([], true); + } + } + index = wrapper ? -1 : length; + while (++index < length) { + func = funcs[index]; + var funcName = getFuncName(func), data = funcName == "wrapper" ? getData(func) : undefined; + if (data && isLaziable(data[0]) && data[1] == (ARY_FLAG | CURRY_FLAG | PARTIAL_FLAG | REARG_FLAG) && !data[4].length && data[9] == 1) { + wrapper = wrapper[getFuncName(data[0])].apply(wrapper, data[3]); + } else { + wrapper = func.length == 1 && isLaziable(func) ? wrapper[funcName]() : wrapper.thru(func); + } + } + return function() { + var args = arguments, value = args[0]; + if (wrapper && args.length == 1 && isArray(value) && value.length >= LARGE_ARRAY_SIZE) { + return wrapper.plant(value).value(); + } + var index = 0, result = length ? funcs[index].apply(this, args) : value; + while (++index < length) { + result = funcs[index].call(this, result); + } + return result; + }; + }; + } + function createForEach(arrayFunc, eachFunc) { + return function(collection, iteratee, thisArg) { + return typeof iteratee == "function" && thisArg === undefined && isArray(collection) ? arrayFunc(collection, iteratee) : eachFunc(collection, bindCallback(iteratee, thisArg, 3)); + }; + } + function createForIn(objectFunc) { + return function(object, iteratee, thisArg) { + if (typeof iteratee != "function" || thisArg !== undefined) { + iteratee = bindCallback(iteratee, thisArg, 3); + } + return objectFunc(object, iteratee, keysIn); + }; + } + function createForOwn(objectFunc) { + return function(object, iteratee, thisArg) { + if (typeof iteratee != "function" || thisArg !== undefined) { + iteratee = bindCallback(iteratee, thisArg, 3); + } + return objectFunc(object, iteratee); + }; + } + function createObjectMapper(isMapKeys) { + return function(object, iteratee, thisArg) { + var result = {}; + iteratee = getCallback(iteratee, thisArg, 3); + baseForOwn(object, function(value, key, object) { + var mapped = iteratee(value, key, object); + key = isMapKeys ? mapped : key; + value = isMapKeys ? value : mapped; + result[key] = value; + }); + return result; + }; + } + function createPadDir(fromRight) { + return function(string, length, chars) { + string = baseToString(string); + return (fromRight ? string : "") + createPadding(string, length, chars) + (fromRight ? "" : string); + }; + } + function createPartial(flag) { + var partialFunc = restParam(function(func, partials) { + var holders = replaceHolders(partials, partialFunc.placeholder); + return createWrapper(func, flag, undefined, partials, holders); + }); + return partialFunc; + } + function createReduce(arrayFunc, eachFunc) { + return function(collection, iteratee, accumulator, thisArg) { + var initFromArray = arguments.length < 3; + return typeof iteratee == "function" && thisArg === undefined && isArray(collection) ? arrayFunc(collection, iteratee, accumulator, initFromArray) : baseReduce(collection, getCallback(iteratee, thisArg, 4), accumulator, initFromArray, eachFunc); + }; + } + function createHybridWrapper(func, bitmask, thisArg, partials, holders, partialsRight, holdersRight, argPos, ary, arity) { + var isAry = bitmask & ARY_FLAG, isBind = bitmask & BIND_FLAG, isBindKey = bitmask & BIND_KEY_FLAG, isCurry = bitmask & CURRY_FLAG, isCurryBound = bitmask & CURRY_BOUND_FLAG, isCurryRight = bitmask & CURRY_RIGHT_FLAG, Ctor = isBindKey ? undefined : createCtorWrapper(func); + function wrapper() { + var length = arguments.length, index = length, args = Array(length); + while (index--) { + args[index] = arguments[index]; + } + if (partials) { + args = composeArgs(args, partials, holders); + } + if (partialsRight) { + args = composeArgsRight(args, partialsRight, holdersRight); + } + if (isCurry || isCurryRight) { + var placeholder = wrapper.placeholder, argsHolders = replaceHolders(args, placeholder); + length -= argsHolders.length; + if (length < arity) { + var newArgPos = argPos ? arrayCopy(argPos) : undefined, newArity = nativeMax(arity - length, 0), newsHolders = isCurry ? argsHolders : undefined, newHoldersRight = isCurry ? undefined : argsHolders, newPartials = isCurry ? args : undefined, newPartialsRight = isCurry ? undefined : args; + bitmask |= isCurry ? PARTIAL_FLAG : PARTIAL_RIGHT_FLAG; + bitmask &= ~(isCurry ? PARTIAL_RIGHT_FLAG : PARTIAL_FLAG); + if (!isCurryBound) { + bitmask &= ~(BIND_FLAG | BIND_KEY_FLAG); + } + var newData = [ func, bitmask, thisArg, newPartials, newsHolders, newPartialsRight, newHoldersRight, newArgPos, ary, newArity ], result = createHybridWrapper.apply(undefined, newData); + if (isLaziable(func)) { + setData(result, newData); + } + result.placeholder = placeholder; + return result; + } + } + var thisBinding = isBind ? thisArg : this, fn = isBindKey ? thisBinding[func] : func; + if (argPos) { + args = reorder(args, argPos); + } + if (isAry && ary < args.length) { + args.length = ary; + } + if (this && this !== root && this instanceof wrapper) { + fn = Ctor || createCtorWrapper(func); + } + return fn.apply(thisBinding, args); + } + return wrapper; + } + function createPadding(string, length, chars) { + var strLength = string.length; + length = +length; + if (strLength >= length || !nativeIsFinite(length)) { + return ""; + } + var padLength = length - strLength; + chars = chars == null ? " " : chars + ""; + return repeat(chars, nativeCeil(padLength / chars.length)).slice(0, padLength); + } + function createPartialWrapper(func, bitmask, thisArg, partials) { + var isBind = bitmask & BIND_FLAG, Ctor = createCtorWrapper(func); + function wrapper() { + var argsIndex = -1, argsLength = arguments.length, leftIndex = -1, leftLength = partials.length, args = Array(leftLength + argsLength); + while (++leftIndex < leftLength) { + args[leftIndex] = partials[leftIndex]; + } + while (argsLength--) { + args[leftIndex++] = arguments[++argsIndex]; + } + var fn = this && this !== root && this instanceof wrapper ? Ctor : func; + return fn.apply(isBind ? thisArg : this, args); + } + return wrapper; + } + function createRound(methodName) { + var func = Math[methodName]; + return function(number, precision) { + precision = precision === undefined ? 0 : +precision || 0; + if (precision) { + precision = pow(10, precision); + return func(number * precision) / precision; + } + return func(number); + }; + } + function createSortedIndex(retHighest) { + return function(array, value, iteratee, thisArg) { + var callback = getCallback(iteratee); + return iteratee == null && callback === baseCallback ? binaryIndex(array, value, retHighest) : binaryIndexBy(array, value, callback(iteratee, thisArg, 1), retHighest); + }; + } + function createWrapper(func, bitmask, thisArg, partials, holders, argPos, ary, arity) { + var isBindKey = bitmask & BIND_KEY_FLAG; + if (!isBindKey && typeof func != "function") { + throw new TypeError(FUNC_ERROR_TEXT); + } + var length = partials ? partials.length : 0; + if (!length) { + bitmask &= ~(PARTIAL_FLAG | PARTIAL_RIGHT_FLAG); + partials = holders = undefined; + } + length -= holders ? holders.length : 0; + if (bitmask & PARTIAL_RIGHT_FLAG) { + var partialsRight = partials, holdersRight = holders; + partials = holders = undefined; + } + var data = isBindKey ? undefined : getData(func), newData = [ func, bitmask, thisArg, partials, holders, partialsRight, holdersRight, argPos, ary, arity ]; + if (data) { + mergeData(newData, data); + bitmask = newData[1]; + arity = newData[9]; + } + newData[9] = arity == null ? isBindKey ? 0 : func.length : nativeMax(arity - length, 0) || 0; + if (bitmask == BIND_FLAG) { + var result = createBindWrapper(newData[0], newData[2]); + } else if ((bitmask == PARTIAL_FLAG || bitmask == (BIND_FLAG | PARTIAL_FLAG)) && !newData[4].length) { + result = createPartialWrapper.apply(undefined, newData); + } else { + result = createHybridWrapper.apply(undefined, newData); + } + var setter = data ? baseSetData : setData; + return setter(result, newData); + } + function equalArrays(array, other, equalFunc, customizer, isLoose, stackA, stackB) { + var index = -1, arrLength = array.length, othLength = other.length; + if (arrLength != othLength && !(isLoose && othLength > arrLength)) { + return false; + } + while (++index < arrLength) { + var arrValue = array[index], othValue = other[index], result = customizer ? customizer(isLoose ? othValue : arrValue, isLoose ? arrValue : othValue, index) : undefined; + if (result !== undefined) { + if (result) { + continue; + } + return false; + } + if (isLoose) { + if (!arraySome(other, function(othValue) { + return arrValue === othValue || equalFunc(arrValue, othValue, customizer, isLoose, stackA, stackB); + })) { + return false; + } + } else if (!(arrValue === othValue || equalFunc(arrValue, othValue, customizer, isLoose, stackA, stackB))) { + return false; + } + } + return true; + } + function equalByTag(object, other, tag) { + switch (tag) { + case boolTag: + case dateTag: + return +object == +other; + + case errorTag: + return object.name == other.name && object.message == other.message; + + case numberTag: + return object != +object ? other != +other : object == +other; + + case regexpTag: + case stringTag: + return object == other + ""; + } + return false; + } + function equalObjects(object, other, equalFunc, customizer, isLoose, stackA, stackB) { + var objProps = keys(object), objLength = objProps.length, othProps = keys(other), othLength = othProps.length; + if (objLength != othLength && !isLoose) { + return false; + } + var index = objLength; + while (index--) { + var key = objProps[index]; + if (!(isLoose ? key in other : hasOwnProperty.call(other, key))) { + return false; + } + } + var skipCtor = isLoose; + while (++index < objLength) { + key = objProps[index]; + var objValue = object[key], othValue = other[key], result = customizer ? customizer(isLoose ? othValue : objValue, isLoose ? objValue : othValue, key) : undefined; + if (!(result === undefined ? equalFunc(objValue, othValue, customizer, isLoose, stackA, stackB) : result)) { + return false; + } + skipCtor || (skipCtor = key == "constructor"); + } + if (!skipCtor) { + var objCtor = object.constructor, othCtor = other.constructor; + if (objCtor != othCtor && ("constructor" in object && "constructor" in other) && !(typeof objCtor == "function" && objCtor instanceof objCtor && typeof othCtor == "function" && othCtor instanceof othCtor)) { + return false; + } + } + return true; + } + function getCallback(func, thisArg, argCount) { + var result = lodash.callback || callback; + result = result === callback ? baseCallback : result; + return argCount ? result(func, thisArg, argCount) : result; + } + var getData = !metaMap ? noop : function(func) { + return metaMap.get(func); + }; + function getFuncName(func) { + var result = func.name + "", array = realNames[result], length = array ? array.length : 0; + while (length--) { + var data = array[length], otherFunc = data.func; + if (otherFunc == null || otherFunc == func) { + return data.name; + } + } + return result; + } + function getIndexOf(collection, target, fromIndex) { + var result = lodash.indexOf || indexOf; + result = result === indexOf ? baseIndexOf : result; + return collection ? result(collection, target, fromIndex) : result; + } + var getLength = baseProperty("length"); + function getMatchData(object) { + var result = pairs(object), length = result.length; + while (length--) { + result[length][2] = isStrictComparable(result[length][1]); + } + return result; + } + function getNative(object, key) { + var value = object == null ? undefined : object[key]; + return isNative(value) ? value : undefined; + } + function getView(start, end, transforms) { + var index = -1, length = transforms.length; + while (++index < length) { + var data = transforms[index], size = data.size; + switch (data.type) { + case "drop": + start += size; + break; + + case "dropRight": + end -= size; + break; + + case "take": + end = nativeMin(end, start + size); + break; + + case "takeRight": + start = nativeMax(start, end - size); + break; + } + } + return { + start: start, + end: end + }; + } + function initCloneArray(array) { + var length = array.length, result = new array.constructor(length); + if (length && typeof array[0] == "string" && hasOwnProperty.call(array, "index")) { + result.index = array.index; + result.input = array.input; + } + return result; + } + function initCloneObject(object) { + var Ctor = object.constructor; + if (!(typeof Ctor == "function" && Ctor instanceof Ctor)) { + Ctor = Object; + } + return new Ctor(); + } + function initCloneByTag(object, tag, isDeep) { + var Ctor = object.constructor; + switch (tag) { + case arrayBufferTag: + return bufferClone(object); + + case boolTag: + case dateTag: + return new Ctor(+object); + + case float32Tag: + case float64Tag: + case int8Tag: + case int16Tag: + case int32Tag: + case uint8Tag: + case uint8ClampedTag: + case uint16Tag: + case uint32Tag: + var buffer = object.buffer; + return new Ctor(isDeep ? bufferClone(buffer) : buffer, object.byteOffset, object.length); + + case numberTag: + case stringTag: + return new Ctor(object); + + case regexpTag: + var result = new Ctor(object.source, reFlags.exec(object)); + result.lastIndex = object.lastIndex; + } + return result; + } + function invokePath(object, path, args) { + if (object != null && !isKey(path, object)) { + path = toPath(path); + object = path.length == 1 ? object : baseGet(object, baseSlice(path, 0, -1)); + path = last(path); + } + var func = object == null ? object : object[path]; + return func == null ? undefined : func.apply(object, args); + } + function isArrayLike(value) { + return value != null && isLength(getLength(value)); + } + function isIndex(value, length) { + value = typeof value == "number" || reIsUint.test(value) ? +value : -1; + length = length == null ? MAX_SAFE_INTEGER : length; + return value > -1 && value % 1 == 0 && value < length; + } + function isIterateeCall(value, index, object) { + if (!isObject(object)) { + return false; + } + var type = typeof index; + if (type == "number" ? isArrayLike(object) && isIndex(index, object.length) : type == "string" && index in object) { + var other = object[index]; + return value === value ? value === other : other !== other; + } + return false; + } + function isKey(value, object) { + var type = typeof value; + if (type == "string" && reIsPlainProp.test(value) || type == "number") { + return true; + } + if (isArray(value)) { + return false; + } + var result = !reIsDeepProp.test(value); + return result || object != null && value in toObject(object); + } + function isLaziable(func) { + var funcName = getFuncName(func), other = lodash[funcName]; + if (typeof other != "function" || !(funcName in LazyWrapper.prototype)) { + return false; + } + if (func === other) { + return true; + } + var data = getData(other); + return !!data && func === data[0]; + } + function isLength(value) { + return typeof value == "number" && value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER; + } + function isStrictComparable(value) { + return value === value && !isObject(value); + } + function mergeData(data, source) { + var bitmask = data[1], srcBitmask = source[1], newBitmask = bitmask | srcBitmask, isCommon = newBitmask < ARY_FLAG; + var isCombo = srcBitmask == ARY_FLAG && bitmask == CURRY_FLAG || srcBitmask == ARY_FLAG && bitmask == REARG_FLAG && data[7].length <= source[8] || srcBitmask == (ARY_FLAG | REARG_FLAG) && bitmask == CURRY_FLAG; + if (!(isCommon || isCombo)) { + return data; + } + if (srcBitmask & BIND_FLAG) { + data[2] = source[2]; + newBitmask |= bitmask & BIND_FLAG ? 0 : CURRY_BOUND_FLAG; + } + var value = source[3]; + if (value) { + var partials = data[3]; + data[3] = partials ? composeArgs(partials, value, source[4]) : arrayCopy(value); + data[4] = partials ? replaceHolders(data[3], PLACEHOLDER) : arrayCopy(source[4]); + } + value = source[5]; + if (value) { + partials = data[5]; + data[5] = partials ? composeArgsRight(partials, value, source[6]) : arrayCopy(value); + data[6] = partials ? replaceHolders(data[5], PLACEHOLDER) : arrayCopy(source[6]); + } + value = source[7]; + if (value) { + data[7] = arrayCopy(value); + } + if (srcBitmask & ARY_FLAG) { + data[8] = data[8] == null ? source[8] : nativeMin(data[8], source[8]); + } + if (data[9] == null) { + data[9] = source[9]; + } + data[0] = source[0]; + data[1] = newBitmask; + return data; + } + function mergeDefaults(objectValue, sourceValue) { + return objectValue === undefined ? sourceValue : merge(objectValue, sourceValue, mergeDefaults); + } + function pickByArray(object, props) { + object = toObject(object); + var index = -1, length = props.length, result = {}; + while (++index < length) { + var key = props[index]; + if (key in object) { + result[key] = object[key]; + } + } + return result; + } + function pickByCallback(object, predicate) { + var result = {}; + baseForIn(object, function(value, key, object) { + if (predicate(value, key, object)) { + result[key] = value; + } + }); + return result; + } + function reorder(array, indexes) { + var arrLength = array.length, length = nativeMin(indexes.length, arrLength), oldArray = arrayCopy(array); + while (length--) { + var index = indexes[length]; + array[length] = isIndex(index, arrLength) ? oldArray[index] : undefined; + } + return array; + } + var setData = function() { + var count = 0, lastCalled = 0; + return function(key, value) { + var stamp = now(), remaining = HOT_SPAN - (stamp - lastCalled); + lastCalled = stamp; + if (remaining > 0) { + if (++count >= HOT_COUNT) { + return key; + } + } else { + count = 0; + } + return baseSetData(key, value); + }; + }(); + function shimKeys(object) { + var props = keysIn(object), propsLength = props.length, length = propsLength && object.length; + var allowIndexes = !!length && isLength(length) && (isArray(object) || isArguments(object)); + var index = -1, result = []; + while (++index < propsLength) { + var key = props[index]; + if (allowIndexes && isIndex(key, length) || hasOwnProperty.call(object, key)) { + result.push(key); + } + } + return result; + } + function toIterable(value) { + if (value == null) { + return []; + } + if (!isArrayLike(value)) { + return values(value); + } + return isObject(value) ? value : Object(value); + } + function toObject(value) { + return isObject(value) ? value : Object(value); + } + function toPath(value) { + if (isArray(value)) { + return value; + } + var result = []; + baseToString(value).replace(rePropName, function(match, number, quote, string) { + result.push(quote ? string.replace(reEscapeChar, "$1") : number || match); + }); + return result; + } + function wrapperClone(wrapper) { + return wrapper instanceof LazyWrapper ? wrapper.clone() : new LodashWrapper(wrapper.__wrapped__, wrapper.__chain__, arrayCopy(wrapper.__actions__)); + } + function chunk(array, size, guard) { + if (guard ? isIterateeCall(array, size, guard) : size == null) { + size = 1; + } else { + size = nativeMax(nativeFloor(size) || 1, 1); + } + var index = 0, length = array ? array.length : 0, resIndex = -1, result = Array(nativeCeil(length / size)); + while (index < length) { + result[++resIndex] = baseSlice(array, index, index += size); + } + return result; + } + function compact(array) { + var index = -1, length = array ? array.length : 0, resIndex = -1, result = []; + while (++index < length) { + var value = array[index]; + if (value) { + result[++resIndex] = value; + } + } + return result; + } + var difference = restParam(function(array, values) { + return isObjectLike(array) && isArrayLike(array) ? baseDifference(array, baseFlatten(values, false, true)) : []; + }); + function drop(array, n, guard) { + var length = array ? array.length : 0; + if (!length) { + return []; + } + if (guard ? isIterateeCall(array, n, guard) : n == null) { + n = 1; + } + return baseSlice(array, n < 0 ? 0 : n); + } + function dropRight(array, n, guard) { + var length = array ? array.length : 0; + if (!length) { + return []; + } + if (guard ? isIterateeCall(array, n, guard) : n == null) { + n = 1; + } + n = length - (+n || 0); + return baseSlice(array, 0, n < 0 ? 0 : n); + } + function dropRightWhile(array, predicate, thisArg) { + return array && array.length ? baseWhile(array, getCallback(predicate, thisArg, 3), true, true) : []; + } + function dropWhile(array, predicate, thisArg) { + return array && array.length ? baseWhile(array, getCallback(predicate, thisArg, 3), true) : []; + } + function fill(array, value, start, end) { + var length = array ? array.length : 0; + if (!length) { + return []; + } + if (start && typeof start != "number" && isIterateeCall(array, value, start)) { + start = 0; + end = length; + } + return baseFill(array, value, start, end); + } + var findIndex = createFindIndex(); + var findLastIndex = createFindIndex(true); + function first(array) { + return array ? array[0] : undefined; + } + function flatten(array, isDeep, guard) { + var length = array ? array.length : 0; + if (guard && isIterateeCall(array, isDeep, guard)) { + isDeep = false; + } + return length ? baseFlatten(array, isDeep) : []; + } + function flattenDeep(array) { + var length = array ? array.length : 0; + return length ? baseFlatten(array, true) : []; + } + function indexOf(array, value, fromIndex) { + var length = array ? array.length : 0; + if (!length) { + return -1; + } + if (typeof fromIndex == "number") { + fromIndex = fromIndex < 0 ? nativeMax(length + fromIndex, 0) : fromIndex; + } else if (fromIndex) { + var index = binaryIndex(array, value); + if (index < length && (value === value ? value === array[index] : array[index] !== array[index])) { + return index; + } + return -1; + } + return baseIndexOf(array, value, fromIndex || 0); + } + function initial(array) { + return dropRight(array, 1); + } + var intersection = restParam(function(arrays) { + var othLength = arrays.length, othIndex = othLength, caches = Array(length), indexOf = getIndexOf(), isCommon = indexOf === baseIndexOf, result = []; + while (othIndex--) { + var value = arrays[othIndex] = isArrayLike(value = arrays[othIndex]) ? value : []; + caches[othIndex] = isCommon && value.length >= 120 ? createCache(othIndex && value) : null; + } + var array = arrays[0], index = -1, length = array ? array.length : 0, seen = caches[0]; + outer: while (++index < length) { + value = array[index]; + if ((seen ? cacheIndexOf(seen, value) : indexOf(result, value, 0)) < 0) { + var othIndex = othLength; + while (--othIndex) { + var cache = caches[othIndex]; + if ((cache ? cacheIndexOf(cache, value) : indexOf(arrays[othIndex], value, 0)) < 0) { + continue outer; + } + } + if (seen) { + seen.push(value); + } + result.push(value); + } + } + return result; + }); + function last(array) { + var length = array ? array.length : 0; + return length ? array[length - 1] : undefined; + } + function lastIndexOf(array, value, fromIndex) { + var length = array ? array.length : 0; + if (!length) { + return -1; + } + var index = length; + if (typeof fromIndex == "number") { + index = (fromIndex < 0 ? nativeMax(length + fromIndex, 0) : nativeMin(fromIndex || 0, length - 1)) + 1; + } else if (fromIndex) { + index = binaryIndex(array, value, true) - 1; + var other = array[index]; + if (value === value ? value === other : other !== other) { + return index; + } + return -1; + } + if (value !== value) { + return indexOfNaN(array, index, true); + } + while (index--) { + if (array[index] === value) { + return index; + } + } + return -1; + } + function pull() { + var args = arguments, array = args[0]; + if (!(array && array.length)) { + return array; + } + var index = 0, indexOf = getIndexOf(), length = args.length; + while (++index < length) { + var fromIndex = 0, value = args[index]; + while ((fromIndex = indexOf(array, value, fromIndex)) > -1) { + splice.call(array, fromIndex, 1); + } + } + return array; + } + var pullAt = restParam(function(array, indexes) { + indexes = baseFlatten(indexes); + var result = baseAt(array, indexes); + basePullAt(array, indexes.sort(baseCompareAscending)); + return result; + }); + function remove(array, predicate, thisArg) { + var result = []; + if (!(array && array.length)) { + return result; + } + var index = -1, indexes = [], length = array.length; + predicate = getCallback(predicate, thisArg, 3); + while (++index < length) { + var value = array[index]; + if (predicate(value, index, array)) { + result.push(value); + indexes.push(index); + } + } + basePullAt(array, indexes); + return result; + } + function rest(array) { + return drop(array, 1); + } + function slice(array, start, end) { + var length = array ? array.length : 0; + if (!length) { + return []; + } + if (end && typeof end != "number" && isIterateeCall(array, start, end)) { + start = 0; + end = length; + } + return baseSlice(array, start, end); + } + var sortedIndex = createSortedIndex(); + var sortedLastIndex = createSortedIndex(true); + function take(array, n, guard) { + var length = array ? array.length : 0; + if (!length) { + return []; + } + if (guard ? isIterateeCall(array, n, guard) : n == null) { + n = 1; + } + return baseSlice(array, 0, n < 0 ? 0 : n); + } + function takeRight(array, n, guard) { + var length = array ? array.length : 0; + if (!length) { + return []; + } + if (guard ? isIterateeCall(array, n, guard) : n == null) { + n = 1; + } + n = length - (+n || 0); + return baseSlice(array, n < 0 ? 0 : n); + } + function takeRightWhile(array, predicate, thisArg) { + return array && array.length ? baseWhile(array, getCallback(predicate, thisArg, 3), false, true) : []; + } + function takeWhile(array, predicate, thisArg) { + return array && array.length ? baseWhile(array, getCallback(predicate, thisArg, 3)) : []; + } + var union = restParam(function(arrays) { + return baseUniq(baseFlatten(arrays, false, true)); + }); + function uniq(array, isSorted, iteratee, thisArg) { + var length = array ? array.length : 0; + if (!length) { + return []; + } + if (isSorted != null && typeof isSorted != "boolean") { + thisArg = iteratee; + iteratee = isIterateeCall(array, isSorted, thisArg) ? undefined : isSorted; + isSorted = false; + } + var callback = getCallback(); + if (!(iteratee == null && callback === baseCallback)) { + iteratee = callback(iteratee, thisArg, 3); + } + return isSorted && getIndexOf() === baseIndexOf ? sortedUniq(array, iteratee) : baseUniq(array, iteratee); + } + function unzip(array) { + if (!(array && array.length)) { + return []; + } + var index = -1, length = 0; + array = arrayFilter(array, function(group) { + if (isArrayLike(group)) { + length = nativeMax(group.length, length); + return true; + } + }); + var result = Array(length); + while (++index < length) { + result[index] = arrayMap(array, baseProperty(index)); + } + return result; + } + function unzipWith(array, iteratee, thisArg) { + var length = array ? array.length : 0; + if (!length) { + return []; + } + var result = unzip(array); + if (iteratee == null) { + return result; + } + iteratee = bindCallback(iteratee, thisArg, 4); + return arrayMap(result, function(group) { + return arrayReduce(group, iteratee, undefined, true); + }); + } + var without = restParam(function(array, values) { + return isArrayLike(array) ? baseDifference(array, values) : []; + }); + function xor() { + var index = -1, length = arguments.length; + while (++index < length) { + var array = arguments[index]; + if (isArrayLike(array)) { + var result = result ? arrayPush(baseDifference(result, array), baseDifference(array, result)) : array; + } + } + return result ? baseUniq(result) : []; + } + var zip = restParam(unzip); + function zipObject(props, values) { + var index = -1, length = props ? props.length : 0, result = {}; + if (length && !values && !isArray(props[0])) { + values = []; + } + while (++index < length) { + var key = props[index]; + if (values) { + result[key] = values[index]; + } else if (key) { + result[key[0]] = key[1]; + } + } + return result; + } + var zipWith = restParam(function(arrays) { + var length = arrays.length, iteratee = length > 2 ? arrays[length - 2] : undefined, thisArg = length > 1 ? arrays[length - 1] : undefined; + if (length > 2 && typeof iteratee == "function") { + length -= 2; + } else { + iteratee = length > 1 && typeof thisArg == "function" ? (--length, thisArg) : undefined; + thisArg = undefined; + } + arrays.length = length; + return unzipWith(arrays, iteratee, thisArg); + }); + function chain(value) { + var result = lodash(value); + result.__chain__ = true; + return result; + } + function tap(value, interceptor, thisArg) { + interceptor.call(thisArg, value); + return value; + } + function thru(value, interceptor, thisArg) { + return interceptor.call(thisArg, value); + } + function wrapperChain() { + return chain(this); + } + function wrapperCommit() { + return new LodashWrapper(this.value(), this.__chain__); + } + var wrapperConcat = restParam(function(values) { + values = baseFlatten(values); + return this.thru(function(array) { + return arrayConcat(isArray(array) ? array : [ toObject(array) ], values); + }); + }); + function wrapperPlant(value) { + var result, parent = this; + while (parent instanceof baseLodash) { + var clone = wrapperClone(parent); + if (result) { + previous.__wrapped__ = clone; + } else { + result = clone; + } + var previous = clone; + parent = parent.__wrapped__; + } + previous.__wrapped__ = value; + return result; + } + function wrapperReverse() { + var value = this.__wrapped__; + var interceptor = function(value) { + return value.reverse(); + }; + if (value instanceof LazyWrapper) { + var wrapped = value; + if (this.__actions__.length) { + wrapped = new LazyWrapper(this); + } + wrapped = wrapped.reverse(); + wrapped.__actions__.push({ + func: thru, + args: [ interceptor ], + thisArg: undefined + }); + return new LodashWrapper(wrapped, this.__chain__); + } + return this.thru(interceptor); + } + function wrapperToString() { + return this.value() + ""; + } + function wrapperValue() { + return baseWrapperValue(this.__wrapped__, this.__actions__); + } + var at = restParam(function(collection, props) { + return baseAt(collection, baseFlatten(props)); + }); + var countBy = createAggregator(function(result, value, key) { + hasOwnProperty.call(result, key) ? ++result[key] : result[key] = 1; + }); + function every(collection, predicate, thisArg) { + var func = isArray(collection) ? arrayEvery : baseEvery; + if (thisArg && isIterateeCall(collection, predicate, thisArg)) { + predicate = undefined; + } + if (typeof predicate != "function" || thisArg !== undefined) { + predicate = getCallback(predicate, thisArg, 3); + } + return func(collection, predicate); + } + function filter(collection, predicate, thisArg) { + var func = isArray(collection) ? arrayFilter : baseFilter; + predicate = getCallback(predicate, thisArg, 3); + return func(collection, predicate); + } + var find = createFind(baseEach); + var findLast = createFind(baseEachRight, true); + function findWhere(collection, source) { + return find(collection, baseMatches(source)); + } + var forEach = createForEach(arrayEach, baseEach); + var forEachRight = createForEach(arrayEachRight, baseEachRight); + var groupBy = createAggregator(function(result, value, key) { + if (hasOwnProperty.call(result, key)) { + result[key].push(value); + } else { + result[key] = [ value ]; + } + }); + function includes(collection, target, fromIndex, guard) { + var length = collection ? getLength(collection) : 0; + if (!isLength(length)) { + collection = values(collection); + length = collection.length; + } + if (typeof fromIndex != "number" || guard && isIterateeCall(target, fromIndex, guard)) { + fromIndex = 0; + } else { + fromIndex = fromIndex < 0 ? nativeMax(length + fromIndex, 0) : fromIndex || 0; + } + return typeof collection == "string" || !isArray(collection) && isString(collection) ? fromIndex <= length && collection.indexOf(target, fromIndex) > -1 : !!length && getIndexOf(collection, target, fromIndex) > -1; + } + var indexBy = createAggregator(function(result, value, key) { + result[key] = value; + }); + var invoke = restParam(function(collection, path, args) { + var index = -1, isFunc = typeof path == "function", isProp = isKey(path), result = isArrayLike(collection) ? Array(collection.length) : []; + baseEach(collection, function(value) { + var func = isFunc ? path : isProp && value != null ? value[path] : undefined; + result[++index] = func ? func.apply(value, args) : invokePath(value, path, args); + }); + return result; + }); + function map(collection, iteratee, thisArg) { + var func = isArray(collection) ? arrayMap : baseMap; + iteratee = getCallback(iteratee, thisArg, 3); + return func(collection, iteratee); + } + var partition = createAggregator(function(result, value, key) { + result[key ? 0 : 1].push(value); + }, function() { + return [ [], [] ]; + }); + function pluck(collection, path) { + return map(collection, property(path)); + } + var reduce = createReduce(arrayReduce, baseEach); + var reduceRight = createReduce(arrayReduceRight, baseEachRight); + function reject(collection, predicate, thisArg) { + var func = isArray(collection) ? arrayFilter : baseFilter; + predicate = getCallback(predicate, thisArg, 3); + return func(collection, function(value, index, collection) { + return !predicate(value, index, collection); + }); + } + function sample(collection, n, guard) { + if (guard ? isIterateeCall(collection, n, guard) : n == null) { + collection = toIterable(collection); + var length = collection.length; + return length > 0 ? collection[baseRandom(0, length - 1)] : undefined; + } + var index = -1, result = toArray(collection), length = result.length, lastIndex = length - 1; + n = nativeMin(n < 0 ? 0 : +n || 0, length); + while (++index < n) { + var rand = baseRandom(index, lastIndex), value = result[rand]; + result[rand] = result[index]; + result[index] = value; + } + result.length = n; + return result; + } + function shuffle(collection) { + return sample(collection, POSITIVE_INFINITY); + } + function size(collection) { + var length = collection ? getLength(collection) : 0; + return isLength(length) ? length : keys(collection).length; + } + function some(collection, predicate, thisArg) { + var func = isArray(collection) ? arraySome : baseSome; + if (thisArg && isIterateeCall(collection, predicate, thisArg)) { + predicate = undefined; + } + if (typeof predicate != "function" || thisArg !== undefined) { + predicate = getCallback(predicate, thisArg, 3); + } + return func(collection, predicate); + } + function sortBy(collection, iteratee, thisArg) { + if (collection == null) { + return []; + } + if (thisArg && isIterateeCall(collection, iteratee, thisArg)) { + iteratee = undefined; + } + var index = -1; + iteratee = getCallback(iteratee, thisArg, 3); + var result = baseMap(collection, function(value, key, collection) { + return { + criteria: iteratee(value, key, collection), + index: ++index, + value: value + }; + }); + return baseSortBy(result, compareAscending); + } + var sortByAll = restParam(function(collection, iteratees) { + if (collection == null) { + return []; + } + var guard = iteratees[2]; + if (guard && isIterateeCall(iteratees[0], iteratees[1], guard)) { + iteratees.length = 1; + } + return baseSortByOrder(collection, baseFlatten(iteratees), []); + }); + function sortByOrder(collection, iteratees, orders, guard) { + if (collection == null) { + return []; + } + if (guard && isIterateeCall(iteratees, orders, guard)) { + orders = undefined; + } + if (!isArray(iteratees)) { + iteratees = iteratees == null ? [] : [ iteratees ]; + } + if (!isArray(orders)) { + orders = orders == null ? [] : [ orders ]; + } + return baseSortByOrder(collection, iteratees, orders); + } + function where(collection, source) { + return filter(collection, baseMatches(source)); + } + var now = nativeNow || function() { + return new Date().getTime(); + }; + function after(n, func) { + if (typeof func != "function") { + if (typeof n == "function") { + var temp = n; + n = func; + func = temp; + } else { + throw new TypeError(FUNC_ERROR_TEXT); + } + } + n = nativeIsFinite(n = +n) ? n : 0; + return function() { + if (--n < 1) { + return func.apply(this, arguments); + } + }; + } + function ary(func, n, guard) { + if (guard && isIterateeCall(func, n, guard)) { + n = undefined; + } + n = func && n == null ? func.length : nativeMax(+n || 0, 0); + return createWrapper(func, ARY_FLAG, undefined, undefined, undefined, undefined, n); + } + function before(n, func) { + var result; + if (typeof func != "function") { + if (typeof n == "function") { + var temp = n; + n = func; + func = temp; + } else { + throw new TypeError(FUNC_ERROR_TEXT); + } + } + return function() { + if (--n > 0) { + result = func.apply(this, arguments); + } + if (n <= 1) { + func = undefined; + } + return result; + }; + } + var bind = restParam(function(func, thisArg, partials) { + var bitmask = BIND_FLAG; + if (partials.length) { + var holders = replaceHolders(partials, bind.placeholder); + bitmask |= PARTIAL_FLAG; + } + return createWrapper(func, bitmask, thisArg, partials, holders); + }); + var bindAll = restParam(function(object, methodNames) { + methodNames = methodNames.length ? baseFlatten(methodNames) : functions(object); + var index = -1, length = methodNames.length; + while (++index < length) { + var key = methodNames[index]; + object[key] = createWrapper(object[key], BIND_FLAG, object); + } + return object; + }); + var bindKey = restParam(function(object, key, partials) { + var bitmask = BIND_FLAG | BIND_KEY_FLAG; + if (partials.length) { + var holders = replaceHolders(partials, bindKey.placeholder); + bitmask |= PARTIAL_FLAG; + } + return createWrapper(key, bitmask, object, partials, holders); + }); + var curry = createCurry(CURRY_FLAG); + var curryRight = createCurry(CURRY_RIGHT_FLAG); + function debounce(func, wait, options) { + var args, maxTimeoutId, result, stamp, thisArg, timeoutId, trailingCall, lastCalled = 0, maxWait = false, trailing = true; + if (typeof func != "function") { + throw new TypeError(FUNC_ERROR_TEXT); + } + wait = wait < 0 ? 0 : +wait || 0; + if (options === true) { + var leading = true; + trailing = false; + } else if (isObject(options)) { + leading = !!options.leading; + maxWait = "maxWait" in options && nativeMax(+options.maxWait || 0, wait); + trailing = "trailing" in options ? !!options.trailing : trailing; + } + function cancel() { + if (timeoutId) { + clearTimeout(timeoutId); + } + if (maxTimeoutId) { + clearTimeout(maxTimeoutId); + } + lastCalled = 0; + maxTimeoutId = timeoutId = trailingCall = undefined; + } + function complete(isCalled, id) { + if (id) { + clearTimeout(id); + } + maxTimeoutId = timeoutId = trailingCall = undefined; + if (isCalled) { + lastCalled = now(); + result = func.apply(thisArg, args); + if (!timeoutId && !maxTimeoutId) { + args = thisArg = undefined; + } + } + } + function delayed() { + var remaining = wait - (now() - stamp); + if (remaining <= 0 || remaining > wait) { + complete(trailingCall, maxTimeoutId); + } else { + timeoutId = setTimeout(delayed, remaining); + } + } + function maxDelayed() { + complete(trailing, timeoutId); + } + function debounced() { + args = arguments; + stamp = now(); + thisArg = this; + trailingCall = trailing && (timeoutId || !leading); + if (maxWait === false) { + var leadingCall = leading && !timeoutId; + } else { + if (!maxTimeoutId && !leading) { + lastCalled = stamp; + } + var remaining = maxWait - (stamp - lastCalled), isCalled = remaining <= 0 || remaining > maxWait; + if (isCalled) { + if (maxTimeoutId) { + maxTimeoutId = clearTimeout(maxTimeoutId); + } + lastCalled = stamp; + result = func.apply(thisArg, args); + } else if (!maxTimeoutId) { + maxTimeoutId = setTimeout(maxDelayed, remaining); + } + } + if (isCalled && timeoutId) { + timeoutId = clearTimeout(timeoutId); + } else if (!timeoutId && wait !== maxWait) { + timeoutId = setTimeout(delayed, wait); + } + if (leadingCall) { + isCalled = true; + result = func.apply(thisArg, args); + } + if (isCalled && !timeoutId && !maxTimeoutId) { + args = thisArg = undefined; + } + return result; + } + debounced.cancel = cancel; + return debounced; + } + var defer = restParam(function(func, args) { + return baseDelay(func, 1, args); + }); + var delay = restParam(function(func, wait, args) { + return baseDelay(func, wait, args); + }); + var flow = createFlow(); + var flowRight = createFlow(true); + function memoize(func, resolver) { + if (typeof func != "function" || resolver && typeof resolver != "function") { + throw new TypeError(FUNC_ERROR_TEXT); + } + var memoized = function() { + var args = arguments, key = resolver ? resolver.apply(this, args) : args[0], cache = memoized.cache; + if (cache.has(key)) { + return cache.get(key); + } + var result = func.apply(this, args); + memoized.cache = cache.set(key, result); + return result; + }; + memoized.cache = new memoize.Cache(); + return memoized; + } + var modArgs = restParam(function(func, transforms) { + transforms = baseFlatten(transforms); + if (typeof func != "function" || !arrayEvery(transforms, baseIsFunction)) { + throw new TypeError(FUNC_ERROR_TEXT); + } + var length = transforms.length; + return restParam(function(args) { + var index = nativeMin(args.length, length); + while (index--) { + args[index] = transforms[index](args[index]); + } + return func.apply(this, args); + }); + }); + function negate(predicate) { + if (typeof predicate != "function") { + throw new TypeError(FUNC_ERROR_TEXT); + } + return function() { + return !predicate.apply(this, arguments); + }; + } + function once(func) { + return before(2, func); + } + var partial = createPartial(PARTIAL_FLAG); + var partialRight = createPartial(PARTIAL_RIGHT_FLAG); + var rearg = restParam(function(func, indexes) { + return createWrapper(func, REARG_FLAG, undefined, undefined, undefined, baseFlatten(indexes)); + }); + function restParam(func, start) { + if (typeof func != "function") { + throw new TypeError(FUNC_ERROR_TEXT); + } + start = nativeMax(start === undefined ? func.length - 1 : +start || 0, 0); + return function() { + var args = arguments, index = -1, length = nativeMax(args.length - start, 0), rest = Array(length); + while (++index < length) { + rest[index] = args[start + index]; + } + switch (start) { + case 0: + return func.call(this, rest); + + case 1: + return func.call(this, args[0], rest); + + case 2: + return func.call(this, args[0], args[1], rest); + } + var otherArgs = Array(start + 1); + index = -1; + while (++index < start) { + otherArgs[index] = args[index]; + } + otherArgs[start] = rest; + return func.apply(this, otherArgs); + }; + } + function spread(func) { + if (typeof func != "function") { + throw new TypeError(FUNC_ERROR_TEXT); + } + return function(array) { + return func.apply(this, array); + }; + } + function throttle(func, wait, options) { + var leading = true, trailing = true; + if (typeof func != "function") { + throw new TypeError(FUNC_ERROR_TEXT); + } + if (options === false) { + leading = false; + } else if (isObject(options)) { + leading = "leading" in options ? !!options.leading : leading; + trailing = "trailing" in options ? !!options.trailing : trailing; + } + return debounce(func, wait, { + leading: leading, + maxWait: +wait, + trailing: trailing + }); + } + function wrap(value, wrapper) { + wrapper = wrapper == null ? identity : wrapper; + return createWrapper(wrapper, PARTIAL_FLAG, undefined, [ value ], []); + } + function clone(value, isDeep, customizer, thisArg) { + if (isDeep && typeof isDeep != "boolean" && isIterateeCall(value, isDeep, customizer)) { + isDeep = false; + } else if (typeof isDeep == "function") { + thisArg = customizer; + customizer = isDeep; + isDeep = false; + } + return typeof customizer == "function" ? baseClone(value, isDeep, bindCallback(customizer, thisArg, 3)) : baseClone(value, isDeep); + } + function cloneDeep(value, customizer, thisArg) { + return typeof customizer == "function" ? baseClone(value, true, bindCallback(customizer, thisArg, 3)) : baseClone(value, true); + } + function gt(value, other) { + return value > other; + } + function gte(value, other) { + return value >= other; + } + function isArguments(value) { + return isObjectLike(value) && isArrayLike(value) && hasOwnProperty.call(value, "callee") && !propertyIsEnumerable.call(value, "callee"); + } + var isArray = nativeIsArray || function(value) { + return isObjectLike(value) && isLength(value.length) && objToString.call(value) == arrayTag; + }; + function isBoolean(value) { + return value === true || value === false || isObjectLike(value) && objToString.call(value) == boolTag; + } + function isDate(value) { + return isObjectLike(value) && objToString.call(value) == dateTag; + } + function isElement(value) { + return !!value && value.nodeType === 1 && isObjectLike(value) && !isPlainObject(value); + } + function isEmpty(value) { + if (value == null) { + return true; + } + if (isArrayLike(value) && (isArray(value) || isString(value) || isArguments(value) || isObjectLike(value) && isFunction(value.splice))) { + return !value.length; + } + return !keys(value).length; + } + function isEqual(value, other, customizer, thisArg) { + customizer = typeof customizer == "function" ? bindCallback(customizer, thisArg, 3) : undefined; + var result = customizer ? customizer(value, other) : undefined; + return result === undefined ? baseIsEqual(value, other, customizer) : !!result; + } + function isError(value) { + return isObjectLike(value) && typeof value.message == "string" && objToString.call(value) == errorTag; + } + function isFinite(value) { + return typeof value == "number" && nativeIsFinite(value); + } + function isFunction(value) { + return isObject(value) && objToString.call(value) == funcTag; + } + function isObject(value) { + var type = typeof value; + return !!value && (type == "object" || type == "function"); + } + function isMatch(object, source, customizer, thisArg) { + customizer = typeof customizer == "function" ? bindCallback(customizer, thisArg, 3) : undefined; + return baseIsMatch(object, getMatchData(source), customizer); + } + function isNaN(value) { + return isNumber(value) && value != +value; + } + function isNative(value) { + if (value == null) { + return false; + } + if (isFunction(value)) { + return reIsNative.test(fnToString.call(value)); + } + return isObjectLike(value) && reIsHostCtor.test(value); + } + function isNull(value) { + return value === null; + } + function isNumber(value) { + return typeof value == "number" || isObjectLike(value) && objToString.call(value) == numberTag; + } + function isPlainObject(value) { + var Ctor; + if (!(isObjectLike(value) && objToString.call(value) == objectTag && !isArguments(value)) || !hasOwnProperty.call(value, "constructor") && (Ctor = value.constructor, + typeof Ctor == "function" && !(Ctor instanceof Ctor))) { + return false; + } + var result; + baseForIn(value, function(subValue, key) { + result = key; + }); + return result === undefined || hasOwnProperty.call(value, result); + } + function isRegExp(value) { + return isObject(value) && objToString.call(value) == regexpTag; + } + function isString(value) { + return typeof value == "string" || isObjectLike(value) && objToString.call(value) == stringTag; + } + function isTypedArray(value) { + return isObjectLike(value) && isLength(value.length) && !!typedArrayTags[objToString.call(value)]; + } + function isUndefined(value) { + return value === undefined; + } + function lt(value, other) { + return value < other; + } + function lte(value, other) { + return value <= other; + } + function toArray(value) { + var length = value ? getLength(value) : 0; + if (!isLength(length)) { + return values(value); + } + if (!length) { + return []; + } + return arrayCopy(value); + } + function toPlainObject(value) { + return baseCopy(value, keysIn(value)); + } + var merge = createAssigner(baseMerge); + var assign = createAssigner(function(object, source, customizer) { + return customizer ? assignWith(object, source, customizer) : baseAssign(object, source); + }); + function create(prototype, properties, guard) { + var result = baseCreate(prototype); + if (guard && isIterateeCall(prototype, properties, guard)) { + properties = undefined; + } + return properties ? baseAssign(result, properties) : result; + } + var defaults = createDefaults(assign, assignDefaults); + var defaultsDeep = createDefaults(merge, mergeDefaults); + var findKey = createFindKey(baseForOwn); + var findLastKey = createFindKey(baseForOwnRight); + var forIn = createForIn(baseFor); + var forInRight = createForIn(baseForRight); + var forOwn = createForOwn(baseForOwn); + var forOwnRight = createForOwn(baseForOwnRight); + function functions(object) { + return baseFunctions(object, keysIn(object)); + } + function get(object, path, defaultValue) { + var result = object == null ? undefined : baseGet(object, toPath(path), path + ""); + return result === undefined ? defaultValue : result; + } + function has(object, path) { + if (object == null) { + return false; + } + var result = hasOwnProperty.call(object, path); + if (!result && !isKey(path)) { + path = toPath(path); + object = path.length == 1 ? object : baseGet(object, baseSlice(path, 0, -1)); + if (object == null) { + return false; + } + path = last(path); + result = hasOwnProperty.call(object, path); + } + return result || isLength(object.length) && isIndex(path, object.length) && (isArray(object) || isArguments(object)); + } + function invert(object, multiValue, guard) { + if (guard && isIterateeCall(object, multiValue, guard)) { + multiValue = undefined; + } + var index = -1, props = keys(object), length = props.length, result = {}; + while (++index < length) { + var key = props[index], value = object[key]; + if (multiValue) { + if (hasOwnProperty.call(result, value)) { + result[value].push(key); + } else { + result[value] = [ key ]; + } + } else { + result[value] = key; + } + } + return result; + } + var keys = !nativeKeys ? shimKeys : function(object) { + var Ctor = object == null ? undefined : object.constructor; + if (typeof Ctor == "function" && Ctor.prototype === object || typeof object != "function" && isArrayLike(object)) { + return shimKeys(object); + } + return isObject(object) ? nativeKeys(object) : []; + }; + function keysIn(object) { + if (object == null) { + return []; + } + if (!isObject(object)) { + object = Object(object); + } + var length = object.length; + length = length && isLength(length) && (isArray(object) || isArguments(object)) && length || 0; + var Ctor = object.constructor, index = -1, isProto = typeof Ctor == "function" && Ctor.prototype === object, result = Array(length), skipIndexes = length > 0; + while (++index < length) { + result[index] = index + ""; + } + for (var key in object) { + if (!(skipIndexes && isIndex(key, length)) && !(key == "constructor" && (isProto || !hasOwnProperty.call(object, key)))) { + result.push(key); + } + } + return result; + } + var mapKeys = createObjectMapper(true); + var mapValues = createObjectMapper(); + var omit = restParam(function(object, props) { + if (object == null) { + return {}; + } + if (typeof props[0] != "function") { + var props = arrayMap(baseFlatten(props), String); + return pickByArray(object, baseDifference(keysIn(object), props)); + } + var predicate = bindCallback(props[0], props[1], 3); + return pickByCallback(object, function(value, key, object) { + return !predicate(value, key, object); + }); + }); + function pairs(object) { + object = toObject(object); + var index = -1, props = keys(object), length = props.length, result = Array(length); + while (++index < length) { + var key = props[index]; + result[index] = [ key, object[key] ]; + } + return result; + } + var pick = restParam(function(object, props) { + if (object == null) { + return {}; + } + return typeof props[0] == "function" ? pickByCallback(object, bindCallback(props[0], props[1], 3)) : pickByArray(object, baseFlatten(props)); + }); + function result(object, path, defaultValue) { + var result = object == null ? undefined : object[path]; + if (result === undefined) { + if (object != null && !isKey(path, object)) { + path = toPath(path); + object = path.length == 1 ? object : baseGet(object, baseSlice(path, 0, -1)); + result = object == null ? undefined : object[last(path)]; + } + result = result === undefined ? defaultValue : result; + } + return isFunction(result) ? result.call(object) : result; + } + function set(object, path, value) { + if (object == null) { + return object; + } + var pathKey = path + ""; + path = object[pathKey] != null || isKey(path, object) ? [ pathKey ] : toPath(path); + var index = -1, length = path.length, lastIndex = length - 1, nested = object; + while (nested != null && ++index < length) { + var key = path[index]; + if (isObject(nested)) { + if (index == lastIndex) { + nested[key] = value; + } else if (nested[key] == null) { + nested[key] = isIndex(path[index + 1]) ? [] : {}; + } + } + nested = nested[key]; + } + return object; + } + function transform(object, iteratee, accumulator, thisArg) { + var isArr = isArray(object) || isTypedArray(object); + iteratee = getCallback(iteratee, thisArg, 4); + if (accumulator == null) { + if (isArr || isObject(object)) { + var Ctor = object.constructor; + if (isArr) { + accumulator = isArray(object) ? new Ctor() : []; + } else { + accumulator = baseCreate(isFunction(Ctor) ? Ctor.prototype : undefined); + } + } else { + accumulator = {}; + } + } + (isArr ? arrayEach : baseForOwn)(object, function(value, index, object) { + return iteratee(accumulator, value, index, object); + }); + return accumulator; + } + function values(object) { + return baseValues(object, keys(object)); + } + function valuesIn(object) { + return baseValues(object, keysIn(object)); + } + function inRange(value, start, end) { + start = +start || 0; + if (end === undefined) { + end = start; + start = 0; + } else { + end = +end || 0; + } + return value >= nativeMin(start, end) && value < nativeMax(start, end); + } + function random(min, max, floating) { + if (floating && isIterateeCall(min, max, floating)) { + max = floating = undefined; + } + var noMin = min == null, noMax = max == null; + if (floating == null) { + if (noMax && typeof min == "boolean") { + floating = min; + min = 1; + } else if (typeof max == "boolean") { + floating = max; + noMax = true; + } + } + if (noMin && noMax) { + max = 1; + noMax = false; + } + min = +min || 0; + if (noMax) { + max = min; + min = 0; + } else { + max = +max || 0; + } + if (floating || min % 1 || max % 1) { + var rand = nativeRandom(); + return nativeMin(min + rand * (max - min + parseFloat("1e-" + ((rand + "").length - 1))), max); + } + return baseRandom(min, max); + } + var camelCase = createCompounder(function(result, word, index) { + word = word.toLowerCase(); + return result + (index ? word.charAt(0).toUpperCase() + word.slice(1) : word); + }); + function capitalize(string) { + string = baseToString(string); + return string && string.charAt(0).toUpperCase() + string.slice(1); + } + function deburr(string) { + string = baseToString(string); + return string && string.replace(reLatin1, deburrLetter).replace(reComboMark, ""); + } + function endsWith(string, target, position) { + string = baseToString(string); + target = target + ""; + var length = string.length; + position = position === undefined ? length : nativeMin(position < 0 ? 0 : +position || 0, length); + position -= target.length; + return position >= 0 && string.indexOf(target, position) == position; + } + function escape(string) { + string = baseToString(string); + return string && reHasUnescapedHtml.test(string) ? string.replace(reUnescapedHtml, escapeHtmlChar) : string; + } + function escapeRegExp(string) { + string = baseToString(string); + return string && reHasRegExpChars.test(string) ? string.replace(reRegExpChars, escapeRegExpChar) : string || "(?:)"; + } + var kebabCase = createCompounder(function(result, word, index) { + return result + (index ? "-" : "") + word.toLowerCase(); + }); + function pad(string, length, chars) { + string = baseToString(string); + length = +length; + var strLength = string.length; + if (strLength >= length || !nativeIsFinite(length)) { + return string; + } + var mid = (length - strLength) / 2, leftLength = nativeFloor(mid), rightLength = nativeCeil(mid); + chars = createPadding("", rightLength, chars); + return chars.slice(0, leftLength) + string + chars; + } + var padLeft = createPadDir(); + var padRight = createPadDir(true); + function parseInt(string, radix, guard) { + if (guard ? isIterateeCall(string, radix, guard) : radix == null) { + radix = 0; + } else if (radix) { + radix = +radix; + } + string = trim(string); + return nativeParseInt(string, radix || (reHasHexPrefix.test(string) ? 16 : 10)); + } + function repeat(string, n) { + var result = ""; + string = baseToString(string); + n = +n; + if (n < 1 || !string || !nativeIsFinite(n)) { + return result; + } + do { + if (n % 2) { + result += string; + } + n = nativeFloor(n / 2); + string += string; + } while (n); + return result; + } + var snakeCase = createCompounder(function(result, word, index) { + return result + (index ? "_" : "") + word.toLowerCase(); + }); + var startCase = createCompounder(function(result, word, index) { + return result + (index ? " " : "") + (word.charAt(0).toUpperCase() + word.slice(1)); + }); + function startsWith(string, target, position) { + string = baseToString(string); + position = position == null ? 0 : nativeMin(position < 0 ? 0 : +position || 0, string.length); + return string.lastIndexOf(target, position) == position; + } + function template(string, options, otherOptions) { + var settings = lodash.templateSettings; + if (otherOptions && isIterateeCall(string, options, otherOptions)) { + options = otherOptions = undefined; + } + string = baseToString(string); + options = assignWith(baseAssign({}, otherOptions || options), settings, assignOwnDefaults); + var imports = assignWith(baseAssign({}, options.imports), settings.imports, assignOwnDefaults), importsKeys = keys(imports), importsValues = baseValues(imports, importsKeys); + var isEscaping, isEvaluating, index = 0, interpolate = options.interpolate || reNoMatch, source = "__p += '"; + var reDelimiters = RegExp((options.escape || reNoMatch).source + "|" + interpolate.source + "|" + (interpolate === reInterpolate ? reEsTemplate : reNoMatch).source + "|" + (options.evaluate || reNoMatch).source + "|$", "g"); + var sourceURL = "//# sourceURL=" + ("sourceURL" in options ? options.sourceURL : "lodash.templateSources[" + ++templateCounter + "]") + "\n"; + string.replace(reDelimiters, function(match, escapeValue, interpolateValue, esTemplateValue, evaluateValue, offset) { + interpolateValue || (interpolateValue = esTemplateValue); + source += string.slice(index, offset).replace(reUnescapedString, escapeStringChar); + if (escapeValue) { + isEscaping = true; + source += "' +\n__e(" + escapeValue + ") +\n'"; + } + if (evaluateValue) { + isEvaluating = true; + source += "';\n" + evaluateValue + ";\n__p += '"; + } + if (interpolateValue) { + source += "' +\n((__t = (" + interpolateValue + ")) == null ? '' : __t) +\n'"; + } + index = offset + match.length; + return match; + }); + source += "';\n"; + var variable = options.variable; + if (!variable) { + source = "with (obj) {\n" + source + "\n}\n"; + } + source = (isEvaluating ? source.replace(reEmptyStringLeading, "") : source).replace(reEmptyStringMiddle, "$1").replace(reEmptyStringTrailing, "$1;"); + source = "function(" + (variable || "obj") + ") {\n" + (variable ? "" : "obj || (obj = {});\n") + "var __t, __p = ''" + (isEscaping ? ", __e = _.escape" : "") + (isEvaluating ? ", __j = Array.prototype.join;\n" + "function print() { __p += __j.call(arguments, '') }\n" : ";\n") + source + "return __p\n}"; + var result = attempt(function() { + return Function(importsKeys, sourceURL + "return " + source).apply(undefined, importsValues); + }); + result.source = source; + if (isError(result)) { + throw result; + } + return result; + } + function trim(string, chars, guard) { + var value = string; + string = baseToString(string); + if (!string) { + return string; + } + if (guard ? isIterateeCall(value, chars, guard) : chars == null) { + return string.slice(trimmedLeftIndex(string), trimmedRightIndex(string) + 1); + } + chars = chars + ""; + return string.slice(charsLeftIndex(string, chars), charsRightIndex(string, chars) + 1); + } + function trimLeft(string, chars, guard) { + var value = string; + string = baseToString(string); + if (!string) { + return string; + } + if (guard ? isIterateeCall(value, chars, guard) : chars == null) { + return string.slice(trimmedLeftIndex(string)); + } + return string.slice(charsLeftIndex(string, chars + "")); + } + function trimRight(string, chars, guard) { + var value = string; + string = baseToString(string); + if (!string) { + return string; + } + if (guard ? isIterateeCall(value, chars, guard) : chars == null) { + return string.slice(0, trimmedRightIndex(string) + 1); + } + return string.slice(0, charsRightIndex(string, chars + "") + 1); + } + function trunc(string, options, guard) { + if (guard && isIterateeCall(string, options, guard)) { + options = undefined; + } + var length = DEFAULT_TRUNC_LENGTH, omission = DEFAULT_TRUNC_OMISSION; + if (options != null) { + if (isObject(options)) { + var separator = "separator" in options ? options.separator : separator; + length = "length" in options ? +options.length || 0 : length; + omission = "omission" in options ? baseToString(options.omission) : omission; + } else { + length = +options || 0; + } + } + string = baseToString(string); + if (length >= string.length) { + return string; + } + var end = length - omission.length; + if (end < 1) { + return omission; + } + var result = string.slice(0, end); + if (separator == null) { + return result + omission; + } + if (isRegExp(separator)) { + if (string.slice(end).search(separator)) { + var match, newEnd, substring = string.slice(0, end); + if (!separator.global) { + separator = RegExp(separator.source, (reFlags.exec(separator) || "") + "g"); + } + separator.lastIndex = 0; + while (match = separator.exec(substring)) { + newEnd = match.index; + } + result = result.slice(0, newEnd == null ? end : newEnd); + } + } else if (string.indexOf(separator, end) != end) { + var index = result.lastIndexOf(separator); + if (index > -1) { + result = result.slice(0, index); + } + } + return result + omission; + } + function unescape(string) { + string = baseToString(string); + return string && reHasEscapedHtml.test(string) ? string.replace(reEscapedHtml, unescapeHtmlChar) : string; + } + function words(string, pattern, guard) { + if (guard && isIterateeCall(string, pattern, guard)) { + pattern = undefined; + } + string = baseToString(string); + return string.match(pattern || reWords) || []; + } + var attempt = restParam(function(func, args) { + try { + return func.apply(undefined, args); + } catch (e) { + return isError(e) ? e : new Error(e); + } + }); + function callback(func, thisArg, guard) { + if (guard && isIterateeCall(func, thisArg, guard)) { + thisArg = undefined; + } + return isObjectLike(func) ? matches(func) : baseCallback(func, thisArg); + } + function constant(value) { + return function() { + return value; + }; + } + function identity(value) { + return value; + } + function matches(source) { + return baseMatches(baseClone(source, true)); + } + function matchesProperty(path, srcValue) { + return baseMatchesProperty(path, baseClone(srcValue, true)); + } + var method = restParam(function(path, args) { + return function(object) { + return invokePath(object, path, args); + }; + }); + var methodOf = restParam(function(object, args) { + return function(path) { + return invokePath(object, path, args); + }; + }); + function mixin(object, source, options) { + if (options == null) { + var isObj = isObject(source), props = isObj ? keys(source) : undefined, methodNames = props && props.length ? baseFunctions(source, props) : undefined; + if (!(methodNames ? methodNames.length : isObj)) { + methodNames = false; + options = source; + source = object; + object = this; + } + } + if (!methodNames) { + methodNames = baseFunctions(source, keys(source)); + } + var chain = true, index = -1, isFunc = isFunction(object), length = methodNames.length; + if (options === false) { + chain = false; + } else if (isObject(options) && "chain" in options) { + chain = options.chain; + } + while (++index < length) { + var methodName = methodNames[index], func = source[methodName]; + object[methodName] = func; + if (isFunc) { + object.prototype[methodName] = function(func) { + return function() { + var chainAll = this.__chain__; + if (chain || chainAll) { + var result = object(this.__wrapped__), actions = result.__actions__ = arrayCopy(this.__actions__); + actions.push({ + func: func, + args: arguments, + thisArg: object + }); + result.__chain__ = chainAll; + return result; + } + return func.apply(object, arrayPush([ this.value() ], arguments)); + }; + }(func); + } + } + return object; + } + function noConflict() { + root._ = oldDash; + return this; + } + function noop() {} + function property(path) { + return isKey(path) ? baseProperty(path) : basePropertyDeep(path); + } + function propertyOf(object) { + return function(path) { + return baseGet(object, toPath(path), path + ""); + }; + } + function range(start, end, step) { + if (step && isIterateeCall(start, end, step)) { + end = step = undefined; + } + start = +start || 0; + step = step == null ? 1 : +step || 0; + if (end == null) { + end = start; + start = 0; + } else { + end = +end || 0; + } + var index = -1, length = nativeMax(nativeCeil((end - start) / (step || 1)), 0), result = Array(length); + while (++index < length) { + result[index] = start; + start += step; + } + return result; + } + function times(n, iteratee, thisArg) { + n = nativeFloor(n); + if (n < 1 || !nativeIsFinite(n)) { + return []; + } + var index = -1, result = Array(nativeMin(n, MAX_ARRAY_LENGTH)); + iteratee = bindCallback(iteratee, thisArg, 1); + while (++index < n) { + if (index < MAX_ARRAY_LENGTH) { + result[index] = iteratee(index); + } else { + iteratee(index); + } + } + return result; + } + function uniqueId(prefix) { + var id = ++idCounter; + return baseToString(prefix) + id; + } + function add(augend, addend) { + return (+augend || 0) + (+addend || 0); + } + var ceil = createRound("ceil"); + var floor = createRound("floor"); + var max = createExtremum(gt, NEGATIVE_INFINITY); + var min = createExtremum(lt, POSITIVE_INFINITY); + var round = createRound("round"); + function sum(collection, iteratee, thisArg) { + if (thisArg && isIterateeCall(collection, iteratee, thisArg)) { + iteratee = undefined; + } + iteratee = getCallback(iteratee, thisArg, 3); + return iteratee.length == 1 ? arraySum(isArray(collection) ? collection : toIterable(collection), iteratee) : baseSum(collection, iteratee); + } + lodash.prototype = baseLodash.prototype; + LodashWrapper.prototype = baseCreate(baseLodash.prototype); + LodashWrapper.prototype.constructor = LodashWrapper; + LazyWrapper.prototype = baseCreate(baseLodash.prototype); + LazyWrapper.prototype.constructor = LazyWrapper; + MapCache.prototype["delete"] = mapDelete; + MapCache.prototype.get = mapGet; + MapCache.prototype.has = mapHas; + MapCache.prototype.set = mapSet; + SetCache.prototype.push = cachePush; + memoize.Cache = MapCache; + lodash.after = after; + lodash.ary = ary; + lodash.assign = assign; + lodash.at = at; + lodash.before = before; + lodash.bind = bind; + lodash.bindAll = bindAll; + lodash.bindKey = bindKey; + lodash.callback = callback; + lodash.chain = chain; + lodash.chunk = chunk; + lodash.compact = compact; + lodash.constant = constant; + lodash.countBy = countBy; + lodash.create = create; + lodash.curry = curry; + lodash.curryRight = curryRight; + lodash.debounce = debounce; + lodash.defaults = defaults; + lodash.defaultsDeep = defaultsDeep; + lodash.defer = defer; + lodash.delay = delay; + lodash.difference = difference; + lodash.drop = drop; + lodash.dropRight = dropRight; + lodash.dropRightWhile = dropRightWhile; + lodash.dropWhile = dropWhile; + lodash.fill = fill; + lodash.filter = filter; + lodash.flatten = flatten; + lodash.flattenDeep = flattenDeep; + lodash.flow = flow; + lodash.flowRight = flowRight; + lodash.forEach = forEach; + lodash.forEachRight = forEachRight; + lodash.forIn = forIn; + lodash.forInRight = forInRight; + lodash.forOwn = forOwn; + lodash.forOwnRight = forOwnRight; + lodash.functions = functions; + lodash.groupBy = groupBy; + lodash.indexBy = indexBy; + lodash.initial = initial; + lodash.intersection = intersection; + lodash.invert = invert; + lodash.invoke = invoke; + lodash.keys = keys; + lodash.keysIn = keysIn; + lodash.map = map; + lodash.mapKeys = mapKeys; + lodash.mapValues = mapValues; + lodash.matches = matches; + lodash.matchesProperty = matchesProperty; + lodash.memoize = memoize; + lodash.merge = merge; + lodash.method = method; + lodash.methodOf = methodOf; + lodash.mixin = mixin; + lodash.modArgs = modArgs; + lodash.negate = negate; + lodash.omit = omit; + lodash.once = once; + lodash.pairs = pairs; + lodash.partial = partial; + lodash.partialRight = partialRight; + lodash.partition = partition; + lodash.pick = pick; + lodash.pluck = pluck; + lodash.property = property; + lodash.propertyOf = propertyOf; + lodash.pull = pull; + lodash.pullAt = pullAt; + lodash.range = range; + lodash.rearg = rearg; + lodash.reject = reject; + lodash.remove = remove; + lodash.rest = rest; + lodash.restParam = restParam; + lodash.set = set; + lodash.shuffle = shuffle; + lodash.slice = slice; + lodash.sortBy = sortBy; + lodash.sortByAll = sortByAll; + lodash.sortByOrder = sortByOrder; + lodash.spread = spread; + lodash.take = take; + lodash.takeRight = takeRight; + lodash.takeRightWhile = takeRightWhile; + lodash.takeWhile = takeWhile; + lodash.tap = tap; + lodash.throttle = throttle; + lodash.thru = thru; + lodash.times = times; + lodash.toArray = toArray; + lodash.toPlainObject = toPlainObject; + lodash.transform = transform; + lodash.union = union; + lodash.uniq = uniq; + lodash.unzip = unzip; + lodash.unzipWith = unzipWith; + lodash.values = values; + lodash.valuesIn = valuesIn; + lodash.where = where; + lodash.without = without; + lodash.wrap = wrap; + lodash.xor = xor; + lodash.zip = zip; + lodash.zipObject = zipObject; + lodash.zipWith = zipWith; + lodash.backflow = flowRight; + lodash.collect = map; + lodash.compose = flowRight; + lodash.each = forEach; + lodash.eachRight = forEachRight; + lodash.extend = assign; + lodash.iteratee = callback; + lodash.methods = functions; + lodash.object = zipObject; + lodash.select = filter; + lodash.tail = rest; + lodash.unique = uniq; + mixin(lodash, lodash); + lodash.add = add; + lodash.attempt = attempt; + lodash.camelCase = camelCase; + lodash.capitalize = capitalize; + lodash.ceil = ceil; + lodash.clone = clone; + lodash.cloneDeep = cloneDeep; + lodash.deburr = deburr; + lodash.endsWith = endsWith; + lodash.escape = escape; + lodash.escapeRegExp = escapeRegExp; + lodash.every = every; + lodash.find = find; + lodash.findIndex = findIndex; + lodash.findKey = findKey; + lodash.findLast = findLast; + lodash.findLastIndex = findLastIndex; + lodash.findLastKey = findLastKey; + lodash.findWhere = findWhere; + lodash.first = first; + lodash.floor = floor; + lodash.get = get; + lodash.gt = gt; + lodash.gte = gte; + lodash.has = has; + lodash.identity = identity; + lodash.includes = includes; + lodash.indexOf = indexOf; + lodash.inRange = inRange; + lodash.isArguments = isArguments; + lodash.isArray = isArray; + lodash.isBoolean = isBoolean; + lodash.isDate = isDate; + lodash.isElement = isElement; + lodash.isEmpty = isEmpty; + lodash.isEqual = isEqual; + lodash.isError = isError; + lodash.isFinite = isFinite; + lodash.isFunction = isFunction; + lodash.isMatch = isMatch; + lodash.isNaN = isNaN; + lodash.isNative = isNative; + lodash.isNull = isNull; + lodash.isNumber = isNumber; + lodash.isObject = isObject; + lodash.isPlainObject = isPlainObject; + lodash.isRegExp = isRegExp; + lodash.isString = isString; + lodash.isTypedArray = isTypedArray; + lodash.isUndefined = isUndefined; + lodash.kebabCase = kebabCase; + lodash.last = last; + lodash.lastIndexOf = lastIndexOf; + lodash.lt = lt; + lodash.lte = lte; + lodash.max = max; + lodash.min = min; + lodash.noConflict = noConflict; + lodash.noop = noop; + lodash.now = now; + lodash.pad = pad; + lodash.padLeft = padLeft; + lodash.padRight = padRight; + lodash.parseInt = parseInt; + lodash.random = random; + lodash.reduce = reduce; + lodash.reduceRight = reduceRight; + lodash.repeat = repeat; + lodash.result = result; + lodash.round = round; + lodash.runInContext = runInContext; + lodash.size = size; + lodash.snakeCase = snakeCase; + lodash.some = some; + lodash.sortedIndex = sortedIndex; + lodash.sortedLastIndex = sortedLastIndex; + lodash.startCase = startCase; + lodash.startsWith = startsWith; + lodash.sum = sum; + lodash.template = template; + lodash.trim = trim; + lodash.trimLeft = trimLeft; + lodash.trimRight = trimRight; + lodash.trunc = trunc; + lodash.unescape = unescape; + lodash.uniqueId = uniqueId; + lodash.words = words; + lodash.all = every; + lodash.any = some; + lodash.contains = includes; + lodash.eq = isEqual; + lodash.detect = find; + lodash.foldl = reduce; + lodash.foldr = reduceRight; + lodash.head = first; + lodash.include = includes; + lodash.inject = reduce; + mixin(lodash, function() { + var source = {}; + baseForOwn(lodash, function(func, methodName) { + if (!lodash.prototype[methodName]) { + source[methodName] = func; + } + }); + return source; + }(), false); + lodash.sample = sample; + lodash.prototype.sample = function(n) { + if (!this.__chain__ && n == null) { + return sample(this.value()); + } + return this.thru(function(value) { + return sample(value, n); + }); + }; + lodash.VERSION = VERSION; + arrayEach([ "bind", "bindKey", "curry", "curryRight", "partial", "partialRight" ], function(methodName) { + lodash[methodName].placeholder = lodash; + }); + arrayEach([ "drop", "take" ], function(methodName, index) { + LazyWrapper.prototype[methodName] = function(n) { + var filtered = this.__filtered__; + if (filtered && !index) { + return new LazyWrapper(this); + } + n = n == null ? 1 : nativeMax(nativeFloor(n) || 0, 0); + var result = this.clone(); + if (filtered) { + result.__takeCount__ = nativeMin(result.__takeCount__, n); + } else { + result.__views__.push({ + size: n, + type: methodName + (result.__dir__ < 0 ? "Right" : "") + }); + } + return result; + }; + LazyWrapper.prototype[methodName + "Right"] = function(n) { + return this.reverse()[methodName](n).reverse(); + }; + }); + arrayEach([ "filter", "map", "takeWhile" ], function(methodName, index) { + var type = index + 1, isFilter = type != LAZY_MAP_FLAG; + LazyWrapper.prototype[methodName] = function(iteratee, thisArg) { + var result = this.clone(); + result.__iteratees__.push({ + iteratee: getCallback(iteratee, thisArg, 1), + type: type + }); + result.__filtered__ = result.__filtered__ || isFilter; + return result; + }; + }); + arrayEach([ "first", "last" ], function(methodName, index) { + var takeName = "take" + (index ? "Right" : ""); + LazyWrapper.prototype[methodName] = function() { + return this[takeName](1).value()[0]; + }; + }); + arrayEach([ "initial", "rest" ], function(methodName, index) { + var dropName = "drop" + (index ? "" : "Right"); + LazyWrapper.prototype[methodName] = function() { + return this.__filtered__ ? new LazyWrapper(this) : this[dropName](1); + }; + }); + arrayEach([ "pluck", "where" ], function(methodName, index) { + var operationName = index ? "filter" : "map", createCallback = index ? baseMatches : property; + LazyWrapper.prototype[methodName] = function(value) { + return this[operationName](createCallback(value)); + }; + }); + LazyWrapper.prototype.compact = function() { + return this.filter(identity); + }; + LazyWrapper.prototype.reject = function(predicate, thisArg) { + predicate = getCallback(predicate, thisArg, 1); + return this.filter(function(value) { + return !predicate(value); + }); + }; + LazyWrapper.prototype.slice = function(start, end) { + start = start == null ? 0 : +start || 0; + var result = this; + if (result.__filtered__ && (start > 0 || end < 0)) { + return new LazyWrapper(result); + } + if (start < 0) { + result = result.takeRight(-start); + } else if (start) { + result = result.drop(start); + } + if (end !== undefined) { + end = +end || 0; + result = end < 0 ? result.dropRight(-end) : result.take(end - start); + } + return result; + }; + LazyWrapper.prototype.takeRightWhile = function(predicate, thisArg) { + return this.reverse().takeWhile(predicate, thisArg).reverse(); + }; + LazyWrapper.prototype.toArray = function() { + return this.take(POSITIVE_INFINITY); + }; + baseForOwn(LazyWrapper.prototype, function(func, methodName) { + var checkIteratee = /^(?:filter|map|reject)|While$/.test(methodName), retUnwrapped = /^(?:first|last)$/.test(methodName), lodashFunc = lodash[retUnwrapped ? "take" + (methodName == "last" ? "Right" : "") : methodName]; + if (!lodashFunc) { + return; + } + lodash.prototype[methodName] = function() { + var args = retUnwrapped ? [ 1 ] : arguments, chainAll = this.__chain__, value = this.__wrapped__, isHybrid = !!this.__actions__.length, isLazy = value instanceof LazyWrapper, iteratee = args[0], useLazy = isLazy || isArray(value); + if (useLazy && checkIteratee && typeof iteratee == "function" && iteratee.length != 1) { + isLazy = useLazy = false; + } + var interceptor = function(value) { + return retUnwrapped && chainAll ? lodashFunc(value, 1)[0] : lodashFunc.apply(undefined, arrayPush([ value ], args)); + }; + var action = { + func: thru, + args: [ interceptor ], + thisArg: undefined + }, onlyLazy = isLazy && !isHybrid; + if (retUnwrapped && !chainAll) { + if (onlyLazy) { + value = value.clone(); + value.__actions__.push(action); + return func.call(value); + } + return lodashFunc.call(undefined, this.value())[0]; + } + if (!retUnwrapped && useLazy) { + value = onlyLazy ? value : new LazyWrapper(this); + var result = func.apply(value, args); + result.__actions__.push(action); + return new LodashWrapper(result, chainAll); + } + return this.thru(interceptor); + }; + }); + arrayEach([ "join", "pop", "push", "replace", "shift", "sort", "splice", "split", "unshift" ], function(methodName) { + var func = (/^(?:replace|split)$/.test(methodName) ? stringProto : arrayProto)[methodName], chainName = /^(?:push|sort|unshift)$/.test(methodName) ? "tap" : "thru", retUnwrapped = /^(?:join|pop|replace|shift)$/.test(methodName); + lodash.prototype[methodName] = function() { + var args = arguments; + if (retUnwrapped && !this.__chain__) { + return func.apply(this.value(), args); + } + return this[chainName](function(value) { + return func.apply(value, args); + }); + }; + }); + baseForOwn(LazyWrapper.prototype, function(func, methodName) { + var lodashFunc = lodash[methodName]; + if (lodashFunc) { + var key = lodashFunc.name + "", names = realNames[key] || (realNames[key] = []); + names.push({ + name: methodName, + func: lodashFunc + }); + } + }); + realNames[createHybridWrapper(undefined, BIND_KEY_FLAG).name] = [ { + name: "wrapper", + func: undefined + } ]; + LazyWrapper.prototype.clone = lazyClone; + LazyWrapper.prototype.reverse = lazyReverse; + LazyWrapper.prototype.value = lazyValue; + lodash.prototype.chain = wrapperChain; + lodash.prototype.commit = wrapperCommit; + lodash.prototype.concat = wrapperConcat; + lodash.prototype.plant = wrapperPlant; + lodash.prototype.reverse = wrapperReverse; + lodash.prototype.toString = wrapperToString; + lodash.prototype.run = lodash.prototype.toJSON = lodash.prototype.valueOf = lodash.prototype.value = wrapperValue; + lodash.prototype.collect = lodash.prototype.map; + lodash.prototype.head = lodash.prototype.first; + lodash.prototype.select = lodash.prototype.filter; + lodash.prototype.tail = lodash.prototype.rest; + return lodash; + } + var _ = runInContext(); + if (typeof define == "function" && typeof define.amd == "object" && define.amd) { + root._ = _; + define(function() { + return _; + }); + } else if (freeExports && freeModule) { + if (moduleExports) { + (freeModule.exports = _)._ = _; + } else { + freeExports._ = _; + } + } else { + root._ = _; + } +}).call(this); + (function(window, document, undefined) { "use strict"; function minErr(module, ErrorConstructor) { @@ -5391,7 +9332,7 @@ } return match; }); - message += "\nhttp://errors.angularjs.org/1.4.6/" + (module ? module + "/" : "") + code; + message += "\nhttp://errors.angularjs.org/1.4.7/" + (module ? module + "/" : "") + code; for (i = SKIP_INDEXES, paramPrefix = "?"; i < templateArgs.length; i++, paramPrefix = "&") { message += paramPrefix + "p" + (i - SKIP_INDEXES) + "=" + encodeURIComponent(toDebugString(templateArgs[i])); } @@ -6210,11 +10151,11 @@ return obj; } var version = { - full: "1.4.6", + full: "1.4.7", major: 1, minor: 4, - dot: 6, - codeName: "multiplicative-elevation" + dot: 7, + codeName: "dark-luminescence" }; function publishExternalAPI(angular) { extend(angular, { @@ -6323,6 +10264,7 @@ $httpParamSerializer: $HttpParamSerializerProvider, $httpParamSerializerJQLike: $HttpParamSerializerJQLikeProvider, $httpBackend: $HttpBackendProvider, + $xhrFactory: $xhrFactoryProvider, $location: $LocationProvider, $log: $LogProvider, $parse: $ParseProvider, @@ -6368,10 +10310,10 @@ return offset ? letter.toUpperCase() : letter; }).replace(MOZ_HACK_REGEXP, "Moz$1"); } - var SINGLE_TAG_REGEXP = /^<(\w+)\s*\/?>(?:<\/\1>|)$/; + var SINGLE_TAG_REGEXP = /^<([\w-]+)\s*\/?>(?:<\/\1>|)$/; var HTML_REGEXP = /<|&#?\w+;/; - var TAG_NAME_REGEXP = /<([\w:]+)/; - var XHTML_TAG_REGEXP = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi; + var TAG_NAME_REGEXP = /<([\w:-]+)/; + var XHTML_TAG_REGEXP = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:-]+)[^>]*)\/>/gi; var wrapMap = { option: [ 1, '" ], thead: [ 1, "", "
                      " ], @@ -7614,6 +11556,9 @@ } }; return function(element, options) { + if (options.cleanupStyles) { + options.from = options.to = null; + } if (options.from) { element.css(options.from); options.from = null; @@ -8879,7 +12824,7 @@ compile: function() { return { pre: function attrInterpolatePreLinkFn(scope, element, attr) { - var $$observers = attr.$$observers || (attr.$$observers = {}); + var $$observers = attr.$$observers || (attr.$$observers = createMap()); if (EVENT_HANDLER_ATTR_REGEXP.test(name)) { throw $compileMinErr("nodomevents", "Interpolations for HTML DOM event attributes are disallowed. Please use the " + "ng- versions (such as ng-click instead of onclick) instead."); } @@ -9542,12 +13487,16 @@ } } ]; } - function createXhr() { - return new window.XMLHttpRequest(); + function $xhrFactoryProvider() { + this.$get = function() { + return function createXhr() { + return new window.XMLHttpRequest(); + }; + }; } function $HttpBackendProvider() { - this.$get = [ "$browser", "$window", "$document", function($browser, $window, $document) { - return createHttpBackend($browser, createXhr, $browser.defer, $window.angular.callbacks, $document[0]); + this.$get = [ "$browser", "$window", "$document", "$xhrFactory", function($browser, $window, $document, $xhrFactory) { + return createHttpBackend($browser, $xhrFactory, $browser.defer, $window.angular.callbacks, $document[0]); } ]; } function createHttpBackend($browser, createXhr, $browserDefer, callbacks, rawDocument) { @@ -9565,7 +13514,7 @@ callbacks[callbackId] = noop; }); } else { - var xhr = createXhr(); + var xhr = createXhr(method, url); xhr.open(method, url, true); forEach(headers, function(value, key) { if (isDefined(value)) { @@ -10273,12 +14222,18 @@ } var $parseMinErr = minErr("$parse"); function ensureSafeMemberName(name, fullExpression) { - name = isObject(name) && name.toString ? name.toString() : name; if (name === "__defineGetter__" || name === "__defineSetter__" || name === "__lookupGetter__" || name === "__lookupSetter__" || name === "__proto__") { throw $parseMinErr("isecfld", "Attempting to access a disallowed field in Angular expressions! " + "Expression: {0}", fullExpression); } return name; } + function getStringValue(name, fullExpression) { + name = name + ""; + if (!isString(name)) { + throw $parseMinErr("iseccst", "Cannot convert object to primitive value! " + "Expression: {0}", fullExpression); + } + return name; + } function ensureSafeObject(obj, fullExpression) { if (obj) { if (obj.constructor === obj) { @@ -10305,6 +14260,13 @@ } } } + function ensureSafeAssignContext(obj, fullExpression) { + if (obj) { + if (obj === 0..constructor || obj === false.constructor || obj === "".constructor || obj === {}.constructor || obj === [].constructor || obj === Function.constructor) { + throw $parseMinErr("isecaf", "Assigning to a constructor is disallowed! Expression: {0}", fullExpression); + } + } + } var OPERATORS = createMap(); forEach("+ - * / % === !== == != < > <= >= && || ! = |".split(" "), function(operator) { OPERATORS[operator] = true; @@ -11053,7 +15015,7 @@ this.stage = "main"; this.recurse(ast); var fnString = '"' + this.USE + " " + this.STRICT + '";\n' + this.filterPrefix() + "var fn=" + this.generateFunction("fn", "s,l,a,i") + extra + this.watchFns() + "return fn;"; - var fn = new Function("$filter", "ensureSafeMemberName", "ensureSafeObject", "ensureSafeFunction", "ifDefined", "plus", "text", fnString)(this.$filter, ensureSafeMemberName, ensureSafeObject, ensureSafeFunction, ifDefined, plusFn, expression); + var fn = new Function("$filter", "ensureSafeMemberName", "ensureSafeObject", "ensureSafeFunction", "getStringValue", "ensureSafeAssignContext", "ifDefined", "plus", "text", fnString)(this.$filter, ensureSafeMemberName, ensureSafeObject, ensureSafeFunction, getStringValue, ensureSafeAssignContext, ifDefined, plusFn, expression); this.state = this.stage = undefined; fn.literal = isLiteral(ast); fn.constant = isConstant(ast); @@ -11190,6 +15152,7 @@ if (ast.computed) { right = self.nextId(); self.recurse(ast.property, right); + self.getStringValue(right); self.addEnsureSafeMemberName(right); if (create && create !== 1) { self.if_(self.not(self.computedMember(left, right)), self.lazyAssign(self.computedMember(left, right), "{}")); @@ -11275,6 +15238,7 @@ self.if_(self.notNull(left.context), function() { self.recurse(ast.right, right); self.addEnsureSafeObject(self.member(left.context, left.name, left.computed)); + self.addEnsureSafeAssignContext(left.context); expression = self.member(left.context, left.name, left.computed) + ast.operator + right; self.assign(intoId, expression); recursionFn(intoId || expression); @@ -11385,6 +15349,9 @@ addEnsureSafeFunction: function(item) { this.current().body.push(this.ensureSafeFunction(item), ";"); }, + addEnsureSafeAssignContext: function(item) { + this.current().body.push(this.ensureSafeAssignContext(item), ";"); + }, ensureSafeObject: function(item) { return "ensureSafeObject(" + item + ",text)"; }, @@ -11394,6 +15361,12 @@ ensureSafeFunction: function(item) { return "ensureSafeFunction(" + item + ",text)"; }, + getStringValue: function(item) { + this.assign(item, "getStringValue(" + item + ",text)"); + }, + ensureSafeAssignContext: function(item) { + return "ensureSafeAssignContext(" + item + ",text)"; + }, lazyRecurse: function(ast, intoId, nameId, recursionFn, create, skipWatchIdCheck) { var self = this; return function() { @@ -11561,6 +15534,7 @@ var lhs = left(scope, locals, assign, inputs); var rhs = right(scope, locals, assign, inputs); ensureSafeObject(lhs.value, self.expression); + ensureSafeAssignContext(lhs.context); lhs.context[lhs.name] = rhs; return context ? { value: rhs @@ -11818,6 +15792,7 @@ var value; if (lhs != null) { rhs = right(scope, locals, assign, inputs); + rhs = getStringValue(rhs); ensureSafeMemberName(rhs, expression); if (create && create !== 1 && lhs && !lhs[rhs]) { lhs[rhs] = {}; @@ -13500,6 +17475,7 @@ if (fractionSize > 0 && number < 1) { formatedText = number.toFixed(fractionSize); number = parseFloat(formatedText); + formatedText = formatedText.replace(DECIMAL_SEP, decimalSep); } } if (number === 0) { @@ -15517,11 +19493,11 @@ function updateOptionElement(option, element) { option.element = element; element.disabled = option.disabled; - if (option.value !== element.value) element.value = option.selectValue; if (option.label !== element.label) { element.label = option.label; element.textContent = option.label; } + if (option.value !== element.value) element.value = option.selectValue; } function addOrReuseElement(parent, current, type, templateElement) { var element; @@ -15549,7 +19525,7 @@ var emptyOption_ = emptyOption && emptyOption[0]; var unknownOption_ = unknownOption && unknownOption[0]; if (emptyOption_ || unknownOption_) { - while (current && (current === emptyOption_ || current === unknownOption_)) { + while (current && (current === emptyOption_ || current === unknownOption_ || emptyOption_ && emptyOption_.nodeType === NODE_TYPE_COMMENT)) { current = current.nextSibling; } } @@ -26225,728 +30201,6 @@ angular.module("template/typeahead/typeahead-popup.html", []).run([ "$templateCa !angular.$$csp() && angular.element(document).find("head").prepend(''); -"use strict"; - -var WaveSurfer = { - defaultParams: { - height: 128, - waveColor: "#999", - progressColor: "#555", - cursorColor: "#333", - cursorWidth: 1, - skipLength: 2, - minPxPerSec: 20, - pixelRatio: window.devicePixelRatio, - fillParent: !0, - scrollParent: !1, - hideScrollbar: !1, - normalize: !1, - audioContext: null, - container: null, - dragSelection: !0, - loopSelection: !0, - audioRate: 1, - interact: !0, - splitChannels: !1, - renderer: "Canvas", - backend: "WebAudio", - mediaType: "audio" - }, - init: function(a) { - if (this.params = WaveSurfer.util.extend({}, this.defaultParams, a), this.container = "string" == typeof a.container ? document.querySelector(this.params.container) : this.params.container, - !this.container) throw new Error("Container element not found"); - if ("undefined" == typeof this.params.mediaContainer ? this.mediaContainer = this.container : "string" == typeof this.params.mediaContainer ? this.mediaContainer = document.querySelector(this.params.mediaContainer) : this.mediaContainer = this.params.mediaContainer, - !this.mediaContainer) throw new Error("Media Container element not found"); - this.savedVolume = 0, this.isMuted = !1, this.tmpEvents = [], this.createDrawer(), - this.createBackend(); - }, - createDrawer: function() { - var a = this; - this.drawer = Object.create(WaveSurfer.Drawer[this.params.renderer]), this.drawer.init(this.container, this.params), - this.drawer.on("redraw", function() { - a.drawBuffer(), a.drawer.progress(a.backend.getPlayedPercents()); - }), this.drawer.on("click", function(b, c) { - setTimeout(function() { - a.seekTo(c); - }, 0); - }), this.drawer.on("scroll", function(b) { - a.fireEvent("scroll", b); - }); - }, - createBackend: function() { - var a = this; - this.backend && this.backend.destroy(), "AudioElement" == this.params.backend && (this.params.backend = "MediaElement"), - "WebAudio" != this.params.backend || WaveSurfer.WebAudio.supportsWebAudio() || (this.params.backend = "MediaElement"), - this.backend = Object.create(WaveSurfer[this.params.backend]), this.backend.init(this.params), - this.backend.on("finish", function() { - a.fireEvent("finish"); - }), this.backend.on("play", function() { - a.fireEvent("play"); - }), this.backend.on("pause", function() { - a.fireEvent("pause"); - }), this.backend.on("audioprocess", function(b) { - a.drawer.progress(a.backend.getPlayedPercents()), a.fireEvent("audioprocess", b); - }); - }, - getDuration: function() { - return this.backend.getDuration(); - }, - getCurrentTime: function() { - return this.backend.getCurrentTime(); - }, - play: function(a, b) { - this.backend.play(a, b); - }, - pause: function() { - this.backend.pause(); - }, - playPause: function() { - this.backend.isPaused() ? this.play() : this.pause(); - }, - isPlaying: function() { - return !this.backend.isPaused(); - }, - skipBackward: function(a) { - this.skip(-a || -this.params.skipLength); - }, - skipForward: function(a) { - this.skip(a || this.params.skipLength); - }, - skip: function(a) { - var b = this.getCurrentTime() || 0, c = this.getDuration() || 1; - b = Math.max(0, Math.min(c, b + (a || 0))), this.seekAndCenter(b / c); - }, - seekAndCenter: function(a) { - this.seekTo(a), this.drawer.recenter(a); - }, - seekTo: function(a) { - var b = this.backend.isPaused(), c = this.params.scrollParent; - b && (this.params.scrollParent = !1), this.backend.seekTo(a * this.getDuration()), - this.drawer.progress(this.backend.getPlayedPercents()), b || (this.backend.pause(), - this.backend.play()), this.params.scrollParent = c, this.fireEvent("seek", a); - }, - stop: function() { - this.pause(), this.seekTo(0), this.drawer.progress(0); - }, - setVolume: function(a) { - this.backend.setVolume(a); - }, - setPlaybackRate: function(a) { - this.backend.setPlaybackRate(a); - }, - toggleMute: function() { - this.isMuted ? (this.backend.setVolume(this.savedVolume), this.isMuted = !1) : (this.savedVolume = this.backend.getVolume(), - this.backend.setVolume(0), this.isMuted = !0); - }, - toggleScroll: function() { - this.params.scrollParent = !this.params.scrollParent, this.drawBuffer(); - }, - toggleInteraction: function() { - this.params.interact = !this.params.interact; - }, - drawBuffer: function() { - var a = Math.round(this.getDuration() * this.params.minPxPerSec * this.params.pixelRatio), b = this.drawer.getWidth(), c = a; - this.params.fillParent && (!this.params.scrollParent || b > a) && (c = b); - var d = this.backend.getPeaks(c); - this.drawer.drawPeaks(d, c), this.fireEvent("redraw", d, c); - }, - zoom: function(a) { - this.params.minPxPerSec = a, this.params.scrollParent = !0, this.drawBuffer(), this.seekAndCenter(this.getCurrentTime() / this.getDuration()); - }, - loadArrayBuffer: function(a) { - this.decodeArrayBuffer(a, function(a) { - this.loadDecodedBuffer(a); - }.bind(this)); - }, - loadDecodedBuffer: function(a) { - this.backend.load(a), this.drawBuffer(), this.fireEvent("ready"); - }, - loadBlob: function(a) { - var b = this, c = new FileReader(); - c.addEventListener("progress", function(a) { - b.onProgress(a); - }), c.addEventListener("load", function(a) { - b.loadArrayBuffer(a.target.result); - }), c.addEventListener("error", function() { - b.fireEvent("error", "Error reading file"); - }), c.readAsArrayBuffer(a), this.empty(); - }, - load: function(a, b) { - switch (this.params.backend) { - case "WebAudio": - return this.loadBuffer(a); - - case "MediaElement": - return this.loadMediaElement(a, b); - } - }, - loadBuffer: function(a) { - return this.empty(), this.getArrayBuffer(a, this.loadArrayBuffer.bind(this)); - }, - loadMediaElement: function(a, b) { - this.empty(), this.backend.load(a, this.mediaContainer, b), this.tmpEvents.push(this.backend.once("canplay", function() { - this.drawBuffer(), this.fireEvent("ready"); - }.bind(this)), this.backend.once("error", function(a) { - this.fireEvent("error", a); - }.bind(this))), !b && this.backend.supportsWebAudio() && this.getArrayBuffer(a, function(a) { - this.decodeArrayBuffer(a, function(a) { - this.backend.buffer = a, this.drawBuffer(); - }.bind(this)); - }.bind(this)); - }, - decodeArrayBuffer: function(a, b) { - this.backend.decodeArrayBuffer(a, this.fireEvent.bind(this, "decoded"), this.fireEvent.bind(this, "error", "Error decoding audiobuffer")), - this.tmpEvents.push(this.once("decoded", b)); - }, - getArrayBuffer: function(a, b) { - var c = this, d = WaveSurfer.util.ajax({ - url: a, - responseType: "arraybuffer" - }); - return this.tmpEvents.push(d.on("progress", function(a) { - c.onProgress(a); - }), d.on("success", b), d.on("error", function(a) { - c.fireEvent("error", "XHR error: " + a.target.statusText); - })), d; - }, - onProgress: function(a) { - if (a.lengthComputable) var b = a.loaded / a.total; else b = a.loaded / (a.loaded + 1e6); - this.fireEvent("loading", Math.round(100 * b), a.target); - }, - exportPCM: function(a, b, c) { - a = a || 1024, b = b || 1e4, c = c || !1; - var d = this.backend.getPeaks(a, b), e = [].map.call(d, function(a) { - return Math.round(a * b) / b; - }), f = JSON.stringify(e); - return c || window.open("data:application/json;charset=utf-8," + encodeURIComponent(f)), - f; - }, - clearTmpEvents: function() { - this.tmpEvents.forEach(function(a) { - a.un(); - }); - }, - empty: function() { - this.backend.isPaused() || (this.stop(), this.backend.disconnectSource()), this.clearTmpEvents(), - this.drawer.progress(0), this.drawer.setWidth(0), this.drawer.drawPeaks({ - length: this.drawer.getWidth() - }, 0); - }, - destroy: function() { - this.fireEvent("destroy"), this.clearTmpEvents(), this.unAll(), this.backend.destroy(), - this.drawer.destroy(); - } -}; - -WaveSurfer.create = function(a) { - var b = Object.create(WaveSurfer); - return b.init(a), b; -}, WaveSurfer.util = { - extend: function(a) { - var b = Array.prototype.slice.call(arguments, 1); - return b.forEach(function(b) { - Object.keys(b).forEach(function(c) { - a[c] = b[c]; - }); - }), a; - }, - getId: function() { - return "wavesurfer_" + Math.random().toString(32).substring(2); - }, - ajax: function(a) { - var b = Object.create(WaveSurfer.Observer), c = new XMLHttpRequest(), d = !1; - return c.open(a.method || "GET", a.url, !0), c.responseType = a.responseType || "json", - c.addEventListener("progress", function(a) { - b.fireEvent("progress", a), a.lengthComputable && a.loaded == a.total && (d = !0); - }), c.addEventListener("load", function(a) { - d || b.fireEvent("progress", a), b.fireEvent("load", a), 200 == c.status || 206 == c.status ? b.fireEvent("success", c.response, a) : b.fireEvent("error", a); - }), c.addEventListener("error", function(a) { - b.fireEvent("error", a); - }), c.send(), b.xhr = c, b; - } -}, WaveSurfer.Observer = { - on: function(a, b) { - this.handlers || (this.handlers = {}); - var c = this.handlers[a]; - return c || (c = this.handlers[a] = []), c.push(b), { - name: a, - callback: b, - un: this.un.bind(this, a, b) - }; - }, - un: function(a, b) { - if (this.handlers) { - var c = this.handlers[a]; - if (c) if (b) for (var d = c.length - 1; d >= 0; d--) c[d] == b && c.splice(d, 1); else c.length = 0; - } - }, - unAll: function() { - this.handlers = null; - }, - once: function(a, b) { - var c = this, d = function() { - b.apply(this, arguments), setTimeout(function() { - c.un(a, d); - }, 0); - }; - return this.on(a, d); - }, - fireEvent: function(a) { - if (this.handlers) { - var b = this.handlers[a], c = Array.prototype.slice.call(arguments, 1); - b && b.forEach(function(a) { - a.apply(null, c); - }); - } - } -}, WaveSurfer.util.extend(WaveSurfer, WaveSurfer.Observer), WaveSurfer.WebAudio = { - scriptBufferSize: 256, - PLAYING_STATE: 0, - PAUSED_STATE: 1, - FINISHED_STATE: 2, - supportsWebAudio: function() { - return !(!window.AudioContext && !window.webkitAudioContext); - }, - getAudioContext: function() { - return WaveSurfer.WebAudio.audioContext || (WaveSurfer.WebAudio.audioContext = new (window.AudioContext || window.webkitAudioContext)()), - WaveSurfer.WebAudio.audioContext; - }, - getOfflineAudioContext: function(a) { - return WaveSurfer.WebAudio.offlineAudioContext || (WaveSurfer.WebAudio.offlineAudioContext = new (window.OfflineAudioContext || window.webkitOfflineAudioContext)(1, 2, a)), - WaveSurfer.WebAudio.offlineAudioContext; - }, - init: function(a) { - this.params = a, this.ac = a.audioContext || this.getAudioContext(), this.lastPlay = this.ac.currentTime, - this.startPosition = 0, this.scheduledPause = null, this.states = [ Object.create(WaveSurfer.WebAudio.state.playing), Object.create(WaveSurfer.WebAudio.state.paused), Object.create(WaveSurfer.WebAudio.state.finished) ], - this.createVolumeNode(), this.createScriptNode(), this.createAnalyserNode(), this.setState(this.PAUSED_STATE), - this.setPlaybackRate(this.params.audioRate); - }, - disconnectFilters: function() { - this.filters && (this.filters.forEach(function(a) { - a && a.disconnect(); - }), this.filters = null, this.analyser.connect(this.gainNode)); - }, - setState: function(a) { - this.state !== this.states[a] && (this.state = this.states[a], this.state.init.call(this)); - }, - setFilter: function() { - this.setFilters([].slice.call(arguments)); - }, - setFilters: function(a) { - this.disconnectFilters(), a && a.length && (this.filters = a, this.analyser.disconnect(), - a.reduce(function(a, b) { - return a.connect(b), b; - }, this.analyser).connect(this.gainNode)); - }, - createScriptNode: function() { - this.ac.createScriptProcessor ? this.scriptNode = this.ac.createScriptProcessor(this.scriptBufferSize) : this.scriptNode = this.ac.createJavaScriptNode(this.scriptBufferSize), - this.scriptNode.connect(this.ac.destination); - }, - addOnAudioProcess: function() { - var a = this; - this.scriptNode.onaudioprocess = function() { - var b = a.getCurrentTime(); - b >= a.getDuration() ? (a.setState(a.FINISHED_STATE), a.fireEvent("pause")) : b >= a.scheduledPause ? (a.setState(a.PAUSED_STATE), - a.fireEvent("pause")) : a.state === a.states[a.PLAYING_STATE] && a.fireEvent("audioprocess", b); - }; - }, - removeOnAudioProcess: function() { - this.scriptNode.onaudioprocess = null; - }, - createAnalyserNode: function() { - this.analyser = this.ac.createAnalyser(), this.analyser.connect(this.gainNode); - }, - createVolumeNode: function() { - this.ac.createGain ? this.gainNode = this.ac.createGain() : this.gainNode = this.ac.createGainNode(), - this.gainNode.connect(this.ac.destination); - }, - setVolume: function(a) { - this.gainNode.gain.value = a; - }, - getVolume: function() { - return this.gainNode.gain.value; - }, - decodeArrayBuffer: function(a, b, c) { - this.offlineAc || (this.offlineAc = this.getOfflineAudioContext(this.ac ? this.ac.sampleRate : 44100)), - this.offlineAc.decodeAudioData(a, function(a) { - b(a); - }.bind(this), c); - }, - getPeaks: function(a) { - for (var b = this.buffer.length / a, c = ~~(b / 10) || 1, d = this.buffer.numberOfChannels, e = [], f = [], g = 0; d > g; g++) for (var h = e[g] = [], i = this.buffer.getChannelData(g), j = 0; a > j; j++) { - for (var k = ~~(j * b), l = ~~(k + b), m = i[0], n = i[0], o = k; l > o; o += c) { - var p = i[o]; - p > n && (n = p), m > p && (m = p); - } - h[2 * j] = n, h[2 * j + 1] = m, (0 == g || n > f[2 * j]) && (f[2 * j] = n), (0 == g || m < f[2 * j + 1]) && (f[2 * j + 1] = m); - } - return this.params.splitChannels ? e : f; - }, - getPlayedPercents: function() { - return this.state.getPlayedPercents.call(this); - }, - disconnectSource: function() { - this.source && this.source.disconnect(); - }, - destroy: function() { - this.isPaused() || this.pause(), this.unAll(), this.buffer = null, this.disconnectFilters(), - this.disconnectSource(), this.gainNode.disconnect(), this.scriptNode.disconnect(), - this.analyser.disconnect(); - }, - load: function(a) { - this.startPosition = 0, this.lastPlay = this.ac.currentTime, this.buffer = a, this.createSource(); - }, - createSource: function() { - this.disconnectSource(), this.source = this.ac.createBufferSource(), this.source.start = this.source.start || this.source.noteGrainOn, - this.source.stop = this.source.stop || this.source.noteOff, this.source.playbackRate.value = this.playbackRate, - this.source.buffer = this.buffer, this.source.connect(this.analyser); - }, - isPaused: function() { - return this.state !== this.states[this.PLAYING_STATE]; - }, - getDuration: function() { - return this.buffer ? this.buffer.duration : 0; - }, - seekTo: function(a, b) { - return this.scheduledPause = null, null == a && (a = this.getCurrentTime(), a >= this.getDuration() && (a = 0)), - null == b && (b = this.getDuration()), this.startPosition = a, this.lastPlay = this.ac.currentTime, - this.state === this.states[this.FINISHED_STATE] && this.setState(this.PAUSED_STATE), - { - start: a, - end: b - }; - }, - getPlayedTime: function() { - return (this.ac.currentTime - this.lastPlay) * this.playbackRate; - }, - play: function(a, b) { - this.createSource(); - var c = this.seekTo(a, b); - a = c.start, b = c.end, this.scheduledPause = b, this.source.start(0, a, b - a), - this.setState(this.PLAYING_STATE), this.fireEvent("play"); - }, - pause: function() { - this.scheduledPause = null, this.startPosition += this.getPlayedTime(), this.source && this.source.stop(0), - this.setState(this.PAUSED_STATE), this.fireEvent("pause"); - }, - getCurrentTime: function() { - return this.state.getCurrentTime.call(this); - }, - setPlaybackRate: function(a) { - a = a || 1, this.isPaused() ? this.playbackRate = a : (this.pause(), this.playbackRate = a, - this.play()); - } -}, WaveSurfer.WebAudio.state = {}, WaveSurfer.WebAudio.state.playing = { - init: function() { - this.addOnAudioProcess(); - }, - getPlayedPercents: function() { - var a = this.getDuration(); - return this.getCurrentTime() / a || 0; - }, - getCurrentTime: function() { - return this.startPosition + this.getPlayedTime(); - } -}, WaveSurfer.WebAudio.state.paused = { - init: function() { - this.removeOnAudioProcess(); - }, - getPlayedPercents: function() { - var a = this.getDuration(); - return this.getCurrentTime() / a || 0; - }, - getCurrentTime: function() { - return this.startPosition; - } -}, WaveSurfer.WebAudio.state.finished = { - init: function() { - this.removeOnAudioProcess(), this.fireEvent("finish"); - }, - getPlayedPercents: function() { - return 1; - }, - getCurrentTime: function() { - return this.getDuration(); - } -}, WaveSurfer.util.extend(WaveSurfer.WebAudio, WaveSurfer.Observer), WaveSurfer.MediaElement = Object.create(WaveSurfer.WebAudio), -WaveSurfer.util.extend(WaveSurfer.MediaElement, { - init: function(a) { - this.params = a, this.media = { - currentTime: 0, - duration: 0, - paused: !0, - playbackRate: 1, - play: function() {}, - pause: function() {} - }, this.mediaType = a.mediaType.toLowerCase(), this.elementPosition = a.elementPosition; - }, - load: function(a, b, c) { - var d = this, e = document.createElement(this.mediaType); - e.controls = !1, e.autoplay = !1, e.preload = "auto", e.src = a, e.addEventListener("error", function() { - d.fireEvent("error", "Error loading media element"); - }), e.addEventListener("canplay", function() { - d.fireEvent("canplay"); - }), e.addEventListener("ended", function() { - d.fireEvent("finish"); - }), e.addEventListener("timeupdate", function() { - d.fireEvent("audioprocess", d.getCurrentTime()); - }); - var f = b.querySelector(this.mediaType); - f && b.removeChild(f), b.appendChild(e), this.media = e, this.peaks = c, this.onPlayEnd = null, - this.buffer = null, this.setPlaybackRate(this.playbackRate); - }, - isPaused: function() { - return !this.media || this.media.paused; - }, - getDuration: function() { - var a = this.media.duration; - return a >= 1 / 0 && (a = this.media.seekable.end()), a; - }, - getCurrentTime: function() { - return this.media && this.media.currentTime; - }, - getPlayedPercents: function() { - return this.getCurrentTime() / this.getDuration() || 0; - }, - setPlaybackRate: function(a) { - this.playbackRate = a || 1, this.media.playbackRate = this.playbackRate; - }, - seekTo: function(a) { - null != a && (this.media.currentTime = a), this.clearPlayEnd(); - }, - play: function(a, b) { - this.seekTo(a), this.media.play(), b && this.setPlayEnd(b), this.fireEvent("play"); - }, - pause: function() { - this.media && this.media.pause(), this.clearPlayEnd(), this.fireEvent("pause"); - }, - setPlayEnd: function(a) { - var b = this; - this.onPlayEnd = function(c) { - c >= a && (b.pause(), b.seekTo(a)); - }, this.on("audioprocess", this.onPlayEnd); - }, - clearPlayEnd: function() { - this.onPlayEnd && (this.un("audioprocess", this.onPlayEnd), this.onPlayEnd = null); - }, - getPeaks: function(a) { - return this.buffer ? WaveSurfer.WebAudio.getPeaks.call(this, a) : this.peaks || []; - }, - getVolume: function() { - return this.media.volume; - }, - setVolume: function(a) { - this.media.volume = a; - }, - destroy: function() { - this.pause(), this.unAll(), this.media && this.media.parentNode && this.media.parentNode.removeChild(this.media), - this.media = null; - } -}), WaveSurfer.AudioElement = WaveSurfer.MediaElement, WaveSurfer.Drawer = { - init: function(a, b) { - this.container = a, this.params = b, this.width = 0, this.height = b.height * this.params.pixelRatio, - this.lastPos = 0, this.createWrapper(), this.createElements(); - }, - createWrapper: function() { - this.wrapper = this.container.appendChild(document.createElement("wave")), this.style(this.wrapper, { - display: "block", - position: "relative", - userSelect: "none", - webkitUserSelect: "none", - height: this.params.height + "px" - }), (this.params.fillParent || this.params.scrollParent) && this.style(this.wrapper, { - width: "100%", - overflowX: this.params.hideScrollbar ? "hidden" : "auto", - overflowY: "hidden" - }), this.setupWrapperEvents(); - }, - handleEvent: function(a) { - a.preventDefault(); - var b = this.wrapper.getBoundingClientRect(); - return (a.clientX - b.left + this.wrapper.scrollLeft) / this.wrapper.scrollWidth || 0; - }, - setupWrapperEvents: function() { - var a = this; - this.wrapper.addEventListener("click", function(b) { - var c = a.wrapper.offsetHeight - a.wrapper.clientHeight; - if (0 != c) { - var d = a.wrapper.getBoundingClientRect(); - if (b.clientY >= d.bottom - c) return; - } - a.params.interact && a.fireEvent("click", b, a.handleEvent(b)); - }), this.wrapper.addEventListener("scroll", function(b) { - a.fireEvent("scroll", b); - }); - }, - drawPeaks: function(a, b) { - this.resetScroll(), this.setWidth(b), this.params.barWidth ? this.drawBars(a) : this.drawWave(a); - }, - style: function(a, b) { - return Object.keys(b).forEach(function(c) { - a.style[c] !== b[c] && (a.style[c] = b[c]); - }), a; - }, - resetScroll: function() { - null !== this.wrapper && (this.wrapper.scrollLeft = 0); - }, - recenter: function(a) { - var b = this.wrapper.scrollWidth * a; - this.recenterOnPosition(b, !0); - }, - recenterOnPosition: function(a, b) { - var c = this.wrapper.scrollLeft, d = ~~(this.wrapper.clientWidth / 2), e = a - d, f = e - c, g = this.wrapper.scrollWidth - this.wrapper.clientWidth; - if (0 != g) { - if (!b && f >= -d && d > f) { - var h = 5; - f = Math.max(-h, Math.min(h, f)), e = c + f; - } - e = Math.max(0, Math.min(g, e)), e != c && (this.wrapper.scrollLeft = e); - } - }, - getWidth: function() { - return Math.round(this.container.clientWidth * this.params.pixelRatio); - }, - setWidth: function(a) { - a != this.width && (this.width = a, this.params.fillParent || this.params.scrollParent ? this.style(this.wrapper, { - width: "" - }) : this.style(this.wrapper, { - width: ~~(this.width / this.params.pixelRatio) + "px" - }), this.updateSize()); - }, - setHeight: function(a) { - a != this.height && (this.height = a, this.style(this.wrapper, { - height: ~~(this.height / this.params.pixelRatio) + "px" - }), this.updateSize()); - }, - progress: function(a) { - var b = 1 / this.params.pixelRatio, c = Math.round(a * this.width) * b; - if (c < this.lastPos || c - this.lastPos >= b) { - if (this.lastPos = c, this.params.scrollParent) { - var d = ~~(this.wrapper.scrollWidth * a); - this.recenterOnPosition(d); - } - this.updateProgress(a); - } - }, - destroy: function() { - this.unAll(), this.wrapper && (this.container.removeChild(this.wrapper), this.wrapper = null); - }, - createElements: function() {}, - updateSize: function() {}, - drawWave: function(a, b) {}, - clearWave: function() {}, - updateProgress: function(a) {} -}, WaveSurfer.util.extend(WaveSurfer.Drawer, WaveSurfer.Observer), WaveSurfer.Drawer.Canvas = Object.create(WaveSurfer.Drawer), -WaveSurfer.util.extend(WaveSurfer.Drawer.Canvas, { - createElements: function() { - var a = this.wrapper.appendChild(this.style(document.createElement("canvas"), { - position: "absolute", - zIndex: 1, - left: 0, - top: 0, - bottom: 0 - })); - if (this.waveCc = a.getContext("2d"), this.progressWave = this.wrapper.appendChild(this.style(document.createElement("wave"), { - position: "absolute", - zIndex: 2, - left: 0, - top: 0, - bottom: 0, - overflow: "hidden", - width: "0", - display: "none", - boxSizing: "border-box", - borderRightStyle: "solid", - borderRightWidth: this.params.cursorWidth + "px", - borderRightColor: this.params.cursorColor - })), this.params.waveColor != this.params.progressColor) { - var b = this.progressWave.appendChild(document.createElement("canvas")); - this.progressCc = b.getContext("2d"); - } - }, - updateSize: function() { - var a = Math.round(this.width / this.params.pixelRatio); - this.waveCc.canvas.width = this.width, this.waveCc.canvas.height = this.height, - this.style(this.waveCc.canvas, { - width: a + "px" - }), this.style(this.progressWave, { - display: "block" - }), this.progressCc && (this.progressCc.canvas.width = this.width, this.progressCc.canvas.height = this.height, - this.style(this.progressCc.canvas, { - width: a + "px" - })), this.clearWave(); - }, - clearWave: function() { - this.waveCc.clearRect(0, 0, this.width, this.height), this.progressCc && this.progressCc.clearRect(0, 0, this.width, this.height); - }, - drawBars: function(a, b) { - if (a[0] instanceof Array) { - var c = a; - if (this.params.splitChannels) return this.setHeight(c.length * this.params.height * this.params.pixelRatio), - void c.forEach(this.drawBars, this); - a = c[0]; - } - var d = .5 / this.params.pixelRatio, e = this.width, f = this.params.height * this.params.pixelRatio, g = f * b || 0, h = f / 2, i = ~~(a.length / 2), j = this.params.barWidth * this.params.pixelRatio, k = Math.max(this.params.pixelRatio, ~~(j / 2)), l = j + k, m = 1; - if (this.params.normalize) { - var n, o; - o = Math.max.apply(Math, a), n = Math.min.apply(Math, a), m = o, -n > m && (m = -n); - } - var p = i / e; - this.waveCc.fillStyle = this.params.waveColor, this.progressCc && (this.progressCc.fillStyle = this.params.progressColor), - [ this.waveCc, this.progressCc ].forEach(function(b) { - if (b) if (this.params.reflection) for (var c = 0; e > c; c += l) { - var f = Math.round(a[2 * c * p] / m * h); - b.fillRect(c + d, h - f + g, j + d, 2 * f); - } else { - for (var c = 0; e > c; c += l) { - var f = Math.round(a[2 * c * p] / m * h); - b.fillRect(c + d, h - f + g, j + d, f); - } - for (var c = 0; e > c; c += l) { - var f = Math.round(a[2 * c * p + 1] / m * h); - b.fillRect(c + d, h - f + g, j + d, f); - } - } - }, this); - }, - drawWave: function(a, b) { - if (a[0] instanceof Array) { - var c = a; - if (this.params.splitChannels) return this.setHeight(c.length * this.params.height * this.params.pixelRatio), - void c.forEach(this.drawWave, this); - a = c[0]; - } - var d = .5 / this.params.pixelRatio, e = this.params.height * this.params.pixelRatio, f = e * b || 0, g = e / 2, h = ~~(a.length / 2), i = 1; - this.params.fillParent && this.width != h && (i = this.width / h); - var j = 1; - if (this.params.normalize) { - var k, l; - l = Math.max.apply(Math, a), k = Math.min.apply(Math, a), j = l, -k > j && (j = -k); - } - this.waveCc.fillStyle = this.params.waveColor, this.progressCc && (this.progressCc.fillStyle = this.params.progressColor), - [ this.waveCc, this.progressCc ].forEach(function(b) { - if (b) { - b.beginPath(), b.moveTo(d, g + f); - for (var c = 0; h > c; c++) { - var e = Math.round(a[2 * c] / j * g); - b.lineTo(c * i + d, g - e + f); - } - for (var c = h - 1; c >= 0; c--) { - var e = Math.round(a[2 * c + 1] / j * g); - b.lineTo(c * i + d, g - e + f); - } - b.closePath(), b.fill(), b.fillRect(0, g + f - d, this.width, d); - } - }, this); - }, - updateProgress: function(a) { - var b = Math.round(this.width * a) / this.params.pixelRatio; - this.style(this.progressWave, { - width: b + "px" - }); - } -}); - function responseHandler($timeout, $modal) { function show(status, message, t) { var timeout = t || 2e3; @@ -26975,9 +30229,34 @@ function responseHandler($timeout, $modal) { function error(message) { show("error", message, 5e3); } + function yesno(status, message, callback) { + var controller = function($scope, $modalInstance) { + $scope.status = status; + $scope.message = message; + $scope.yes = function() { + $modalInstance.close(true); + }; + $scope.no = function() { + $modalInstance.close(false); + }; + }; + $modal.open({ + animation: true, + templateUrl: "responseHandlerYesNoModal.html", + controller: controller, + size: "lg", + backdrop: "static", + keyboard: false + }).result.then(function(result) { + callback(result); + }, function() { + callback(false); + }); + } return { success: success, - error: error + error: error, + yesno: yesno }; } @@ -27007,7 +30286,7 @@ angular.module("UserUploadModule", [ "ui.bootstrap" ]).directive("onReadFile", f $scope.upload = function(file) { var fd = new FormData(); fd.append("blob", file); - fd.append("data_type", "dialeqt_dictionary"); + fd.append("data_type", $scope.dataType); $scope.uploadMsg = true; $http.post("/blob", fd, { transformRequest: angular.identity, diff --git a/lingvodoc/static/js/view-dictionary.js b/lingvodoc/static/js/view-dictionary.js index d3b945850..00629820f 100644 --- a/lingvodoc/static/js/view-dictionary.js +++ b/lingvodoc/static/js/view-dictionary.js @@ -5377,6 +5377,3947 @@ return jQuery; }); +(function() { + var undefined; + var VERSION = "3.10.1"; + var BIND_FLAG = 1, BIND_KEY_FLAG = 2, CURRY_BOUND_FLAG = 4, CURRY_FLAG = 8, CURRY_RIGHT_FLAG = 16, PARTIAL_FLAG = 32, PARTIAL_RIGHT_FLAG = 64, ARY_FLAG = 128, REARG_FLAG = 256; + var DEFAULT_TRUNC_LENGTH = 30, DEFAULT_TRUNC_OMISSION = "..."; + var HOT_COUNT = 150, HOT_SPAN = 16; + var LARGE_ARRAY_SIZE = 200; + var LAZY_FILTER_FLAG = 1, LAZY_MAP_FLAG = 2; + var FUNC_ERROR_TEXT = "Expected a function"; + var PLACEHOLDER = "__lodash_placeholder__"; + var argsTag = "[object Arguments]", arrayTag = "[object Array]", boolTag = "[object Boolean]", dateTag = "[object Date]", errorTag = "[object Error]", funcTag = "[object Function]", mapTag = "[object Map]", numberTag = "[object Number]", objectTag = "[object Object]", regexpTag = "[object RegExp]", setTag = "[object Set]", stringTag = "[object String]", weakMapTag = "[object WeakMap]"; + var arrayBufferTag = "[object ArrayBuffer]", float32Tag = "[object Float32Array]", float64Tag = "[object Float64Array]", int8Tag = "[object Int8Array]", int16Tag = "[object Int16Array]", int32Tag = "[object Int32Array]", uint8Tag = "[object Uint8Array]", uint8ClampedTag = "[object Uint8ClampedArray]", uint16Tag = "[object Uint16Array]", uint32Tag = "[object Uint32Array]"; + var reEmptyStringLeading = /\b__p \+= '';/g, reEmptyStringMiddle = /\b(__p \+=) '' \+/g, reEmptyStringTrailing = /(__e\(.*?\)|\b__t\)) \+\n'';/g; + var reEscapedHtml = /&(?:amp|lt|gt|quot|#39|#96);/g, reUnescapedHtml = /[&<>"'`]/g, reHasEscapedHtml = RegExp(reEscapedHtml.source), reHasUnescapedHtml = RegExp(reUnescapedHtml.source); + var reEscape = /<%-([\s\S]+?)%>/g, reEvaluate = /<%([\s\S]+?)%>/g, reInterpolate = /<%=([\s\S]+?)%>/g; + var reIsDeepProp = /\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\n\\]|\\.)*?\1)\]/, reIsPlainProp = /^\w*$/, rePropName = /[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\n\\]|\\.)*?)\2)\]/g; + var reRegExpChars = /^[:!,]|[\\^$.*+?()[\]{}|\/]|(^[0-9a-fA-Fnrtuvx])|([\n\r\u2028\u2029])/g, reHasRegExpChars = RegExp(reRegExpChars.source); + var reComboMark = /[\u0300-\u036f\ufe20-\ufe23]/g; + var reEscapeChar = /\\(\\)?/g; + var reEsTemplate = /\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g; + var reFlags = /\w*$/; + var reHasHexPrefix = /^0[xX]/; + var reIsHostCtor = /^\[object .+?Constructor\]$/; + var reIsUint = /^\d+$/; + var reLatin1 = /[\xc0-\xd6\xd8-\xde\xdf-\xf6\xf8-\xff]/g; + var reNoMatch = /($^)/; + var reUnescapedString = /['\n\r\u2028\u2029\\]/g; + var reWords = function() { + var upper = "[A-Z\\xc0-\\xd6\\xd8-\\xde]", lower = "[a-z\\xdf-\\xf6\\xf8-\\xff]+"; + return RegExp(upper + "+(?=" + upper + lower + ")|" + upper + "?" + lower + "|" + upper + "+|[0-9]+", "g"); + }(); + var contextProps = [ "Array", "ArrayBuffer", "Date", "Error", "Float32Array", "Float64Array", "Function", "Int8Array", "Int16Array", "Int32Array", "Math", "Number", "Object", "RegExp", "Set", "String", "_", "clearTimeout", "isFinite", "parseFloat", "parseInt", "setTimeout", "TypeError", "Uint8Array", "Uint8ClampedArray", "Uint16Array", "Uint32Array", "WeakMap" ]; + var templateCounter = -1; + var typedArrayTags = {}; + typedArrayTags[float32Tag] = typedArrayTags[float64Tag] = typedArrayTags[int8Tag] = typedArrayTags[int16Tag] = typedArrayTags[int32Tag] = typedArrayTags[uint8Tag] = typedArrayTags[uint8ClampedTag] = typedArrayTags[uint16Tag] = typedArrayTags[uint32Tag] = true; + typedArrayTags[argsTag] = typedArrayTags[arrayTag] = typedArrayTags[arrayBufferTag] = typedArrayTags[boolTag] = typedArrayTags[dateTag] = typedArrayTags[errorTag] = typedArrayTags[funcTag] = typedArrayTags[mapTag] = typedArrayTags[numberTag] = typedArrayTags[objectTag] = typedArrayTags[regexpTag] = typedArrayTags[setTag] = typedArrayTags[stringTag] = typedArrayTags[weakMapTag] = false; + var cloneableTags = {}; + cloneableTags[argsTag] = cloneableTags[arrayTag] = cloneableTags[arrayBufferTag] = cloneableTags[boolTag] = cloneableTags[dateTag] = cloneableTags[float32Tag] = cloneableTags[float64Tag] = cloneableTags[int8Tag] = cloneableTags[int16Tag] = cloneableTags[int32Tag] = cloneableTags[numberTag] = cloneableTags[objectTag] = cloneableTags[regexpTag] = cloneableTags[stringTag] = cloneableTags[uint8Tag] = cloneableTags[uint8ClampedTag] = cloneableTags[uint16Tag] = cloneableTags[uint32Tag] = true; + cloneableTags[errorTag] = cloneableTags[funcTag] = cloneableTags[mapTag] = cloneableTags[setTag] = cloneableTags[weakMapTag] = false; + var deburredLetters = { + "À": "A", + "Á": "A", + "Â": "A", + "Ã": "A", + "Ä": "A", + "Å": "A", + "à": "a", + "á": "a", + "â": "a", + "ã": "a", + "ä": "a", + "å": "a", + "Ç": "C", + "ç": "c", + "Ð": "D", + "ð": "d", + "È": "E", + "É": "E", + "Ê": "E", + "Ë": "E", + "è": "e", + "é": "e", + "ê": "e", + "ë": "e", + "Ì": "I", + "Í": "I", + "Î": "I", + "Ï": "I", + "ì": "i", + "í": "i", + "î": "i", + "ï": "i", + "Ñ": "N", + "ñ": "n", + "Ò": "O", + "Ó": "O", + "Ô": "O", + "Õ": "O", + "Ö": "O", + "Ø": "O", + "ò": "o", + "ó": "o", + "ô": "o", + "õ": "o", + "ö": "o", + "ø": "o", + "Ù": "U", + "Ú": "U", + "Û": "U", + "Ü": "U", + "ù": "u", + "ú": "u", + "û": "u", + "ü": "u", + "Ý": "Y", + "ý": "y", + "ÿ": "y", + "Æ": "Ae", + "æ": "ae", + "Þ": "Th", + "þ": "th", + "ß": "ss" + }; + var htmlEscapes = { + "&": "&", + "<": "<", + ">": ">", + '"': """, + "'": "'", + "`": "`" + }; + var htmlUnescapes = { + "&": "&", + "<": "<", + ">": ">", + """: '"', + "'": "'", + "`": "`" + }; + var objectTypes = { + "function": true, + object: true + }; + var regexpEscapes = { + "0": "x30", + "1": "x31", + "2": "x32", + "3": "x33", + "4": "x34", + "5": "x35", + "6": "x36", + "7": "x37", + "8": "x38", + "9": "x39", + A: "x41", + B: "x42", + C: "x43", + D: "x44", + E: "x45", + F: "x46", + a: "x61", + b: "x62", + c: "x63", + d: "x64", + e: "x65", + f: "x66", + n: "x6e", + r: "x72", + t: "x74", + u: "x75", + v: "x76", + x: "x78" + }; + var stringEscapes = { + "\\": "\\", + "'": "'", + "\n": "n", + "\r": "r", + "\u2028": "u2028", + "\u2029": "u2029" + }; + var freeExports = objectTypes[typeof exports] && exports && !exports.nodeType && exports; + var freeModule = objectTypes[typeof module] && module && !module.nodeType && module; + var freeGlobal = freeExports && freeModule && typeof global == "object" && global && global.Object && global; + var freeSelf = objectTypes[typeof self] && self && self.Object && self; + var freeWindow = objectTypes[typeof window] && window && window.Object && window; + var moduleExports = freeModule && freeModule.exports === freeExports && freeExports; + var root = freeGlobal || freeWindow !== (this && this.window) && freeWindow || freeSelf || this; + function baseCompareAscending(value, other) { + if (value !== other) { + var valIsNull = value === null, valIsUndef = value === undefined, valIsReflexive = value === value; + var othIsNull = other === null, othIsUndef = other === undefined, othIsReflexive = other === other; + if (value > other && !othIsNull || !valIsReflexive || valIsNull && !othIsUndef && othIsReflexive || valIsUndef && othIsReflexive) { + return 1; + } + if (value < other && !valIsNull || !othIsReflexive || othIsNull && !valIsUndef && valIsReflexive || othIsUndef && valIsReflexive) { + return -1; + } + } + return 0; + } + function baseFindIndex(array, predicate, fromRight) { + var length = array.length, index = fromRight ? length : -1; + while (fromRight ? index-- : ++index < length) { + if (predicate(array[index], index, array)) { + return index; + } + } + return -1; + } + function baseIndexOf(array, value, fromIndex) { + if (value !== value) { + return indexOfNaN(array, fromIndex); + } + var index = fromIndex - 1, length = array.length; + while (++index < length) { + if (array[index] === value) { + return index; + } + } + return -1; + } + function baseIsFunction(value) { + return typeof value == "function" || false; + } + function baseToString(value) { + return value == null ? "" : value + ""; + } + function charsLeftIndex(string, chars) { + var index = -1, length = string.length; + while (++index < length && chars.indexOf(string.charAt(index)) > -1) {} + return index; + } + function charsRightIndex(string, chars) { + var index = string.length; + while (index-- && chars.indexOf(string.charAt(index)) > -1) {} + return index; + } + function compareAscending(object, other) { + return baseCompareAscending(object.criteria, other.criteria) || object.index - other.index; + } + function compareMultiple(object, other, orders) { + var index = -1, objCriteria = object.criteria, othCriteria = other.criteria, length = objCriteria.length, ordersLength = orders.length; + while (++index < length) { + var result = baseCompareAscending(objCriteria[index], othCriteria[index]); + if (result) { + if (index >= ordersLength) { + return result; + } + var order = orders[index]; + return result * (order === "asc" || order === true ? 1 : -1); + } + } + return object.index - other.index; + } + function deburrLetter(letter) { + return deburredLetters[letter]; + } + function escapeHtmlChar(chr) { + return htmlEscapes[chr]; + } + function escapeRegExpChar(chr, leadingChar, whitespaceChar) { + if (leadingChar) { + chr = regexpEscapes[chr]; + } else if (whitespaceChar) { + chr = stringEscapes[chr]; + } + return "\\" + chr; + } + function escapeStringChar(chr) { + return "\\" + stringEscapes[chr]; + } + function indexOfNaN(array, fromIndex, fromRight) { + var length = array.length, index = fromIndex + (fromRight ? 0 : -1); + while (fromRight ? index-- : ++index < length) { + var other = array[index]; + if (other !== other) { + return index; + } + } + return -1; + } + function isObjectLike(value) { + return !!value && typeof value == "object"; + } + function isSpace(charCode) { + return charCode <= 160 && (charCode >= 9 && charCode <= 13) || charCode == 32 || charCode == 160 || charCode == 5760 || charCode == 6158 || charCode >= 8192 && (charCode <= 8202 || charCode == 8232 || charCode == 8233 || charCode == 8239 || charCode == 8287 || charCode == 12288 || charCode == 65279); + } + function replaceHolders(array, placeholder) { + var index = -1, length = array.length, resIndex = -1, result = []; + while (++index < length) { + if (array[index] === placeholder) { + array[index] = PLACEHOLDER; + result[++resIndex] = index; + } + } + return result; + } + function sortedUniq(array, iteratee) { + var seen, index = -1, length = array.length, resIndex = -1, result = []; + while (++index < length) { + var value = array[index], computed = iteratee ? iteratee(value, index, array) : value; + if (!index || seen !== computed) { + seen = computed; + result[++resIndex] = value; + } + } + return result; + } + function trimmedLeftIndex(string) { + var index = -1, length = string.length; + while (++index < length && isSpace(string.charCodeAt(index))) {} + return index; + } + function trimmedRightIndex(string) { + var index = string.length; + while (index-- && isSpace(string.charCodeAt(index))) {} + return index; + } + function unescapeHtmlChar(chr) { + return htmlUnescapes[chr]; + } + function runInContext(context) { + context = context ? _.defaults(root.Object(), context, _.pick(root, contextProps)) : root; + var Array = context.Array, Date = context.Date, Error = context.Error, Function = context.Function, Math = context.Math, Number = context.Number, Object = context.Object, RegExp = context.RegExp, String = context.String, TypeError = context.TypeError; + var arrayProto = Array.prototype, objectProto = Object.prototype, stringProto = String.prototype; + var fnToString = Function.prototype.toString; + var hasOwnProperty = objectProto.hasOwnProperty; + var idCounter = 0; + var objToString = objectProto.toString; + var oldDash = root._; + var reIsNative = RegExp("^" + fnToString.call(hasOwnProperty).replace(/[\\^$.*+?()[\]{}|]/g, "\\$&").replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g, "$1.*?") + "$"); + var ArrayBuffer = context.ArrayBuffer, clearTimeout = context.clearTimeout, parseFloat = context.parseFloat, pow = Math.pow, propertyIsEnumerable = objectProto.propertyIsEnumerable, Set = getNative(context, "Set"), setTimeout = context.setTimeout, splice = arrayProto.splice, Uint8Array = context.Uint8Array, WeakMap = getNative(context, "WeakMap"); + var nativeCeil = Math.ceil, nativeCreate = getNative(Object, "create"), nativeFloor = Math.floor, nativeIsArray = getNative(Array, "isArray"), nativeIsFinite = context.isFinite, nativeKeys = getNative(Object, "keys"), nativeMax = Math.max, nativeMin = Math.min, nativeNow = getNative(Date, "now"), nativeParseInt = context.parseInt, nativeRandom = Math.random; + var NEGATIVE_INFINITY = Number.NEGATIVE_INFINITY, POSITIVE_INFINITY = Number.POSITIVE_INFINITY; + var MAX_ARRAY_LENGTH = 4294967295, MAX_ARRAY_INDEX = MAX_ARRAY_LENGTH - 1, HALF_MAX_ARRAY_LENGTH = MAX_ARRAY_LENGTH >>> 1; + var MAX_SAFE_INTEGER = 9007199254740991; + var metaMap = WeakMap && new WeakMap(); + var realNames = {}; + function lodash(value) { + if (isObjectLike(value) && !isArray(value) && !(value instanceof LazyWrapper)) { + if (value instanceof LodashWrapper) { + return value; + } + if (hasOwnProperty.call(value, "__chain__") && hasOwnProperty.call(value, "__wrapped__")) { + return wrapperClone(value); + } + } + return new LodashWrapper(value); + } + function baseLodash() {} + function LodashWrapper(value, chainAll, actions) { + this.__wrapped__ = value; + this.__actions__ = actions || []; + this.__chain__ = !!chainAll; + } + var support = lodash.support = {}; + lodash.templateSettings = { + escape: reEscape, + evaluate: reEvaluate, + interpolate: reInterpolate, + variable: "", + imports: { + _: lodash + } + }; + function LazyWrapper(value) { + this.__wrapped__ = value; + this.__actions__ = []; + this.__dir__ = 1; + this.__filtered__ = false; + this.__iteratees__ = []; + this.__takeCount__ = POSITIVE_INFINITY; + this.__views__ = []; + } + function lazyClone() { + var result = new LazyWrapper(this.__wrapped__); + result.__actions__ = arrayCopy(this.__actions__); + result.__dir__ = this.__dir__; + result.__filtered__ = this.__filtered__; + result.__iteratees__ = arrayCopy(this.__iteratees__); + result.__takeCount__ = this.__takeCount__; + result.__views__ = arrayCopy(this.__views__); + return result; + } + function lazyReverse() { + if (this.__filtered__) { + var result = new LazyWrapper(this); + result.__dir__ = -1; + result.__filtered__ = true; + } else { + result = this.clone(); + result.__dir__ *= -1; + } + return result; + } + function lazyValue() { + var array = this.__wrapped__.value(), dir = this.__dir__, isArr = isArray(array), isRight = dir < 0, arrLength = isArr ? array.length : 0, view = getView(0, arrLength, this.__views__), start = view.start, end = view.end, length = end - start, index = isRight ? end : start - 1, iteratees = this.__iteratees__, iterLength = iteratees.length, resIndex = 0, takeCount = nativeMin(length, this.__takeCount__); + if (!isArr || arrLength < LARGE_ARRAY_SIZE || arrLength == length && takeCount == length) { + return baseWrapperValue(array, this.__actions__); + } + var result = []; + outer: while (length-- && resIndex < takeCount) { + index += dir; + var iterIndex = -1, value = array[index]; + while (++iterIndex < iterLength) { + var data = iteratees[iterIndex], iteratee = data.iteratee, type = data.type, computed = iteratee(value); + if (type == LAZY_MAP_FLAG) { + value = computed; + } else if (!computed) { + if (type == LAZY_FILTER_FLAG) { + continue outer; + } else { + break outer; + } + } + } + result[resIndex++] = value; + } + return result; + } + function MapCache() { + this.__data__ = {}; + } + function mapDelete(key) { + return this.has(key) && delete this.__data__[key]; + } + function mapGet(key) { + return key == "__proto__" ? undefined : this.__data__[key]; + } + function mapHas(key) { + return key != "__proto__" && hasOwnProperty.call(this.__data__, key); + } + function mapSet(key, value) { + if (key != "__proto__") { + this.__data__[key] = value; + } + return this; + } + function SetCache(values) { + var length = values ? values.length : 0; + this.data = { + hash: nativeCreate(null), + set: new Set() + }; + while (length--) { + this.push(values[length]); + } + } + function cacheIndexOf(cache, value) { + var data = cache.data, result = typeof value == "string" || isObject(value) ? data.set.has(value) : data.hash[value]; + return result ? 0 : -1; + } + function cachePush(value) { + var data = this.data; + if (typeof value == "string" || isObject(value)) { + data.set.add(value); + } else { + data.hash[value] = true; + } + } + function arrayConcat(array, other) { + var index = -1, length = array.length, othIndex = -1, othLength = other.length, result = Array(length + othLength); + while (++index < length) { + result[index] = array[index]; + } + while (++othIndex < othLength) { + result[index++] = other[othIndex]; + } + return result; + } + function arrayCopy(source, array) { + var index = -1, length = source.length; + array || (array = Array(length)); + while (++index < length) { + array[index] = source[index]; + } + return array; + } + function arrayEach(array, iteratee) { + var index = -1, length = array.length; + while (++index < length) { + if (iteratee(array[index], index, array) === false) { + break; + } + } + return array; + } + function arrayEachRight(array, iteratee) { + var length = array.length; + while (length--) { + if (iteratee(array[length], length, array) === false) { + break; + } + } + return array; + } + function arrayEvery(array, predicate) { + var index = -1, length = array.length; + while (++index < length) { + if (!predicate(array[index], index, array)) { + return false; + } + } + return true; + } + function arrayExtremum(array, iteratee, comparator, exValue) { + var index = -1, length = array.length, computed = exValue, result = computed; + while (++index < length) { + var value = array[index], current = +iteratee(value); + if (comparator(current, computed)) { + computed = current; + result = value; + } + } + return result; + } + function arrayFilter(array, predicate) { + var index = -1, length = array.length, resIndex = -1, result = []; + while (++index < length) { + var value = array[index]; + if (predicate(value, index, array)) { + result[++resIndex] = value; + } + } + return result; + } + function arrayMap(array, iteratee) { + var index = -1, length = array.length, result = Array(length); + while (++index < length) { + result[index] = iteratee(array[index], index, array); + } + return result; + } + function arrayPush(array, values) { + var index = -1, length = values.length, offset = array.length; + while (++index < length) { + array[offset + index] = values[index]; + } + return array; + } + function arrayReduce(array, iteratee, accumulator, initFromArray) { + var index = -1, length = array.length; + if (initFromArray && length) { + accumulator = array[++index]; + } + while (++index < length) { + accumulator = iteratee(accumulator, array[index], index, array); + } + return accumulator; + } + function arrayReduceRight(array, iteratee, accumulator, initFromArray) { + var length = array.length; + if (initFromArray && length) { + accumulator = array[--length]; + } + while (length--) { + accumulator = iteratee(accumulator, array[length], length, array); + } + return accumulator; + } + function arraySome(array, predicate) { + var index = -1, length = array.length; + while (++index < length) { + if (predicate(array[index], index, array)) { + return true; + } + } + return false; + } + function arraySum(array, iteratee) { + var length = array.length, result = 0; + while (length--) { + result += +iteratee(array[length]) || 0; + } + return result; + } + function assignDefaults(objectValue, sourceValue) { + return objectValue === undefined ? sourceValue : objectValue; + } + function assignOwnDefaults(objectValue, sourceValue, key, object) { + return objectValue === undefined || !hasOwnProperty.call(object, key) ? sourceValue : objectValue; + } + function assignWith(object, source, customizer) { + var index = -1, props = keys(source), length = props.length; + while (++index < length) { + var key = props[index], value = object[key], result = customizer(value, source[key], key, object, source); + if ((result === result ? result !== value : value === value) || value === undefined && !(key in object)) { + object[key] = result; + } + } + return object; + } + function baseAssign(object, source) { + return source == null ? object : baseCopy(source, keys(source), object); + } + function baseAt(collection, props) { + var index = -1, isNil = collection == null, isArr = !isNil && isArrayLike(collection), length = isArr ? collection.length : 0, propsLength = props.length, result = Array(propsLength); + while (++index < propsLength) { + var key = props[index]; + if (isArr) { + result[index] = isIndex(key, length) ? collection[key] : undefined; + } else { + result[index] = isNil ? undefined : collection[key]; + } + } + return result; + } + function baseCopy(source, props, object) { + object || (object = {}); + var index = -1, length = props.length; + while (++index < length) { + var key = props[index]; + object[key] = source[key]; + } + return object; + } + function baseCallback(func, thisArg, argCount) { + var type = typeof func; + if (type == "function") { + return thisArg === undefined ? func : bindCallback(func, thisArg, argCount); + } + if (func == null) { + return identity; + } + if (type == "object") { + return baseMatches(func); + } + return thisArg === undefined ? property(func) : baseMatchesProperty(func, thisArg); + } + function baseClone(value, isDeep, customizer, key, object, stackA, stackB) { + var result; + if (customizer) { + result = object ? customizer(value, key, object) : customizer(value); + } + if (result !== undefined) { + return result; + } + if (!isObject(value)) { + return value; + } + var isArr = isArray(value); + if (isArr) { + result = initCloneArray(value); + if (!isDeep) { + return arrayCopy(value, result); + } + } else { + var tag = objToString.call(value), isFunc = tag == funcTag; + if (tag == objectTag || tag == argsTag || isFunc && !object) { + result = initCloneObject(isFunc ? {} : value); + if (!isDeep) { + return baseAssign(result, value); + } + } else { + return cloneableTags[tag] ? initCloneByTag(value, tag, isDeep) : object ? value : {}; + } + } + stackA || (stackA = []); + stackB || (stackB = []); + var length = stackA.length; + while (length--) { + if (stackA[length] == value) { + return stackB[length]; + } + } + stackA.push(value); + stackB.push(result); + (isArr ? arrayEach : baseForOwn)(value, function(subValue, key) { + result[key] = baseClone(subValue, isDeep, customizer, key, value, stackA, stackB); + }); + return result; + } + var baseCreate = function() { + function object() {} + return function(prototype) { + if (isObject(prototype)) { + object.prototype = prototype; + var result = new object(); + object.prototype = undefined; + } + return result || {}; + }; + }(); + function baseDelay(func, wait, args) { + if (typeof func != "function") { + throw new TypeError(FUNC_ERROR_TEXT); + } + return setTimeout(function() { + func.apply(undefined, args); + }, wait); + } + function baseDifference(array, values) { + var length = array ? array.length : 0, result = []; + if (!length) { + return result; + } + var index = -1, indexOf = getIndexOf(), isCommon = indexOf === baseIndexOf, cache = isCommon && values.length >= LARGE_ARRAY_SIZE ? createCache(values) : null, valuesLength = values.length; + if (cache) { + indexOf = cacheIndexOf; + isCommon = false; + values = cache; + } + outer: while (++index < length) { + var value = array[index]; + if (isCommon && value === value) { + var valuesIndex = valuesLength; + while (valuesIndex--) { + if (values[valuesIndex] === value) { + continue outer; + } + } + result.push(value); + } else if (indexOf(values, value, 0) < 0) { + result.push(value); + } + } + return result; + } + var baseEach = createBaseEach(baseForOwn); + var baseEachRight = createBaseEach(baseForOwnRight, true); + function baseEvery(collection, predicate) { + var result = true; + baseEach(collection, function(value, index, collection) { + result = !!predicate(value, index, collection); + return result; + }); + return result; + } + function baseExtremum(collection, iteratee, comparator, exValue) { + var computed = exValue, result = computed; + baseEach(collection, function(value, index, collection) { + var current = +iteratee(value, index, collection); + if (comparator(current, computed) || current === exValue && current === result) { + computed = current; + result = value; + } + }); + return result; + } + function baseFill(array, value, start, end) { + var length = array.length; + start = start == null ? 0 : +start || 0; + if (start < 0) { + start = -start > length ? 0 : length + start; + } + end = end === undefined || end > length ? length : +end || 0; + if (end < 0) { + end += length; + } + length = start > end ? 0 : end >>> 0; + start >>>= 0; + while (start < length) { + array[start++] = value; + } + return array; + } + function baseFilter(collection, predicate) { + var result = []; + baseEach(collection, function(value, index, collection) { + if (predicate(value, index, collection)) { + result.push(value); + } + }); + return result; + } + function baseFind(collection, predicate, eachFunc, retKey) { + var result; + eachFunc(collection, function(value, key, collection) { + if (predicate(value, key, collection)) { + result = retKey ? key : value; + return false; + } + }); + return result; + } + function baseFlatten(array, isDeep, isStrict, result) { + result || (result = []); + var index = -1, length = array.length; + while (++index < length) { + var value = array[index]; + if (isObjectLike(value) && isArrayLike(value) && (isStrict || isArray(value) || isArguments(value))) { + if (isDeep) { + baseFlatten(value, isDeep, isStrict, result); + } else { + arrayPush(result, value); + } + } else if (!isStrict) { + result[result.length] = value; + } + } + return result; + } + var baseFor = createBaseFor(); + var baseForRight = createBaseFor(true); + function baseForIn(object, iteratee) { + return baseFor(object, iteratee, keysIn); + } + function baseForOwn(object, iteratee) { + return baseFor(object, iteratee, keys); + } + function baseForOwnRight(object, iteratee) { + return baseForRight(object, iteratee, keys); + } + function baseFunctions(object, props) { + var index = -1, length = props.length, resIndex = -1, result = []; + while (++index < length) { + var key = props[index]; + if (isFunction(object[key])) { + result[++resIndex] = key; + } + } + return result; + } + function baseGet(object, path, pathKey) { + if (object == null) { + return; + } + if (pathKey !== undefined && pathKey in toObject(object)) { + path = [ pathKey ]; + } + var index = 0, length = path.length; + while (object != null && index < length) { + object = object[path[index++]]; + } + return index && index == length ? object : undefined; + } + function baseIsEqual(value, other, customizer, isLoose, stackA, stackB) { + if (value === other) { + return true; + } + if (value == null || other == null || !isObject(value) && !isObjectLike(other)) { + return value !== value && other !== other; + } + return baseIsEqualDeep(value, other, baseIsEqual, customizer, isLoose, stackA, stackB); + } + function baseIsEqualDeep(object, other, equalFunc, customizer, isLoose, stackA, stackB) { + var objIsArr = isArray(object), othIsArr = isArray(other), objTag = arrayTag, othTag = arrayTag; + if (!objIsArr) { + objTag = objToString.call(object); + if (objTag == argsTag) { + objTag = objectTag; + } else if (objTag != objectTag) { + objIsArr = isTypedArray(object); + } + } + if (!othIsArr) { + othTag = objToString.call(other); + if (othTag == argsTag) { + othTag = objectTag; + } else if (othTag != objectTag) { + othIsArr = isTypedArray(other); + } + } + var objIsObj = objTag == objectTag, othIsObj = othTag == objectTag, isSameTag = objTag == othTag; + if (isSameTag && !(objIsArr || objIsObj)) { + return equalByTag(object, other, objTag); + } + if (!isLoose) { + var objIsWrapped = objIsObj && hasOwnProperty.call(object, "__wrapped__"), othIsWrapped = othIsObj && hasOwnProperty.call(other, "__wrapped__"); + if (objIsWrapped || othIsWrapped) { + return equalFunc(objIsWrapped ? object.value() : object, othIsWrapped ? other.value() : other, customizer, isLoose, stackA, stackB); + } + } + if (!isSameTag) { + return false; + } + stackA || (stackA = []); + stackB || (stackB = []); + var length = stackA.length; + while (length--) { + if (stackA[length] == object) { + return stackB[length] == other; + } + } + stackA.push(object); + stackB.push(other); + var result = (objIsArr ? equalArrays : equalObjects)(object, other, equalFunc, customizer, isLoose, stackA, stackB); + stackA.pop(); + stackB.pop(); + return result; + } + function baseIsMatch(object, matchData, customizer) { + var index = matchData.length, length = index, noCustomizer = !customizer; + if (object == null) { + return !length; + } + object = toObject(object); + while (index--) { + var data = matchData[index]; + if (noCustomizer && data[2] ? data[1] !== object[data[0]] : !(data[0] in object)) { + return false; + } + } + while (++index < length) { + data = matchData[index]; + var key = data[0], objValue = object[key], srcValue = data[1]; + if (noCustomizer && data[2]) { + if (objValue === undefined && !(key in object)) { + return false; + } + } else { + var result = customizer ? customizer(objValue, srcValue, key) : undefined; + if (!(result === undefined ? baseIsEqual(srcValue, objValue, customizer, true) : result)) { + return false; + } + } + } + return true; + } + function baseMap(collection, iteratee) { + var index = -1, result = isArrayLike(collection) ? Array(collection.length) : []; + baseEach(collection, function(value, key, collection) { + result[++index] = iteratee(value, key, collection); + }); + return result; + } + function baseMatches(source) { + var matchData = getMatchData(source); + if (matchData.length == 1 && matchData[0][2]) { + var key = matchData[0][0], value = matchData[0][1]; + return function(object) { + if (object == null) { + return false; + } + return object[key] === value && (value !== undefined || key in toObject(object)); + }; + } + return function(object) { + return baseIsMatch(object, matchData); + }; + } + function baseMatchesProperty(path, srcValue) { + var isArr = isArray(path), isCommon = isKey(path) && isStrictComparable(srcValue), pathKey = path + ""; + path = toPath(path); + return function(object) { + if (object == null) { + return false; + } + var key = pathKey; + object = toObject(object); + if ((isArr || !isCommon) && !(key in object)) { + object = path.length == 1 ? object : baseGet(object, baseSlice(path, 0, -1)); + if (object == null) { + return false; + } + key = last(path); + object = toObject(object); + } + return object[key] === srcValue ? srcValue !== undefined || key in object : baseIsEqual(srcValue, object[key], undefined, true); + }; + } + function baseMerge(object, source, customizer, stackA, stackB) { + if (!isObject(object)) { + return object; + } + var isSrcArr = isArrayLike(source) && (isArray(source) || isTypedArray(source)), props = isSrcArr ? undefined : keys(source); + arrayEach(props || source, function(srcValue, key) { + if (props) { + key = srcValue; + srcValue = source[key]; + } + if (isObjectLike(srcValue)) { + stackA || (stackA = []); + stackB || (stackB = []); + baseMergeDeep(object, source, key, baseMerge, customizer, stackA, stackB); + } else { + var value = object[key], result = customizer ? customizer(value, srcValue, key, object, source) : undefined, isCommon = result === undefined; + if (isCommon) { + result = srcValue; + } + if ((result !== undefined || isSrcArr && !(key in object)) && (isCommon || (result === result ? result !== value : value === value))) { + object[key] = result; + } + } + }); + return object; + } + function baseMergeDeep(object, source, key, mergeFunc, customizer, stackA, stackB) { + var length = stackA.length, srcValue = source[key]; + while (length--) { + if (stackA[length] == srcValue) { + object[key] = stackB[length]; + return; + } + } + var value = object[key], result = customizer ? customizer(value, srcValue, key, object, source) : undefined, isCommon = result === undefined; + if (isCommon) { + result = srcValue; + if (isArrayLike(srcValue) && (isArray(srcValue) || isTypedArray(srcValue))) { + result = isArray(value) ? value : isArrayLike(value) ? arrayCopy(value) : []; + } else if (isPlainObject(srcValue) || isArguments(srcValue)) { + result = isArguments(value) ? toPlainObject(value) : isPlainObject(value) ? value : {}; + } else { + isCommon = false; + } + } + stackA.push(srcValue); + stackB.push(result); + if (isCommon) { + object[key] = mergeFunc(result, srcValue, customizer, stackA, stackB); + } else if (result === result ? result !== value : value === value) { + object[key] = result; + } + } + function baseProperty(key) { + return function(object) { + return object == null ? undefined : object[key]; + }; + } + function basePropertyDeep(path) { + var pathKey = path + ""; + path = toPath(path); + return function(object) { + return baseGet(object, path, pathKey); + }; + } + function basePullAt(array, indexes) { + var length = array ? indexes.length : 0; + while (length--) { + var index = indexes[length]; + if (index != previous && isIndex(index)) { + var previous = index; + splice.call(array, index, 1); + } + } + return array; + } + function baseRandom(min, max) { + return min + nativeFloor(nativeRandom() * (max - min + 1)); + } + function baseReduce(collection, iteratee, accumulator, initFromCollection, eachFunc) { + eachFunc(collection, function(value, index, collection) { + accumulator = initFromCollection ? (initFromCollection = false, value) : iteratee(accumulator, value, index, collection); + }); + return accumulator; + } + var baseSetData = !metaMap ? identity : function(func, data) { + metaMap.set(func, data); + return func; + }; + function baseSlice(array, start, end) { + var index = -1, length = array.length; + start = start == null ? 0 : +start || 0; + if (start < 0) { + start = -start > length ? 0 : length + start; + } + end = end === undefined || end > length ? length : +end || 0; + if (end < 0) { + end += length; + } + length = start > end ? 0 : end - start >>> 0; + start >>>= 0; + var result = Array(length); + while (++index < length) { + result[index] = array[index + start]; + } + return result; + } + function baseSome(collection, predicate) { + var result; + baseEach(collection, function(value, index, collection) { + result = predicate(value, index, collection); + return !result; + }); + return !!result; + } + function baseSortBy(array, comparer) { + var length = array.length; + array.sort(comparer); + while (length--) { + array[length] = array[length].value; + } + return array; + } + function baseSortByOrder(collection, iteratees, orders) { + var callback = getCallback(), index = -1; + iteratees = arrayMap(iteratees, function(iteratee) { + return callback(iteratee); + }); + var result = baseMap(collection, function(value) { + var criteria = arrayMap(iteratees, function(iteratee) { + return iteratee(value); + }); + return { + criteria: criteria, + index: ++index, + value: value + }; + }); + return baseSortBy(result, function(object, other) { + return compareMultiple(object, other, orders); + }); + } + function baseSum(collection, iteratee) { + var result = 0; + baseEach(collection, function(value, index, collection) { + result += +iteratee(value, index, collection) || 0; + }); + return result; + } + function baseUniq(array, iteratee) { + var index = -1, indexOf = getIndexOf(), length = array.length, isCommon = indexOf === baseIndexOf, isLarge = isCommon && length >= LARGE_ARRAY_SIZE, seen = isLarge ? createCache() : null, result = []; + if (seen) { + indexOf = cacheIndexOf; + isCommon = false; + } else { + isLarge = false; + seen = iteratee ? [] : result; + } + outer: while (++index < length) { + var value = array[index], computed = iteratee ? iteratee(value, index, array) : value; + if (isCommon && value === value) { + var seenIndex = seen.length; + while (seenIndex--) { + if (seen[seenIndex] === computed) { + continue outer; + } + } + if (iteratee) { + seen.push(computed); + } + result.push(value); + } else if (indexOf(seen, computed, 0) < 0) { + if (iteratee || isLarge) { + seen.push(computed); + } + result.push(value); + } + } + return result; + } + function baseValues(object, props) { + var index = -1, length = props.length, result = Array(length); + while (++index < length) { + result[index] = object[props[index]]; + } + return result; + } + function baseWhile(array, predicate, isDrop, fromRight) { + var length = array.length, index = fromRight ? length : -1; + while ((fromRight ? index-- : ++index < length) && predicate(array[index], index, array)) {} + return isDrop ? baseSlice(array, fromRight ? 0 : index, fromRight ? index + 1 : length) : baseSlice(array, fromRight ? index + 1 : 0, fromRight ? length : index); + } + function baseWrapperValue(value, actions) { + var result = value; + if (result instanceof LazyWrapper) { + result = result.value(); + } + var index = -1, length = actions.length; + while (++index < length) { + var action = actions[index]; + result = action.func.apply(action.thisArg, arrayPush([ result ], action.args)); + } + return result; + } + function binaryIndex(array, value, retHighest) { + var low = 0, high = array ? array.length : low; + if (typeof value == "number" && value === value && high <= HALF_MAX_ARRAY_LENGTH) { + while (low < high) { + var mid = low + high >>> 1, computed = array[mid]; + if ((retHighest ? computed <= value : computed < value) && computed !== null) { + low = mid + 1; + } else { + high = mid; + } + } + return high; + } + return binaryIndexBy(array, value, identity, retHighest); + } + function binaryIndexBy(array, value, iteratee, retHighest) { + value = iteratee(value); + var low = 0, high = array ? array.length : 0, valIsNaN = value !== value, valIsNull = value === null, valIsUndef = value === undefined; + while (low < high) { + var mid = nativeFloor((low + high) / 2), computed = iteratee(array[mid]), isDef = computed !== undefined, isReflexive = computed === computed; + if (valIsNaN) { + var setLow = isReflexive || retHighest; + } else if (valIsNull) { + setLow = isReflexive && isDef && (retHighest || computed != null); + } else if (valIsUndef) { + setLow = isReflexive && (retHighest || isDef); + } else if (computed == null) { + setLow = false; + } else { + setLow = retHighest ? computed <= value : computed < value; + } + if (setLow) { + low = mid + 1; + } else { + high = mid; + } + } + return nativeMin(high, MAX_ARRAY_INDEX); + } + function bindCallback(func, thisArg, argCount) { + if (typeof func != "function") { + return identity; + } + if (thisArg === undefined) { + return func; + } + switch (argCount) { + case 1: + return function(value) { + return func.call(thisArg, value); + }; + + case 3: + return function(value, index, collection) { + return func.call(thisArg, value, index, collection); + }; + + case 4: + return function(accumulator, value, index, collection) { + return func.call(thisArg, accumulator, value, index, collection); + }; + + case 5: + return function(value, other, key, object, source) { + return func.call(thisArg, value, other, key, object, source); + }; + } + return function() { + return func.apply(thisArg, arguments); + }; + } + function bufferClone(buffer) { + var result = new ArrayBuffer(buffer.byteLength), view = new Uint8Array(result); + view.set(new Uint8Array(buffer)); + return result; + } + function composeArgs(args, partials, holders) { + var holdersLength = holders.length, argsIndex = -1, argsLength = nativeMax(args.length - holdersLength, 0), leftIndex = -1, leftLength = partials.length, result = Array(leftLength + argsLength); + while (++leftIndex < leftLength) { + result[leftIndex] = partials[leftIndex]; + } + while (++argsIndex < holdersLength) { + result[holders[argsIndex]] = args[argsIndex]; + } + while (argsLength--) { + result[leftIndex++] = args[argsIndex++]; + } + return result; + } + function composeArgsRight(args, partials, holders) { + var holdersIndex = -1, holdersLength = holders.length, argsIndex = -1, argsLength = nativeMax(args.length - holdersLength, 0), rightIndex = -1, rightLength = partials.length, result = Array(argsLength + rightLength); + while (++argsIndex < argsLength) { + result[argsIndex] = args[argsIndex]; + } + var offset = argsIndex; + while (++rightIndex < rightLength) { + result[offset + rightIndex] = partials[rightIndex]; + } + while (++holdersIndex < holdersLength) { + result[offset + holders[holdersIndex]] = args[argsIndex++]; + } + return result; + } + function createAggregator(setter, initializer) { + return function(collection, iteratee, thisArg) { + var result = initializer ? initializer() : {}; + iteratee = getCallback(iteratee, thisArg, 3); + if (isArray(collection)) { + var index = -1, length = collection.length; + while (++index < length) { + var value = collection[index]; + setter(result, value, iteratee(value, index, collection), collection); + } + } else { + baseEach(collection, function(value, key, collection) { + setter(result, value, iteratee(value, key, collection), collection); + }); + } + return result; + }; + } + function createAssigner(assigner) { + return restParam(function(object, sources) { + var index = -1, length = object == null ? 0 : sources.length, customizer = length > 2 ? sources[length - 2] : undefined, guard = length > 2 ? sources[2] : undefined, thisArg = length > 1 ? sources[length - 1] : undefined; + if (typeof customizer == "function") { + customizer = bindCallback(customizer, thisArg, 5); + length -= 2; + } else { + customizer = typeof thisArg == "function" ? thisArg : undefined; + length -= customizer ? 1 : 0; + } + if (guard && isIterateeCall(sources[0], sources[1], guard)) { + customizer = length < 3 ? undefined : customizer; + length = 1; + } + while (++index < length) { + var source = sources[index]; + if (source) { + assigner(object, source, customizer); + } + } + return object; + }); + } + function createBaseEach(eachFunc, fromRight) { + return function(collection, iteratee) { + var length = collection ? getLength(collection) : 0; + if (!isLength(length)) { + return eachFunc(collection, iteratee); + } + var index = fromRight ? length : -1, iterable = toObject(collection); + while (fromRight ? index-- : ++index < length) { + if (iteratee(iterable[index], index, iterable) === false) { + break; + } + } + return collection; + }; + } + function createBaseFor(fromRight) { + return function(object, iteratee, keysFunc) { + var iterable = toObject(object), props = keysFunc(object), length = props.length, index = fromRight ? length : -1; + while (fromRight ? index-- : ++index < length) { + var key = props[index]; + if (iteratee(iterable[key], key, iterable) === false) { + break; + } + } + return object; + }; + } + function createBindWrapper(func, thisArg) { + var Ctor = createCtorWrapper(func); + function wrapper() { + var fn = this && this !== root && this instanceof wrapper ? Ctor : func; + return fn.apply(thisArg, arguments); + } + return wrapper; + } + function createCache(values) { + return nativeCreate && Set ? new SetCache(values) : null; + } + function createCompounder(callback) { + return function(string) { + var index = -1, array = words(deburr(string)), length = array.length, result = ""; + while (++index < length) { + result = callback(result, array[index], index); + } + return result; + }; + } + function createCtorWrapper(Ctor) { + return function() { + var args = arguments; + switch (args.length) { + case 0: + return new Ctor(); + + case 1: + return new Ctor(args[0]); + + case 2: + return new Ctor(args[0], args[1]); + + case 3: + return new Ctor(args[0], args[1], args[2]); + + case 4: + return new Ctor(args[0], args[1], args[2], args[3]); + + case 5: + return new Ctor(args[0], args[1], args[2], args[3], args[4]); + + case 6: + return new Ctor(args[0], args[1], args[2], args[3], args[4], args[5]); + + case 7: + return new Ctor(args[0], args[1], args[2], args[3], args[4], args[5], args[6]); + } + var thisBinding = baseCreate(Ctor.prototype), result = Ctor.apply(thisBinding, args); + return isObject(result) ? result : thisBinding; + }; + } + function createCurry(flag) { + function curryFunc(func, arity, guard) { + if (guard && isIterateeCall(func, arity, guard)) { + arity = undefined; + } + var result = createWrapper(func, flag, undefined, undefined, undefined, undefined, undefined, arity); + result.placeholder = curryFunc.placeholder; + return result; + } + return curryFunc; + } + function createDefaults(assigner, customizer) { + return restParam(function(args) { + var object = args[0]; + if (object == null) { + return object; + } + args.push(customizer); + return assigner.apply(undefined, args); + }); + } + function createExtremum(comparator, exValue) { + return function(collection, iteratee, thisArg) { + if (thisArg && isIterateeCall(collection, iteratee, thisArg)) { + iteratee = undefined; + } + iteratee = getCallback(iteratee, thisArg, 3); + if (iteratee.length == 1) { + collection = isArray(collection) ? collection : toIterable(collection); + var result = arrayExtremum(collection, iteratee, comparator, exValue); + if (!(collection.length && result === exValue)) { + return result; + } + } + return baseExtremum(collection, iteratee, comparator, exValue); + }; + } + function createFind(eachFunc, fromRight) { + return function(collection, predicate, thisArg) { + predicate = getCallback(predicate, thisArg, 3); + if (isArray(collection)) { + var index = baseFindIndex(collection, predicate, fromRight); + return index > -1 ? collection[index] : undefined; + } + return baseFind(collection, predicate, eachFunc); + }; + } + function createFindIndex(fromRight) { + return function(array, predicate, thisArg) { + if (!(array && array.length)) { + return -1; + } + predicate = getCallback(predicate, thisArg, 3); + return baseFindIndex(array, predicate, fromRight); + }; + } + function createFindKey(objectFunc) { + return function(object, predicate, thisArg) { + predicate = getCallback(predicate, thisArg, 3); + return baseFind(object, predicate, objectFunc, true); + }; + } + function createFlow(fromRight) { + return function() { + var wrapper, length = arguments.length, index = fromRight ? length : -1, leftIndex = 0, funcs = Array(length); + while (fromRight ? index-- : ++index < length) { + var func = funcs[leftIndex++] = arguments[index]; + if (typeof func != "function") { + throw new TypeError(FUNC_ERROR_TEXT); + } + if (!wrapper && LodashWrapper.prototype.thru && getFuncName(func) == "wrapper") { + wrapper = new LodashWrapper([], true); + } + } + index = wrapper ? -1 : length; + while (++index < length) { + func = funcs[index]; + var funcName = getFuncName(func), data = funcName == "wrapper" ? getData(func) : undefined; + if (data && isLaziable(data[0]) && data[1] == (ARY_FLAG | CURRY_FLAG | PARTIAL_FLAG | REARG_FLAG) && !data[4].length && data[9] == 1) { + wrapper = wrapper[getFuncName(data[0])].apply(wrapper, data[3]); + } else { + wrapper = func.length == 1 && isLaziable(func) ? wrapper[funcName]() : wrapper.thru(func); + } + } + return function() { + var args = arguments, value = args[0]; + if (wrapper && args.length == 1 && isArray(value) && value.length >= LARGE_ARRAY_SIZE) { + return wrapper.plant(value).value(); + } + var index = 0, result = length ? funcs[index].apply(this, args) : value; + while (++index < length) { + result = funcs[index].call(this, result); + } + return result; + }; + }; + } + function createForEach(arrayFunc, eachFunc) { + return function(collection, iteratee, thisArg) { + return typeof iteratee == "function" && thisArg === undefined && isArray(collection) ? arrayFunc(collection, iteratee) : eachFunc(collection, bindCallback(iteratee, thisArg, 3)); + }; + } + function createForIn(objectFunc) { + return function(object, iteratee, thisArg) { + if (typeof iteratee != "function" || thisArg !== undefined) { + iteratee = bindCallback(iteratee, thisArg, 3); + } + return objectFunc(object, iteratee, keysIn); + }; + } + function createForOwn(objectFunc) { + return function(object, iteratee, thisArg) { + if (typeof iteratee != "function" || thisArg !== undefined) { + iteratee = bindCallback(iteratee, thisArg, 3); + } + return objectFunc(object, iteratee); + }; + } + function createObjectMapper(isMapKeys) { + return function(object, iteratee, thisArg) { + var result = {}; + iteratee = getCallback(iteratee, thisArg, 3); + baseForOwn(object, function(value, key, object) { + var mapped = iteratee(value, key, object); + key = isMapKeys ? mapped : key; + value = isMapKeys ? value : mapped; + result[key] = value; + }); + return result; + }; + } + function createPadDir(fromRight) { + return function(string, length, chars) { + string = baseToString(string); + return (fromRight ? string : "") + createPadding(string, length, chars) + (fromRight ? "" : string); + }; + } + function createPartial(flag) { + var partialFunc = restParam(function(func, partials) { + var holders = replaceHolders(partials, partialFunc.placeholder); + return createWrapper(func, flag, undefined, partials, holders); + }); + return partialFunc; + } + function createReduce(arrayFunc, eachFunc) { + return function(collection, iteratee, accumulator, thisArg) { + var initFromArray = arguments.length < 3; + return typeof iteratee == "function" && thisArg === undefined && isArray(collection) ? arrayFunc(collection, iteratee, accumulator, initFromArray) : baseReduce(collection, getCallback(iteratee, thisArg, 4), accumulator, initFromArray, eachFunc); + }; + } + function createHybridWrapper(func, bitmask, thisArg, partials, holders, partialsRight, holdersRight, argPos, ary, arity) { + var isAry = bitmask & ARY_FLAG, isBind = bitmask & BIND_FLAG, isBindKey = bitmask & BIND_KEY_FLAG, isCurry = bitmask & CURRY_FLAG, isCurryBound = bitmask & CURRY_BOUND_FLAG, isCurryRight = bitmask & CURRY_RIGHT_FLAG, Ctor = isBindKey ? undefined : createCtorWrapper(func); + function wrapper() { + var length = arguments.length, index = length, args = Array(length); + while (index--) { + args[index] = arguments[index]; + } + if (partials) { + args = composeArgs(args, partials, holders); + } + if (partialsRight) { + args = composeArgsRight(args, partialsRight, holdersRight); + } + if (isCurry || isCurryRight) { + var placeholder = wrapper.placeholder, argsHolders = replaceHolders(args, placeholder); + length -= argsHolders.length; + if (length < arity) { + var newArgPos = argPos ? arrayCopy(argPos) : undefined, newArity = nativeMax(arity - length, 0), newsHolders = isCurry ? argsHolders : undefined, newHoldersRight = isCurry ? undefined : argsHolders, newPartials = isCurry ? args : undefined, newPartialsRight = isCurry ? undefined : args; + bitmask |= isCurry ? PARTIAL_FLAG : PARTIAL_RIGHT_FLAG; + bitmask &= ~(isCurry ? PARTIAL_RIGHT_FLAG : PARTIAL_FLAG); + if (!isCurryBound) { + bitmask &= ~(BIND_FLAG | BIND_KEY_FLAG); + } + var newData = [ func, bitmask, thisArg, newPartials, newsHolders, newPartialsRight, newHoldersRight, newArgPos, ary, newArity ], result = createHybridWrapper.apply(undefined, newData); + if (isLaziable(func)) { + setData(result, newData); + } + result.placeholder = placeholder; + return result; + } + } + var thisBinding = isBind ? thisArg : this, fn = isBindKey ? thisBinding[func] : func; + if (argPos) { + args = reorder(args, argPos); + } + if (isAry && ary < args.length) { + args.length = ary; + } + if (this && this !== root && this instanceof wrapper) { + fn = Ctor || createCtorWrapper(func); + } + return fn.apply(thisBinding, args); + } + return wrapper; + } + function createPadding(string, length, chars) { + var strLength = string.length; + length = +length; + if (strLength >= length || !nativeIsFinite(length)) { + return ""; + } + var padLength = length - strLength; + chars = chars == null ? " " : chars + ""; + return repeat(chars, nativeCeil(padLength / chars.length)).slice(0, padLength); + } + function createPartialWrapper(func, bitmask, thisArg, partials) { + var isBind = bitmask & BIND_FLAG, Ctor = createCtorWrapper(func); + function wrapper() { + var argsIndex = -1, argsLength = arguments.length, leftIndex = -1, leftLength = partials.length, args = Array(leftLength + argsLength); + while (++leftIndex < leftLength) { + args[leftIndex] = partials[leftIndex]; + } + while (argsLength--) { + args[leftIndex++] = arguments[++argsIndex]; + } + var fn = this && this !== root && this instanceof wrapper ? Ctor : func; + return fn.apply(isBind ? thisArg : this, args); + } + return wrapper; + } + function createRound(methodName) { + var func = Math[methodName]; + return function(number, precision) { + precision = precision === undefined ? 0 : +precision || 0; + if (precision) { + precision = pow(10, precision); + return func(number * precision) / precision; + } + return func(number); + }; + } + function createSortedIndex(retHighest) { + return function(array, value, iteratee, thisArg) { + var callback = getCallback(iteratee); + return iteratee == null && callback === baseCallback ? binaryIndex(array, value, retHighest) : binaryIndexBy(array, value, callback(iteratee, thisArg, 1), retHighest); + }; + } + function createWrapper(func, bitmask, thisArg, partials, holders, argPos, ary, arity) { + var isBindKey = bitmask & BIND_KEY_FLAG; + if (!isBindKey && typeof func != "function") { + throw new TypeError(FUNC_ERROR_TEXT); + } + var length = partials ? partials.length : 0; + if (!length) { + bitmask &= ~(PARTIAL_FLAG | PARTIAL_RIGHT_FLAG); + partials = holders = undefined; + } + length -= holders ? holders.length : 0; + if (bitmask & PARTIAL_RIGHT_FLAG) { + var partialsRight = partials, holdersRight = holders; + partials = holders = undefined; + } + var data = isBindKey ? undefined : getData(func), newData = [ func, bitmask, thisArg, partials, holders, partialsRight, holdersRight, argPos, ary, arity ]; + if (data) { + mergeData(newData, data); + bitmask = newData[1]; + arity = newData[9]; + } + newData[9] = arity == null ? isBindKey ? 0 : func.length : nativeMax(arity - length, 0) || 0; + if (bitmask == BIND_FLAG) { + var result = createBindWrapper(newData[0], newData[2]); + } else if ((bitmask == PARTIAL_FLAG || bitmask == (BIND_FLAG | PARTIAL_FLAG)) && !newData[4].length) { + result = createPartialWrapper.apply(undefined, newData); + } else { + result = createHybridWrapper.apply(undefined, newData); + } + var setter = data ? baseSetData : setData; + return setter(result, newData); + } + function equalArrays(array, other, equalFunc, customizer, isLoose, stackA, stackB) { + var index = -1, arrLength = array.length, othLength = other.length; + if (arrLength != othLength && !(isLoose && othLength > arrLength)) { + return false; + } + while (++index < arrLength) { + var arrValue = array[index], othValue = other[index], result = customizer ? customizer(isLoose ? othValue : arrValue, isLoose ? arrValue : othValue, index) : undefined; + if (result !== undefined) { + if (result) { + continue; + } + return false; + } + if (isLoose) { + if (!arraySome(other, function(othValue) { + return arrValue === othValue || equalFunc(arrValue, othValue, customizer, isLoose, stackA, stackB); + })) { + return false; + } + } else if (!(arrValue === othValue || equalFunc(arrValue, othValue, customizer, isLoose, stackA, stackB))) { + return false; + } + } + return true; + } + function equalByTag(object, other, tag) { + switch (tag) { + case boolTag: + case dateTag: + return +object == +other; + + case errorTag: + return object.name == other.name && object.message == other.message; + + case numberTag: + return object != +object ? other != +other : object == +other; + + case regexpTag: + case stringTag: + return object == other + ""; + } + return false; + } + function equalObjects(object, other, equalFunc, customizer, isLoose, stackA, stackB) { + var objProps = keys(object), objLength = objProps.length, othProps = keys(other), othLength = othProps.length; + if (objLength != othLength && !isLoose) { + return false; + } + var index = objLength; + while (index--) { + var key = objProps[index]; + if (!(isLoose ? key in other : hasOwnProperty.call(other, key))) { + return false; + } + } + var skipCtor = isLoose; + while (++index < objLength) { + key = objProps[index]; + var objValue = object[key], othValue = other[key], result = customizer ? customizer(isLoose ? othValue : objValue, isLoose ? objValue : othValue, key) : undefined; + if (!(result === undefined ? equalFunc(objValue, othValue, customizer, isLoose, stackA, stackB) : result)) { + return false; + } + skipCtor || (skipCtor = key == "constructor"); + } + if (!skipCtor) { + var objCtor = object.constructor, othCtor = other.constructor; + if (objCtor != othCtor && ("constructor" in object && "constructor" in other) && !(typeof objCtor == "function" && objCtor instanceof objCtor && typeof othCtor == "function" && othCtor instanceof othCtor)) { + return false; + } + } + return true; + } + function getCallback(func, thisArg, argCount) { + var result = lodash.callback || callback; + result = result === callback ? baseCallback : result; + return argCount ? result(func, thisArg, argCount) : result; + } + var getData = !metaMap ? noop : function(func) { + return metaMap.get(func); + }; + function getFuncName(func) { + var result = func.name + "", array = realNames[result], length = array ? array.length : 0; + while (length--) { + var data = array[length], otherFunc = data.func; + if (otherFunc == null || otherFunc == func) { + return data.name; + } + } + return result; + } + function getIndexOf(collection, target, fromIndex) { + var result = lodash.indexOf || indexOf; + result = result === indexOf ? baseIndexOf : result; + return collection ? result(collection, target, fromIndex) : result; + } + var getLength = baseProperty("length"); + function getMatchData(object) { + var result = pairs(object), length = result.length; + while (length--) { + result[length][2] = isStrictComparable(result[length][1]); + } + return result; + } + function getNative(object, key) { + var value = object == null ? undefined : object[key]; + return isNative(value) ? value : undefined; + } + function getView(start, end, transforms) { + var index = -1, length = transforms.length; + while (++index < length) { + var data = transforms[index], size = data.size; + switch (data.type) { + case "drop": + start += size; + break; + + case "dropRight": + end -= size; + break; + + case "take": + end = nativeMin(end, start + size); + break; + + case "takeRight": + start = nativeMax(start, end - size); + break; + } + } + return { + start: start, + end: end + }; + } + function initCloneArray(array) { + var length = array.length, result = new array.constructor(length); + if (length && typeof array[0] == "string" && hasOwnProperty.call(array, "index")) { + result.index = array.index; + result.input = array.input; + } + return result; + } + function initCloneObject(object) { + var Ctor = object.constructor; + if (!(typeof Ctor == "function" && Ctor instanceof Ctor)) { + Ctor = Object; + } + return new Ctor(); + } + function initCloneByTag(object, tag, isDeep) { + var Ctor = object.constructor; + switch (tag) { + case arrayBufferTag: + return bufferClone(object); + + case boolTag: + case dateTag: + return new Ctor(+object); + + case float32Tag: + case float64Tag: + case int8Tag: + case int16Tag: + case int32Tag: + case uint8Tag: + case uint8ClampedTag: + case uint16Tag: + case uint32Tag: + var buffer = object.buffer; + return new Ctor(isDeep ? bufferClone(buffer) : buffer, object.byteOffset, object.length); + + case numberTag: + case stringTag: + return new Ctor(object); + + case regexpTag: + var result = new Ctor(object.source, reFlags.exec(object)); + result.lastIndex = object.lastIndex; + } + return result; + } + function invokePath(object, path, args) { + if (object != null && !isKey(path, object)) { + path = toPath(path); + object = path.length == 1 ? object : baseGet(object, baseSlice(path, 0, -1)); + path = last(path); + } + var func = object == null ? object : object[path]; + return func == null ? undefined : func.apply(object, args); + } + function isArrayLike(value) { + return value != null && isLength(getLength(value)); + } + function isIndex(value, length) { + value = typeof value == "number" || reIsUint.test(value) ? +value : -1; + length = length == null ? MAX_SAFE_INTEGER : length; + return value > -1 && value % 1 == 0 && value < length; + } + function isIterateeCall(value, index, object) { + if (!isObject(object)) { + return false; + } + var type = typeof index; + if (type == "number" ? isArrayLike(object) && isIndex(index, object.length) : type == "string" && index in object) { + var other = object[index]; + return value === value ? value === other : other !== other; + } + return false; + } + function isKey(value, object) { + var type = typeof value; + if (type == "string" && reIsPlainProp.test(value) || type == "number") { + return true; + } + if (isArray(value)) { + return false; + } + var result = !reIsDeepProp.test(value); + return result || object != null && value in toObject(object); + } + function isLaziable(func) { + var funcName = getFuncName(func), other = lodash[funcName]; + if (typeof other != "function" || !(funcName in LazyWrapper.prototype)) { + return false; + } + if (func === other) { + return true; + } + var data = getData(other); + return !!data && func === data[0]; + } + function isLength(value) { + return typeof value == "number" && value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER; + } + function isStrictComparable(value) { + return value === value && !isObject(value); + } + function mergeData(data, source) { + var bitmask = data[1], srcBitmask = source[1], newBitmask = bitmask | srcBitmask, isCommon = newBitmask < ARY_FLAG; + var isCombo = srcBitmask == ARY_FLAG && bitmask == CURRY_FLAG || srcBitmask == ARY_FLAG && bitmask == REARG_FLAG && data[7].length <= source[8] || srcBitmask == (ARY_FLAG | REARG_FLAG) && bitmask == CURRY_FLAG; + if (!(isCommon || isCombo)) { + return data; + } + if (srcBitmask & BIND_FLAG) { + data[2] = source[2]; + newBitmask |= bitmask & BIND_FLAG ? 0 : CURRY_BOUND_FLAG; + } + var value = source[3]; + if (value) { + var partials = data[3]; + data[3] = partials ? composeArgs(partials, value, source[4]) : arrayCopy(value); + data[4] = partials ? replaceHolders(data[3], PLACEHOLDER) : arrayCopy(source[4]); + } + value = source[5]; + if (value) { + partials = data[5]; + data[5] = partials ? composeArgsRight(partials, value, source[6]) : arrayCopy(value); + data[6] = partials ? replaceHolders(data[5], PLACEHOLDER) : arrayCopy(source[6]); + } + value = source[7]; + if (value) { + data[7] = arrayCopy(value); + } + if (srcBitmask & ARY_FLAG) { + data[8] = data[8] == null ? source[8] : nativeMin(data[8], source[8]); + } + if (data[9] == null) { + data[9] = source[9]; + } + data[0] = source[0]; + data[1] = newBitmask; + return data; + } + function mergeDefaults(objectValue, sourceValue) { + return objectValue === undefined ? sourceValue : merge(objectValue, sourceValue, mergeDefaults); + } + function pickByArray(object, props) { + object = toObject(object); + var index = -1, length = props.length, result = {}; + while (++index < length) { + var key = props[index]; + if (key in object) { + result[key] = object[key]; + } + } + return result; + } + function pickByCallback(object, predicate) { + var result = {}; + baseForIn(object, function(value, key, object) { + if (predicate(value, key, object)) { + result[key] = value; + } + }); + return result; + } + function reorder(array, indexes) { + var arrLength = array.length, length = nativeMin(indexes.length, arrLength), oldArray = arrayCopy(array); + while (length--) { + var index = indexes[length]; + array[length] = isIndex(index, arrLength) ? oldArray[index] : undefined; + } + return array; + } + var setData = function() { + var count = 0, lastCalled = 0; + return function(key, value) { + var stamp = now(), remaining = HOT_SPAN - (stamp - lastCalled); + lastCalled = stamp; + if (remaining > 0) { + if (++count >= HOT_COUNT) { + return key; + } + } else { + count = 0; + } + return baseSetData(key, value); + }; + }(); + function shimKeys(object) { + var props = keysIn(object), propsLength = props.length, length = propsLength && object.length; + var allowIndexes = !!length && isLength(length) && (isArray(object) || isArguments(object)); + var index = -1, result = []; + while (++index < propsLength) { + var key = props[index]; + if (allowIndexes && isIndex(key, length) || hasOwnProperty.call(object, key)) { + result.push(key); + } + } + return result; + } + function toIterable(value) { + if (value == null) { + return []; + } + if (!isArrayLike(value)) { + return values(value); + } + return isObject(value) ? value : Object(value); + } + function toObject(value) { + return isObject(value) ? value : Object(value); + } + function toPath(value) { + if (isArray(value)) { + return value; + } + var result = []; + baseToString(value).replace(rePropName, function(match, number, quote, string) { + result.push(quote ? string.replace(reEscapeChar, "$1") : number || match); + }); + return result; + } + function wrapperClone(wrapper) { + return wrapper instanceof LazyWrapper ? wrapper.clone() : new LodashWrapper(wrapper.__wrapped__, wrapper.__chain__, arrayCopy(wrapper.__actions__)); + } + function chunk(array, size, guard) { + if (guard ? isIterateeCall(array, size, guard) : size == null) { + size = 1; + } else { + size = nativeMax(nativeFloor(size) || 1, 1); + } + var index = 0, length = array ? array.length : 0, resIndex = -1, result = Array(nativeCeil(length / size)); + while (index < length) { + result[++resIndex] = baseSlice(array, index, index += size); + } + return result; + } + function compact(array) { + var index = -1, length = array ? array.length : 0, resIndex = -1, result = []; + while (++index < length) { + var value = array[index]; + if (value) { + result[++resIndex] = value; + } + } + return result; + } + var difference = restParam(function(array, values) { + return isObjectLike(array) && isArrayLike(array) ? baseDifference(array, baseFlatten(values, false, true)) : []; + }); + function drop(array, n, guard) { + var length = array ? array.length : 0; + if (!length) { + return []; + } + if (guard ? isIterateeCall(array, n, guard) : n == null) { + n = 1; + } + return baseSlice(array, n < 0 ? 0 : n); + } + function dropRight(array, n, guard) { + var length = array ? array.length : 0; + if (!length) { + return []; + } + if (guard ? isIterateeCall(array, n, guard) : n == null) { + n = 1; + } + n = length - (+n || 0); + return baseSlice(array, 0, n < 0 ? 0 : n); + } + function dropRightWhile(array, predicate, thisArg) { + return array && array.length ? baseWhile(array, getCallback(predicate, thisArg, 3), true, true) : []; + } + function dropWhile(array, predicate, thisArg) { + return array && array.length ? baseWhile(array, getCallback(predicate, thisArg, 3), true) : []; + } + function fill(array, value, start, end) { + var length = array ? array.length : 0; + if (!length) { + return []; + } + if (start && typeof start != "number" && isIterateeCall(array, value, start)) { + start = 0; + end = length; + } + return baseFill(array, value, start, end); + } + var findIndex = createFindIndex(); + var findLastIndex = createFindIndex(true); + function first(array) { + return array ? array[0] : undefined; + } + function flatten(array, isDeep, guard) { + var length = array ? array.length : 0; + if (guard && isIterateeCall(array, isDeep, guard)) { + isDeep = false; + } + return length ? baseFlatten(array, isDeep) : []; + } + function flattenDeep(array) { + var length = array ? array.length : 0; + return length ? baseFlatten(array, true) : []; + } + function indexOf(array, value, fromIndex) { + var length = array ? array.length : 0; + if (!length) { + return -1; + } + if (typeof fromIndex == "number") { + fromIndex = fromIndex < 0 ? nativeMax(length + fromIndex, 0) : fromIndex; + } else if (fromIndex) { + var index = binaryIndex(array, value); + if (index < length && (value === value ? value === array[index] : array[index] !== array[index])) { + return index; + } + return -1; + } + return baseIndexOf(array, value, fromIndex || 0); + } + function initial(array) { + return dropRight(array, 1); + } + var intersection = restParam(function(arrays) { + var othLength = arrays.length, othIndex = othLength, caches = Array(length), indexOf = getIndexOf(), isCommon = indexOf === baseIndexOf, result = []; + while (othIndex--) { + var value = arrays[othIndex] = isArrayLike(value = arrays[othIndex]) ? value : []; + caches[othIndex] = isCommon && value.length >= 120 ? createCache(othIndex && value) : null; + } + var array = arrays[0], index = -1, length = array ? array.length : 0, seen = caches[0]; + outer: while (++index < length) { + value = array[index]; + if ((seen ? cacheIndexOf(seen, value) : indexOf(result, value, 0)) < 0) { + var othIndex = othLength; + while (--othIndex) { + var cache = caches[othIndex]; + if ((cache ? cacheIndexOf(cache, value) : indexOf(arrays[othIndex], value, 0)) < 0) { + continue outer; + } + } + if (seen) { + seen.push(value); + } + result.push(value); + } + } + return result; + }); + function last(array) { + var length = array ? array.length : 0; + return length ? array[length - 1] : undefined; + } + function lastIndexOf(array, value, fromIndex) { + var length = array ? array.length : 0; + if (!length) { + return -1; + } + var index = length; + if (typeof fromIndex == "number") { + index = (fromIndex < 0 ? nativeMax(length + fromIndex, 0) : nativeMin(fromIndex || 0, length - 1)) + 1; + } else if (fromIndex) { + index = binaryIndex(array, value, true) - 1; + var other = array[index]; + if (value === value ? value === other : other !== other) { + return index; + } + return -1; + } + if (value !== value) { + return indexOfNaN(array, index, true); + } + while (index--) { + if (array[index] === value) { + return index; + } + } + return -1; + } + function pull() { + var args = arguments, array = args[0]; + if (!(array && array.length)) { + return array; + } + var index = 0, indexOf = getIndexOf(), length = args.length; + while (++index < length) { + var fromIndex = 0, value = args[index]; + while ((fromIndex = indexOf(array, value, fromIndex)) > -1) { + splice.call(array, fromIndex, 1); + } + } + return array; + } + var pullAt = restParam(function(array, indexes) { + indexes = baseFlatten(indexes); + var result = baseAt(array, indexes); + basePullAt(array, indexes.sort(baseCompareAscending)); + return result; + }); + function remove(array, predicate, thisArg) { + var result = []; + if (!(array && array.length)) { + return result; + } + var index = -1, indexes = [], length = array.length; + predicate = getCallback(predicate, thisArg, 3); + while (++index < length) { + var value = array[index]; + if (predicate(value, index, array)) { + result.push(value); + indexes.push(index); + } + } + basePullAt(array, indexes); + return result; + } + function rest(array) { + return drop(array, 1); + } + function slice(array, start, end) { + var length = array ? array.length : 0; + if (!length) { + return []; + } + if (end && typeof end != "number" && isIterateeCall(array, start, end)) { + start = 0; + end = length; + } + return baseSlice(array, start, end); + } + var sortedIndex = createSortedIndex(); + var sortedLastIndex = createSortedIndex(true); + function take(array, n, guard) { + var length = array ? array.length : 0; + if (!length) { + return []; + } + if (guard ? isIterateeCall(array, n, guard) : n == null) { + n = 1; + } + return baseSlice(array, 0, n < 0 ? 0 : n); + } + function takeRight(array, n, guard) { + var length = array ? array.length : 0; + if (!length) { + return []; + } + if (guard ? isIterateeCall(array, n, guard) : n == null) { + n = 1; + } + n = length - (+n || 0); + return baseSlice(array, n < 0 ? 0 : n); + } + function takeRightWhile(array, predicate, thisArg) { + return array && array.length ? baseWhile(array, getCallback(predicate, thisArg, 3), false, true) : []; + } + function takeWhile(array, predicate, thisArg) { + return array && array.length ? baseWhile(array, getCallback(predicate, thisArg, 3)) : []; + } + var union = restParam(function(arrays) { + return baseUniq(baseFlatten(arrays, false, true)); + }); + function uniq(array, isSorted, iteratee, thisArg) { + var length = array ? array.length : 0; + if (!length) { + return []; + } + if (isSorted != null && typeof isSorted != "boolean") { + thisArg = iteratee; + iteratee = isIterateeCall(array, isSorted, thisArg) ? undefined : isSorted; + isSorted = false; + } + var callback = getCallback(); + if (!(iteratee == null && callback === baseCallback)) { + iteratee = callback(iteratee, thisArg, 3); + } + return isSorted && getIndexOf() === baseIndexOf ? sortedUniq(array, iteratee) : baseUniq(array, iteratee); + } + function unzip(array) { + if (!(array && array.length)) { + return []; + } + var index = -1, length = 0; + array = arrayFilter(array, function(group) { + if (isArrayLike(group)) { + length = nativeMax(group.length, length); + return true; + } + }); + var result = Array(length); + while (++index < length) { + result[index] = arrayMap(array, baseProperty(index)); + } + return result; + } + function unzipWith(array, iteratee, thisArg) { + var length = array ? array.length : 0; + if (!length) { + return []; + } + var result = unzip(array); + if (iteratee == null) { + return result; + } + iteratee = bindCallback(iteratee, thisArg, 4); + return arrayMap(result, function(group) { + return arrayReduce(group, iteratee, undefined, true); + }); + } + var without = restParam(function(array, values) { + return isArrayLike(array) ? baseDifference(array, values) : []; + }); + function xor() { + var index = -1, length = arguments.length; + while (++index < length) { + var array = arguments[index]; + if (isArrayLike(array)) { + var result = result ? arrayPush(baseDifference(result, array), baseDifference(array, result)) : array; + } + } + return result ? baseUniq(result) : []; + } + var zip = restParam(unzip); + function zipObject(props, values) { + var index = -1, length = props ? props.length : 0, result = {}; + if (length && !values && !isArray(props[0])) { + values = []; + } + while (++index < length) { + var key = props[index]; + if (values) { + result[key] = values[index]; + } else if (key) { + result[key[0]] = key[1]; + } + } + return result; + } + var zipWith = restParam(function(arrays) { + var length = arrays.length, iteratee = length > 2 ? arrays[length - 2] : undefined, thisArg = length > 1 ? arrays[length - 1] : undefined; + if (length > 2 && typeof iteratee == "function") { + length -= 2; + } else { + iteratee = length > 1 && typeof thisArg == "function" ? (--length, thisArg) : undefined; + thisArg = undefined; + } + arrays.length = length; + return unzipWith(arrays, iteratee, thisArg); + }); + function chain(value) { + var result = lodash(value); + result.__chain__ = true; + return result; + } + function tap(value, interceptor, thisArg) { + interceptor.call(thisArg, value); + return value; + } + function thru(value, interceptor, thisArg) { + return interceptor.call(thisArg, value); + } + function wrapperChain() { + return chain(this); + } + function wrapperCommit() { + return new LodashWrapper(this.value(), this.__chain__); + } + var wrapperConcat = restParam(function(values) { + values = baseFlatten(values); + return this.thru(function(array) { + return arrayConcat(isArray(array) ? array : [ toObject(array) ], values); + }); + }); + function wrapperPlant(value) { + var result, parent = this; + while (parent instanceof baseLodash) { + var clone = wrapperClone(parent); + if (result) { + previous.__wrapped__ = clone; + } else { + result = clone; + } + var previous = clone; + parent = parent.__wrapped__; + } + previous.__wrapped__ = value; + return result; + } + function wrapperReverse() { + var value = this.__wrapped__; + var interceptor = function(value) { + return value.reverse(); + }; + if (value instanceof LazyWrapper) { + var wrapped = value; + if (this.__actions__.length) { + wrapped = new LazyWrapper(this); + } + wrapped = wrapped.reverse(); + wrapped.__actions__.push({ + func: thru, + args: [ interceptor ], + thisArg: undefined + }); + return new LodashWrapper(wrapped, this.__chain__); + } + return this.thru(interceptor); + } + function wrapperToString() { + return this.value() + ""; + } + function wrapperValue() { + return baseWrapperValue(this.__wrapped__, this.__actions__); + } + var at = restParam(function(collection, props) { + return baseAt(collection, baseFlatten(props)); + }); + var countBy = createAggregator(function(result, value, key) { + hasOwnProperty.call(result, key) ? ++result[key] : result[key] = 1; + }); + function every(collection, predicate, thisArg) { + var func = isArray(collection) ? arrayEvery : baseEvery; + if (thisArg && isIterateeCall(collection, predicate, thisArg)) { + predicate = undefined; + } + if (typeof predicate != "function" || thisArg !== undefined) { + predicate = getCallback(predicate, thisArg, 3); + } + return func(collection, predicate); + } + function filter(collection, predicate, thisArg) { + var func = isArray(collection) ? arrayFilter : baseFilter; + predicate = getCallback(predicate, thisArg, 3); + return func(collection, predicate); + } + var find = createFind(baseEach); + var findLast = createFind(baseEachRight, true); + function findWhere(collection, source) { + return find(collection, baseMatches(source)); + } + var forEach = createForEach(arrayEach, baseEach); + var forEachRight = createForEach(arrayEachRight, baseEachRight); + var groupBy = createAggregator(function(result, value, key) { + if (hasOwnProperty.call(result, key)) { + result[key].push(value); + } else { + result[key] = [ value ]; + } + }); + function includes(collection, target, fromIndex, guard) { + var length = collection ? getLength(collection) : 0; + if (!isLength(length)) { + collection = values(collection); + length = collection.length; + } + if (typeof fromIndex != "number" || guard && isIterateeCall(target, fromIndex, guard)) { + fromIndex = 0; + } else { + fromIndex = fromIndex < 0 ? nativeMax(length + fromIndex, 0) : fromIndex || 0; + } + return typeof collection == "string" || !isArray(collection) && isString(collection) ? fromIndex <= length && collection.indexOf(target, fromIndex) > -1 : !!length && getIndexOf(collection, target, fromIndex) > -1; + } + var indexBy = createAggregator(function(result, value, key) { + result[key] = value; + }); + var invoke = restParam(function(collection, path, args) { + var index = -1, isFunc = typeof path == "function", isProp = isKey(path), result = isArrayLike(collection) ? Array(collection.length) : []; + baseEach(collection, function(value) { + var func = isFunc ? path : isProp && value != null ? value[path] : undefined; + result[++index] = func ? func.apply(value, args) : invokePath(value, path, args); + }); + return result; + }); + function map(collection, iteratee, thisArg) { + var func = isArray(collection) ? arrayMap : baseMap; + iteratee = getCallback(iteratee, thisArg, 3); + return func(collection, iteratee); + } + var partition = createAggregator(function(result, value, key) { + result[key ? 0 : 1].push(value); + }, function() { + return [ [], [] ]; + }); + function pluck(collection, path) { + return map(collection, property(path)); + } + var reduce = createReduce(arrayReduce, baseEach); + var reduceRight = createReduce(arrayReduceRight, baseEachRight); + function reject(collection, predicate, thisArg) { + var func = isArray(collection) ? arrayFilter : baseFilter; + predicate = getCallback(predicate, thisArg, 3); + return func(collection, function(value, index, collection) { + return !predicate(value, index, collection); + }); + } + function sample(collection, n, guard) { + if (guard ? isIterateeCall(collection, n, guard) : n == null) { + collection = toIterable(collection); + var length = collection.length; + return length > 0 ? collection[baseRandom(0, length - 1)] : undefined; + } + var index = -1, result = toArray(collection), length = result.length, lastIndex = length - 1; + n = nativeMin(n < 0 ? 0 : +n || 0, length); + while (++index < n) { + var rand = baseRandom(index, lastIndex), value = result[rand]; + result[rand] = result[index]; + result[index] = value; + } + result.length = n; + return result; + } + function shuffle(collection) { + return sample(collection, POSITIVE_INFINITY); + } + function size(collection) { + var length = collection ? getLength(collection) : 0; + return isLength(length) ? length : keys(collection).length; + } + function some(collection, predicate, thisArg) { + var func = isArray(collection) ? arraySome : baseSome; + if (thisArg && isIterateeCall(collection, predicate, thisArg)) { + predicate = undefined; + } + if (typeof predicate != "function" || thisArg !== undefined) { + predicate = getCallback(predicate, thisArg, 3); + } + return func(collection, predicate); + } + function sortBy(collection, iteratee, thisArg) { + if (collection == null) { + return []; + } + if (thisArg && isIterateeCall(collection, iteratee, thisArg)) { + iteratee = undefined; + } + var index = -1; + iteratee = getCallback(iteratee, thisArg, 3); + var result = baseMap(collection, function(value, key, collection) { + return { + criteria: iteratee(value, key, collection), + index: ++index, + value: value + }; + }); + return baseSortBy(result, compareAscending); + } + var sortByAll = restParam(function(collection, iteratees) { + if (collection == null) { + return []; + } + var guard = iteratees[2]; + if (guard && isIterateeCall(iteratees[0], iteratees[1], guard)) { + iteratees.length = 1; + } + return baseSortByOrder(collection, baseFlatten(iteratees), []); + }); + function sortByOrder(collection, iteratees, orders, guard) { + if (collection == null) { + return []; + } + if (guard && isIterateeCall(iteratees, orders, guard)) { + orders = undefined; + } + if (!isArray(iteratees)) { + iteratees = iteratees == null ? [] : [ iteratees ]; + } + if (!isArray(orders)) { + orders = orders == null ? [] : [ orders ]; + } + return baseSortByOrder(collection, iteratees, orders); + } + function where(collection, source) { + return filter(collection, baseMatches(source)); + } + var now = nativeNow || function() { + return new Date().getTime(); + }; + function after(n, func) { + if (typeof func != "function") { + if (typeof n == "function") { + var temp = n; + n = func; + func = temp; + } else { + throw new TypeError(FUNC_ERROR_TEXT); + } + } + n = nativeIsFinite(n = +n) ? n : 0; + return function() { + if (--n < 1) { + return func.apply(this, arguments); + } + }; + } + function ary(func, n, guard) { + if (guard && isIterateeCall(func, n, guard)) { + n = undefined; + } + n = func && n == null ? func.length : nativeMax(+n || 0, 0); + return createWrapper(func, ARY_FLAG, undefined, undefined, undefined, undefined, n); + } + function before(n, func) { + var result; + if (typeof func != "function") { + if (typeof n == "function") { + var temp = n; + n = func; + func = temp; + } else { + throw new TypeError(FUNC_ERROR_TEXT); + } + } + return function() { + if (--n > 0) { + result = func.apply(this, arguments); + } + if (n <= 1) { + func = undefined; + } + return result; + }; + } + var bind = restParam(function(func, thisArg, partials) { + var bitmask = BIND_FLAG; + if (partials.length) { + var holders = replaceHolders(partials, bind.placeholder); + bitmask |= PARTIAL_FLAG; + } + return createWrapper(func, bitmask, thisArg, partials, holders); + }); + var bindAll = restParam(function(object, methodNames) { + methodNames = methodNames.length ? baseFlatten(methodNames) : functions(object); + var index = -1, length = methodNames.length; + while (++index < length) { + var key = methodNames[index]; + object[key] = createWrapper(object[key], BIND_FLAG, object); + } + return object; + }); + var bindKey = restParam(function(object, key, partials) { + var bitmask = BIND_FLAG | BIND_KEY_FLAG; + if (partials.length) { + var holders = replaceHolders(partials, bindKey.placeholder); + bitmask |= PARTIAL_FLAG; + } + return createWrapper(key, bitmask, object, partials, holders); + }); + var curry = createCurry(CURRY_FLAG); + var curryRight = createCurry(CURRY_RIGHT_FLAG); + function debounce(func, wait, options) { + var args, maxTimeoutId, result, stamp, thisArg, timeoutId, trailingCall, lastCalled = 0, maxWait = false, trailing = true; + if (typeof func != "function") { + throw new TypeError(FUNC_ERROR_TEXT); + } + wait = wait < 0 ? 0 : +wait || 0; + if (options === true) { + var leading = true; + trailing = false; + } else if (isObject(options)) { + leading = !!options.leading; + maxWait = "maxWait" in options && nativeMax(+options.maxWait || 0, wait); + trailing = "trailing" in options ? !!options.trailing : trailing; + } + function cancel() { + if (timeoutId) { + clearTimeout(timeoutId); + } + if (maxTimeoutId) { + clearTimeout(maxTimeoutId); + } + lastCalled = 0; + maxTimeoutId = timeoutId = trailingCall = undefined; + } + function complete(isCalled, id) { + if (id) { + clearTimeout(id); + } + maxTimeoutId = timeoutId = trailingCall = undefined; + if (isCalled) { + lastCalled = now(); + result = func.apply(thisArg, args); + if (!timeoutId && !maxTimeoutId) { + args = thisArg = undefined; + } + } + } + function delayed() { + var remaining = wait - (now() - stamp); + if (remaining <= 0 || remaining > wait) { + complete(trailingCall, maxTimeoutId); + } else { + timeoutId = setTimeout(delayed, remaining); + } + } + function maxDelayed() { + complete(trailing, timeoutId); + } + function debounced() { + args = arguments; + stamp = now(); + thisArg = this; + trailingCall = trailing && (timeoutId || !leading); + if (maxWait === false) { + var leadingCall = leading && !timeoutId; + } else { + if (!maxTimeoutId && !leading) { + lastCalled = stamp; + } + var remaining = maxWait - (stamp - lastCalled), isCalled = remaining <= 0 || remaining > maxWait; + if (isCalled) { + if (maxTimeoutId) { + maxTimeoutId = clearTimeout(maxTimeoutId); + } + lastCalled = stamp; + result = func.apply(thisArg, args); + } else if (!maxTimeoutId) { + maxTimeoutId = setTimeout(maxDelayed, remaining); + } + } + if (isCalled && timeoutId) { + timeoutId = clearTimeout(timeoutId); + } else if (!timeoutId && wait !== maxWait) { + timeoutId = setTimeout(delayed, wait); + } + if (leadingCall) { + isCalled = true; + result = func.apply(thisArg, args); + } + if (isCalled && !timeoutId && !maxTimeoutId) { + args = thisArg = undefined; + } + return result; + } + debounced.cancel = cancel; + return debounced; + } + var defer = restParam(function(func, args) { + return baseDelay(func, 1, args); + }); + var delay = restParam(function(func, wait, args) { + return baseDelay(func, wait, args); + }); + var flow = createFlow(); + var flowRight = createFlow(true); + function memoize(func, resolver) { + if (typeof func != "function" || resolver && typeof resolver != "function") { + throw new TypeError(FUNC_ERROR_TEXT); + } + var memoized = function() { + var args = arguments, key = resolver ? resolver.apply(this, args) : args[0], cache = memoized.cache; + if (cache.has(key)) { + return cache.get(key); + } + var result = func.apply(this, args); + memoized.cache = cache.set(key, result); + return result; + }; + memoized.cache = new memoize.Cache(); + return memoized; + } + var modArgs = restParam(function(func, transforms) { + transforms = baseFlatten(transforms); + if (typeof func != "function" || !arrayEvery(transforms, baseIsFunction)) { + throw new TypeError(FUNC_ERROR_TEXT); + } + var length = transforms.length; + return restParam(function(args) { + var index = nativeMin(args.length, length); + while (index--) { + args[index] = transforms[index](args[index]); + } + return func.apply(this, args); + }); + }); + function negate(predicate) { + if (typeof predicate != "function") { + throw new TypeError(FUNC_ERROR_TEXT); + } + return function() { + return !predicate.apply(this, arguments); + }; + } + function once(func) { + return before(2, func); + } + var partial = createPartial(PARTIAL_FLAG); + var partialRight = createPartial(PARTIAL_RIGHT_FLAG); + var rearg = restParam(function(func, indexes) { + return createWrapper(func, REARG_FLAG, undefined, undefined, undefined, baseFlatten(indexes)); + }); + function restParam(func, start) { + if (typeof func != "function") { + throw new TypeError(FUNC_ERROR_TEXT); + } + start = nativeMax(start === undefined ? func.length - 1 : +start || 0, 0); + return function() { + var args = arguments, index = -1, length = nativeMax(args.length - start, 0), rest = Array(length); + while (++index < length) { + rest[index] = args[start + index]; + } + switch (start) { + case 0: + return func.call(this, rest); + + case 1: + return func.call(this, args[0], rest); + + case 2: + return func.call(this, args[0], args[1], rest); + } + var otherArgs = Array(start + 1); + index = -1; + while (++index < start) { + otherArgs[index] = args[index]; + } + otherArgs[start] = rest; + return func.apply(this, otherArgs); + }; + } + function spread(func) { + if (typeof func != "function") { + throw new TypeError(FUNC_ERROR_TEXT); + } + return function(array) { + return func.apply(this, array); + }; + } + function throttle(func, wait, options) { + var leading = true, trailing = true; + if (typeof func != "function") { + throw new TypeError(FUNC_ERROR_TEXT); + } + if (options === false) { + leading = false; + } else if (isObject(options)) { + leading = "leading" in options ? !!options.leading : leading; + trailing = "trailing" in options ? !!options.trailing : trailing; + } + return debounce(func, wait, { + leading: leading, + maxWait: +wait, + trailing: trailing + }); + } + function wrap(value, wrapper) { + wrapper = wrapper == null ? identity : wrapper; + return createWrapper(wrapper, PARTIAL_FLAG, undefined, [ value ], []); + } + function clone(value, isDeep, customizer, thisArg) { + if (isDeep && typeof isDeep != "boolean" && isIterateeCall(value, isDeep, customizer)) { + isDeep = false; + } else if (typeof isDeep == "function") { + thisArg = customizer; + customizer = isDeep; + isDeep = false; + } + return typeof customizer == "function" ? baseClone(value, isDeep, bindCallback(customizer, thisArg, 3)) : baseClone(value, isDeep); + } + function cloneDeep(value, customizer, thisArg) { + return typeof customizer == "function" ? baseClone(value, true, bindCallback(customizer, thisArg, 3)) : baseClone(value, true); + } + function gt(value, other) { + return value > other; + } + function gte(value, other) { + return value >= other; + } + function isArguments(value) { + return isObjectLike(value) && isArrayLike(value) && hasOwnProperty.call(value, "callee") && !propertyIsEnumerable.call(value, "callee"); + } + var isArray = nativeIsArray || function(value) { + return isObjectLike(value) && isLength(value.length) && objToString.call(value) == arrayTag; + }; + function isBoolean(value) { + return value === true || value === false || isObjectLike(value) && objToString.call(value) == boolTag; + } + function isDate(value) { + return isObjectLike(value) && objToString.call(value) == dateTag; + } + function isElement(value) { + return !!value && value.nodeType === 1 && isObjectLike(value) && !isPlainObject(value); + } + function isEmpty(value) { + if (value == null) { + return true; + } + if (isArrayLike(value) && (isArray(value) || isString(value) || isArguments(value) || isObjectLike(value) && isFunction(value.splice))) { + return !value.length; + } + return !keys(value).length; + } + function isEqual(value, other, customizer, thisArg) { + customizer = typeof customizer == "function" ? bindCallback(customizer, thisArg, 3) : undefined; + var result = customizer ? customizer(value, other) : undefined; + return result === undefined ? baseIsEqual(value, other, customizer) : !!result; + } + function isError(value) { + return isObjectLike(value) && typeof value.message == "string" && objToString.call(value) == errorTag; + } + function isFinite(value) { + return typeof value == "number" && nativeIsFinite(value); + } + function isFunction(value) { + return isObject(value) && objToString.call(value) == funcTag; + } + function isObject(value) { + var type = typeof value; + return !!value && (type == "object" || type == "function"); + } + function isMatch(object, source, customizer, thisArg) { + customizer = typeof customizer == "function" ? bindCallback(customizer, thisArg, 3) : undefined; + return baseIsMatch(object, getMatchData(source), customizer); + } + function isNaN(value) { + return isNumber(value) && value != +value; + } + function isNative(value) { + if (value == null) { + return false; + } + if (isFunction(value)) { + return reIsNative.test(fnToString.call(value)); + } + return isObjectLike(value) && reIsHostCtor.test(value); + } + function isNull(value) { + return value === null; + } + function isNumber(value) { + return typeof value == "number" || isObjectLike(value) && objToString.call(value) == numberTag; + } + function isPlainObject(value) { + var Ctor; + if (!(isObjectLike(value) && objToString.call(value) == objectTag && !isArguments(value)) || !hasOwnProperty.call(value, "constructor") && (Ctor = value.constructor, + typeof Ctor == "function" && !(Ctor instanceof Ctor))) { + return false; + } + var result; + baseForIn(value, function(subValue, key) { + result = key; + }); + return result === undefined || hasOwnProperty.call(value, result); + } + function isRegExp(value) { + return isObject(value) && objToString.call(value) == regexpTag; + } + function isString(value) { + return typeof value == "string" || isObjectLike(value) && objToString.call(value) == stringTag; + } + function isTypedArray(value) { + return isObjectLike(value) && isLength(value.length) && !!typedArrayTags[objToString.call(value)]; + } + function isUndefined(value) { + return value === undefined; + } + function lt(value, other) { + return value < other; + } + function lte(value, other) { + return value <= other; + } + function toArray(value) { + var length = value ? getLength(value) : 0; + if (!isLength(length)) { + return values(value); + } + if (!length) { + return []; + } + return arrayCopy(value); + } + function toPlainObject(value) { + return baseCopy(value, keysIn(value)); + } + var merge = createAssigner(baseMerge); + var assign = createAssigner(function(object, source, customizer) { + return customizer ? assignWith(object, source, customizer) : baseAssign(object, source); + }); + function create(prototype, properties, guard) { + var result = baseCreate(prototype); + if (guard && isIterateeCall(prototype, properties, guard)) { + properties = undefined; + } + return properties ? baseAssign(result, properties) : result; + } + var defaults = createDefaults(assign, assignDefaults); + var defaultsDeep = createDefaults(merge, mergeDefaults); + var findKey = createFindKey(baseForOwn); + var findLastKey = createFindKey(baseForOwnRight); + var forIn = createForIn(baseFor); + var forInRight = createForIn(baseForRight); + var forOwn = createForOwn(baseForOwn); + var forOwnRight = createForOwn(baseForOwnRight); + function functions(object) { + return baseFunctions(object, keysIn(object)); + } + function get(object, path, defaultValue) { + var result = object == null ? undefined : baseGet(object, toPath(path), path + ""); + return result === undefined ? defaultValue : result; + } + function has(object, path) { + if (object == null) { + return false; + } + var result = hasOwnProperty.call(object, path); + if (!result && !isKey(path)) { + path = toPath(path); + object = path.length == 1 ? object : baseGet(object, baseSlice(path, 0, -1)); + if (object == null) { + return false; + } + path = last(path); + result = hasOwnProperty.call(object, path); + } + return result || isLength(object.length) && isIndex(path, object.length) && (isArray(object) || isArguments(object)); + } + function invert(object, multiValue, guard) { + if (guard && isIterateeCall(object, multiValue, guard)) { + multiValue = undefined; + } + var index = -1, props = keys(object), length = props.length, result = {}; + while (++index < length) { + var key = props[index], value = object[key]; + if (multiValue) { + if (hasOwnProperty.call(result, value)) { + result[value].push(key); + } else { + result[value] = [ key ]; + } + } else { + result[value] = key; + } + } + return result; + } + var keys = !nativeKeys ? shimKeys : function(object) { + var Ctor = object == null ? undefined : object.constructor; + if (typeof Ctor == "function" && Ctor.prototype === object || typeof object != "function" && isArrayLike(object)) { + return shimKeys(object); + } + return isObject(object) ? nativeKeys(object) : []; + }; + function keysIn(object) { + if (object == null) { + return []; + } + if (!isObject(object)) { + object = Object(object); + } + var length = object.length; + length = length && isLength(length) && (isArray(object) || isArguments(object)) && length || 0; + var Ctor = object.constructor, index = -1, isProto = typeof Ctor == "function" && Ctor.prototype === object, result = Array(length), skipIndexes = length > 0; + while (++index < length) { + result[index] = index + ""; + } + for (var key in object) { + if (!(skipIndexes && isIndex(key, length)) && !(key == "constructor" && (isProto || !hasOwnProperty.call(object, key)))) { + result.push(key); + } + } + return result; + } + var mapKeys = createObjectMapper(true); + var mapValues = createObjectMapper(); + var omit = restParam(function(object, props) { + if (object == null) { + return {}; + } + if (typeof props[0] != "function") { + var props = arrayMap(baseFlatten(props), String); + return pickByArray(object, baseDifference(keysIn(object), props)); + } + var predicate = bindCallback(props[0], props[1], 3); + return pickByCallback(object, function(value, key, object) { + return !predicate(value, key, object); + }); + }); + function pairs(object) { + object = toObject(object); + var index = -1, props = keys(object), length = props.length, result = Array(length); + while (++index < length) { + var key = props[index]; + result[index] = [ key, object[key] ]; + } + return result; + } + var pick = restParam(function(object, props) { + if (object == null) { + return {}; + } + return typeof props[0] == "function" ? pickByCallback(object, bindCallback(props[0], props[1], 3)) : pickByArray(object, baseFlatten(props)); + }); + function result(object, path, defaultValue) { + var result = object == null ? undefined : object[path]; + if (result === undefined) { + if (object != null && !isKey(path, object)) { + path = toPath(path); + object = path.length == 1 ? object : baseGet(object, baseSlice(path, 0, -1)); + result = object == null ? undefined : object[last(path)]; + } + result = result === undefined ? defaultValue : result; + } + return isFunction(result) ? result.call(object) : result; + } + function set(object, path, value) { + if (object == null) { + return object; + } + var pathKey = path + ""; + path = object[pathKey] != null || isKey(path, object) ? [ pathKey ] : toPath(path); + var index = -1, length = path.length, lastIndex = length - 1, nested = object; + while (nested != null && ++index < length) { + var key = path[index]; + if (isObject(nested)) { + if (index == lastIndex) { + nested[key] = value; + } else if (nested[key] == null) { + nested[key] = isIndex(path[index + 1]) ? [] : {}; + } + } + nested = nested[key]; + } + return object; + } + function transform(object, iteratee, accumulator, thisArg) { + var isArr = isArray(object) || isTypedArray(object); + iteratee = getCallback(iteratee, thisArg, 4); + if (accumulator == null) { + if (isArr || isObject(object)) { + var Ctor = object.constructor; + if (isArr) { + accumulator = isArray(object) ? new Ctor() : []; + } else { + accumulator = baseCreate(isFunction(Ctor) ? Ctor.prototype : undefined); + } + } else { + accumulator = {}; + } + } + (isArr ? arrayEach : baseForOwn)(object, function(value, index, object) { + return iteratee(accumulator, value, index, object); + }); + return accumulator; + } + function values(object) { + return baseValues(object, keys(object)); + } + function valuesIn(object) { + return baseValues(object, keysIn(object)); + } + function inRange(value, start, end) { + start = +start || 0; + if (end === undefined) { + end = start; + start = 0; + } else { + end = +end || 0; + } + return value >= nativeMin(start, end) && value < nativeMax(start, end); + } + function random(min, max, floating) { + if (floating && isIterateeCall(min, max, floating)) { + max = floating = undefined; + } + var noMin = min == null, noMax = max == null; + if (floating == null) { + if (noMax && typeof min == "boolean") { + floating = min; + min = 1; + } else if (typeof max == "boolean") { + floating = max; + noMax = true; + } + } + if (noMin && noMax) { + max = 1; + noMax = false; + } + min = +min || 0; + if (noMax) { + max = min; + min = 0; + } else { + max = +max || 0; + } + if (floating || min % 1 || max % 1) { + var rand = nativeRandom(); + return nativeMin(min + rand * (max - min + parseFloat("1e-" + ((rand + "").length - 1))), max); + } + return baseRandom(min, max); + } + var camelCase = createCompounder(function(result, word, index) { + word = word.toLowerCase(); + return result + (index ? word.charAt(0).toUpperCase() + word.slice(1) : word); + }); + function capitalize(string) { + string = baseToString(string); + return string && string.charAt(0).toUpperCase() + string.slice(1); + } + function deburr(string) { + string = baseToString(string); + return string && string.replace(reLatin1, deburrLetter).replace(reComboMark, ""); + } + function endsWith(string, target, position) { + string = baseToString(string); + target = target + ""; + var length = string.length; + position = position === undefined ? length : nativeMin(position < 0 ? 0 : +position || 0, length); + position -= target.length; + return position >= 0 && string.indexOf(target, position) == position; + } + function escape(string) { + string = baseToString(string); + return string && reHasUnescapedHtml.test(string) ? string.replace(reUnescapedHtml, escapeHtmlChar) : string; + } + function escapeRegExp(string) { + string = baseToString(string); + return string && reHasRegExpChars.test(string) ? string.replace(reRegExpChars, escapeRegExpChar) : string || "(?:)"; + } + var kebabCase = createCompounder(function(result, word, index) { + return result + (index ? "-" : "") + word.toLowerCase(); + }); + function pad(string, length, chars) { + string = baseToString(string); + length = +length; + var strLength = string.length; + if (strLength >= length || !nativeIsFinite(length)) { + return string; + } + var mid = (length - strLength) / 2, leftLength = nativeFloor(mid), rightLength = nativeCeil(mid); + chars = createPadding("", rightLength, chars); + return chars.slice(0, leftLength) + string + chars; + } + var padLeft = createPadDir(); + var padRight = createPadDir(true); + function parseInt(string, radix, guard) { + if (guard ? isIterateeCall(string, radix, guard) : radix == null) { + radix = 0; + } else if (radix) { + radix = +radix; + } + string = trim(string); + return nativeParseInt(string, radix || (reHasHexPrefix.test(string) ? 16 : 10)); + } + function repeat(string, n) { + var result = ""; + string = baseToString(string); + n = +n; + if (n < 1 || !string || !nativeIsFinite(n)) { + return result; + } + do { + if (n % 2) { + result += string; + } + n = nativeFloor(n / 2); + string += string; + } while (n); + return result; + } + var snakeCase = createCompounder(function(result, word, index) { + return result + (index ? "_" : "") + word.toLowerCase(); + }); + var startCase = createCompounder(function(result, word, index) { + return result + (index ? " " : "") + (word.charAt(0).toUpperCase() + word.slice(1)); + }); + function startsWith(string, target, position) { + string = baseToString(string); + position = position == null ? 0 : nativeMin(position < 0 ? 0 : +position || 0, string.length); + return string.lastIndexOf(target, position) == position; + } + function template(string, options, otherOptions) { + var settings = lodash.templateSettings; + if (otherOptions && isIterateeCall(string, options, otherOptions)) { + options = otherOptions = undefined; + } + string = baseToString(string); + options = assignWith(baseAssign({}, otherOptions || options), settings, assignOwnDefaults); + var imports = assignWith(baseAssign({}, options.imports), settings.imports, assignOwnDefaults), importsKeys = keys(imports), importsValues = baseValues(imports, importsKeys); + var isEscaping, isEvaluating, index = 0, interpolate = options.interpolate || reNoMatch, source = "__p += '"; + var reDelimiters = RegExp((options.escape || reNoMatch).source + "|" + interpolate.source + "|" + (interpolate === reInterpolate ? reEsTemplate : reNoMatch).source + "|" + (options.evaluate || reNoMatch).source + "|$", "g"); + var sourceURL = "//# sourceURL=" + ("sourceURL" in options ? options.sourceURL : "lodash.templateSources[" + ++templateCounter + "]") + "\n"; + string.replace(reDelimiters, function(match, escapeValue, interpolateValue, esTemplateValue, evaluateValue, offset) { + interpolateValue || (interpolateValue = esTemplateValue); + source += string.slice(index, offset).replace(reUnescapedString, escapeStringChar); + if (escapeValue) { + isEscaping = true; + source += "' +\n__e(" + escapeValue + ") +\n'"; + } + if (evaluateValue) { + isEvaluating = true; + source += "';\n" + evaluateValue + ";\n__p += '"; + } + if (interpolateValue) { + source += "' +\n((__t = (" + interpolateValue + ")) == null ? '' : __t) +\n'"; + } + index = offset + match.length; + return match; + }); + source += "';\n"; + var variable = options.variable; + if (!variable) { + source = "with (obj) {\n" + source + "\n}\n"; + } + source = (isEvaluating ? source.replace(reEmptyStringLeading, "") : source).replace(reEmptyStringMiddle, "$1").replace(reEmptyStringTrailing, "$1;"); + source = "function(" + (variable || "obj") + ") {\n" + (variable ? "" : "obj || (obj = {});\n") + "var __t, __p = ''" + (isEscaping ? ", __e = _.escape" : "") + (isEvaluating ? ", __j = Array.prototype.join;\n" + "function print() { __p += __j.call(arguments, '') }\n" : ";\n") + source + "return __p\n}"; + var result = attempt(function() { + return Function(importsKeys, sourceURL + "return " + source).apply(undefined, importsValues); + }); + result.source = source; + if (isError(result)) { + throw result; + } + return result; + } + function trim(string, chars, guard) { + var value = string; + string = baseToString(string); + if (!string) { + return string; + } + if (guard ? isIterateeCall(value, chars, guard) : chars == null) { + return string.slice(trimmedLeftIndex(string), trimmedRightIndex(string) + 1); + } + chars = chars + ""; + return string.slice(charsLeftIndex(string, chars), charsRightIndex(string, chars) + 1); + } + function trimLeft(string, chars, guard) { + var value = string; + string = baseToString(string); + if (!string) { + return string; + } + if (guard ? isIterateeCall(value, chars, guard) : chars == null) { + return string.slice(trimmedLeftIndex(string)); + } + return string.slice(charsLeftIndex(string, chars + "")); + } + function trimRight(string, chars, guard) { + var value = string; + string = baseToString(string); + if (!string) { + return string; + } + if (guard ? isIterateeCall(value, chars, guard) : chars == null) { + return string.slice(0, trimmedRightIndex(string) + 1); + } + return string.slice(0, charsRightIndex(string, chars + "") + 1); + } + function trunc(string, options, guard) { + if (guard && isIterateeCall(string, options, guard)) { + options = undefined; + } + var length = DEFAULT_TRUNC_LENGTH, omission = DEFAULT_TRUNC_OMISSION; + if (options != null) { + if (isObject(options)) { + var separator = "separator" in options ? options.separator : separator; + length = "length" in options ? +options.length || 0 : length; + omission = "omission" in options ? baseToString(options.omission) : omission; + } else { + length = +options || 0; + } + } + string = baseToString(string); + if (length >= string.length) { + return string; + } + var end = length - omission.length; + if (end < 1) { + return omission; + } + var result = string.slice(0, end); + if (separator == null) { + return result + omission; + } + if (isRegExp(separator)) { + if (string.slice(end).search(separator)) { + var match, newEnd, substring = string.slice(0, end); + if (!separator.global) { + separator = RegExp(separator.source, (reFlags.exec(separator) || "") + "g"); + } + separator.lastIndex = 0; + while (match = separator.exec(substring)) { + newEnd = match.index; + } + result = result.slice(0, newEnd == null ? end : newEnd); + } + } else if (string.indexOf(separator, end) != end) { + var index = result.lastIndexOf(separator); + if (index > -1) { + result = result.slice(0, index); + } + } + return result + omission; + } + function unescape(string) { + string = baseToString(string); + return string && reHasEscapedHtml.test(string) ? string.replace(reEscapedHtml, unescapeHtmlChar) : string; + } + function words(string, pattern, guard) { + if (guard && isIterateeCall(string, pattern, guard)) { + pattern = undefined; + } + string = baseToString(string); + return string.match(pattern || reWords) || []; + } + var attempt = restParam(function(func, args) { + try { + return func.apply(undefined, args); + } catch (e) { + return isError(e) ? e : new Error(e); + } + }); + function callback(func, thisArg, guard) { + if (guard && isIterateeCall(func, thisArg, guard)) { + thisArg = undefined; + } + return isObjectLike(func) ? matches(func) : baseCallback(func, thisArg); + } + function constant(value) { + return function() { + return value; + }; + } + function identity(value) { + return value; + } + function matches(source) { + return baseMatches(baseClone(source, true)); + } + function matchesProperty(path, srcValue) { + return baseMatchesProperty(path, baseClone(srcValue, true)); + } + var method = restParam(function(path, args) { + return function(object) { + return invokePath(object, path, args); + }; + }); + var methodOf = restParam(function(object, args) { + return function(path) { + return invokePath(object, path, args); + }; + }); + function mixin(object, source, options) { + if (options == null) { + var isObj = isObject(source), props = isObj ? keys(source) : undefined, methodNames = props && props.length ? baseFunctions(source, props) : undefined; + if (!(methodNames ? methodNames.length : isObj)) { + methodNames = false; + options = source; + source = object; + object = this; + } + } + if (!methodNames) { + methodNames = baseFunctions(source, keys(source)); + } + var chain = true, index = -1, isFunc = isFunction(object), length = methodNames.length; + if (options === false) { + chain = false; + } else if (isObject(options) && "chain" in options) { + chain = options.chain; + } + while (++index < length) { + var methodName = methodNames[index], func = source[methodName]; + object[methodName] = func; + if (isFunc) { + object.prototype[methodName] = function(func) { + return function() { + var chainAll = this.__chain__; + if (chain || chainAll) { + var result = object(this.__wrapped__), actions = result.__actions__ = arrayCopy(this.__actions__); + actions.push({ + func: func, + args: arguments, + thisArg: object + }); + result.__chain__ = chainAll; + return result; + } + return func.apply(object, arrayPush([ this.value() ], arguments)); + }; + }(func); + } + } + return object; + } + function noConflict() { + root._ = oldDash; + return this; + } + function noop() {} + function property(path) { + return isKey(path) ? baseProperty(path) : basePropertyDeep(path); + } + function propertyOf(object) { + return function(path) { + return baseGet(object, toPath(path), path + ""); + }; + } + function range(start, end, step) { + if (step && isIterateeCall(start, end, step)) { + end = step = undefined; + } + start = +start || 0; + step = step == null ? 1 : +step || 0; + if (end == null) { + end = start; + start = 0; + } else { + end = +end || 0; + } + var index = -1, length = nativeMax(nativeCeil((end - start) / (step || 1)), 0), result = Array(length); + while (++index < length) { + result[index] = start; + start += step; + } + return result; + } + function times(n, iteratee, thisArg) { + n = nativeFloor(n); + if (n < 1 || !nativeIsFinite(n)) { + return []; + } + var index = -1, result = Array(nativeMin(n, MAX_ARRAY_LENGTH)); + iteratee = bindCallback(iteratee, thisArg, 1); + while (++index < n) { + if (index < MAX_ARRAY_LENGTH) { + result[index] = iteratee(index); + } else { + iteratee(index); + } + } + return result; + } + function uniqueId(prefix) { + var id = ++idCounter; + return baseToString(prefix) + id; + } + function add(augend, addend) { + return (+augend || 0) + (+addend || 0); + } + var ceil = createRound("ceil"); + var floor = createRound("floor"); + var max = createExtremum(gt, NEGATIVE_INFINITY); + var min = createExtremum(lt, POSITIVE_INFINITY); + var round = createRound("round"); + function sum(collection, iteratee, thisArg) { + if (thisArg && isIterateeCall(collection, iteratee, thisArg)) { + iteratee = undefined; + } + iteratee = getCallback(iteratee, thisArg, 3); + return iteratee.length == 1 ? arraySum(isArray(collection) ? collection : toIterable(collection), iteratee) : baseSum(collection, iteratee); + } + lodash.prototype = baseLodash.prototype; + LodashWrapper.prototype = baseCreate(baseLodash.prototype); + LodashWrapper.prototype.constructor = LodashWrapper; + LazyWrapper.prototype = baseCreate(baseLodash.prototype); + LazyWrapper.prototype.constructor = LazyWrapper; + MapCache.prototype["delete"] = mapDelete; + MapCache.prototype.get = mapGet; + MapCache.prototype.has = mapHas; + MapCache.prototype.set = mapSet; + SetCache.prototype.push = cachePush; + memoize.Cache = MapCache; + lodash.after = after; + lodash.ary = ary; + lodash.assign = assign; + lodash.at = at; + lodash.before = before; + lodash.bind = bind; + lodash.bindAll = bindAll; + lodash.bindKey = bindKey; + lodash.callback = callback; + lodash.chain = chain; + lodash.chunk = chunk; + lodash.compact = compact; + lodash.constant = constant; + lodash.countBy = countBy; + lodash.create = create; + lodash.curry = curry; + lodash.curryRight = curryRight; + lodash.debounce = debounce; + lodash.defaults = defaults; + lodash.defaultsDeep = defaultsDeep; + lodash.defer = defer; + lodash.delay = delay; + lodash.difference = difference; + lodash.drop = drop; + lodash.dropRight = dropRight; + lodash.dropRightWhile = dropRightWhile; + lodash.dropWhile = dropWhile; + lodash.fill = fill; + lodash.filter = filter; + lodash.flatten = flatten; + lodash.flattenDeep = flattenDeep; + lodash.flow = flow; + lodash.flowRight = flowRight; + lodash.forEach = forEach; + lodash.forEachRight = forEachRight; + lodash.forIn = forIn; + lodash.forInRight = forInRight; + lodash.forOwn = forOwn; + lodash.forOwnRight = forOwnRight; + lodash.functions = functions; + lodash.groupBy = groupBy; + lodash.indexBy = indexBy; + lodash.initial = initial; + lodash.intersection = intersection; + lodash.invert = invert; + lodash.invoke = invoke; + lodash.keys = keys; + lodash.keysIn = keysIn; + lodash.map = map; + lodash.mapKeys = mapKeys; + lodash.mapValues = mapValues; + lodash.matches = matches; + lodash.matchesProperty = matchesProperty; + lodash.memoize = memoize; + lodash.merge = merge; + lodash.method = method; + lodash.methodOf = methodOf; + lodash.mixin = mixin; + lodash.modArgs = modArgs; + lodash.negate = negate; + lodash.omit = omit; + lodash.once = once; + lodash.pairs = pairs; + lodash.partial = partial; + lodash.partialRight = partialRight; + lodash.partition = partition; + lodash.pick = pick; + lodash.pluck = pluck; + lodash.property = property; + lodash.propertyOf = propertyOf; + lodash.pull = pull; + lodash.pullAt = pullAt; + lodash.range = range; + lodash.rearg = rearg; + lodash.reject = reject; + lodash.remove = remove; + lodash.rest = rest; + lodash.restParam = restParam; + lodash.set = set; + lodash.shuffle = shuffle; + lodash.slice = slice; + lodash.sortBy = sortBy; + lodash.sortByAll = sortByAll; + lodash.sortByOrder = sortByOrder; + lodash.spread = spread; + lodash.take = take; + lodash.takeRight = takeRight; + lodash.takeRightWhile = takeRightWhile; + lodash.takeWhile = takeWhile; + lodash.tap = tap; + lodash.throttle = throttle; + lodash.thru = thru; + lodash.times = times; + lodash.toArray = toArray; + lodash.toPlainObject = toPlainObject; + lodash.transform = transform; + lodash.union = union; + lodash.uniq = uniq; + lodash.unzip = unzip; + lodash.unzipWith = unzipWith; + lodash.values = values; + lodash.valuesIn = valuesIn; + lodash.where = where; + lodash.without = without; + lodash.wrap = wrap; + lodash.xor = xor; + lodash.zip = zip; + lodash.zipObject = zipObject; + lodash.zipWith = zipWith; + lodash.backflow = flowRight; + lodash.collect = map; + lodash.compose = flowRight; + lodash.each = forEach; + lodash.eachRight = forEachRight; + lodash.extend = assign; + lodash.iteratee = callback; + lodash.methods = functions; + lodash.object = zipObject; + lodash.select = filter; + lodash.tail = rest; + lodash.unique = uniq; + mixin(lodash, lodash); + lodash.add = add; + lodash.attempt = attempt; + lodash.camelCase = camelCase; + lodash.capitalize = capitalize; + lodash.ceil = ceil; + lodash.clone = clone; + lodash.cloneDeep = cloneDeep; + lodash.deburr = deburr; + lodash.endsWith = endsWith; + lodash.escape = escape; + lodash.escapeRegExp = escapeRegExp; + lodash.every = every; + lodash.find = find; + lodash.findIndex = findIndex; + lodash.findKey = findKey; + lodash.findLast = findLast; + lodash.findLastIndex = findLastIndex; + lodash.findLastKey = findLastKey; + lodash.findWhere = findWhere; + lodash.first = first; + lodash.floor = floor; + lodash.get = get; + lodash.gt = gt; + lodash.gte = gte; + lodash.has = has; + lodash.identity = identity; + lodash.includes = includes; + lodash.indexOf = indexOf; + lodash.inRange = inRange; + lodash.isArguments = isArguments; + lodash.isArray = isArray; + lodash.isBoolean = isBoolean; + lodash.isDate = isDate; + lodash.isElement = isElement; + lodash.isEmpty = isEmpty; + lodash.isEqual = isEqual; + lodash.isError = isError; + lodash.isFinite = isFinite; + lodash.isFunction = isFunction; + lodash.isMatch = isMatch; + lodash.isNaN = isNaN; + lodash.isNative = isNative; + lodash.isNull = isNull; + lodash.isNumber = isNumber; + lodash.isObject = isObject; + lodash.isPlainObject = isPlainObject; + lodash.isRegExp = isRegExp; + lodash.isString = isString; + lodash.isTypedArray = isTypedArray; + lodash.isUndefined = isUndefined; + lodash.kebabCase = kebabCase; + lodash.last = last; + lodash.lastIndexOf = lastIndexOf; + lodash.lt = lt; + lodash.lte = lte; + lodash.max = max; + lodash.min = min; + lodash.noConflict = noConflict; + lodash.noop = noop; + lodash.now = now; + lodash.pad = pad; + lodash.padLeft = padLeft; + lodash.padRight = padRight; + lodash.parseInt = parseInt; + lodash.random = random; + lodash.reduce = reduce; + lodash.reduceRight = reduceRight; + lodash.repeat = repeat; + lodash.result = result; + lodash.round = round; + lodash.runInContext = runInContext; + lodash.size = size; + lodash.snakeCase = snakeCase; + lodash.some = some; + lodash.sortedIndex = sortedIndex; + lodash.sortedLastIndex = sortedLastIndex; + lodash.startCase = startCase; + lodash.startsWith = startsWith; + lodash.sum = sum; + lodash.template = template; + lodash.trim = trim; + lodash.trimLeft = trimLeft; + lodash.trimRight = trimRight; + lodash.trunc = trunc; + lodash.unescape = unescape; + lodash.uniqueId = uniqueId; + lodash.words = words; + lodash.all = every; + lodash.any = some; + lodash.contains = includes; + lodash.eq = isEqual; + lodash.detect = find; + lodash.foldl = reduce; + lodash.foldr = reduceRight; + lodash.head = first; + lodash.include = includes; + lodash.inject = reduce; + mixin(lodash, function() { + var source = {}; + baseForOwn(lodash, function(func, methodName) { + if (!lodash.prototype[methodName]) { + source[methodName] = func; + } + }); + return source; + }(), false); + lodash.sample = sample; + lodash.prototype.sample = function(n) { + if (!this.__chain__ && n == null) { + return sample(this.value()); + } + return this.thru(function(value) { + return sample(value, n); + }); + }; + lodash.VERSION = VERSION; + arrayEach([ "bind", "bindKey", "curry", "curryRight", "partial", "partialRight" ], function(methodName) { + lodash[methodName].placeholder = lodash; + }); + arrayEach([ "drop", "take" ], function(methodName, index) { + LazyWrapper.prototype[methodName] = function(n) { + var filtered = this.__filtered__; + if (filtered && !index) { + return new LazyWrapper(this); + } + n = n == null ? 1 : nativeMax(nativeFloor(n) || 0, 0); + var result = this.clone(); + if (filtered) { + result.__takeCount__ = nativeMin(result.__takeCount__, n); + } else { + result.__views__.push({ + size: n, + type: methodName + (result.__dir__ < 0 ? "Right" : "") + }); + } + return result; + }; + LazyWrapper.prototype[methodName + "Right"] = function(n) { + return this.reverse()[methodName](n).reverse(); + }; + }); + arrayEach([ "filter", "map", "takeWhile" ], function(methodName, index) { + var type = index + 1, isFilter = type != LAZY_MAP_FLAG; + LazyWrapper.prototype[methodName] = function(iteratee, thisArg) { + var result = this.clone(); + result.__iteratees__.push({ + iteratee: getCallback(iteratee, thisArg, 1), + type: type + }); + result.__filtered__ = result.__filtered__ || isFilter; + return result; + }; + }); + arrayEach([ "first", "last" ], function(methodName, index) { + var takeName = "take" + (index ? "Right" : ""); + LazyWrapper.prototype[methodName] = function() { + return this[takeName](1).value()[0]; + }; + }); + arrayEach([ "initial", "rest" ], function(methodName, index) { + var dropName = "drop" + (index ? "" : "Right"); + LazyWrapper.prototype[methodName] = function() { + return this.__filtered__ ? new LazyWrapper(this) : this[dropName](1); + }; + }); + arrayEach([ "pluck", "where" ], function(methodName, index) { + var operationName = index ? "filter" : "map", createCallback = index ? baseMatches : property; + LazyWrapper.prototype[methodName] = function(value) { + return this[operationName](createCallback(value)); + }; + }); + LazyWrapper.prototype.compact = function() { + return this.filter(identity); + }; + LazyWrapper.prototype.reject = function(predicate, thisArg) { + predicate = getCallback(predicate, thisArg, 1); + return this.filter(function(value) { + return !predicate(value); + }); + }; + LazyWrapper.prototype.slice = function(start, end) { + start = start == null ? 0 : +start || 0; + var result = this; + if (result.__filtered__ && (start > 0 || end < 0)) { + return new LazyWrapper(result); + } + if (start < 0) { + result = result.takeRight(-start); + } else if (start) { + result = result.drop(start); + } + if (end !== undefined) { + end = +end || 0; + result = end < 0 ? result.dropRight(-end) : result.take(end - start); + } + return result; + }; + LazyWrapper.prototype.takeRightWhile = function(predicate, thisArg) { + return this.reverse().takeWhile(predicate, thisArg).reverse(); + }; + LazyWrapper.prototype.toArray = function() { + return this.take(POSITIVE_INFINITY); + }; + baseForOwn(LazyWrapper.prototype, function(func, methodName) { + var checkIteratee = /^(?:filter|map|reject)|While$/.test(methodName), retUnwrapped = /^(?:first|last)$/.test(methodName), lodashFunc = lodash[retUnwrapped ? "take" + (methodName == "last" ? "Right" : "") : methodName]; + if (!lodashFunc) { + return; + } + lodash.prototype[methodName] = function() { + var args = retUnwrapped ? [ 1 ] : arguments, chainAll = this.__chain__, value = this.__wrapped__, isHybrid = !!this.__actions__.length, isLazy = value instanceof LazyWrapper, iteratee = args[0], useLazy = isLazy || isArray(value); + if (useLazy && checkIteratee && typeof iteratee == "function" && iteratee.length != 1) { + isLazy = useLazy = false; + } + var interceptor = function(value) { + return retUnwrapped && chainAll ? lodashFunc(value, 1)[0] : lodashFunc.apply(undefined, arrayPush([ value ], args)); + }; + var action = { + func: thru, + args: [ interceptor ], + thisArg: undefined + }, onlyLazy = isLazy && !isHybrid; + if (retUnwrapped && !chainAll) { + if (onlyLazy) { + value = value.clone(); + value.__actions__.push(action); + return func.call(value); + } + return lodashFunc.call(undefined, this.value())[0]; + } + if (!retUnwrapped && useLazy) { + value = onlyLazy ? value : new LazyWrapper(this); + var result = func.apply(value, args); + result.__actions__.push(action); + return new LodashWrapper(result, chainAll); + } + return this.thru(interceptor); + }; + }); + arrayEach([ "join", "pop", "push", "replace", "shift", "sort", "splice", "split", "unshift" ], function(methodName) { + var func = (/^(?:replace|split)$/.test(methodName) ? stringProto : arrayProto)[methodName], chainName = /^(?:push|sort|unshift)$/.test(methodName) ? "tap" : "thru", retUnwrapped = /^(?:join|pop|replace|shift)$/.test(methodName); + lodash.prototype[methodName] = function() { + var args = arguments; + if (retUnwrapped && !this.__chain__) { + return func.apply(this.value(), args); + } + return this[chainName](function(value) { + return func.apply(value, args); + }); + }; + }); + baseForOwn(LazyWrapper.prototype, function(func, methodName) { + var lodashFunc = lodash[methodName]; + if (lodashFunc) { + var key = lodashFunc.name + "", names = realNames[key] || (realNames[key] = []); + names.push({ + name: methodName, + func: lodashFunc + }); + } + }); + realNames[createHybridWrapper(undefined, BIND_KEY_FLAG).name] = [ { + name: "wrapper", + func: undefined + } ]; + LazyWrapper.prototype.clone = lazyClone; + LazyWrapper.prototype.reverse = lazyReverse; + LazyWrapper.prototype.value = lazyValue; + lodash.prototype.chain = wrapperChain; + lodash.prototype.commit = wrapperCommit; + lodash.prototype.concat = wrapperConcat; + lodash.prototype.plant = wrapperPlant; + lodash.prototype.reverse = wrapperReverse; + lodash.prototype.toString = wrapperToString; + lodash.prototype.run = lodash.prototype.toJSON = lodash.prototype.valueOf = lodash.prototype.value = wrapperValue; + lodash.prototype.collect = lodash.prototype.map; + lodash.prototype.head = lodash.prototype.first; + lodash.prototype.select = lodash.prototype.filter; + lodash.prototype.tail = lodash.prototype.rest; + return lodash; + } + var _ = runInContext(); + if (typeof define == "function" && typeof define.amd == "object" && define.amd) { + root._ = _; + define(function() { + return _; + }); + } else if (freeExports && freeModule) { + if (moduleExports) { + (freeModule.exports = _)._ = _; + } else { + freeExports._ = _; + } + } else { + root._ = _; + } +}).call(this); + (function(window, document, undefined) { "use strict"; function minErr(module, ErrorConstructor) { @@ -5391,7 +9332,7 @@ } return match; }); - message += "\nhttp://errors.angularjs.org/1.4.6/" + (module ? module + "/" : "") + code; + message += "\nhttp://errors.angularjs.org/1.4.7/" + (module ? module + "/" : "") + code; for (i = SKIP_INDEXES, paramPrefix = "?"; i < templateArgs.length; i++, paramPrefix = "&") { message += paramPrefix + "p" + (i - SKIP_INDEXES) + "=" + encodeURIComponent(toDebugString(templateArgs[i])); } @@ -6210,11 +10151,11 @@ return obj; } var version = { - full: "1.4.6", + full: "1.4.7", major: 1, minor: 4, - dot: 6, - codeName: "multiplicative-elevation" + dot: 7, + codeName: "dark-luminescence" }; function publishExternalAPI(angular) { extend(angular, { @@ -6323,6 +10264,7 @@ $httpParamSerializer: $HttpParamSerializerProvider, $httpParamSerializerJQLike: $HttpParamSerializerJQLikeProvider, $httpBackend: $HttpBackendProvider, + $xhrFactory: $xhrFactoryProvider, $location: $LocationProvider, $log: $LogProvider, $parse: $ParseProvider, @@ -6368,10 +10310,10 @@ return offset ? letter.toUpperCase() : letter; }).replace(MOZ_HACK_REGEXP, "Moz$1"); } - var SINGLE_TAG_REGEXP = /^<(\w+)\s*\/?>(?:<\/\1>|)$/; + var SINGLE_TAG_REGEXP = /^<([\w-]+)\s*\/?>(?:<\/\1>|)$/; var HTML_REGEXP = /<|&#?\w+;/; - var TAG_NAME_REGEXP = /<([\w:]+)/; - var XHTML_TAG_REGEXP = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi; + var TAG_NAME_REGEXP = /<([\w:-]+)/; + var XHTML_TAG_REGEXP = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:-]+)[^>]*)\/>/gi; var wrapMap = { option: [ 1, '" ], thead: [ 1, "", "
                      " ], @@ -7614,6 +11556,9 @@ } }; return function(element, options) { + if (options.cleanupStyles) { + options.from = options.to = null; + } if (options.from) { element.css(options.from); options.from = null; @@ -8879,7 +12824,7 @@ compile: function() { return { pre: function attrInterpolatePreLinkFn(scope, element, attr) { - var $$observers = attr.$$observers || (attr.$$observers = {}); + var $$observers = attr.$$observers || (attr.$$observers = createMap()); if (EVENT_HANDLER_ATTR_REGEXP.test(name)) { throw $compileMinErr("nodomevents", "Interpolations for HTML DOM event attributes are disallowed. Please use the " + "ng- versions (such as ng-click instead of onclick) instead."); } @@ -9542,12 +13487,16 @@ } } ]; } - function createXhr() { - return new window.XMLHttpRequest(); + function $xhrFactoryProvider() { + this.$get = function() { + return function createXhr() { + return new window.XMLHttpRequest(); + }; + }; } function $HttpBackendProvider() { - this.$get = [ "$browser", "$window", "$document", function($browser, $window, $document) { - return createHttpBackend($browser, createXhr, $browser.defer, $window.angular.callbacks, $document[0]); + this.$get = [ "$browser", "$window", "$document", "$xhrFactory", function($browser, $window, $document, $xhrFactory) { + return createHttpBackend($browser, $xhrFactory, $browser.defer, $window.angular.callbacks, $document[0]); } ]; } function createHttpBackend($browser, createXhr, $browserDefer, callbacks, rawDocument) { @@ -9565,7 +13514,7 @@ callbacks[callbackId] = noop; }); } else { - var xhr = createXhr(); + var xhr = createXhr(method, url); xhr.open(method, url, true); forEach(headers, function(value, key) { if (isDefined(value)) { @@ -10273,12 +14222,18 @@ } var $parseMinErr = minErr("$parse"); function ensureSafeMemberName(name, fullExpression) { - name = isObject(name) && name.toString ? name.toString() : name; if (name === "__defineGetter__" || name === "__defineSetter__" || name === "__lookupGetter__" || name === "__lookupSetter__" || name === "__proto__") { throw $parseMinErr("isecfld", "Attempting to access a disallowed field in Angular expressions! " + "Expression: {0}", fullExpression); } return name; } + function getStringValue(name, fullExpression) { + name = name + ""; + if (!isString(name)) { + throw $parseMinErr("iseccst", "Cannot convert object to primitive value! " + "Expression: {0}", fullExpression); + } + return name; + } function ensureSafeObject(obj, fullExpression) { if (obj) { if (obj.constructor === obj) { @@ -10305,6 +14260,13 @@ } } } + function ensureSafeAssignContext(obj, fullExpression) { + if (obj) { + if (obj === 0..constructor || obj === false.constructor || obj === "".constructor || obj === {}.constructor || obj === [].constructor || obj === Function.constructor) { + throw $parseMinErr("isecaf", "Assigning to a constructor is disallowed! Expression: {0}", fullExpression); + } + } + } var OPERATORS = createMap(); forEach("+ - * / % === !== == != < > <= >= && || ! = |".split(" "), function(operator) { OPERATORS[operator] = true; @@ -11053,7 +15015,7 @@ this.stage = "main"; this.recurse(ast); var fnString = '"' + this.USE + " " + this.STRICT + '";\n' + this.filterPrefix() + "var fn=" + this.generateFunction("fn", "s,l,a,i") + extra + this.watchFns() + "return fn;"; - var fn = new Function("$filter", "ensureSafeMemberName", "ensureSafeObject", "ensureSafeFunction", "ifDefined", "plus", "text", fnString)(this.$filter, ensureSafeMemberName, ensureSafeObject, ensureSafeFunction, ifDefined, plusFn, expression); + var fn = new Function("$filter", "ensureSafeMemberName", "ensureSafeObject", "ensureSafeFunction", "getStringValue", "ensureSafeAssignContext", "ifDefined", "plus", "text", fnString)(this.$filter, ensureSafeMemberName, ensureSafeObject, ensureSafeFunction, getStringValue, ensureSafeAssignContext, ifDefined, plusFn, expression); this.state = this.stage = undefined; fn.literal = isLiteral(ast); fn.constant = isConstant(ast); @@ -11190,6 +15152,7 @@ if (ast.computed) { right = self.nextId(); self.recurse(ast.property, right); + self.getStringValue(right); self.addEnsureSafeMemberName(right); if (create && create !== 1) { self.if_(self.not(self.computedMember(left, right)), self.lazyAssign(self.computedMember(left, right), "{}")); @@ -11275,6 +15238,7 @@ self.if_(self.notNull(left.context), function() { self.recurse(ast.right, right); self.addEnsureSafeObject(self.member(left.context, left.name, left.computed)); + self.addEnsureSafeAssignContext(left.context); expression = self.member(left.context, left.name, left.computed) + ast.operator + right; self.assign(intoId, expression); recursionFn(intoId || expression); @@ -11385,6 +15349,9 @@ addEnsureSafeFunction: function(item) { this.current().body.push(this.ensureSafeFunction(item), ";"); }, + addEnsureSafeAssignContext: function(item) { + this.current().body.push(this.ensureSafeAssignContext(item), ";"); + }, ensureSafeObject: function(item) { return "ensureSafeObject(" + item + ",text)"; }, @@ -11394,6 +15361,12 @@ ensureSafeFunction: function(item) { return "ensureSafeFunction(" + item + ",text)"; }, + getStringValue: function(item) { + this.assign(item, "getStringValue(" + item + ",text)"); + }, + ensureSafeAssignContext: function(item) { + return "ensureSafeAssignContext(" + item + ",text)"; + }, lazyRecurse: function(ast, intoId, nameId, recursionFn, create, skipWatchIdCheck) { var self = this; return function() { @@ -11561,6 +15534,7 @@ var lhs = left(scope, locals, assign, inputs); var rhs = right(scope, locals, assign, inputs); ensureSafeObject(lhs.value, self.expression); + ensureSafeAssignContext(lhs.context); lhs.context[lhs.name] = rhs; return context ? { value: rhs @@ -11818,6 +15792,7 @@ var value; if (lhs != null) { rhs = right(scope, locals, assign, inputs); + rhs = getStringValue(rhs); ensureSafeMemberName(rhs, expression); if (create && create !== 1 && lhs && !lhs[rhs]) { lhs[rhs] = {}; @@ -13500,6 +17475,7 @@ if (fractionSize > 0 && number < 1) { formatedText = number.toFixed(fractionSize); number = parseFloat(formatedText); + formatedText = formatedText.replace(DECIMAL_SEP, decimalSep); } } if (number === 0) { @@ -15517,11 +19493,11 @@ function updateOptionElement(option, element) { option.element = element; element.disabled = option.disabled; - if (option.value !== element.value) element.value = option.selectValue; if (option.label !== element.label) { element.label = option.label; element.textContent = option.label; } + if (option.value !== element.value) element.value = option.selectValue; } function addOrReuseElement(parent, current, type, templateElement) { var element; @@ -15549,7 +19525,7 @@ var emptyOption_ = emptyOption && emptyOption[0]; var unknownOption_ = unknownOption && unknownOption[0]; if (emptyOption_ || unknownOption_) { - while (current && (current === emptyOption_ || current === unknownOption_)) { + while (current && (current === emptyOption_ || current === unknownOption_ || emptyOption_ && emptyOption_.nodeType === NODE_TYPE_COMMENT)) { current = current.nextSibling; } } @@ -26949,6 +30925,284 @@ WaveSurfer.util.extend(WaveSurfer.Drawer.Canvas, { "use strict"; +WaveSurfer.Regions = { + init: function(a) { + this.wavesurfer = a, this.wrapper = this.wavesurfer.drawer.wrapper, this.list = {}; + }, + add: function(a) { + var b = Object.create(WaveSurfer.Region); + return b.init(a, this.wavesurfer), this.list[b.id] = b, b.on("remove", function() { + delete this.list[b.id]; + }.bind(this)), b; + }, + clear: function() { + Object.keys(this.list).forEach(function(a) { + this.list[a].remove(); + }, this); + }, + enableDragSelection: function(a) { + var b, c, d, e = this; + this.wrapper.addEventListener("mousedown", function(a) { + b = !0, c = e.wavesurfer.drawer.handleEvent(a), d = null; + }), this.wrapper.addEventListener("mouseup", function(a) { + b = !1, d && (d.fireEvent("update-end", a), e.wavesurfer.fireEvent("region-update-end", d, a)), + d = null; + }), this.wrapper.addEventListener("mousemove", function(f) { + if (b) { + d || (d = e.add(a || {})); + var g = e.wavesurfer.getDuration(), h = e.wavesurfer.drawer.handleEvent(f); + d.update({ + start: Math.min(h * g, c * g), + end: Math.max(h * g, c * g) + }); + } + }); + } +}, WaveSurfer.Region = { + style: WaveSurfer.Drawer.style, + init: function(a, b) { + this.wavesurfer = b, this.wrapper = b.drawer.wrapper, this.id = null == a.id ? WaveSurfer.util.getId() : a.id, + this.start = Number(a.start) || 0, this.end = null == a.end ? this.start + 4 / this.wrapper.scrollWidth * this.wavesurfer.getDuration() : Number(a.end), + this.resize = void 0 === a.resize ? !0 : Boolean(a.resize), this.drag = void 0 === a.drag ? !0 : Boolean(a.drag), + this.loop = Boolean(a.loop), this.color = a.color || "rgba(0, 0, 0, 0.1)", this.data = a.data || {}, + this.maxLength = a.maxLength, this.minLength = a.minLength, this.bindInOut(), this.render(), + this.wavesurfer.fireEvent("region-created", this); + }, + update: function(a) { + null != a.start && (this.start = Number(a.start)), null != a.end && (this.end = Number(a.end)), + null != a.loop && (this.loop = Boolean(a.loop)), null != a.color && (this.color = a.color), + null != a.data && (this.data = a.data), null != a.resize && (this.resize = Boolean(a.resize)), + null != a.drag && (this.drag = Boolean(a.drag)), null != a.maxLength && (this.maxLength = Number(a.maxLength)), + null != a.minLength && (this.minLength = Number(a.minLength)), this.updateRender(), + this.fireEvent("update"), this.wavesurfer.fireEvent("region-updated", this); + }, + remove: function(a) { + this.element && (this.wrapper.removeChild(this.element), this.element = null, this.fireEvent("remove"), + this.wavesurfer.fireEvent("region-removed", this)); + }, + play: function() { + this.wavesurfer.play(this.start, this.end), this.fireEvent("play"), this.wavesurfer.fireEvent("region-play", this); + }, + playLoop: function() { + this.play(), this.once("out", this.playLoop.bind(this)); + }, + render: function() { + var a = document.createElement("region"); + a.className = "wavesurfer-region", a.title = this.formatTime(this.start, this.end), + a.setAttribute("data-id", this.id); + this.wrapper.scrollWidth; + if (this.style(a, { + position: "absolute", + zIndex: 2, + height: "100%", + top: "0px" + }), this.resize) { + var b = a.appendChild(document.createElement("handle")), c = a.appendChild(document.createElement("handle")); + b.className = "wavesurfer-handle wavesurfer-handle-start", c.className = "wavesurfer-handle wavesurfer-handle-end"; + var d = { + cursor: "col-resize", + position: "absolute", + left: "0px", + top: "0px", + width: "1%", + maxWidth: "4px", + height: "100%" + }; + this.style(b, d), this.style(c, d), this.style(c, { + left: "100%" + }); + } + this.element = this.wrapper.appendChild(a), this.updateRender(), this.bindEvents(a); + }, + formatTime: function(a, b) { + return (a == b ? [ a ] : [ a, b ]).map(function(a) { + return [ Math.floor(a % 3600 / 60), ("00" + Math.floor(a % 60)).slice(-2) ].join(":"); + }).join("–"); + }, + updateRender: function() { + var a = this.wavesurfer.getDuration(), b = this.wrapper.scrollWidth; + this.start < 0 && (this.start = 0, this.end = this.end - this.start), this.end > a && (this.end = a, + this.start = a - (this.end - this.start)), null != this.minLength && (this.end = Math.max(this.start + this.minLength, this.end)), + null != this.maxLength && (this.end = Math.min(this.start + this.maxLength, this.end)), + this.style(this.element, { + left: ~~(this.start / a * b) + "px", + width: ~~((this.end - this.start) / a * b) + "px", + backgroundColor: this.color, + cursor: this.drag ? "move" : "default" + }), this.element.title = this.formatTime(this.start, this.end); + }, + bindInOut: function() { + var a = this, b = function() { + a.firedIn = !1, a.firedOut = !1; + }, c = function(b) { + !a.firedIn && a.start <= b && a.end > b && (a.firedIn = !0, a.fireEvent("in"), a.wavesurfer.fireEvent("region-in", a)), + !a.firedOut && a.firedIn && a.end <= Math.round(100 * b) / 100 && (a.firedOut = !0, + a.fireEvent("out"), a.wavesurfer.fireEvent("region-out", a)); + }; + this.wavesurfer.on("play", b), this.wavesurfer.backend.on("audioprocess", c), this.on("remove", function() { + a.wavesurfer.un("play", b), a.wavesurfer.backend.un("audioprocess", c); + }), this.on("out", function() { + a.loop && a.wavesurfer.play(a.start); + }); + }, + bindEvents: function() { + var a = this; + this.element.addEventListener("mouseenter", function(b) { + a.fireEvent("mouseenter", b), a.wavesurfer.fireEvent("region-mouseenter", a, b); + }), this.element.addEventListener("mouseleave", function(b) { + a.fireEvent("mouseleave", b), a.wavesurfer.fireEvent("region-mouseleave", a, b); + }), this.element.addEventListener("click", function(b) { + b.preventDefault(), a.fireEvent("click", b), a.wavesurfer.fireEvent("region-click", a, b); + }), this.element.addEventListener("dblclick", function(b) { + b.stopPropagation(), b.preventDefault(), a.fireEvent("dblclick", b), a.wavesurfer.fireEvent("region-dblclick", a, b); + }), (this.drag || this.resize) && function() { + var b, c, d, e = a.wavesurfer.getDuration(), f = function(f) { + f.stopPropagation(), d = a.wavesurfer.drawer.handleEvent(f) * e, "handle" == f.target.tagName.toLowerCase() ? c = f.target.classList.contains("wavesurfer-handle-start") ? "start" : "end" : b = !0; + }, g = function(d) { + (b || c) && (b = !1, c = !1, d.stopPropagation(), d.preventDefault(), a.fireEvent("update-end", d), + a.wavesurfer.fireEvent("region-update-end", a, d)); + }, h = function(f) { + if (b || c) { + var g = a.wavesurfer.drawer.handleEvent(f) * e, h = g - d; + d = g, a.drag && b && a.onDrag(h), a.resize && c && a.onResize(h, c); + } + }; + a.element.addEventListener("mousedown", f), a.wrapper.addEventListener("mousemove", h), + document.body.addEventListener("mouseup", g), a.on("remove", function() { + document.body.removeEventListener("mouseup", g), a.wrapper.removeEventListener("mousemove", h); + }), a.wavesurfer.on("destroy", function() { + document.body.removeEventListener("mouseup", g); + }); + }(); + }, + onDrag: function(a) { + this.update({ + start: this.start + a, + end: this.end + a + }); + }, + onResize: function(a, b) { + "start" == b ? this.update({ + start: Math.min(this.start + a, this.end), + end: Math.max(this.start + a, this.end) + }) : this.update({ + start: Math.min(this.end + a, this.start), + end: Math.max(this.end + a, this.start) + }); + } +}, WaveSurfer.util.extend(WaveSurfer.Region, WaveSurfer.Observer), WaveSurfer.initRegions = function() { + this.regions || (this.regions = Object.create(WaveSurfer.Regions), this.regions.init(this)); +}, WaveSurfer.addRegion = function(a) { + return this.initRegions(), this.regions.add(a); +}, WaveSurfer.clearRegions = function() { + this.regions && this.regions.clear(); +}, WaveSurfer.enableDragSelection = function(a) { + this.initRegions(), this.regions.enableDragSelection(a); +}; + +"use strict"; + +WaveSurfer.Spectrogram = { + init: function(a) { + this.params = a; + var b = this.wavesurfer = a.wavesurfer; + if (!this.wavesurfer) throw Error("No WaveSurfer instance provided"); + this.frequenciesDataUrl = a.frequenciesDataUrl; + var c = this.drawer = this.wavesurfer.drawer; + if (this.buffer = this.wavesurfer.backend.buffer, this.container = "string" == typeof a.container ? document.querySelector(a.container) : a.container, + !this.container) throw Error("No container for WaveSurfer spectrogram"); + this.width = c.width, this.pixelRatio = this.params.pixelRatio || b.params.pixelRatio, + this.fftSamples = this.params.fftSamples || b.params.fftSamples || 512, this.height = this.fftSamples / 2, + this.createWrapper(), this.createCanvas(), this.render(), b.drawer.wrapper.onscroll = this.updateScroll.bind(this), + b.on("destroy", this.destroy.bind(this)); + }, + destroy: function() { + this.unAll(), this.wrapper && (this.wrapper.parentNode.removeChild(this.wrapper), + this.wrapper = null); + }, + createWrapper: function() { + var a = this.container.querySelector("spectrogram"); + a && this.container.removeChild(a); + var b = this.wavesurfer.params; + this.wrapper = this.container.appendChild(document.createElement("spectrogram")), + this.drawer.style(this.wrapper, { + display: "block", + position: "relative", + userSelect: "none", + webkitUserSelect: "none", + height: this.height + "px" + }), (b.fillParent || b.scrollParent) && this.drawer.style(this.wrapper, { + width: "100%", + overflowX: "hidden", + overflowY: "hidden" + }); + var c = this; + this.wrapper.addEventListener("click", function(a) { + a.preventDefault(); + var b = "offsetX" in a ? a.offsetX : a.layerX; + c.fireEvent("click", b / c.scrollWidth || 0); + }); + }, + createCanvas: function() { + var a = this.canvas = this.wrapper.appendChild(document.createElement("canvas")); + this.spectrCc = a.getContext("2d"), this.wavesurfer.drawer.style(a, { + position: "absolute", + zIndex: 4 + }); + }, + render: function() { + this.updateCanvasStyle(), this.frequenciesDataUrl ? this.loadFrequenciesData(this.frequenciesDataUrl) : this.getFrequencies(this.drawSpectrogram); + }, + updateCanvasStyle: function() { + var a = Math.round(this.width / this.pixelRatio) + "px"; + this.canvas.width = this.width, this.canvas.height = this.height, this.canvas.style.width = a; + }, + drawSpectrogram: function(a, b) { + for (var c = (b.spectrCc, b.wavesurfer.backend.getDuration(), b.height), d = b.resample(a), e = 2 / b.buffer.numberOfChannels, f = 0; f < d.length; f++) for (var g = 0; g < d[f].length; g++) { + var h = 255 - d[f][g]; + b.spectrCc.fillStyle = "rgb(" + h + ", " + h + ", " + h + ")", b.spectrCc.fillRect(f, c - g * e, 1, 1 * e); + } + }, + getFrequencies: function(a) { + var b = this.fftSamples, c = this.buffer, d = [], e = new window.OfflineAudioContext(1, c.length, c.sampleRate), f = e.createBufferSource(), g = e.createScriptProcessor(0, 1, 1), h = e.createAnalyser(); + h.fftSize = b, h.smoothingTimeConstant = this.width / c.duration < 10 ? .75 : .25, + f.buffer = c, f.connect(h), h.connect(g), g.connect(e.destination), g.onaudioprocess = function() { + var a = new Uint8Array(h.frequencyBinCount); + h.getByteFrequencyData(a), d.push(a); + }, f.start(0), e.startRendering(); + var i = this; + e.oncomplete = function() { + a(d, i); + }; + }, + loadFrequenciesData: function(a) { + var b = this, c = WaveSurfer.util.ajax({ + url: a + }); + return c.on("success", function(a) { + b.drawSpectrogram(JSON.parse(a), b); + }), c.on("error", function(a) { + b.fireEvent("error", "XHR error: " + a.target.statusText); + }), c; + }, + updateScroll: function(a) { + this.wrapper.scrollLeft = a.target.scrollLeft; + }, + resample: function(a, b) { + for (var b = this.width, c = [], d = 1 / a.length, e = 1 / b, f = 0; b > f; f++) { + for (var g = new Array(a[0].length), h = 0; h < a.length; h++) { + var i = h * d, j = i + d, k = f * e, l = k + e, m = k >= j || i >= l ? 0 : Math.min(Math.max(j, k), Math.max(l, i)) - Math.max(Math.min(j, k), Math.min(l, i)); + if (m > 0) for (var n = 0; n < a[0].length; n++) null == g[n] && (g[n] = 0), g[n] += m / e * a[h][n]; + } + for (var o = new Uint8Array(a[0].length), n = 0; n < a[0].length; n++) o[n] = g[n]; + c.push(o); + } + return c; + } +}, WaveSurfer.util.extend(WaveSurfer.Spectrogram, WaveSurfer.Observer); + +"use strict"; + var model = {}; model.Value = function() { @@ -27120,8 +31374,10 @@ var elan = function() { var header = xml.querySelector("HEADER"); var inMilliseconds = header.getAttribute("TIME_UNITS") == "milliseconds"; var media = header.querySelector("MEDIA_DESCRIPTOR"); - this.mediaUrl = media.getAttribute("MEDIA_URL"); - this.mediaType = media.getAttribute("MIME_TYPE"); + if (media) { + this.mediaUrl = media.getAttribute("MEDIA_URL"); + this.mediaType = media.getAttribute("MIME_TYPE"); + } var properties = xml.querySelectorAll("PROPERTY"); _forEach.call(properties, function(prop) { var name = prop.getAttribute("NAME"); @@ -27301,6 +31557,12 @@ var cloneObject = function(oldObject) { return JSON.parse(JSON.stringify(oldObject)); }; +var enableControls = function(controls, enabled) { + _.each(controls, function(value, key) { + controls[key] = enabled; + }); +}; + var lingvodoc = {}; lingvodoc.Object = function(clientId, objectId) { @@ -27308,10 +31570,7 @@ lingvodoc.Object = function(clientId, objectId) { this.object_id = objectId; this.type = "abstract"; this.getId = function() { - return this.client_id + "" + this.object_id; - }; - this.export = function() { - return {}; + return this.client_id + "_" + this.object_id; }; }; @@ -27372,13 +31631,33 @@ lingvodoc.Perspective = function(client_id, object_id, parent_client_id, parent_ this.is_template = is_template; this.marked_for_deletion = marked_for_deletion; this.fields = []; + this.location = null; + this.blobs = []; + this.additional_metadata = {}; this.equals = function(obj) { return lingvodoc.Object.prototype.equals.call(this, obj) && this.translation == obj.translation; }; }; lingvodoc.Perspective.fromJS = function(js) { - return new lingvodoc.Perspective(js.client_id, js.object_id, js.parent_client_id, js.parent_object_id, js.translation, js.translation_string, js.status, js.is_template, js.marked_for_deletion); + var perspective = new lingvodoc.Perspective(js.client_id, js.object_id, js.parent_client_id, js.parent_object_id, js.translation, js.translation_string, js.status, js.is_template, js.marked_for_deletion); + if (_.has(js, "location") && _.has(js.location, "content")) { + perspective["location"] = { + lat: js.location.content.lat, + lng: js.location.content.lng + }; + } + if (_.has(js, "info") && js.info.type == "list") { + if (_.isArray(js.info.content)) { + perspective["blobs"] = _.map(js.info.content, function(e) { + var blob = new lingvodoc.Blob(e.info.content.client_id, e.info.content.object_id, e.info.content.name, e.info.content.data_type); + blob.url = e.info.content.content; + return blob; + }); + } + } + perspective.additional_metadata = js.additional_metadata; + return perspective; }; lingvodoc.Perspective.prototype = new lingvodoc.Object(); @@ -27403,6 +31682,25 @@ lingvodoc.User.fromJS = function(js) { return new lingvodoc.User(js.id, js.login, js.name, js.email, js.intl_name, js.about, js.signup_date, js.organizations); }; +lingvodoc.Blob = function(clientId, objectId, name, data_type) { + lingvodoc.Object.call(this, clientId, objectId); + this.type = "blob"; + this.name = name; + this.data_type = data_type; + this.url = null; + this.equals = function(obj) { + return lingvodoc.Object.prototype.equals.call(this, obj) && this.name == obj.name; + }; +}; + +lingvodoc.Blob.fromJS = function(js) { + return new lingvodoc.Blob(js.client_id, js.object_id, js.name, js.data_type); +}; + +lingvodoc.Blob.prototype = new lingvodoc.Object(); + +lingvodoc.Blob.prototype.constructor = lingvodoc.Blob; + function lingvodocAPI($http, $q) { var addUrlParameter = function(url, key, value) { return url + (url.indexOf("?") >= 0 ? "&" : "?") + encodeURIComponent(key) + "=" + encodeURIComponent(value); @@ -27476,6 +31774,21 @@ function lingvodocAPI($http, $q) { }); return deferred.promise; }; + var getPerspectiveDictionaryFieldsNew = function(perspective) { + var deferred = $q.defer(); + var url = "/dictionary/" + perspective.parent_client_id + "/" + perspective.parent_object_id + "/perspective/" + perspective.client_id + "/" + perspective.object_id + "/fields"; + $http.get(url).success(function(data, status, headers, config) { + if (_.isArray(data.fields)) { + var fields = perspectiveToDictionaryFields(data.fields); + deferred.resolve(fields); + } else { + deferred.reject("An error occurred while fetching perspective fields"); + } + }).error(function(data, status, headers, config) { + deferred.reject("An error occurred while fetching perspective fields"); + }); + return deferred.promise; + }; var removeValue = function(entry, field, fieldValue, parent) { var deferred = $q.defer(); var url; @@ -27642,8 +31955,9 @@ function lingvodocAPI($http, $q) { }); return deferred.promise; }; - var getDictionaryProperties = function(url) { + var getDictionaryProperties = function(dictionary) { var deferred = $q.defer(); + var url = "/dictionary/" + encodeURIComponent(dictionary.client_id) + "/" + encodeURIComponent(dictionary.object_id); $http.get(url).success(function(data, status, headers, config) { deferred.resolve(data); }).error(function(data, status, headers, config) { @@ -27651,8 +31965,9 @@ function lingvodocAPI($http, $q) { }); return deferred.promise; }; - var setDictionaryProperties = function(url, properties) { + var setDictionaryProperties = function(dictionary, properties) { var deferred = $q.defer(); + var url = "/dictionary/" + encodeURIComponent(dictionary.client_id) + "/" + encodeURIComponent(dictionary.object_id); $http.put(url, properties).success(function(data, status, headers, config) { deferred.resolve(data); }).error(function(data, status, headers, config) { @@ -27660,6 +31975,16 @@ function lingvodocAPI($http, $q) { }); return deferred.promise; }; + var removeDictionary = function(dictionary) { + var deferred = $q.defer(); + var url = "/dictionary/" + encodeURIComponent(dictionary.client_id) + "/" + encodeURIComponent(dictionary.object_id); + $http.delete(url).success(function(data, status, headers, config) { + deferred.resolve(); + }).error(function(data, status, headers, config) { + deferred.reject("An error occurred while trying to delete dictionary"); + }); + return deferred.promise; + }; var getLanguages = function(url) { var deferred = $q.defer(); var flatLanguages = function(languages) { @@ -27743,6 +32068,16 @@ function lingvodocAPI($http, $q) { }); return deferred.promise; }; + var removePerspective = function(perspective) { + var deferred = $q.defer(); + var url = "/dictionary/" + perspective.parent_client_id + "/" + perspective.parent_object_id + "/perspective/" + perspective.client_id + "/" + perspective.object_id; + $http.delete(url).success(function(data, status, headers, config) { + deferred.resolve(); + }).error(function(data, status, headers, config) { + deferred.reject("An error occurred while trying to delete perspective"); + }); + return deferred.promise; + }; var getUserInfo = function(userId, clientId) { var deferred = $q.defer(); var url = "/user" + "?client_id= " + encodeURIComponent(clientId) + "&user_id= " + encodeURIComponent(userId); @@ -27823,13 +32158,14 @@ function lingvodocAPI($http, $q) { }; var getDictionaries = function(query) { var deferred = $q.defer(); - var dictionaries = []; $http.post("/dictionaries", query).success(function(data, status, headers, config) { - for (var i = 0; i < data.dictionaries.length; i++) { - var dictionary = data.dictionaries[i]; - dictionaries.push(lingvodoc.Dictionary.fromJS(dictionary)); + if (_.isArray(data.dictionaries)) { + deferred.resolve(_.map(data.dictionaries, function(d) { + return lingvodoc.Dictionary.fromJS(d); + })); + } else { + deferred.reject("Failed to fetch dictionaries list. Malformed response."); } - deferred.resolve(dictionaries); }).error(function(data, status, headers, config) { deferred.reject("Failed to fetch dictionaries list"); }); @@ -28046,8 +32382,8 @@ function lingvodocAPI($http, $q) { }; $http.post("/dictionaries", req).success(function(data, status, headers, config) { var dictionaries = []; - if (angular.isArray(data.dictionaries)) { - angular.forEach(data.dictionaries, function(jsdict) { + if (_.isArray(data.dictionaries)) { + _.forEach(data.dictionaries, function(jsdict) { var dictionary = lingvodoc.Dictionary.fromJS(jsdict); if (language.client_id == dictionary.parent_client_id && language.object_id == dictionary.parent_object_id) { dictionaries.push(dictionary); @@ -28056,7 +32392,7 @@ function lingvodocAPI($http, $q) { } deferred.resolve(dictionaries); }).error(function(data, status, headers, config) { - deferred.reject("Failed to move lexical entry"); + deferred.reject("Failed to fetch list of dictionaries"); }); return deferred.promise; }; @@ -28239,10 +32575,140 @@ function lingvodocAPI($http, $q) { }); return deferred.promise; }; + var getUserBlobs = function() { + var deferred = $q.defer(); + $http.get("/blobs").success(function(data, status, headers, config) { + var blobs = _.map(data, lingvodoc.Blob.fromJS); + deferred.resolve(blobs); + }).error(function(data, status, headers, config) { + deferred.reject("Failed to fetch list of available blobs"); + }); + return deferred.promise; + }; + var checkDictionaryBlob = function(blob, parent) { + var deferred = $q.defer(); + var query = { + blob_client_id: blob.client_id, + blob_object_id: blob.object_id, + parent_client_id: parent.client_id, + parent_object_id: parent.object_id + }; + $http.post("/convert_check", query).success(function(data, status, headers, config) { + var perspectives = _.map(data, lingvodoc.Perspective.fromJS); + deferred.resolve(perspectives); + }).error(function(data, status, headers, config) { + deferred.reject("Failed to convert dictionary"); + }); + return deferred.promise; + }; + var convertDictionary = function(req) { + var deferred = $q.defer(); + $http.post("/convert", req).success(function(data, status, headers, config) { + deferred.resolve(data); + }).error(function(data, status, headers, config) { + deferred.reject("Failed to convert dictionary"); + }); + return deferred.promise; + }; + var getPerspectiveMeta = function(dictionary, perspective) { + var deferred = $q.defer(); + var url = "/dictionary/" + encodeURIComponent(dictionary.client_id) + "/" + encodeURIComponent(dictionary.object_id) + "/perspective/" + encodeURIComponent(perspective.client_id) + "/" + encodeURIComponent(perspective.object_id) + "/meta"; + $http.get(url).success(function(data, status, headers, config) { + deferred.resolve(data); + }).error(function(data, status, headers, config) { + deferred.reject("Failed to get perspective meta data!"); + }); + return deferred.promise; + }; + var setPerspectiveMeta = function(dictionary, perspective, meta) { + var deferred = $q.defer(); + var url = "/dictionary/" + encodeURIComponent(dictionary.client_id) + "/" + encodeURIComponent(dictionary.object_id) + "/perspective/" + encodeURIComponent(perspective.client_id) + "/" + encodeURIComponent(perspective.object_id) + "/meta"; + $http.put(url, meta).success(function(data, status, headers, config) { + deferred.resolve(data); + }).error(function(data, status, headers, config) { + deferred.reject("Failed to set perspective meta data!"); + }); + return deferred.promise; + }; + var removePerspectiveMeta = function(dictionary, perspective, meta) { + var deferred = $q.defer(); + var url = "/dictionary/" + encodeURIComponent(dictionary.client_id) + "/" + encodeURIComponent(dictionary.object_id) + "/perspective/" + encodeURIComponent(perspective.client_id) + "/" + encodeURIComponent(perspective.object_id) + "/meta"; + var config = { + method: "DELETE", + url: url, + data: meta, + headers: { + "Content-Type": "application/json;charset=utf-8" + } + }; + $http(config).success(function(data, status, headers, config) { + deferred.resolve(data); + }).error(function(data, status, headers, config) { + deferred.reject("Failed to remove perspective meta data!"); + }); + return deferred.promise; + }; + var advancedSearch = function(query, where, adopted, etymology) { + var deferred = $q.defer(); + var url = "/advanced_search"; + var perspectives = where.map(function(o) { + if (o.type == "perspective") { + return { + client_id: o.client_id, + object_id: o.object_id + }; + } + }).filter(function(o) { + return typeof o !== "undefined"; + }); + var req = { + searchstrings: query, + perspectives: perspectives + }; + if (_.isBoolean(adopted)) { + req.adopted = adopted; + } + if (_.isBoolean(etymology)) { + req.with_etimology = etymology; + } + $http.post(url, req).success(function(data, status, headers, config) { + var r = data.map(function(e) { + var perspective = lingvodoc.Perspective.fromJS(e); + return getPerspectiveOriginById(perspective.client_id, perspective.object_id); + }); + $q.all(r).then(function(paths) { + var out = []; + _.each(data, function(entry, i) { + entry.lexical_entry["origin"] = paths[i]; + out.push(entry.lexical_entry); + }); + deferred.resolve(out); + }, function(reason) { + deferred.reject("An error occurred while doing basic search"); + }); + }).error(function(data, status, headers, config) { + deferred.reject("An error occurred while doing advanced search"); + }); + return deferred.promise; + }; + var convertMarkup = function(object) { + var deferred = $q.defer(); + var obj = { + client_id: object.client_id, + object_id: object.object_id + }; + $http.post("/convert/markup", obj).success(function(data, status, headers, config) { + deferred.resolve(data); + }).error(function(data, status, headers, config) { + deferred.reject("Failed to convert markup!"); + }); + return deferred.promise; + }; return { getLexicalEntries: getLexicalEntries, getLexicalEntriesCount: getLexicalEntriesCount, getPerspectiveDictionaryFields: getPerspectiveDictionaryFields, + getPerspectiveDictionaryFieldsNew: getPerspectiveDictionaryFieldsNew, addNewLexicalEntry: addNewLexicalEntry, saveValue: saveValue, removeValue: removeValue, @@ -28253,6 +32719,7 @@ function lingvodocAPI($http, $q) { approveAll: approveAll, getDictionaryProperties: getDictionaryProperties, setDictionaryProperties: setDictionaryProperties, + removeDictionary: removeDictionary, getLanguages: getLanguages, setDictionaryStatus: setDictionaryStatus, setPerspectiveStatus: setPerspectiveStatus, @@ -28260,6 +32727,7 @@ function lingvodocAPI($http, $q) { getPerspectiveFields: getPerspectiveFields, setPerspectiveFields: setPerspectiveFields, getPerspectiveFieldsNew: getPerspectiveFieldsNew, + removePerspective: removePerspective, getUserInfo: getUserInfo, setUserInfo: setUserInfo, getOrganizations: getOrganizations, @@ -28286,7 +32754,15 @@ function lingvodocAPI($http, $q) { deleteDictionaryRoles: deleteDictionaryRoles, getPerspectiveRoles: getPerspectiveRoles, addPerspectiveRoles: addPerspectiveRoles, - deletePerspectiveRoles: deletePerspectiveRoles + deletePerspectiveRoles: deletePerspectiveRoles, + getUserBlobs: getUserBlobs, + checkDictionaryBlob: checkDictionaryBlob, + convertDictionary: convertDictionary, + getPerspectiveMeta: getPerspectiveMeta, + setPerspectiveMeta: setPerspectiveMeta, + removePerspectiveMeta: removePerspectiveMeta, + advancedSearch: advancedSearch, + convertMarkup: convertMarkup }; } @@ -28318,9 +32794,34 @@ function responseHandler($timeout, $modal) { function error(message) { show("error", message, 5e3); } + function yesno(status, message, callback) { + var controller = function($scope, $modalInstance) { + $scope.status = status; + $scope.message = message; + $scope.yes = function() { + $modalInstance.close(true); + }; + $scope.no = function() { + $modalInstance.close(false); + }; + }; + $modal.open({ + animation: true, + templateUrl: "responseHandlerYesNoModal.html", + controller: controller, + size: "lg", + backdrop: "static", + keyboard: false + }).result.then(function(result) { + callback(result); + }, function() { + callback(false); + }); + } return { success: success, - error: error + error: error, + yesno: yesno }; } @@ -28336,7 +32837,7 @@ angular.module("ViewDictionaryModule", [ "ui.bootstrap" ]).service("dictionarySe if ($attrs.url) { wavesurfer.load($attrs.url, $attrs.data || null); } - $scope.$emit("wavesurferInit", wavesurfer); + $scope.$emit("wavesurferInit", wavesurfer, $element); } }; }).directive("onReadFile", function($parse) { @@ -28363,8 +32864,6 @@ angular.module("ViewDictionaryModule", [ "ui.bootstrap" ]).service("dictionarySe } }; }).controller("ViewDictionaryController", [ "$scope", "$window", "$http", "$modal", "$log", "dictionaryService", "responseHandler", function($scope, $window, $http, $modal, $log, dictionaryService, responseHandler) { - var dictionaryClientId = $("#dictionaryClientId").data("lingvodoc"); - var dictionaryObjectId = $("#dictionaryObjectId").data("lingvodoc"); var perspectiveClientId = $("#perspectiveClientId").data("lingvodoc"); var perspectiveId = $("#perspectiveId").data("lingvodoc"); WaveSurferController.call(this, $scope); @@ -28419,6 +32918,8 @@ angular.module("ViewDictionaryModule", [ "ui.bootstrap" ]).service("dictionarySe return input; }; $scope.viewGroup = function(entry, field, values) { + $log.info(entry); + $log.info(values); $modal.open({ animation: true, templateUrl: "viewGroupModal.html", @@ -28453,18 +32954,18 @@ angular.module("ViewDictionaryModule", [ "ui.bootstrap" ]).service("dictionarySe } }); }; - $scope.annotate = function(soundEntity, markupEntity) { + $scope.annotate = function(sound, markup) { var modalInstance = $modal.open({ animation: true, templateUrl: "annotationModal.html", controller: "AnnotationController", size: "lg", resolve: { - soundUrl: function() { - return soundEntity.content; - }, - annotationUrl: function() { - return markupEntity.content; + params: function() { + return { + sound: sound, + markup: markup + }; } } }); @@ -28528,7 +33029,7 @@ angular.module("ViewDictionaryModule", [ "ui.bootstrap" ]).service("dictionarySe }, function(reason) { responseHandler.error(reason); }); -} ]).controller("AnnotationController", [ "$scope", "$http", "soundUrl", "annotationUrl", "responseHandler", function($scope, $http, soundUrl, annotationUrl, responseHandler) { +} ]).controller("AnnotationController", [ "$scope", "$http", "dictionaryService", "responseHandler", "params", function($scope, $http, dictionaryService, responseHandler, params) { var activeUrl = null; var createRegions = function(annotaion) { if (annotaion instanceof elan.Document) { @@ -28546,21 +33047,6 @@ angular.module("ViewDictionaryModule", [ "ui.bootstrap" ]).service("dictionarySe }); } }; - var loadAnnotation = function(url) { - $http.get(url).success(function(data, status, headers, config) { - try { - var xml = new DOMParser().parseFromString(data, "application/xml"); - var annotation = new elan.Document(); - annotation.importXML(xml); - $scope.annotation = annotation; - createRegions(annotation); - } catch (e) { - responseHandler.error("Failed to parse ELAN annotation: " + e); - } - }).error(function(data, status, headers, config) { - responseHandler.error(data); - }); - }; $scope.paused = true; $scope.annotation = null; $scope.playPause = function() { @@ -28599,20 +33085,28 @@ angular.module("ViewDictionaryModule", [ "ui.bootstrap" ]).service("dictionarySe region.remove(region); }); $scope.wavesurfer.once("ready", function() { - loadAnnotation(annotationUrl); + dictionaryService.convertMarkup(params.markup).then(function(data) { + try { + var xml = new DOMParser().parseFromString(data.content, "application/xml"); + var annotation = new elan.Document(); + annotation.importXML(xml); + $scope.annotation = annotation; + createRegions(annotation); + } catch (e) { + responseHandler.error("Failed to parse ELAN annotation: " + e); + } + }, function(reason) { + responseHandler.error(reason); + }); $scope.$apply(); }); - $scope.wavesurfer.load(soundUrl); + $scope.wavesurfer.load(params.sound.content); }); $scope.$on("modal.closing", function(e) { $scope.wavesurfer.stop(); $scope.wavesurfer.destroy(); }); } ]).controller("viewGroupController", [ "$scope", "$http", "$modalInstance", "$log", "dictionaryService", "responseHandler", "groupParams", function($scope, $http, $modalInstance, $log, dictionaryService, responseHandler, groupParams) { - var dictionaryClientId = $("#dictionaryClientId").data("lingvodoc"); - var dictionaryObjectId = $("#dictionaryObjectId").data("lingvodoc"); - var perspectiveClientId = $("#perspectiveClientId").data("lingvodoc"); - var perspectiveId = $("#perspectiveId").data("lingvodoc"); WaveSurferController.call(this, $scope); $scope.title = groupParams.field.entity_type; $scope.fields = groupParams.field.contains; @@ -28620,10 +33114,8 @@ angular.module("ViewDictionaryModule", [ "ui.bootstrap" ]).service("dictionarySe var createVirtualEntries = function(values) { var virtualEntries = []; var addValue = function(value, entries) { - var createNewEntry = true; if (value.additional_metadata) { for (var entryIndex = 0; entryIndex < entries.length; entryIndex++) { - var currentEntry = entries[entryIndex]; if (entries[entryIndex].client_id == value.client_id && entries[entryIndex].row_id == value.additional_metadata.row_id) { entries[entryIndex].contains.push(value); return; @@ -28685,27 +33177,6 @@ angular.module("ViewDictionaryModule", [ "ui.bootstrap" ]).service("dictionarySe } return values; }; - $scope.approve = function(lexicalEntry, field, fieldValue, approved) { - var url = $("#approveEntityUrl").data("lingvodoc"); - var obj = { - type: field.level, - client_id: fieldValue.client_id, - object_id: fieldValue.object_id - }; - dictionaryService.approve(url, { - entities: [ obj ] - }, approved).then(function(data) { - fieldValue["published"] = approved; - }, function(reason) { - responseHandler.error(reason); - }); - }; - $scope.approved = function(lexicalEntry, field, fieldValue) { - if (!fieldValue.published) { - return false; - } - return !!fieldValue.published; - }; $scope.ok = function() { $modalInstance.close($scope.entries); }; @@ -28713,10 +33184,6 @@ angular.module("ViewDictionaryModule", [ "ui.bootstrap" ]).service("dictionarySe $scope.mapFieldValues(updatedEntries, $scope.fields); }, true); } ]).controller("viewGroupingTagController", [ "$scope", "$http", "$modalInstance", "$q", "$log", "dictionaryService", "responseHandler", "groupParams", function($scope, $http, $modalInstance, $q, $log, dictionaryService, responseHandler, groupParams) { - var dictionaryClientId = $("#dictionaryClientId").data("lingvodoc"); - var dictionaryObjectId = $("#dictionaryObjectId").data("lingvodoc"); - var perspectiveClientId = $("#perspectiveClientId").data("lingvodoc"); - var perspectiveId = $("#perspectiveId").data("lingvodoc"); WaveSurferController.call(this, $scope); $scope.fields = groupParams.fields; $scope.connectedEntries = []; @@ -28812,7 +33279,7 @@ function WaveSurferController($scope) { $scope.isMediaFileAvailable = function() { return activeUrl != null; }; - $scope.$on("wavesurferInit", function(e, wavesurfer) { + $scope.$on("wavesurferInit", function(e, wavesurfer, container) { $scope.wavesurfer = wavesurfer; $scope.wavesurfer.on("play", function() { $scope.paused = false; diff --git a/lingvodoc/templates/annotation.pt b/lingvodoc/templates/annotation.pt new file mode 100644 index 000000000..152c0db79 --- /dev/null +++ b/lingvodoc/templates/annotation.pt @@ -0,0 +1,72 @@ + \ No newline at end of file diff --git a/lingvodoc/templates/create_dictionary.pt b/lingvodoc/templates/create_dictionary.pt index 77012e877..fc3f38cf5 100644 --- a/lingvodoc/templates/create_dictionary.pt +++ b/lingvodoc/templates/create_dictionary.pt @@ -82,11 +82,12 @@
                      (Upload dictionary) - + -
                      +
                    @@ -327,6 +328,68 @@ + + + + + + + + + + + + + + + + + +
                    diff --git a/lingvodoc/templates/dashboard.pt b/lingvodoc/templates/dashboard.pt index 2d8d40378..9f21e9eeb 100644 --- a/lingvodoc/templates/dashboard.pt +++ b/lingvodoc/templates/dashboard.pt @@ -54,6 +54,7 @@ @@ -73,6 +74,7 @@
                  • Published
                  • +


                    @@ -98,8 +100,8 @@
                  • Edit roles
                  • -
                  • Edit - properties
                  • +
                  • Edit properties
                  • +
                  • Remove perspective
                  • @@ -177,6 +179,10 @@ + + +
                    @@ -303,11 +309,42 @@
                    + +
                    +
                    + Files +
                    +
                    + + + + + +
                    {{ blob.name }}
                    + + + + +
                    + +
                    + +
                    +
                    + Location +
                    +
                    + +
                    +
                    + @@ -523,7 +560,6 @@ - + + + + + + + + + + +
                    + +
                    + + + + \ No newline at end of file diff --git a/lingvodoc/templates/nav.pt b/lingvodoc/templates/nav.pt index ca8ece018..5296065d9 100644 --- a/lingvodoc/templates/nav.pt +++ b/lingvodoc/templates/nav.pt @@ -25,6 +25,7 @@
                  • Languages
                  • Organizations
                  • +
                  • Maps search
                  • My files
                  • diff --git a/lingvodoc/templates/publish_dictionary.pt b/lingvodoc/templates/publish_dictionary.pt index fb299d310..7fa23bdfe 100644 --- a/lingvodoc/templates/publish_dictionary.pt +++ b/lingvodoc/templates/publish_dictionary.pt @@ -60,6 +60,7 @@
                    +
                    @@ -221,79 +222,6 @@
                    - - - - +
                    +
                    diff --git a/lingvodoc/templates/response_handler.pt b/lingvodoc/templates/response_handler.pt index 4cd7efd33..c4fba9ca3 100644 --- a/lingvodoc/templates/response_handler.pt +++ b/lingvodoc/templates/response_handler.pt @@ -12,3 +12,20 @@ + + + + diff --git a/lingvodoc/templates/user_upload.pt b/lingvodoc/templates/user_upload.pt index 57d24208f..e12260c5a 100644 --- a/lingvodoc/templates/user_upload.pt +++ b/lingvodoc/templates/user_upload.pt @@ -73,7 +73,15 @@ - Upload + Upload + + + + +
                    diff --git a/lingvodoc/templates/view_dictionary.pt b/lingvodoc/templates/view_dictionary.pt index a92ef49c0..2fca22ce9 100644 --- a/lingvodoc/templates/view_dictionary.pt +++ b/lingvodoc/templates/view_dictionary.pt @@ -52,6 +52,7 @@
                    +
                    @@ -176,79 +177,6 @@
                    - - - - +
                    +
                    diff --git a/lingvodoc/views.py b/lingvodoc/views.py index 543249551..19d48290f 100755 --- a/lingvodoc/views.py +++ b/lingvodoc/views.py @@ -1,10 +1,11 @@ +import tgt import webob from pyramid.response import Response from pyramid.view import view_config from sqlalchemy.exc import DBAPIError -from .scripts.lingvodoc_converter import convert_one +from .scripts.lingvodoc_converter import convert_one, get_dict_attributes from .models import ( DBSession, @@ -35,11 +36,13 @@ About ) +from .scripts.convert_rules import rules + from .merge_perspectives import ( mergeDicts ) -from sqlalchemy.orm import sessionmaker +from sqlalchemy.orm import sessionmaker, aliased from pyramid.security import ( Everyone, Allow, @@ -50,7 +53,9 @@ from sqlalchemy import ( func, or_, - and_ + and_, + tuple_, + not_ ) from sqlalchemy.orm import joinedload, subqueryload, noload, join, joinedload_all from sqlalchemy.sql.expression import case, true, false @@ -95,6 +100,9 @@ import logging log = logging.getLogger(__name__) +from sqlalchemy import tuple_ + +import hashlib class CommonException(Exception): def __init__(self, value): @@ -104,6 +112,36 @@ def __str__(self): return repr(self.value) +@view_config(route_name='entity_metadata_search', renderer='json', request_method='GET') +def entity_metadata_search(request): + # TODO: add same check for permission as in basic_search + searchstring = request.params.get('searchstring') + if type(searchstring) != str: + searchstring = str(searchstring) + searchtype = request.params.get('searchtype') + perspective_client_id = request.params.get('perspective_client_id') + perspective_object_id = request.params.get('perspective_object_id') + results_cursor = DBSession.query(LevelOneEntity)\ + .filter(LevelOneEntity.entity_type.like('%'+searchtype+'%'), + LevelOneEntity.additional_metadata.like('%'+searchstring+'%')) + if perspective_client_id and perspective_object_id: + results_cursor = results_cursor.join(LexicalEntry).join(DictionaryPerspective).filter(DictionaryPerspective.client_id == perspective_client_id, + DictionaryPerspective.object_id == perspective_object_id) + results = [] + entries = set() + for item in results_cursor: + entries.add(item) + for entry in entries: + if not entry.marked_for_deletion: + result = dict() + result['client_id'] = entry.client_id + result['object_id'] = entry.object_id + result['additional_metadata'] = entry.additional_metadata + results.append(result) + + return results + + @view_config(route_name='basic_search_old', renderer='json', request_method='GET') def basic_search_old(request): searchstring = request.params.get('leveloneentity') @@ -136,8 +174,9 @@ def basic_search_old(request): @view_config(route_name='basic_search', renderer='json', request_method='GET') def basic_search(request): can_add_tags = request.params.get('can_add_tags') - print(can_add_tags) searchstring = request.params.get('leveloneentity') + perspective_client_id = request.params.get('perspective_client_id') + perspective_object_id = request.params.get('perspective_object_id') if searchstring: if len(searchstring) >= 2: searchstring = request.params.get('leveloneentity') @@ -147,11 +186,19 @@ def basic_search(request): .filter(Client.id == request.authenticated_userid).first() if group: results_cursor = DBSession.query(LevelOneEntity).filter(LevelOneEntity.content.like('%'+searchstring+'%')) + if perspective_client_id and perspective_object_id: + results_cursor = results_cursor.join(LexicalEntry)\ + .join(DictionaryPerspective)\ + .filter(DictionaryPerspective.client_id == perspective_client_id, + DictionaryPerspective.object_id == perspective_object_id) else: results_cursor = DBSession.query(LevelOneEntity)\ .join(LexicalEntry)\ - .join(DictionaryPerspective)\ - .join(Group, and_(DictionaryPerspective.client_id == Group.subject_client_id, DictionaryPerspective.object_id == Group.subject_object_id ))\ + .join(DictionaryPerspective) + if perspective_client_id and perspective_object_id: + results_cursor = results_cursor.filter(DictionaryPerspective.client_id == perspective_client_id, + DictionaryPerspective.object_id == perspective_object_id) + results_cursor = results_cursor.join(Group, and_(DictionaryPerspective.client_id == Group.subject_client_id, DictionaryPerspective.object_id == Group.subject_object_id ))\ .join(BaseGroup)\ .join(User, Group.users)\ .join(Client)\ @@ -191,7 +238,227 @@ def basic_search(request): return {'error': 'search is too short'} -#TODO: make it normal, it's just a test +@view_config(route_name='advanced_search', renderer='json', request_method='POST') +def advanced_search(request): + req = request.json + perspectives = req.get('perspectives') + searchstrings = req.get('searchstrings') or [] + adopted = req.get('adopted') + adopted_type = req.get('adopted_type') or 'Word' + with_etimology = req.get('with_etimology') + count = req.get('count') or False + results = [] + results_cursor = DBSession.query(LexicalEntry)\ + .join(DictionaryPerspective, and_(LexicalEntry.parent_client_id == DictionaryPerspective.client_id, + LexicalEntry.parent_object_id == DictionaryPerspective.object_id))\ + .join(LevelOneEntity, and_(LevelOneEntity.parent_client_id == LexicalEntry.client_id, + LevelOneEntity.parent_object_id == LexicalEntry.object_id))\ + .join(PublishLevelOneEntity, + and_(PublishLevelOneEntity.entity_client_id == LevelOneEntity.client_id, + PublishLevelOneEntity.entity_object_id == LevelOneEntity.object_id))\ + .filter(PublishLevelOneEntity.marked_for_deletion == False, + LevelOneEntity.marked_for_deletion == False, + DictionaryPerspective.state == 'Published') + if perspectives: + perspectives = [(o["client_id"], o["object_id"]) for o in perspectives] + results_cursor = results_cursor\ + .filter(tuple_(DictionaryPerspective.client_id, DictionaryPerspective.object_id).in_(perspectives)) + if searchstrings == []: + request.response.status = HTTPBadRequest.code + return {'error': 'No search'} + length_search = [len(o['searchstring']) for o in searchstrings if len(o['searchstring']) >= 1] + if length_search == []: + request.response.status = HTTPBadRequest.code + return {'error': 'search is too short'} + if adopted is not None: + if adopted: + sub = results_cursor.subquery() + sublexes = aliased(LexicalEntry, sub) + results_cursor = DBSession.query(sublexes)\ + .join(LevelOneEntity, and_(LevelOneEntity.parent_client_id == sublexes.client_id, + LevelOneEntity.parent_object_id == sublexes.object_id))\ + .join(PublishLevelOneEntity, + and_(PublishLevelOneEntity.entity_client_id == LevelOneEntity.client_id, + PublishLevelOneEntity.entity_object_id == LevelOneEntity.object_id))\ + .filter(PublishLevelOneEntity.marked_for_deletion == False, + LevelOneEntity.marked_for_deletion == False, + LevelOneEntity.content.like('%заим.%'), + LevelOneEntity.entity_type == adopted_type) + else: + sub = results_cursor.subquery() + sublexes = aliased(LexicalEntry, sub) + wronglexes = DBSession.query(sublexes)\ + .join(LevelOneEntity, and_(LevelOneEntity.parent_client_id == sublexes.client_id, + LevelOneEntity.parent_object_id == sublexes.object_id))\ + .join(PublishLevelOneEntity, + and_(PublishLevelOneEntity.entity_client_id == LevelOneEntity.client_id, + PublishLevelOneEntity.entity_object_id == LevelOneEntity.object_id))\ + .filter(PublishLevelOneEntity.marked_for_deletion == False, + LevelOneEntity.marked_for_deletion == False, + LevelOneEntity.content.like('%заим.%'), + LevelOneEntity.entity_type == adopted_type) + results_cursor = results_cursor.except_(wronglexes) + if with_etimology is not None: + grouping_tags = DBSession.query(GroupingEntity.content,func.count(tuple_(LexicalEntry.client_id, LexicalEntry.object_id)) )\ + .join(PublishGroupingEntity, + and_(PublishGroupingEntity.entity_client_id == GroupingEntity.client_id, + PublishGroupingEntity.entity_object_id == GroupingEntity.object_id))\ + .join(LexicalEntry, and_(GroupingEntity.parent_client_id == LexicalEntry.client_id, + GroupingEntity.parent_object_id == LexicalEntry.object_id))\ + .filter(PublishGroupingEntity.marked_for_deletion == False, + GroupingEntity.marked_for_deletion == False)\ + .group_by(GroupingEntity.content)\ + .having(func.count(tuple_(LexicalEntry.client_id, LexicalEntry.object_id)) >= 2).all() + grouping_tags = [o.content for o in grouping_tags] + if with_etimology: + sub = results_cursor.subquery() + sublexes = aliased(LexicalEntry, sub) + results_cursor = DBSession.query(sublexes)\ + .join(GroupingEntity, and_(GroupingEntity.parent_client_id == sublexes.client_id, + GroupingEntity.parent_object_id == sublexes.object_id))\ + .join(PublishGroupingEntity, + and_(PublishGroupingEntity.entity_client_id == GroupingEntity.client_id, + PublishGroupingEntity.entity_object_id == GroupingEntity.object_id))\ + .filter(PublishGroupingEntity.marked_for_deletion == False, + GroupingEntity.marked_for_deletion == False, + GroupingEntity.content.in_(grouping_tags)) + else: + sub = results_cursor.subquery() + sublexes = aliased(LexicalEntry, sub) + wronglexes = DBSession.query(sublexes)\ + .join(GroupingEntity, and_(GroupingEntity.parent_client_id == sublexes.client_id, + GroupingEntity.parent_object_id == sublexes.object_id))\ + .join(PublishGroupingEntity, + and_(PublishGroupingEntity.entity_client_id == GroupingEntity.client_id, + PublishGroupingEntity.entity_object_id == GroupingEntity.object_id))\ + .filter(PublishGroupingEntity.marked_for_deletion == False, + GroupingEntity.marked_for_deletion == False, + GroupingEntity.content.in_(grouping_tags)) + results_cursor = results_cursor.except_(wronglexes) + + sub = results_cursor.subquery() + sublexes = aliased(LexicalEntry, sub) + new_results_cursor = DBSession.query(LexicalEntry).filter(False) + for search in searchstrings: + new_results_cursor = new_results_cursor.subquery().select() + search_by_or = search.get('search_by_or') + searchstring = search.get('searchstring') + entity_type = search.get('entity_type') + if searchstring: + if len(searchstring) >= 1: + searchstring = searchstring.split(' ') + if entity_type: + if search_by_or: + new_results_cursor = DBSession.query(sublexes)\ + .join(LevelOneEntity, and_(LevelOneEntity.parent_client_id == sublexes.client_id, + LevelOneEntity.parent_object_id == sublexes.object_id))\ + .join(PublishLevelOneEntity, + and_(PublishLevelOneEntity.entity_client_id == LevelOneEntity.client_id, + PublishLevelOneEntity.entity_object_id == LevelOneEntity.object_id))\ + .filter(PublishLevelOneEntity.marked_for_deletion == False, + LevelOneEntity.marked_for_deletion == False, + or_(*[LevelOneEntity.content.like('%'+name+'%') for name in searchstring]), + LevelOneEntity.entity_type == entity_type).union_all(new_results_cursor) + # .filter(or_(*[MyTable.my_column.like(name) for name in foo])) + else: + new_results_cursor = DBSession.query(sublexes)\ + .join(LevelOneEntity, and_(LevelOneEntity.parent_client_id == sublexes.client_id, + LevelOneEntity.parent_object_id == sublexes.object_id))\ + .join(PublishLevelOneEntity, + and_(PublishLevelOneEntity.entity_client_id == LevelOneEntity.client_id, + PublishLevelOneEntity.entity_object_id == LevelOneEntity.object_id))\ + .filter(PublishLevelOneEntity.marked_for_deletion == False, + LevelOneEntity.marked_for_deletion == False, + and_(*[LevelOneEntity.content.like('%'+name+'%') for name in searchstring]), + LevelOneEntity.entity_type == entity_type).union_all(new_results_cursor) + else: + if search_by_or: + new_results_cursor = DBSession.query(sublexes)\ + .join(LevelOneEntity, and_(LevelOneEntity.parent_client_id == sublexes.client_id, + LevelOneEntity.parent_object_id == sublexes.object_id))\ + .join(PublishLevelOneEntity, + and_(PublishLevelOneEntity.entity_client_id == LevelOneEntity.client_id, + PublishLevelOneEntity.entity_object_id == LevelOneEntity.object_id))\ + .filter(PublishLevelOneEntity.marked_for_deletion == False, + LevelOneEntity.marked_for_deletion == False, + or_(*[LevelOneEntity.content.like('%'+name+'%') for name in searchstring])).union_all(new_results_cursor) + # .filter(or_(*[MyTable.my_column.like(name) for name in foo])) + else: + new_results_cursor = DBSession.query(sublexes)\ + .join(LevelOneEntity, and_(LevelOneEntity.parent_client_id == sublexes.client_id, + LevelOneEntity.parent_object_id == sublexes.object_id))\ + .join(PublishLevelOneEntity, + and_(PublishLevelOneEntity.entity_client_id == LevelOneEntity.client_id, + PublishLevelOneEntity.entity_object_id == LevelOneEntity.object_id))\ + .filter(PublishLevelOneEntity.marked_for_deletion == False, + LevelOneEntity.marked_for_deletion == False, + and_(*[LevelOneEntity.content.like('%'+name+'%') for name in searchstring])).union_all(new_results_cursor) + results_cursor = new_results_cursor + results_cursor = results_cursor.group_by(LexicalEntry) + # return {'result': str(results_cursor.statement)} + if count: + request.response.status = HTTPOk.code + return{'count': results_cursor.count()} + entries = set() + for item in results_cursor: + entries.add(item) + for entry in entries: + if not entry.marked_for_deletion: + result = dict() + result['lexical_entry'] = entry.track(True) + result['client_id'] = entry.parent_client_id + result['object_id'] = entry.parent_object_id + perspective_tr = entry.parent.get_translation(request) + result['translation_string'] = perspective_tr['translation_string'] + result['translation'] = perspective_tr['translation'] + result['is_template'] = entry.parent.is_template + result['status'] = entry.parent.state + result['marked_for_deletion'] = entry.parent.marked_for_deletion + result['parent_client_id'] = entry.parent.parent_client_id + result['parent_object_id'] = entry.parent.parent_object_id + dict_tr = entry.parent.parent.get_translation(request) + result['parent_translation_string'] = dict_tr['translation_string'] + result['parent_translation'] = dict_tr['translation'] + results.append(result) + request.response.status = HTTPOk.code + return results + + +@view_config(route_name='convert_dictionary_check', renderer='json', request_method='POST') +def convert_dictionary_check(request): + import sqlite3 + req = request.json_body + + client_id = req['blob_client_id'] + object_id = req['blob_object_id'] + # parent_client_id = req['parent_client_id'] + # parent_object_id = req['parent_object_id'] + client = DBSession.query(Client).filter_by(id=authenticated_userid(request)).first() + user = client.user + + blob = DBSession.query(UserBlobs).filter_by(client_id=client_id, object_id=object_id).first() + filename = blob.real_storage_path + sqconn = sqlite3.connect(filename) + res = get_dict_attributes(sqconn) + dialeqt_id = res['dialeqt_id'] + persps = DBSession.query(DictionaryPerspective).filter(DictionaryPerspective.import_hash == dialeqt_id).all() + perspectives = [] + for perspective in persps: + path = request.route_url('perspective', + dictionary_client_id=perspective.parent_client_id, + dictionary_object_id=perspective.parent_object_id, + perspective_client_id=perspective.client_id, + perspective_id=perspective.object_id) + subreq = Request.blank(path) + subreq.method = 'GET' + subreq.headers = request.headers + resp = request.invoke_subrequest(subreq) + if 'error' not in resp.json: + perspectives += [resp.json] + request.response.status = HTTPOk.code + return perspectives + + @view_config(route_name='convert_dictionary', renderer='json', request_method='POST') def convert_dictionary(request): req = request.json_body @@ -200,6 +467,10 @@ def convert_dictionary(request): object_id = req['blob_object_id'] parent_client_id = req['parent_client_id'] parent_object_id = req['parent_object_id'] + dictionary_client_id = req.get('dictionary_client_id') + dictionary_object_id = req.get('dictionary_object_id') + perspective_client_id = req.get('perspective_client_id') + perspective_object_id = req.get('perspective_object_id') client = DBSession.query(Client).filter_by(id=authenticated_userid(request)).first() user = client.user @@ -217,7 +488,11 @@ def convert_dictionary(request): user.login, user.password.hash, parent_client_id, - parent_object_id)) + parent_object_id, + dictionary_client_id, + dictionary_object_id, + perspective_client_id, + perspective_object_id)) log.debug("Conversion started") p.start() request.response.status = HTTPOk.code @@ -286,7 +561,7 @@ def view_languages_list(request): return response -@view_config(route_name='language', renderer='json', request_method='PUT', permission='edit') +@view_config(route_name='language', renderer='json', request_method='PUT') def edit_language(request): try: response = dict() @@ -400,6 +675,7 @@ def view_dictionary(request): response['translation_string'] = translation_string['translation_string'] response['translation'] = translation_string['translation'] response['status'] = dictionary.state + response['additional_metadata'] = dictionary.additional_metadata request.response.status = HTTPOk.code return response request.response.status = HTTPNotFound.code @@ -425,9 +701,16 @@ def edit_dictionary(request): dictionary.parent_object_id = req['parent_object_id'] if 'translation' in req: dictionary.set_translation(request) + additional_metadata = req.get('additional_metadata') + if additional_metadata: + # additional_metadata = json.dumps(additional_metadata) + + old_meta = json.loads(dictionary.additional_metadata) + old_meta.update(additional_metadata) + new_meta = json.dumps(old_meta) + dictionary.additional_metadata = new_meta request.response.status = HTTPOk.code return response - request.response.status = HTTPNotFound.code return {'error': str("No such dictionary in the system")} except KeyError as e: @@ -469,11 +752,15 @@ def create_dictionary(request): if not user: raise CommonException("This client id is orphaned. Try to logout and then login once more.") parent = DBSession.query(Language).filter_by(client_id=parent_client_id, object_id=parent_object_id).first() + additional_metadata = req.get('additional_metadata') + if additional_metadata: + additional_metadata = json.dumps(additional_metadata) dictionary = Dictionary(object_id=DBSession.query(Dictionary).filter_by(client_id=client.id).count() + 1, client_id=variables['auth'], state='WiP', - parent=parent) + parent=parent, + additional_metadata=additional_metadata) dictionary.set_translation(request) DBSession.add(dictionary) DBSession.flush() @@ -523,7 +810,11 @@ def edit_dictionary_status(request): dictionary = DBSession.query(Dictionary).filter_by(client_id=client_id, object_id=object_id).first() if dictionary: if not dictionary.marked_for_deletion: - req = request.json_body + + if type(request.json_body) == str: + req = json.loads(request.json_body) + else: + req = request.json_body status = req['status'] dictionary.state = status DBSession.add(dictionary) @@ -534,6 +825,247 @@ def edit_dictionary_status(request): return {'error': str("No such dictionary in the system")} +@view_config(route_name='dictionary_copy', renderer='json', request_method='POST', permission='edit') +def copy_dictionary(request): + response = dict() + parent_client_id = request.matchdict.get('client_id') + parent_object_id = request.matchdict.get('object_id') + parent = DBSession.query(Dictionary).filter_by(client_id=parent_client_id, object_id=parent_object_id).first() + if parent: + path = request.route_url('create_dictionary') + subreq = Request.blank(path) + subreq.method = 'POST' + subreq.json = json.dumps({'translation_string': parent.translation_string, + 'parent_client_id': parent.parent_client_id, + 'parent_object_id': parent.parent_object_id}) + headers = {'Cookie':request.headers['Cookie']} + subreq.headers = headers + resp = request.invoke_subrequest(subreq) + new_dict = DBSession.query(Dictionary)\ + .filter_by(client_id=resp.json['client_id'], object_id=resp.json['object_id'])\ + .first() + if parent.marked_for_deletion: + new_dict.marked_for_deletion = True + + path = request.route_url('dictionary_roles', + client_id=parent.client_id, + object_id=parent.object_id) + subreq = Request.blank(path) + subreq.method = 'GET' + headers = {'Cookie':request.headers['Cookie']} + + subreq.headers = headers + resp = request.invoke_subrequest(subreq) + path = request.route_url('dictionary_roles', + client_id=new_dict.client_id, + object_id=new_dict.object_id) + subreq = Request.blank(path) + subreq.method = 'POST' + subreq.json = json.dumps(resp.json) + headers = {'Cookie':request.headers['Cookie']} + subreq.headers = headers + resp = request.invoke_subrequest(subreq) + path = request.route_url('dictionary_status', + client_id=parent.client_id, + object_id=parent.object_id) + subreq = Request.blank(path) + subreq.method = 'GET' + headers = {'Cookie':request.headers['Cookie']} + + subreq.headers = headers + resp = request.invoke_subrequest(subreq) + path = request.route_url('dictionary_status', + client_id=new_dict.client_id, + object_id=new_dict.object_id) + subreq = Request.blank(path) + subreq.method = 'PUT' + subreq.json = json.dumps(resp.json) + headers = {'Cookie':request.headers['Cookie']} + subreq.headers = headers + resp = request.invoke_subrequest(subreq) + + perspectives = DBSession.query(DictionaryPerspective).filter_by(parent=parent) + for perspective in perspectives: + path = request.route_url('create_perspective', + dictionary_client_id=new_dict.client_id, + dictionary_object_id=new_dict.object_id) + subreq = Request.blank(path) + subreq.method = 'POST' + subreq.json = json.dumps({'translation_string': perspective.translation_string}) + headers = {'Cookie':request.headers['Cookie']} + subreq.headers = headers + resp = request.invoke_subrequest(subreq) + new_persp = DBSession.query(DictionaryPerspective)\ + .filter_by(client_id=resp.json['client_id'], object_id=resp.json['object_id'])\ + .first() + + if perspective.marked_for_deletion: + new_persp.marked_for_deletion = True + + path = request.route_url('perspective_fields', + dictionary_client_id=parent.client_id, + dictionary_object_id=parent.object_id, + perspective_client_id=perspective.client_id, + perspective_id=perspective.object_id) + subreq = Request.blank(path) + subreq.method = 'GET' + headers = {'Cookie':request.headers['Cookie']} + subreq.headers = headers + resp = request.invoke_subrequest(subreq) + + path = request.route_url('perspective_fields', + dictionary_client_id=new_dict.client_id, + dictionary_object_id=new_dict.object_id, + perspective_client_id=new_persp.client_id, + perspective_id=new_persp.object_id) + subreq = Request.blank(path) + subreq.method = 'POST' + subreq.json = json.dumps(resp.json) + headers = {'Cookie':request.headers['Cookie']} + subreq.headers = headers + resp = request.invoke_subrequest(subreq) + + path = request.route_url('perspective_status', + dictionary_client_id=parent.client_id, + dictionary_object_id=parent.object_id, + perspective_client_id=perspective.client_id, + perspective_id=perspective.object_id) + subreq = Request.blank(path) + subreq.method = 'GET' + headers = {'Cookie':request.headers['Cookie']} + subreq.headers = headers + resp = request.invoke_subrequest(subreq) + + path = request.route_url('perspective_status', + dictionary_client_id=new_dict.client_id, + dictionary_object_id=new_dict.object_id, + perspective_client_id=new_persp.client_id, + perspective_id=new_persp.object_id) + subreq = Request.blank(path) + subreq.method = 'PUT' + subreq.json = json.dumps(resp.json) + headers = {'Cookie':request.headers['Cookie']} + subreq.headers = headers + resp = request.invoke_subrequest(subreq) + + path = request.route_url('perspective_roles', + client_id=parent.client_id, + object_id=parent.object_id, + perspective_client_id=perspective.client_id, + perspective_id=perspective.object_id) + subreq = Request.blank(path) + subreq.method = 'GET' + headers = {'Cookie':request.headers['Cookie']} + subreq.headers = headers + resp = request.invoke_subrequest(subreq) + + path = request.route_url('perspective_roles', + client_id=new_dict.client_id, + object_id=new_dict.object_id, + perspective_client_id=new_persp.client_id, + perspective_id=new_persp.object_id) + subreq = Request.blank(path) + subreq.method = 'POST' + subreq.json = json.dumps(resp.json) + headers = {'Cookie':request.headers['Cookie']} + subreq.headers = headers + resp = request.invoke_subrequest(subreq) + + lexes = DBSession.query(LexicalEntry).filter_by(parent=perspective) + for lex in lexes: + new_lex = LexicalEntry(object_id=DBSession.query(LexicalEntry).filter_by(client_id=lex.client_id).count() + 1, + client_id=lex.client_id, + parent=new_persp, + marked_for_deletion=lex.marked_for_deletion, + additional_metadata=lex.additional_metadata, + moved_to=lex.moved_to) # if moved_to in this dict, should it be moved to in new dict? + DBSession.add(new_lex) + DBSession.flush() + + l1es = DBSession.query(LevelOneEntity).filter_by(parent=lex) + for l1e in l1es: + new_l1e = LevelOneEntity(client_id=l1e.client_id, + object_id=DBSession.query(LevelOneEntity).filter_by(client_id=l1e.client_id).count() + 1, + content=l1e.content, + entity_type=l1e.entity_type, + locale_id=l1e.locale_id, + additional_metadata=l1e.additional_metadata, + parent=new_lex, + marked_for_deletion=l1e.marked_for_deletion, + is_translatable=l1e.is_translatable, + created_at=l1e.created_at) + DBSession.add(new_l1e) + DBSession.add(new_l1e) + DBSession.flush() + for pl1e in l1e.publishleveloneentity: + new_pl1e = PublishLevelOneEntity(client_id=pl1e.client_id, + object_id=DBSession.query(PublishLevelOneEntity).filter_by(client_id=pl1e.client_id).count() + 1, + content=pl1e.content, + entity_type=pl1e.entity_type, + parent=new_lex, + entity=new_l1e, + marked_for_deletion=pl1e.marked_for_deletion, + created_at=pl1e.created_at) + DBSession.add(new_pl1e) + DBSession.flush() + + l2es = DBSession.query(LevelTwoEntity).filter_by(parent=l1e) + for l2e in l2es: + new_l2e = LevelTwoEntity(client_id=l2e.client_id, + object_id=DBSession.query(LevelTwoEntity).filter_by(client_id=l2e.client_id).count() + 1, + content=l2e.content, + entity_type=l2e.entity_type, + locale_id=l2e.locale_id, + additional_metadata=l2e.additional_metadata, + parent=new_l1e, + marked_for_deletion=l2e.marked_for_deletion, + is_translatable=l2e.is_translatable, + created_at=l2e.created_at) + DBSession.add(new_l2e) + DBSession.flush() + for pl2e in l2e.publishleveltwoentity: + new_pl2e = PublishLevelTwoEntity(client_id=pl2e.client_id, + object_id=DBSession.query(PublishLevelTwoEntity).filter_by(client_id=pl2e.client_id).count() + 1, + content=pl2e.content, + entity_type=pl2e.entity_type, + parent=new_lex, + entity=new_l2e, + marked_for_deletion=pl2e.marked_for_deletion, + created_at=pl2e.created_at) + DBSession.add(new_pl2e) + DBSession.flush() + ges = DBSession.query(GroupingEntity).filter_by(parent=lex) + for ge in ges: + new_ge = GroupingEntity(client_id=ge.client_id, + object_id=DBSession.query(GroupingEntity).filter_by(client_id=ge.client_id).count() + 1, + content=ge.content, # same tag? + entity_type=ge.entity_type, + locale_id=ge.locale_id, + additional_metadata=ge.additional_metadata, + parent=new_lex, + marked_for_deletion=ge.marked_for_deletion, + is_translatable=ge.is_translatable, + created_at=ge.created_at) + DBSession.add(new_ge) + DBSession.flush() + for pge in ge.publishgroupingentity: + new_pge = PublishGroupingEntity(client_id=pge.client_id, + object_id=DBSession.query(PublishGroupingEntity).filter_by(client_id=pge.client_id).count() + 1, + content=pge.content, + entity_type=pge.entity_type, + parent=new_lex, + entity=new_ge, + marked_for_deletion=pge.marked_for_deletion, + created_at=pge.created_at) + DBSession.add(new_pge) + DBSession.flush() + request.response.status = HTTPOk.code + return {'client_id':new_dict.client_id, + 'object_id':new_dict.object_id} + request.response.status = HTTPNotFound.code + return {'error': str("No such dictionary in the system")} + + @view_config(route_name='dictionary_delete', renderer='json', request_method='DELETE', permission='delete') def real_delete_dictionary(request): response = dict() @@ -622,6 +1154,31 @@ def view_perspective(request): response['status'] = perspective.state response['marked_for_deletion'] = perspective.marked_for_deletion response['is_template'] = perspective.is_template + response['additional_metadata'] = perspective.additional_metadata + if perspective.additional_metadata: + meta = json.loads(perspective.additional_metadata) + if 'location' in meta: + response['location'] = meta['location'] + if 'info' in meta: + response['info'] = meta['info'] + remove_list = [] + info_list = response['info']['content'] + for info in info_list: + content = info['info']['content'] + path = request.route_url('get_user_blob', + client_id=content['client_id'], + object_id=content['object_id']) + subreq = Request.blank(path) + subreq.method = 'GET' + subreq.headers = request.headers + resp = request.invoke_subrequest(subreq) + if 'error' not in resp.json: + info['info']['content'] = resp.json + else: + if info not in remove_list: + remove_list.append(info) + for info in remove_list: + info_list.remove(info) request.response.status = HTTPOk.code return response request.response.status = HTTPNotFound.code @@ -695,6 +1252,107 @@ def view_perspective_tree(request): return {'error': str("No such perspective in the system")} +@view_config(route_name='perspective_meta', renderer='json', request_method='PUT', permission='edit') +def edit_perspective_meta(request): + response = dict() + client_id = request.matchdict.get('perspective_client_id') + object_id = request.matchdict.get('perspective_id') + client = DBSession.query(Client).filter_by(id=request.authenticated_userid).first() + if not client: + raise KeyError("Invalid client id (not registered on server). Try to logout and then login.") + parent_client_id = request.matchdict.get('dictionary_client_id') + parent_object_id = request.matchdict.get('dictionary_object_id') + parent = DBSession.query(Dictionary).filter_by(client_id=parent_client_id, object_id=parent_object_id).first() + if not parent: + request.response.status = HTTPNotFound.code + return {'error': str("No such dictionary in the system")} + + perspective = DBSession.query(DictionaryPerspective).filter_by(client_id=client_id, object_id=object_id).first() + if perspective: + if not perspective.marked_for_deletion: + if perspective.parent != parent: + request.response.status = HTTPNotFound.code + return {'error': str("No such pair of dictionary/perspective in the system")} + req = request.json_body + if perspective.additional_metadata: + old_meta = json.loads(perspective.additional_metadata) + new_meta = req + old_meta.update(new_meta) + perspective.additional_metadata = json.dumps(old_meta) + else: + perspective.additional_metadata = json.dumps(req) + request.response.status = HTTPOk.code + return response + request.response.status = HTTPNotFound.code + return {'error': str("No such perspective in the system")} + + +@view_config(route_name='perspective_meta', renderer='json', request_method='DELETE', permission='edit') +def delete_perspective_meta(request): + response = dict() + client_id = request.matchdict.get('perspective_client_id') + object_id = request.matchdict.get('perspective_id') + client = DBSession.query(Client).filter_by(id=request.authenticated_userid).first() + if not client: + raise KeyError("Invalid client id (not registered on server). Try to logout and then login.") + parent_client_id = request.matchdict.get('dictionary_client_id') + parent_object_id = request.matchdict.get('dictionary_object_id') + parent = DBSession.query(Dictionary).filter_by(client_id=parent_client_id, object_id=parent_object_id).first() + if not parent: + request.response.status = HTTPNotFound.code + return {'error': str("No such dictionary in the system")} + + perspective = DBSession.query(DictionaryPerspective).filter_by(client_id=client_id, object_id=object_id).first() + if perspective: + if not perspective.marked_for_deletion: + if perspective.parent != parent: + request.response.status = HTTPNotFound.code + return {'error': str("No such pair of dictionary/perspective in the system")} + req = request.json_body + + old_meta = json.loads(perspective.additional_metadata) + new_meta = req + for entry in new_meta: + if entry in old_meta: + del old_meta[entry] + perspective.additional_metadata = json.dumps(old_meta) + request.response.status = HTTPOk.code + return response + request.response.status = HTTPNotFound.code + return {'error': str("No such perspective in the system")} + + +@view_config(route_name='perspective_meta', renderer='json', request_method='GET', permission='edit') +def view_perspective_meta(request): + response = dict() + client_id = request.matchdict.get('perspective_client_id') + object_id = request.matchdict.get('perspective_id') + client = DBSession.query(Client).filter_by(id=request.authenticated_userid).first() + if not client: + raise KeyError("Invalid client id (not registered on server). Try to logout and then login.") + parent_client_id = request.matchdict.get('dictionary_client_id') + parent_object_id = request.matchdict.get('dictionary_object_id') + parent = DBSession.query(Dictionary).filter_by(client_id=parent_client_id, object_id=parent_object_id).first() + if not parent: + request.response.status = HTTPNotFound.code + return {'error': str("No such dictionary in the system")} + + perspective = DBSession.query(DictionaryPerspective).filter_by(client_id=client_id, object_id=object_id).first() + if perspective: + if not perspective.marked_for_deletion: + if perspective.parent != parent: + request.response.status = HTTPNotFound.code + return {'error': str("No such pair of dictionary/perspective in the system")} + + old_meta = json.loads(perspective.additional_metadata) + response = old_meta + request.response.status = HTTPOk.code + return response + request.response.status = HTTPNotFound.code + return {'error': str("No such perspective in the system")} + + + @view_config(route_name='perspective', renderer='json', request_method='PUT', permission='edit') def edit_perspective(request): try: @@ -718,12 +1376,14 @@ def edit_perspective(request): request.response.status = HTTPNotFound.code return {'error': str("No such pair of dictionary/perspective in the system")} req = request.json_body + if 'translation' in req: perspective.set_translation(request) if 'parent_client_id' in req: perspective.parent_client_id = req['parent_client_id'] if 'parent_object_id' in req: perspective.parent_object_id = req['parent_object_id'] + is_template = req.get('is_template') if is_template is not None: perspective.is_template = is_template @@ -812,12 +1472,27 @@ def create_perspective(request): if not parent: request.response.status = HTTPNotFound.code return {'error': str("No such dictionary in the system")} + coord = {} + latitude = req.get('latitude') + longitude = req.get('longitude') + if latitude: + coord['latitude']=latitude + if longitude: + coord['longitude']=longitude + additional_metadata = req.get('additional_metadata') + if additional_metadata: + additional_metadata.update(coord) + else: + additional_metadata = coord + additional_metadata = json.dumps(additional_metadata) + perspective = DictionaryPerspective(object_id=DBSession.query(DictionaryPerspective).filter_by(client_id=client.id).count() + 1, client_id=variables['auth'], state='WiP', parent=parent, import_source=req.get('import_source'), - import_hash=req.get('import_hash')) + import_hash=req.get('import_hash'), + additional_metadata=additional_metadata) if is_template is not None: perspective.is_template = is_template perspective.set_translation(request) @@ -893,7 +1568,11 @@ def edit_perspective_status(request): if perspective.parent != parent: request.response.status = HTTPNotFound.code return {'error': str("No such pair of dictionary/perspective in the system")} - req = request.json_body + + if type(request.json_body) == str: + req = json.loads(request.json_body) + else: + req = request.json_body perspective.state = req['status'] request.response.status = HTTPOk.code return response @@ -939,7 +1618,11 @@ def edit_dictionary_roles(request): response = dict() client_id = request.matchdict.get('client_id') object_id = request.matchdict.get('object_id') - req = request.json_body + + if type(request.json_body) == str: + req = json.loads(request.json_body) + else: + req = request.json_body roles_users = None if 'roles_users' in req: roles_users = req['roles_users'] @@ -1166,7 +1849,11 @@ def edit_perspective_roles(request): object_id = request.matchdict.get('perspective_id') parent_client_id = request.matchdict.get('client_id') parent_object_id = request.matchdict.get('object_id') - req = request.json_body + + if type(request.json_body) == str: + req = json.loads(request.json_body) + else: + req = request.json_body roles_users = None if 'roles_users' in req: roles_users = req['roles_users'] @@ -1882,6 +2569,7 @@ def delete_perspective_fields(request): @view_config(route_name='perspective_fields', renderer='json', request_method='POST', permission='edit') def create_perspective_fields(request): + # TODO: stop recreating fields. Needs to be done both there and in web try: variables = {'auth': authenticated_userid(request)} parent_client_id = request.matchdict.get('perspective_client_id') @@ -2065,6 +2753,21 @@ class Object(object): return response +@view_config(route_name='get_user_blob', renderer='json', request_method='GET') +def get_user_blob(request): + variables = {'auth': authenticated_userid(request)} + response = dict() + client_id = request.matchdict.get('client_id') + object_id = request.matchdict.get('object_id') + blob = DBSession.query(UserBlobs).filter_by(client_id=client_id, object_id=object_id).first() + if blob: + response = {'name': blob.name, 'content': blob.content, 'data_type': blob.data_type, + 'client_id': blob.client_id, 'object_id': blob.object_id} + request.response.status = HTTPOk.code + return response + request.response.status = HTTPNotFound.code + return {'error': str("No such blob in the system")} + # seems to be redundant # @view_config(route_name='get_user_blob', request_method='GET') # def get_user_blob(request): @@ -2076,6 +2779,7 @@ class Object(object): # else: # raise HTTPNotFound + @view_config(route_name='list_user_blobs', renderer='json', request_method='GET') def list_user_blobs(request): variables = {'auth': authenticated_userid(request)} @@ -2108,9 +2812,7 @@ def create_l1_entity(request): if not parent: request.response.status = HTTPNotFound.code return {'error': str("No such lexical entry in the system")} - additional_metadata=req.get('additional_metadata') - if additional_metadata: - additional_metadata = json.dumps(additional_metadata) + additional_metadata = req.get('additional_metadata') entity = LevelOneEntity(client_id=client.id, object_id=DBSession.query(LevelOneEntity).filter_by(client_id=client.id).count() + 1, entity_type=req['entity_type'], locale_id=req['locale_id'], additional_metadata=additional_metadata, parent=parent) @@ -2125,6 +2827,22 @@ def create_l1_entity(request): if url and real_location: entity.content = url + old_meta = entity.additional_metadata + + need_hash = True + if old_meta: + new_meta=json.loads(old_meta) + if new_meta.get('hash'): + need_hash = False + if need_hash: + hash = hashlib.sha224(base64.urlsafe_b64decode(req['content'])).hexdigest() + hash_dict = {'hash': hash} + if old_meta: + new_meta = json.loads(old_meta) + new_meta.update(hash_dict) + else: + new_meta = hash_dict + entity.additional_metadata = json.dumps(new_meta) else: entity.content = req['content'] DBSession.add(entity) @@ -2144,6 +2862,7 @@ def create_l1_entity(request): request.response.status = HTTPConflict.code return {'error': str(e)} + @view_config(route_name='create_entities_bulk', renderer='json', request_method='POST', permission='create') def create_entities_bulk(request): try: @@ -2195,6 +2914,22 @@ def create_entities_bulk(request): if url and real_location: entity.content = url + old_meta = entity.additional_metadata + + need_hash = True + if old_meta: + new_meta=json.loads(old_meta) + if new_meta.get('hash'): + need_hash = False + if need_hash: + hash = hashlib.sha224(base64.urlsafe_b64decode(req['content'])).hexdigest() + hash_dict = {'hash': hash} + if old_meta: + new_meta = json.loads(old_meta) + new_meta.update(hash_dict) + else: + new_meta = hash_dict + entity.additional_metadata = json.dumps(new_meta) else: entity.content = item['content'] DBSession.add(entity) @@ -2291,6 +3026,7 @@ def delete_l2_entity(request): @view_config(route_name='create_level_two_entity', renderer='json', request_method='POST', permission='create') def create_l2_entity(request): try: + variables = {'auth': authenticated_userid(request)} response = dict() parent_client_id = request.matchdict.get('level_one_client_id') @@ -2307,9 +3043,11 @@ def create_l2_entity(request): if not parent: request.response.status = HTTPNotFound.code return {'error': str("No such level one entity in the system")} + additional_metadata = req.get('additional_metadata') entity = LevelTwoEntity(client_id=client.id, object_id=DBSession.query(LevelTwoEntity).filter_by(client_id=client.id).count() + 1, entity_type=req['entity_type'], - locale_id=req['locale_id'], additional_metadata=req.get('additional_metadata'), + locale_id=req['locale_id'], additional_metadata=additional_metadata, parent=parent) + DBSession.add(entity) DBSession.flush() data_type = req.get('data_type') @@ -2321,6 +3059,22 @@ def create_l2_entity(request): if url and real_location: entity.content = url + old_meta = entity.additional_metadata + + need_hash = True + if old_meta: + new_meta=json.loads(old_meta) + if new_meta.get('hash'): + need_hash = False + if need_hash: + hash = hashlib.sha224(base64.urlsafe_b64decode(req['content'])).hexdigest() + hash_dict = {'hash': hash} + if old_meta: + new_meta = json.loads(old_meta) + new_meta.update(hash_dict) + else: + new_meta = hash_dict + entity.additional_metadata = json.dumps(new_meta) else: entity.content = req['content'] DBSession.add(entity) @@ -2457,7 +3211,7 @@ def delete_group_entity(request): @view_config(route_name='add_group_indict', renderer='json', request_method='POST') # TODO: check for permission -@view_config(route_name='add_group_entity', renderer='json', request_method='POST') # TODO: check for permission +@view_config(route_name='add_group_entity', renderer='json', request_method='POST') def create_group_entity(request): try: variables = {'auth': authenticated_userid(request)} @@ -2714,8 +3468,8 @@ def lexical_entries_published(request): .join(LevelOneEntity, and_(LevelOneEntity.parent_client_id == LexicalEntry.client_id, LevelOneEntity.parent_object_id == LexicalEntry.object_id, LevelOneEntity.marked_for_deletion == False)) \ - .outerjoin(PublishLevelOneEntity, and_(PublishLevelOneEntity.parent_client_id == LevelOneEntity.client_id, - PublishLevelOneEntity.parent_object_id == LevelOneEntity.object_id, + .join(PublishLevelOneEntity, and_(PublishLevelOneEntity.entity_client_id == LevelOneEntity.client_id, + PublishLevelOneEntity.entity_object_id == LevelOneEntity.object_id, PublishLevelOneEntity.marked_for_deletion == False)) \ .order_by(func.min(case([(LevelOneEntity.entity_type != sort_criterion, 'яяяяяя')], else_=LevelOneEntity.content))) \ .offset(start_from).limit(count) @@ -2817,10 +3571,18 @@ def get_user_info(request): request.response.status = HTTPNotFound.code return {'error': str("No such user in the system")} - else: + elif user_id: user = DBSession.query(User).filter_by(id=user_id).first() if not user: - + request.response.status = HTTPNotFound.code + return {'error': str("No such user in the system")} + else: + client = DBSession.query(Client).filter_by(id=authenticated_userid(request)).first() + if not client: + request.response.status = HTTPNotFound.code + return {'error': str("No such client in the system")} + user = DBSession.query(User).filter_by(id=client.user_id).first() + if not user: request.response.status = HTTPNotFound.code return {'error': str("No such user in the system")} response['id']=user.id @@ -2853,15 +3615,18 @@ def get_user_info(request): @view_config(route_name='get_user_info', renderer='json', request_method='PUT') def edit_user_info(request): + from passlib.hash import bcrypt response = dict() + + req = request.json_body client_id = None try: - client_id = request.params.get('client_id') + client_id = req.get('client_id') except: pass user_id=None try: - user_id = request.params.get('user_id') + user_id = req.get('user_id') except: pass user = None @@ -2872,6 +3637,7 @@ def edit_user_info(request): request.response.status = HTTPNotFound.code return {'error': str("No such client in the system")} user = DBSession.query(User).filter_by(id=client.user_id).first() + user_id = client.user_id if not user: request.response.status = HTTPNotFound.code @@ -2882,25 +3648,51 @@ def edit_user_info(request): request.response.status = HTTPNotFound.code return {'error': str("No such user in the system")} - req = request.json_body - user.name=req['name'] - user.default_locale_id = req['default_locale_id'] - user.birthday = datetime.date(response['birthday']) - if user.email: - for em in user.email: - em.email = req['email'] - else: - new_email = Email(user=user, email=req['email']) - DBSession.add(new_email) - DBSession.flush() - if user.about: - for ab in user.about: - ab.content = req['about'] - else: - new_about = About(user=user, email=req['about']) - DBSession.add(new_about) - DBSession.flush() - + new_password = req.get('new_password') + old_password = req.get('old_password') + if new_password: + if not old_password: + request.response.status = HTTPBadRequest.code + return {'error': str("Need old password to confirm")} + old_hash = DBSession.query(Passhash).filter_by(user_id=user_id).first() + if old_hash: + if not user.check_password(old_password): + request.response.status = HTTPBadRequest.code + return {'error': str("Wrong password")} + else: + old_hash.hash = bcrypt.encrypt(new_password) + else: + request.response.status = HTTPInternalServerError.code + return {'error': str("User has no password")} + + name = req.get('name') + if name: + user.name = name + default_locale_id = req.get('default_locale_id') + if default_locale_id: + user.default_locale_id = default_locale_id + birthday = req.get('birthday') + if birthday: + user.birthday = datetime.date(birthday) + email = req.get('email') + if email: + if user.email: + for em in user.email: + + em.email = email + else: + new_email = Email(user=user, email=email) + DBSession.add(new_email) + DBSession.flush() + about = req.get('about') + if about: + if user.about: + for ab in user.about: + ab.content = req['about'] + else: + new_about = About(user=user, about=about) + DBSession.add(new_about) + DBSession.flush() # response['is_active']=str(user.is_active) request.response.status = HTTPOk.code return response @@ -3089,7 +3881,11 @@ def get_translations(request): return response -@view_config(route_name='merge_dictionaries', renderer='json', request_method='POST') # TODO: check for permission + + + + +@view_config(route_name='merge_dictionaries', renderer='json', request_method='POST') def merge_dictionaries(request): try: req = request.json_body @@ -3217,7 +4013,7 @@ def merge_dictionaries(request): return {'error': str(e)} -@view_config(route_name='merge_perspectives', renderer='json', request_method='POST') # TODO: check for permission +@view_config(route_name='merge_perspectives', renderer='json', request_method='POST') def merge_perspectives_api(request): try: req = request.json_body @@ -3534,7 +4330,6 @@ def move_lexical_entry_bulk(request): DBSession.flush() entry.moved_to = str(cli_id) + '/' + str(obj_id) entry.marked_for_deletion = True - print(client_id, object_id) request.response.status = HTTPOk.code return {} @@ -3858,18 +4653,256 @@ def create_organization(request): """ +@view_config(route_name='dangerous_perspectives_hash', renderer='json', request_method='PUT', permission='edit') +def dangerous_perspectives_hash(request): + response = dict() + perspectives = DBSession.query(DictionaryPerspective) + for perspective in perspectives: + path = request.route_url('perspective_hash', + dictionary_client_id=perspective.parent_client_id, + dictionary_object_id=perspective.parent_object_id, + perspective_client_id=perspective.client_id, + perspective_id=perspective.object_id) + subreq = Request.blank(path) + subreq.method = 'PUT' + subreq.headers = request.headers + resp = request.invoke_subrequest(subreq) + print('Perspective', perspective.client_id, perspective.object_id, 'ready') + request.response.status = HTTPOk.code + return response + + +@view_config(route_name='perspective_hash', renderer='json', request_method='PUT', permission='edit') +def edit_perspective_hash(request): + import requests + try: + response = dict() + client_id = request.matchdict.get('perspective_client_id') + object_id = request.matchdict.get('perspective_id') + client = DBSession.query(Client).filter_by(id=request.authenticated_userid).first() + if not client: + raise KeyError("Invalid client id (not registered on server). Try to logout and then login.") + parent_client_id = request.matchdict.get('dictionary_client_id') + parent_object_id = request.matchdict.get('dictionary_object_id') + parent = DBSession.query(Dictionary).filter_by(client_id=parent_client_id, object_id=parent_object_id).first() + if not parent: + request.response.status = HTTPNotFound.code + return {'error': str("No such dictionary in the system")} + + perspective = DBSession.query(DictionaryPerspective).filter_by(client_id=client_id, object_id=object_id).first() + if perspective: + if not perspective.marked_for_deletion: + l1es = DBSession.query(LevelOneEntity)\ + .join(LexicalEntry, + and_(LevelOneEntity.parent_client_id == LexicalEntry.client_id, + LevelOneEntity.parent_object_id == LexicalEntry.object_id, + LexicalEntry.parent_client_id == client_id, + LexicalEntry.parent_object_id == object_id))\ + .filter(func.lower(LevelOneEntity.entity_type).like('%sound%'), or_(LevelOneEntity.additional_metadata == None, + not_(LevelOneEntity.additional_metadata.like('%hash%')))) + count_l1e = l1es.count() + for l1e in l1es: + + url = l1e.content + try: + r = requests.get(url) + hash = hashlib.sha224(r.content).hexdigest() + old_meta = l1e.additional_metadata + hash_dict = {'hash': hash} + if old_meta: + new_meta = json.loads(old_meta) + new_meta.update(hash_dict) + else: + new_meta = hash_dict + l1e.additional_metadata = json.dumps(new_meta) + except: + print('fail with sound', l1e.client_id, l1e.object_id) + l2es = DBSession.query(LevelTwoEntity)\ + .join(LevelOneEntity, + and_(LevelTwoEntity.parent_client_id == LevelOneEntity.client_id, + LevelTwoEntity.parent_object_id == LevelOneEntity.object_id))\ + .join(LexicalEntry, + and_(LevelOneEntity.parent_client_id == LexicalEntry.client_id, + LevelOneEntity.parent_object_id == LexicalEntry.object_id, + LexicalEntry.parent_client_id == client_id, + LexicalEntry.parent_object_id == object_id))\ + .filter(func.lower(LevelTwoEntity.entity_type).like('%markup%'), or_(LevelTwoEntity.additional_metadata == None, + not_(LevelTwoEntity.additional_metadata.like('%hash%')))) + count_l2e = l2es.count() + for l2e in l2es: + url = l2e.content + try: + r = requests.get(url) + hash = hashlib.sha224(r.content).hexdigest() + old_meta = l2e.additional_metadata + hash_dict = {'hash': hash} + if old_meta: + new_meta = json.loads(old_meta) + new_meta.update(hash_dict) + else: + new_meta = hash_dict + l2e.additional_metadata = json.dumps(new_meta) + except: + print('fail with markup', l2e.client_id, l2e.object_id) + response['count_l1e'] = count_l1e + response['count_l2e'] = count_l2e + request.response.status = HTTPOk.code + return response + else: + request.response.status = HTTPNotFound.code + return {'error': str("No such perspective in the system")} + except KeyError as e: + request.response.status = HTTPBadRequest.code + return {'error': str(e)} + + +@view_config(route_name='convert', renderer='json', request_method='POST') +def convert(request): # TODO: test when convert in blobs will be needed + import requests + try: + variables = {'auth': request.authenticated_userid} + req = request.json_body + client = DBSession.query(Client).filter_by(id=variables['auth']).first() + if not client: + raise KeyError("Invalid client id (not registered on server). Try to logout and then login.") + user = DBSession.query(User).filter_by(id=client.user_id).first() + if not user: + raise CommonException("This client id is orphaned. Try to logout and then login once more.") + out_type = req['out_type'] + client_id = req['client_id'] + object_id = req['object_id'] + + blob = DBSession.query(UserBlobs).filter_by(client_id=client_id, object_id=object_id).first() + if not blob: + raise KeyError("No such file") + r = requests.get(blob.content) + if not r: + raise CommonException("Cannot access file") + content = r.content + try: + n = 10 + filename = time.ctime() + ''.join(random.SystemRandom().choice(string.ascii_uppercase + string.digits) + for c in range(n)) + extension = os.path.splitext(blob.content)[1] + f = open(filename + extension, 'wb') + except Exception as e: + request.response.status = HTTPInternalServerError.code + return {'error': str(e)} + try: + f.write(content) + f.close() + data_type = blob.data_type + for rule in rules: + if data_type == rule.in_type and out_type == rule.out_type: + if extension in rule.in_extensions: + if os.path.getsize(filename) / 1024 / 1024.0 < rule.max_in_size: + content = rule.convert(filename, req.get('config'), rule.converter_config) + if sys.getsizeof(content) / 1024 / 1024.0 < rule.max_out_size: + request.response.status = HTTPOk.code + return {'content': content} + raise KeyError("Cannot access file") + except Exception as e: + request.response.status = HTTPInternalServerError.code + return {'error': str(e)} + finally: + os.remove(filename) + pass + except KeyError as e: + request.response.status = HTTPBadRequest.code + return {'error': str(e)} + + except IntegrityError as e: + request.response.status = HTTPInternalServerError.code + return {'error': str(e)} + + except CommonException as e: + request.response.status = HTTPConflict.code + return {'error': str(e)} + + +@view_config(route_name='convert_markup', renderer='json', request_method='POST') +def convert_markup(request): + import requests + from .scripts.convert_rules import praat_to_elan + try: + variables = {'auth': request.authenticated_userid} + req = request.json_body + client = DBSession.query(Client).filter_by(id=variables['auth']).first() + if not client: + raise KeyError("Invalid client id (not registered on server). Try to logout and then login.") + user = DBSession.query(User).filter_by(id=client.user_id).first() + if not user: + raise CommonException("This client id is orphaned. Try to logout and then login once more.") + # out_type = req['out_type'] + client_id = req['client_id'] + object_id = req['object_id'] + + l2e = DBSession.query(LevelTwoEntity).filter_by(client_id=client_id, object_id=object_id).first() + if not l2e: + raise KeyError("No such file") + r = requests.get(l2e.content) + if not r: + raise CommonException("Cannot access file") + content = r.content + try: + n = 10 + filename = time.ctime() + ''.join(random.SystemRandom().choice(string.ascii_uppercase + string.digits) + for c in range(n)) + # extension = os.path.splitext(blob.content)[1] + f = open(filename, 'wb') + except Exception as e: + request.response.status = HTTPInternalServerError.code + return {'error': str(e)} + try: + f.write(content) + f.close() + if os.path.getsize(filename) / 1024 / 1024.0 < 1: + if 'praat' in l2e.entity_type.lower(): + content = praat_to_elan(filename) + if sys.getsizeof(content) / 1024 / 1024.0 < 1: + # filename2 = 'abc.xml' + # f2 = open(filename2, 'w') + # try: + # f2.write(content) + # f2.close() + # # os.system('xmllint --noout --dtdvalid ' + filename2 + '> xmloutput 2>&1') + # os.system('xmllint --dvalid ' + filename2 + '> xmloutput 2>&1') + # except: + # print('fail with xmllint') + # finally: + # pass + # os.remove(filename2) + return {'content': content} + raise KeyError('File too big') + raise KeyError("Not allowed convert option") + raise KeyError('File too big') + except Exception as e: + request.response.status = HTTPInternalServerError.code + return {'error': str(e)} + finally: + os.remove(filename) + pass + except KeyError as e: + request.response.status = HTTPBadRequest.code + return {'error': str(e)} + + except IntegrityError as e: + request.response.status = HTTPInternalServerError.code + return {'error': str(e)} + + except CommonException as e: + request.response.status = HTTPConflict.code + return {'error': str(e)} + + @view_config(route_name='testing', renderer='json') def testing(request): - lexes = list(DBSession.query(LexicalEntry).filter_by(parent_client_id = 2, parent_object_id = 1).all()) - lexes_1 = [] - lexes_2 = [] - if not lexes: - return json.dumps({}) - # first_persp = json.loads(lexes[0].additional_metadata)['came_from'] - lexes_1 = [o.track(False) for o in lexes] - remove_deleted(lexes_1) - lexes_2 = list(lexes_1) - return {'list_1':lexes_1, 'list_2':lexes_2} + try: + return 20/15 + except Exception as e: + return str(e) + finally: + print('Good news, everyone!') @view_config(route_name='login', renderer='templates/login.pt', request_method='GET') @@ -4168,21 +5201,22 @@ def remove_deleted(lst): @view_config(route_name='merge_suggestions', renderer='json', request_method='POST') def merge_suggestions(request): req = request.json - entity_type_primary = req['entity_type_primary'] or 'Word' - entity_type_secondary = req['entity_type_secondary'] or 'Transcription' + entity_type_primary = req.get('entity_type_primary') or 'Transcription' + entity_type_secondary = req.get('entity_type_secondary') or 'Translation' threshold = req['threshold'] or 0.2 levenstein = req['levenstein'] or 1 client_id = req['client_id'] object_id = req['object_id'] - lexes = list(DBSession.query(LexicalEntry).filter_by(parent_client_id = client_id, parent_object_id = object_id).all()) - lexes_1 = [] - lexes_2 = [] + lexes = list(DBSession.query(LexicalEntry).filter_by(parent_client_id=client_id, + parent_object_id=object_id, + marked_for_deletion=False).all()) if not lexes: - return json.dumps({}) + return json.dumps([]) # first_persp = json.loads(lexes[0].additional_metadata)['came_from'] lexes_1 = [o.track(False) for o in lexes] remove_deleted(lexes_1) lexes_2 = list(lexes_1) + def parse_response(elem): words = filter(lambda x: x['entity_type'] == entity_type_primary and not x['marked_for_deletion'], elem['contains']) words = map(lambda x: x['content'], words) @@ -4190,6 +5224,7 @@ def parse_response(elem): trans = map(lambda x: x['content'], trans) tuples_res = [(i_word, i_trans, (elem['client_id'], elem['object_id'])) for i_word in words for i_trans in trans] return tuples_res + tuples_1 = [parse_response(i) for i in lexes_1] tuples_1 = [item for sublist in tuples_1 for item in sublist] tuples_2 = [parse_response(i) for i in lexes_2] @@ -4203,6 +5238,7 @@ def get_dict(elem): if (not tuples_1) or (not tuples_2): return {} results = [get_dict(i) for i in mergeDicts(tuples_1, tuples_2, float(threshold), int(levenstein))] + results = sorted(results, key=lambda k: k['confidence']) return results @view_config(route_name='profile', renderer='templates/profile.pt', request_method='GET') @@ -4234,3 +5270,13 @@ def merge_master_get(request): return HTTPFound(location=request.route_url('login'), headers=response.headers) variables = {'client_id': client_id, 'user': user } return render_to_response('templates/merge_master.pt', variables, request=request) + +@view_config(route_name='maps', renderer='templates/maps.pt', request_method='GET') +def maps_get(request): + client_id = authenticated_userid(request) + user = get_user_by_client_id(client_id) + if user is None: + response = Response() + return HTTPFound(location=request.route_url('login'), headers=response.headers) + variables = {'client_id': client_id, 'user': user } + return render_to_response('templates/maps.pt', variables, request=request) diff --git a/webui/Gruntfile.js b/webui/Gruntfile.js index 4abb6b062..43c0dd2fa 100755 --- a/webui/Gruntfile.js +++ b/webui/Gruntfile.js @@ -56,6 +56,7 @@ module.exports = function(grunt) { login: { src: [ 'bower_components/jquery/dist/jquery.js', + 'bower_components/lodash/lodash.js', 'bower_components/angular/angular.js', 'bower_components/bootstrap-sass/assets/javascripts/bootstrap.js', 'bower_components/angular-bootstrap/ui-bootstrap.js', @@ -68,6 +69,7 @@ module.exports = function(grunt) { home: { src: [ 'bower_components/jquery/dist/jquery.js', + 'bower_components/lodash/lodash.js', 'bower_components/angular/angular.js', 'bower_components/bootstrap-sass/assets/javascripts/bootstrap.js', 'bower_components/angular-bootstrap/ui-bootstrap.js', @@ -82,11 +84,12 @@ module.exports = function(grunt) { dashboard: { src: [ 'bower_components/jquery/dist/jquery.js', - 'bower_components/underscore/underscore.js', + 'bower_components/lodash/lodash.js', 'bower_components/angular/angular.js', 'bower_components/bootstrap-sass/assets/javascripts/bootstrap.js', 'bower_components/angular-bootstrap/ui-bootstrap.js', 'bower_components/angular-bootstrap/ui-bootstrap-tpls.js', + 'bower_components/ngmap/build/scripts/ng-map.js', 'src/js/util.js', 'src/js/api.js', 'src/js/response_handler.js', @@ -97,11 +100,11 @@ module.exports = function(grunt) { languages: { src: [ 'bower_components/jquery/dist/jquery.js', + 'bower_components/lodash/lodash.js', 'bower_components/angular/angular.js', 'bower_components/bootstrap-sass/assets/javascripts/bootstrap.js', 'bower_components/angular-bootstrap/ui-bootstrap.js', 'bower_components/angular-bootstrap/ui-bootstrap-tpls.js', - 'bower_components/wavesurfer.js/dist/wavesurfer.min.js', 'bower_components/autocomplete/script/autocomplete.js', 'src/js/languages.js', 'src/js/response_handler.js' @@ -111,6 +114,7 @@ module.exports = function(grunt) { createdictionary: { src: [ 'bower_components/jquery/dist/jquery.js', + 'bower_components/lodash/lodash.js', 'bower_components/angular/angular.js', 'bower_components/bootstrap-sass/assets/javascripts/bootstrap.js', 'bower_components/angular-bootstrap/ui-bootstrap.js', @@ -129,11 +133,14 @@ module.exports = function(grunt) { viewdictionary: { src: [ 'bower_components/jquery/dist/jquery.js', + 'bower_components/lodash/lodash.js', 'bower_components/angular/angular.js', 'bower_components/bootstrap-sass/assets/javascripts/bootstrap.js', 'bower_components/angular-bootstrap/ui-bootstrap.js', 'bower_components/angular-bootstrap/ui-bootstrap-tpls.js', 'bower_components/wavesurfer.js/dist/wavesurfer.min.js', + 'bower_components/wavesurfer.js/dist/plugin/wavesurfer.regions.min.js', + 'bower_components/wavesurfer.js/dist/plugin/wavesurfer.spectrogram.min.js', 'src/js/model.js', 'src/js/elan.js', 'src/js/util.js', @@ -147,11 +154,14 @@ module.exports = function(grunt) { publishdictionary: { src: [ 'bower_components/jquery/dist/jquery.js', + 'bower_components/lodash/lodash.js', 'bower_components/angular/angular.js', 'bower_components/bootstrap-sass/assets/javascripts/bootstrap.js', 'bower_components/angular-bootstrap/ui-bootstrap.js', 'bower_components/angular-bootstrap/ui-bootstrap-tpls.js', 'bower_components/wavesurfer.js/dist/wavesurfer.min.js', + 'bower_components/wavesurfer.js/dist/plugin/wavesurfer.regions.min.js', + 'bower_components/wavesurfer.js/dist/plugin/wavesurfer.spectrogram.min.js', 'src/js/model.js', 'src/js/elan.js', 'src/js/util.js', @@ -165,12 +175,14 @@ module.exports = function(grunt) { editdictionary: { src: [ 'bower_components/jquery/dist/jquery.js', - 'bower_components/underscore/underscore.js', + 'bower_components/lodash/lodash.js', 'bower_components/angular/angular.js', 'bower_components/bootstrap-sass/assets/javascripts/bootstrap.js', 'bower_components/angular-bootstrap/ui-bootstrap.js', 'bower_components/angular-bootstrap/ui-bootstrap-tpls.js', 'bower_components/wavesurfer.js/dist/wavesurfer.min.js', + 'bower_components/wavesurfer.js/dist/plugin/wavesurfer.regions.min.js', + 'bower_components/wavesurfer.js/dist/plugin/wavesurfer.spectrogram.min.js', 'src/js/model.js', 'src/js/elan.js', 'src/js/util.js', @@ -184,11 +196,11 @@ module.exports = function(grunt) { userupload: { src: [ 'bower_components/jquery/dist/jquery.js', + 'bower_components/lodash/lodash.js', 'bower_components/angular/angular.js', 'bower_components/bootstrap-sass/assets/javascripts/bootstrap.js', 'bower_components/angular-bootstrap/ui-bootstrap.js', 'bower_components/angular-bootstrap/ui-bootstrap-tpls.js', - 'bower_components/wavesurfer.js/dist/wavesurfer.min.js', 'src/js/response_handler.js', 'src/js/user_upload.js' ], @@ -197,12 +209,11 @@ module.exports = function(grunt) { profile: { src: [ 'bower_components/jquery/dist/jquery.js', + 'bower_components/lodash/lodash.js', 'bower_components/angular/angular.js', 'bower_components/bootstrap-sass/assets/javascripts/bootstrap.js', 'bower_components/angular-bootstrap/ui-bootstrap.js', 'bower_components/angular-bootstrap/ui-bootstrap-tpls.js', - 'bower_components/wavesurfer.js/dist/wavesurfer.min.js', - 'bower_components/autocomplete/script/autocomplete.js', 'src/js/util.js', 'src/js/api.js', 'src/js/response_handler.js', @@ -213,12 +224,11 @@ module.exports = function(grunt) { organizations: { src: [ 'bower_components/jquery/dist/jquery.js', + 'bower_components/lodash/lodash.js', 'bower_components/angular/angular.js', 'bower_components/bootstrap-sass/assets/javascripts/bootstrap.js', 'bower_components/angular-bootstrap/ui-bootstrap.js', 'bower_components/angular-bootstrap/ui-bootstrap-tpls.js', - 'bower_components/wavesurfer.js/dist/wavesurfer.min.js', - 'bower_components/autocomplete/script/autocomplete.js', 'src/js/util.js', 'src/js/api.js', 'src/js/response_handler.js', @@ -229,6 +239,7 @@ module.exports = function(grunt) { merge_master: { src: [ 'bower_components/jquery/dist/jquery.js', + 'bower_components/lodash/lodash.js', 'bower_components/angular/angular.js', 'bower_components/bootstrap-sass/assets/javascripts/bootstrap.js', 'bower_components/angular-bootstrap/ui-bootstrap.js', @@ -240,6 +251,28 @@ module.exports = function(grunt) { 'src/js/merge_master.js' ], dest: '../lingvodoc/static/js/merge-master.js' + }, + maps: { + src: [ + 'bower_components/jquery/dist/jquery.js', + 'bower_components/lodash/lodash.js', + 'bower_components/angular/angular.js', + 'bower_components/bootstrap-sass/assets/javascripts/bootstrap.js', + 'bower_components/angular-bootstrap/ui-bootstrap.js', + 'bower_components/angular-bootstrap/ui-bootstrap-tpls.js', + 'bower_components/angular-animate/angular-animate.js', + 'bower_components/ngmap/build/scripts/ng-map.js', + 'bower_components/wavesurfer.js/dist/wavesurfer.min.js', + 'bower_components/wavesurfer.js/dist/plugin/wavesurfer.regions.min.js', + 'bower_components/wavesurfer.js/dist/plugin/wavesurfer.spectrogram.min.js', + 'src/js/elan.js', + 'src/js/lingvowave.js', + 'src/js/util.js', + 'src/js/api.js', + 'src/js/response_handler.js', + 'src/js/maps.js' + ], + dest: '../lingvodoc/static/js/maps.js' } } }); diff --git a/webui/bower.json b/webui/bower.json index 39d059a18..e2f21a30f 100755 --- a/webui/bower.json +++ b/webui/bower.json @@ -13,16 +13,15 @@ "tests" ], "dependencies": { - "underscore": "~1.8.3", + "lodash": "~3.10", "angular": "~1.4.6", - "autocomplete": "git://github.com/JustGoscha/allmighty-autocomplete", "bootstrap-sass": "bootstrap-sass-official#~3.3.5", "bootstrap-validator": "git://github.com/1000hz/bootstrap-validator", "angular-bootstrap": "0.13.4", "angular-route": "~1.4.6", "angular-ui-router": "0.2.15", "angular-animate": "~1.4.6", - "wavesurfer.js": "git://github.com/katspaugh/wavesurfer.js#~1.0.42" - + "ngmap": "1.14.14", + "wavesurfer.js": "git://github.com/katspaugh/wavesurfer.js#1.0.42" } } diff --git a/webui/src/js/api.js b/webui/src/js/api.js index f2f4270ec..5181c9ba0 100755 --- a/webui/src/js/api.js +++ b/webui/src/js/api.js @@ -7,12 +7,8 @@ lingvodoc.Object = function(clientId, objectId) { this.type = 'abstract'; this.getId = function() { - return this.client_id + '' + this.object_id; + return this.client_id + '_' + this.object_id; }; - - this.export = function() { - return {}; - } }; lingvodoc.Object.prototype.equals = function(obj) { return !!(this.client_id == obj.client_id && this.object_id == obj.object_id); @@ -86,6 +82,9 @@ lingvodoc.Perspective = function(client_id, object_id, parent_client_id, parent_ this.is_template = is_template; this.marked_for_deletion = marked_for_deletion; this.fields = []; + this.location = null; + this.blobs = []; + this.additional_metadata = {}; this.equals = function(obj) { return lingvodoc.Object.prototype.equals.call(this, obj) && @@ -93,8 +92,27 @@ lingvodoc.Perspective = function(client_id, object_id, parent_client_id, parent_ }; }; lingvodoc.Perspective.fromJS = function (js) { - return new lingvodoc.Perspective(js.client_id, js.object_id, js.parent_client_id, js.parent_object_id, + var perspective = new lingvodoc.Perspective(js.client_id, js.object_id, js.parent_client_id, js.parent_object_id, js.translation, js.translation_string, js.status, js.is_template, js.marked_for_deletion); + + if (_.has(js, 'location') && _.has(js.location, 'content')) { + perspective['location'] = {'lat': js.location.content.lat, 'lng': js.location.content.lng}; + } + + if (_.has(js, 'info') && js.info.type == 'list') { + if (_.isArray(js.info.content)) { + perspective['blobs'] = _.map(js.info.content, function(e) { + var blob = new lingvodoc.Blob(e.info.content.client_id, e.info.content.object_id, e.info.content.name, e.info.content.data_type); + blob.url = e.info.content.content; + return blob; + }); + } + } + + perspective.additional_metadata = js.additional_metadata; + + return perspective; + }; lingvodoc.Perspective.prototype = new lingvodoc.Object(); lingvodoc.Perspective.prototype.constructor = lingvodoc.Perspective; @@ -118,6 +136,25 @@ lingvodoc.User.fromJS = function (js) { return new lingvodoc.User(js.id, js.login, js.name, js.email, js.intl_name, js.about, js.signup_date, js.organizations); }; +lingvodoc.Blob = function(clientId, objectId, name, data_type) { + + lingvodoc.Object.call(this, clientId, objectId); + this.type = 'blob'; + this.name = name; + this.data_type = data_type; + this.url = null; + + this.equals = function(obj) { + return lingvodoc.Object.prototype.equals.call(this, obj) && (this.name == obj.name); + }; +}; +lingvodoc.Blob.fromJS = function (js) { + return new lingvodoc.Blob(js.client_id, js.object_id, js.name, js.data_type); +}; +lingvodoc.Blob.prototype = new lingvodoc.Object(); +lingvodoc.Blob.prototype.constructor = lingvodoc.Blob; + + function lingvodocAPI($http, $q) { @@ -208,6 +245,22 @@ function lingvodocAPI($http, $q) { return deferred.promise; }; + var getPerspectiveDictionaryFieldsNew = function(perspective) { + var deferred = $q.defer(); + var url = '/dictionary/' + perspective.parent_client_id + '/' + perspective.parent_object_id + '/perspective/' + perspective.client_id + '/' + perspective.object_id + '/fields'; + $http.get(url).success(function(data, status, headers, config) { + if (_.isArray(data.fields)) { + var fields = perspectiveToDictionaryFields(data.fields); + deferred.resolve(fields); + } else { + deferred.reject('An error occurred while fetching perspective fields'); + } + }).error(function(data, status, headers, config) { + deferred.reject('An error occurred while fetching perspective fields'); + }); + return deferred.promise; + }; + var removeValue = function(entry, field, fieldValue, parent) { var deferred = $q.defer(); @@ -405,21 +458,20 @@ function lingvodocAPI($http, $q) { return deferred.promise; }; - var getDictionaryProperties = function(url) { - + var getDictionaryProperties = function(dictionary) { var deferred = $q.defer(); + var url = '/dictionary/' + encodeURIComponent(dictionary.client_id) + '/' + encodeURIComponent(dictionary.object_id); $http.get(url).success(function(data, status, headers, config) { deferred.resolve(data); }).error(function(data, status, headers, config) { deferred.reject('An error occurred while trying to get dictionary properties'); }); - return deferred.promise; }; - var setDictionaryProperties = function(url, properties) { - + var setDictionaryProperties = function(dictionary, properties) { var deferred = $q.defer(); + var url = '/dictionary/' + encodeURIComponent(dictionary.client_id) + '/' + encodeURIComponent(dictionary.object_id); $http.put(url, properties).success(function(data, status, headers, config) { deferred.resolve(data); }).error(function(data, status, headers, config) { @@ -429,6 +481,19 @@ function lingvodocAPI($http, $q) { return deferred.promise; }; + var removeDictionary = function(dictionary) { + var deferred = $q.defer(); + var url = '/dictionary/' + encodeURIComponent(dictionary.client_id) + '/' + encodeURIComponent(dictionary.object_id); + $http.delete(url).success(function(data, status, headers, config) { + deferred.resolve(); + }).error(function(data, status, headers, config) { + deferred.reject('An error occurred while trying to delete dictionary'); + }); + return deferred.promise; + }; + + + var getLanguages = function(url) { var deferred = $q.defer(); var flatLanguages = function (languages) { @@ -530,6 +595,17 @@ function lingvodocAPI($http, $q) { return deferred.promise; }; + var removePerspective = function(perspective) { + var deferred = $q.defer(); + var url = '/dictionary/' + perspective.parent_client_id + '/' + perspective.parent_object_id + '/perspective/' + perspective.client_id + '/' + perspective.object_id; + $http.delete(url).success(function(data, status, headers, config) { + deferred.resolve(); + }).error(function(data, status, headers, config) { + deferred.reject('An error occurred while trying to delete perspective'); + }); + return deferred.promise; + }; + var getUserInfo = function(userId, clientId) { var deferred = $q.defer(); var url = '/user' + '?client_id= ' + encodeURIComponent(clientId) + '&user_id= ' + encodeURIComponent(userId); @@ -635,17 +711,16 @@ function lingvodocAPI($http, $q) { }; var getDictionaries = function(query) { - var deferred = $q.defer(); - var dictionaries = []; $http.post('/dictionaries', query).success(function (data, status, headers, config) { - - for (var i = 0; i < data.dictionaries.length; i++) { - var dictionary = data.dictionaries[i]; - dictionaries.push(lingvodoc.Dictionary.fromJS(dictionary)); + if (_.isArray(data.dictionaries)) { + deferred.resolve(_.map(data.dictionaries, function(d) { + return lingvodoc.Dictionary.fromJS(d); + })); + } else { + deferred.reject('Failed to fetch dictionaries list. Malformed response.'); } - deferred.resolve(dictionaries); }).error(function (data, status, headers, config) { deferred.reject('Failed to fetch dictionaries list'); }); @@ -892,8 +967,8 @@ function lingvodocAPI($http, $q) { $http.post('/dictionaries', req).success(function(data, status, headers, config) { var dictionaries = []; - if (angular.isArray(data.dictionaries)) { - angular.forEach(data.dictionaries, function(jsdict) { + if (_.isArray(data.dictionaries)) { + _.forEach(data.dictionaries, function(jsdict) { var dictionary = lingvodoc.Dictionary.fromJS(jsdict); if (language.client_id == dictionary.parent_client_id && language.object_id == dictionary.parent_object_id) { dictionaries.push(dictionary); @@ -902,7 +977,7 @@ function lingvodocAPI($http, $q) { } deferred.resolve(dictionaries); }).error(function(data, status, headers, config) { - deferred.reject('Failed to move lexical entry'); + deferred.reject('Failed to fetch list of dictionaries'); }); return deferred.promise; }; @@ -1112,6 +1187,148 @@ function lingvodocAPI($http, $q) { }; + var getUserBlobs = function() { + var deferred = $q.defer(); + $http.get('/blobs').success(function(data, status, headers, config) { + var blobs = _.map(data, lingvodoc.Blob.fromJS); + deferred.resolve(blobs); + }).error(function(data, status, headers, config) { + deferred.reject('Failed to fetch list of available blobs'); + }); + return deferred.promise; + }; + + var checkDictionaryBlob = function(blob, parent) { + var deferred = $q.defer(); + var query = { + 'blob_client_id': blob.client_id, + 'blob_object_id': blob.object_id, + 'parent_client_id': parent.client_id, + 'parent_object_id': parent.object_id + }; + + $http.post('/convert_check', query).success(function(data, status, headers, config) { + var perspectives = _.map(data, lingvodoc.Perspective.fromJS); + deferred.resolve(perspectives); + }).error(function(data, status, headers, config) { + deferred.reject('Failed to convert dictionary'); + }); + return deferred.promise; + }; + + var convertDictionary = function(req) { + var deferred = $q.defer(); + $http.post('/convert', req).success(function(data, status, headers, config) { + deferred.resolve(data); + }).error(function(data, status, headers, config) { + deferred.reject('Failed to convert dictionary'); + }); + return deferred.promise; + }; + + var getPerspectiveMeta = function(dictionary, perspective) { + var deferred = $q.defer(); + var url = '/dictionary/' + encodeURIComponent(dictionary.client_id) + '/' + encodeURIComponent(dictionary.object_id) + '/perspective/' + encodeURIComponent(perspective.client_id) + '/' + encodeURIComponent(perspective.object_id) + '/meta'; + $http.get(url).success(function(data, status, headers, config) { + deferred.resolve(data); + }).error(function(data, status, headers, config) { + deferred.reject('Failed to get perspective meta data!'); + }); + return deferred.promise; + }; + + var setPerspectiveMeta = function(dictionary, perspective, meta) { + var deferred = $q.defer(); + var url = '/dictionary/' + encodeURIComponent(dictionary.client_id) + '/' + encodeURIComponent(dictionary.object_id) + '/perspective/' + encodeURIComponent(perspective.client_id) + '/' + encodeURIComponent(perspective.object_id) + '/meta'; + $http.put(url, meta).success(function(data, status, headers, config) { + deferred.resolve(data); + }).error(function(data, status, headers, config) { + deferred.reject('Failed to set perspective meta data!'); + }); + return deferred.promise; + }; + + var removePerspectiveMeta = function(dictionary, perspective, meta) { + var deferred = $q.defer(); + var url = '/dictionary/' + encodeURIComponent(dictionary.client_id) + '/' + encodeURIComponent(dictionary.object_id) + '/perspective/' + encodeURIComponent(perspective.client_id) + '/' + encodeURIComponent(perspective.object_id) + '/meta'; + var config = { + method: 'DELETE', + url: url, + data: meta, + headers: {'Content-Type': 'application/json;charset=utf-8'} + }; + + $http(config).success(function(data, status, headers, config) { + deferred.resolve(data); + }).error(function(data, status, headers, config) { + deferred.reject('Failed to remove perspective meta data!'); + }); + return deferred.promise; + }; + + var advancedSearch = function(query, where, adopted, etymology) { + var deferred = $q.defer(); + var url = '/advanced_search'; + + var perspectives = where.map(function(o) { + if (o.type == 'perspective') { + return {'client_id': o.client_id, 'object_id': o.object_id}; + } + }).filter(function(o) { + return typeof o !== 'undefined'; + }); + + var req = { + 'searchstrings': query, + 'perspectives': perspectives + }; + + if (_.isBoolean(adopted)) { + req.adopted = adopted; + } + + if (_.isBoolean(etymology)) { + req.with_etimology = etymology; + } + + $http.post(url, req).success(function(data, status, headers, config) { + var r = data.map(function(e) { + var perspective = lingvodoc.Perspective.fromJS(e); + return getPerspectiveOriginById(perspective.client_id, perspective.object_id); + }); + + $q.all(r).then(function(paths) { + var out = []; + _.each(data, function(entry, i) { + entry.lexical_entry['origin'] = paths[i]; + out.push(entry.lexical_entry); + }); + deferred.resolve(out); + + }, function(reason) { + deferred.reject('An error occurred while doing basic search'); + }); + + }).error(function(data, status, headers, config) { + deferred.reject('An error occurred while doing advanced search'); + }); + + return deferred.promise; + }; + + var convertMarkup = function(object) { + var deferred = $q.defer(); + var obj = { + 'client_id': object.client_id, + 'object_id': object.object_id + }; + $http.post('/convert/markup', obj).success(function(data, status, headers, config) { + deferred.resolve(data); + }).error(function(data, status, headers, config) { + deferred.reject('Failed to convert markup!'); + }); + return deferred.promise; + }; // Return public API. @@ -1119,6 +1336,7 @@ function lingvodocAPI($http, $q) { 'getLexicalEntries': getLexicalEntries, 'getLexicalEntriesCount': getLexicalEntriesCount, 'getPerspectiveDictionaryFields': getPerspectiveDictionaryFields, + 'getPerspectiveDictionaryFieldsNew': getPerspectiveDictionaryFieldsNew, 'addNewLexicalEntry': addNewLexicalEntry, 'saveValue': saveValue, 'removeValue': removeValue, @@ -1129,6 +1347,7 @@ function lingvodocAPI($http, $q) { 'approveAll': approveAll, 'getDictionaryProperties': getDictionaryProperties, 'setDictionaryProperties': setDictionaryProperties, + 'removeDictionary': removeDictionary, 'getLanguages': getLanguages, 'setDictionaryStatus': setDictionaryStatus, 'setPerspectiveStatus': setPerspectiveStatus, @@ -1136,6 +1355,7 @@ function lingvodocAPI($http, $q) { 'getPerspectiveFields': getPerspectiveFields, 'setPerspectiveFields': setPerspectiveFields, 'getPerspectiveFieldsNew': getPerspectiveFieldsNew, + 'removePerspective': removePerspective, 'getUserInfo': getUserInfo, 'setUserInfo': setUserInfo, 'getOrganizations': getOrganizations, @@ -1162,6 +1382,14 @@ function lingvodocAPI($http, $q) { 'deleteDictionaryRoles': deleteDictionaryRoles, 'getPerspectiveRoles': getPerspectiveRoles, 'addPerspectiveRoles': addPerspectiveRoles, - 'deletePerspectiveRoles': deletePerspectiveRoles + 'deletePerspectiveRoles': deletePerspectiveRoles, + 'getUserBlobs': getUserBlobs, + 'checkDictionaryBlob': checkDictionaryBlob, + 'convertDictionary': convertDictionary, + 'getPerspectiveMeta': getPerspectiveMeta, + 'setPerspectiveMeta': setPerspectiveMeta, + 'removePerspectiveMeta': removePerspectiveMeta, + 'advancedSearch': advancedSearch, + 'convertMarkup': convertMarkup }); -}; +} diff --git a/webui/src/js/create_dictionary.js b/webui/src/js/create_dictionary.js index 44de4dfc9..1cf49d6e1 100755 --- a/webui/src/js/create_dictionary.js +++ b/webui/src/js/create_dictionary.js @@ -1,8 +1,8 @@ -var app = angular.module('CreateDictionaryModule', ['ui.router', 'ngAnimate', 'ui.bootstrap', 'autocomplete']); +var app = angular.module('CreateDictionaryModule', ['ui.router', 'ui.bootstrap']); app.service('dictionaryService', lingvodocAPI); -app.config(function ($stateProvider, $urlRouterProvider) { +app.config(function($stateProvider, $urlRouterProvider) { $stateProvider @@ -32,7 +32,7 @@ app.config(function ($stateProvider, $urlRouterProvider) { app.factory('responseHandler', ['$timeout', '$modal', responseHandler]); -app.controller('CreateDictionaryController', ['$scope', '$http', '$modal', '$interval', '$state', '$location', '$log', 'dictionaryService', 'responseHandler', function ($scope, $http, $modal, $interval, $state, $location, $log, dictionaryService, responseHandler) { +app.controller('CreateDictionaryController', ['$scope', '$http', '$modal', '$interval', '$state', '$window', '$log', 'dictionaryService', 'responseHandler', function($scope, $http, $modal, $interval, $state, $window, $log, dictionaryService, responseHandler) { var clientId = $('#clientId').data('lingvodoc'); var userId = $('#userId').data('lingvodoc'); @@ -53,7 +53,7 @@ app.controller('CreateDictionaryController', ['$scope', '$http', '$modal', '$int $scope.uploadedDictionaries = []; - var flatLanguages = function (languages) { + var flatLanguages = function(languages) { var flat = []; for (var i = 0; i < languages.length; i++) { var language = languages[i]; @@ -66,7 +66,7 @@ app.controller('CreateDictionaryController', ['$scope', '$http', '$modal', '$int return flat; }; - var getLanguageById = function (id) { + var getLanguageById = function(id) { if (typeof id == 'string') { var ids = id.split('_'); for (var i = 0; i < $scope.languages.length; i++) { @@ -102,13 +102,13 @@ app.controller('CreateDictionaryController', ['$scope', '$http', '$modal', '$int // Event handlers - $scope.getLanguageId = function (language) { + $scope.getLanguageId = function(language) { if (language) { return language.client_id + '_' + language.object_id; } }; - $scope.newLanguage = function () { + $scope.newLanguage = function() { var modalInstance = $modal.open({ animation: true, templateUrl: 'createLanguageModal.html', @@ -116,21 +116,27 @@ app.controller('CreateDictionaryController', ['$scope', '$http', '$modal', '$int size: 'lg' }); - modalInstance.result.then(function (languageObj) { - $http.post(createLanguageUrl, languageObj).success(function (data, status, headers, config) { + modalInstance.result.then(function(languageObj) { + $http.post(createLanguageUrl, languageObj).success(function(data, status, headers, config) { loadLanguages(); - }).error(function (data, status, headers, config) { + }).error(function(data, status, headers, config) { alert('Failed to save language!'); }); - }, function () { + }, function() { }); }; - $scope.addField = function () { - $scope.perspective.fields.push({'entity_type': '', 'entity_type_translation': '', 'data_type': 'text', 'data_type_translation': 'text', 'status': 'enabled'}); + $scope.addField = function() { + $scope.perspective.fields.push({ + 'entity_type': '', + 'entity_type_translation': '', + 'data_type': 'text', + 'data_type_translation': 'text', + 'status': 'enabled' + }); }; - $scope.enableGroup = function (fieldIndex) { + $scope.enableGroup = function(fieldIndex) { if (typeof $scope.perspective.fields[fieldIndex].group === 'undefined') { $scope.perspective.fields[fieldIndex].group = ''; } else { @@ -138,7 +144,7 @@ app.controller('CreateDictionaryController', ['$scope', '$http', '$modal', '$int } }; - $scope.enableLinkedField = function (fieldIndex) { + $scope.enableLinkedField = function(fieldIndex) { if (typeof $scope.perspective.fields[fieldIndex].contains === 'undefined') { $scope.perspective.fields[fieldIndex].contains = [{ 'entity_type': '', @@ -152,6 +158,15 @@ app.controller('CreateDictionaryController', ['$scope', '$http', '$modal', '$int } }; + var convert = function(req) { + dictionaryService.convertDictionary(req).then(function(response) { + responseHandler.success(response); + $window.location.href = '/dashboard'; + }, function(reason) { + responseHandler.error(reason); + }); + }; + // Save dictionary $scope.createDictionary = function() { @@ -171,7 +186,7 @@ app.controller('CreateDictionaryController', ['$scope', '$http', '$modal', '$int $scope.controls.createDictionary = false; - $http.post(createDictionaryUrl, dictionaryObj).success(function (data, status, headers, config) { + $http.post(createDictionaryUrl, dictionaryObj).success(function(data, status, headers, config) { if (data.object_id && data.client_id) { $scope.dictionaryData.dictionary_client_id = data.client_id; @@ -183,7 +198,7 @@ app.controller('CreateDictionaryController', ['$scope', '$http', '$modal', '$int } $scope.controls.createDictionary = true; - }).error(function (data, status, headers, config) { + }).error(function(data, status, headers, config) { $scope.controls.createDictionary = true; responseHandler.error('Failed to create dictionary!'); }); @@ -196,21 +211,45 @@ app.controller('CreateDictionaryController', ['$scope', '$http', '$modal', '$int $scope.controls.createDictionary = false; - var ids = $scope.wizard.importedDictionaryId.split('_'); - var url = $('#convertUrl').data('lingvodoc'); - var convertObject = { - 'blob_client_id': parseInt(ids[0]), - 'blob_object_id': parseInt(ids[1]), - 'parent_client_id': language.client_id, - 'parent_object_id': language.object_id - }; + var blob = _.find($scope.uploadedDictionaries, function(d) { + return d.getId() == $scope.wizard.importedDictionaryId; + }); - $http.post(url, convertObject).success(function (data, status, headers, config) { - $scope.controls.createDictionary = true; - responseHandler.success(data.status); - }).error(function (data, status, headers, config) { - $scope.controls.createDictionary = true; - responseHandler.error(data); + dictionaryService.checkDictionaryBlob(blob, language).then(function(perspectives) { + + if (_.size(perspectives) > 0) { + + $modal.open({ + animation: true, + templateUrl: 'importModal.html', + controller: 'ImportController', + size: 'lg', + backdrop: 'static', + keyboard: false, + resolve: { + 'params': function() { + return { + 'perspectives': perspectives, + 'blob': blob, + 'language': language + }; + } + } + }).result.then(function(req) { + convert(req); + }, function() { + + }); + } else { + convert({ + 'blob_client_id': blob.client_id, + 'blob_object_id': blob.object_id, + 'parent_client_id': language.client_id, + 'parent_object_id': language.object_id + }); + } + }, function(reason) { + responseHandler.error(reason); }); } } @@ -261,10 +300,10 @@ app.controller('CreateDictionaryController', ['$scope', '$http', '$modal', '$int $scope.searchUsers = function(query) { - var promise = $http.get('/users?search=' + encodeURIComponent(query)).then(function (response) { + var promise = $http.get('/users?search=' + encodeURIComponent(query)).then(function(response) { return response.data; }); - promise.then(function(data){ + promise.then(function(data) { var userLogins = []; if (data.users) { for (var i = 0; i < data.users.length; i++) { @@ -287,37 +326,14 @@ app.controller('CreateDictionaryController', ['$scope', '$http', '$modal', '$int // Load list of languages var loadLanguages = function() { - $http.get(languagesUrl).success(function (data, status, headers, config) { + $http.get(languagesUrl).success(function(data, status, headers, config) { $scope.languages = flatLanguages(data.languages); - }).error(function (data, status, headers, config) { + }).error(function(data, status, headers, config) { // error handling }); }; - - var loadBlobs = function() { - $http.get(listBlobsUrl).success(function (data, status, headers, config) { - $scope.uploadedDictionaries = []; - - - for (var i = 0; i < data.length; i++) { - if (data[i].data_type='dialeqt_dictionary') { - var id = data[i].client_id + '_' + data[i].object_id; - - $scope.uploadedDictionaries.push({ - 'id': id, - 'data': data[i] - }); - } - } - - - }).error(function (data, status, headers, config) { - }); - }; - - - $scope.$watch('dictionaryData.perspectiveId', function (id) { + $scope.$watch('dictionaryData.perspectiveId', function(id) { if (typeof id == 'string') { for (var i = 0; i < $scope.perspectives.length; i++) { if ($scope.perspectives[i].getId() == id) { @@ -342,11 +358,21 @@ app.controller('CreateDictionaryController', ['$scope', '$http', '$modal', '$int loadLanguages(); - loadBlobs(); + + dictionaryService.getUserBlobs().then(function(blobs) { + + $scope.uploadedDictionaries = _.filter(blobs, function(e) { + return e.data_type == 'dialeqt_dictionary'; + }); + + }, function(reason) { + responseHandler.error(reason); + }); + }]); -app.controller('CreateLanguageController', ['$scope', '$http', '$interval', '$modalInstance', 'responseHandler', function ($scope, $http, $interval, $modalInstance, responseHandler) { +app.controller('CreateLanguageController', ['$scope', '$http', '$interval', '$modalInstance', 'responseHandler', function($scope, $http, $interval, $modalInstance, responseHandler) { var clientId = $('#clientId').data('lingvodoc'); var userId = $('#userId').data('lingvodoc'); @@ -358,7 +384,7 @@ app.controller('CreateLanguageController', ['$scope', '$http', '$interval', '$mo $scope.translation = ''; $scope.translationString = ''; - var getLanguageById = function (id) { + var getLanguageById = function(id) { var ids = id.split('_'); for (var i = 0; i < $scope.languages.length; i++) { if ($scope.languages[i].client_id == ids[0] && $scope.languages[i].object_id == ids[1]) @@ -366,7 +392,7 @@ app.controller('CreateLanguageController', ['$scope', '$http', '$interval', '$mo } }; - var flatLanguages = function (languages) { + var flatLanguages = function(languages) { var flat = []; for (var i = 0; i < languages.length; i++) { var language = languages[i]; @@ -379,13 +405,13 @@ app.controller('CreateLanguageController', ['$scope', '$http', '$interval', '$mo return flat; }; - $scope.getLanguageId = function (language) { + $scope.getLanguageId = function(language) { if (language) { return language.client_id + '_' + language.object_id; } }; - $scope.ok = function () { + $scope.ok = function() { if (!$scope.translation) { return; @@ -407,13 +433,124 @@ app.controller('CreateLanguageController', ['$scope', '$http', '$interval', '$mo $modalInstance.close(languageObj); }; - $scope.cancel = function () { + $scope.cancel = function() { $modalInstance.dismiss('cancel'); }; - $http.get(languagesUrl).success(function (data, status, headers, config) { + $http.get(languagesUrl).success(function(data, status, headers, config) { $scope.languages = flatLanguages(data.languages); - }).error(function (data, status, headers, config) { + }).error(function(data, status, headers, config) { // error handling }); -}]); \ No newline at end of file +}]); + +app.controller('ImportController', ['$scope', '$http', '$q', '$log', '$modalInstance', 'dictionaryService', 'responseHandler', 'params', function($scope, $http, $q, $log, $modalInstance, dictionaryService, responseHandler, params) { + + $scope.mode = 'create'; + $scope.perspectives = params.perspectives; + $scope.paths = []; + $scope.import = {}; + $scope.import.dictionaryId = ''; + $scope.import.perspectiveId = ''; + $scope.import.createNewPerspective = false; + + + var getSelectedPerspective = function() { + return _.find($scope.perspectives, function(e) { + return e.getId() === $scope.import.perspectiveId; + }); + }; + + var getSelectedDictionary = function() { + return _.find($scope.dictionaries, function(e) { + return e.getId() === $scope.import.dictionaryId; + }); + }; + + $scope.ok = function() { + + var req = { + 'blob_client_id': params.blob.client_id, + 'blob_object_id': params.blob.object_id, + 'parent_client_id': params.language.client_id, + 'parent_object_id': params.language.object_id + }; + + if ($scope.mode === 'import') { + + var dictionary = getSelectedDictionary(); + if (dictionary) { + + req.dictionary_client_id = dictionary.client_id; + req.dictionary_object_id = dictionary.object_id; + + if (!$scope.import.createNewPerspective) { + + var perspective = getSelectedPerspective(); + if (perspective) { + req.perspective_client_id = perspective.client_id; + req.perspective_object_id = perspective.object_id; + } else { + responseHandler.error('Please, select perspective.'); + return; + } + } + } else { + responseHandler.error('Please, select dictionary.'); + return; + } + } + $modalInstance.close(req); + }; + + $scope.cancel = function() { + $modalInstance.dismiss('cancel'); + }; + + + $scope.$watch('import.dictionaryId', function(id) { + + var dictionary = _.find($scope.dictionaries, function(d) { + return d.getId() === id; + }); + + if (dictionary) { + $scope.perspectives = _.filter(params.perspectives, function(p) { + return p.parent_client_id == dictionary.client_id && p.parent_object_id == dictionary.object_id; + }); + } + }); + + // load list of dictionaries + var r = params.perspectives.map(function(perspective) { + return dictionaryService.getPerspectiveOriginById(perspective.client_id, perspective.parent_object_id); + }); + + $q.all(r).then(function(paths) { + $scope.paths = paths; + var dictionaries = _.reduce(paths, function(acc, path) { + var pathDicts = _.filter(path, function(e) { + return e.type === 'dictionary'; + }); + _.each(pathDicts, function(d) { + acc.push(d); + }); + + return acc; + }, []); + + // remove duplicates + $scope.dictionaries = _.uniq(dictionaries, function(d, key, a) { + return d.getId(); + }); + + }, function(reason) { + responseHandler.error(reason); + }); + + +}]); + + + + diff --git a/webui/src/js/dashboard.js b/webui/src/js/dashboard.js index 1ec615402..b91d4157b 100755 --- a/webui/src/js/dashboard.js +++ b/webui/src/js/dashboard.js @@ -1,6 +1,6 @@ 'use strict'; -var app = angular.module('DashboardModule', ['ui.bootstrap']); +var app = angular.module('DashboardModule', ['ui.bootstrap', 'ngMap']); app.service('dictionaryService', lingvodocAPI); @@ -10,26 +10,13 @@ app.controller('DashboardController', ['$scope', '$http', '$q', '$modal', '$log' var userId = $('#userId').data('lingvodoc'); var languagesUrl = $('#languagesUrl').data('lingvodoc'); - var dictionariesUrl = $('#dictionariesUrl').data('lingvodoc'); - var getUserInfoUrl = $('#getUserInfoUrl').data('lingvodoc'); $scope.dictionaries = []; - var getObjectByCompositeKey = function (id, arr) { - if (typeof id == 'string') { - var ids = id.split('_'); - for (var i = 0; i < arr.length; i++) { - if (arr[i].client_id == ids[0] && arr[i].object_id == ids[1]) - return arr[i]; - } - } - }; - $scope.getActionLink = function (dictionary, perspective, action) { return '/dictionary/' + encodeURIComponent(dictionary.client_id) + '/' + encodeURIComponent(dictionary.object_id) + '/perspective/' + encodeURIComponent(perspective.client_id) + '/' + encodeURIComponent(perspective.object_id) + '/' + action; }; - $scope.editDictionaryProperties = function(dictionary) { var modalInstance = $modal.open({ animation: true, @@ -48,7 +35,6 @@ app.controller('DashboardController', ['$scope', '$http', '$q', '$modal', '$log' }); }; - $scope.editPerspectiveProperties = function(dictionary, perspective) { $modal.open({ @@ -134,21 +120,6 @@ app.controller('DashboardController', ['$scope', '$http', '$q', '$modal', '$log' }); }; - - $scope.follow = function(link) { - if (!link) { - alert('Please, select perspective first.'); - return; - } - window.location = link; - }; - - $scope.getCompositeKey = function (object) { - if (object) { - return object.client_id + '_' + object.object_id; - } - }; - $scope.setPerspectiveStatus = function(dictionary, perspective, status) { dictionaryService.setPerspectiveStatus(dictionary, perspective, status).then(function(data) { perspective.status = status; @@ -166,6 +137,34 @@ app.controller('DashboardController', ['$scope', '$http', '$q', '$modal', '$log' }; + $scope.removeDictionary = function(dictionary) { + responseHandler.yesno('', 'Do you really want to remove dictionary?', function(confirmed) { + if (confirmed) { + dictionaryService.removeDictionary(dictionary).then(function() { + _.remove($scope.dictionaries, function(d) { + return d.equals(dictionary); + }); + }, function(reason) { + responseHandler.error(reason); + }); + } + }); + }; + + $scope.removePerspective = function(dictionary, perspective) { + responseHandler.yesno('', 'Do you really want to remove perspective?', function(confirmed) { + if (confirmed) { + dictionaryService.removePerspective(perspective).then(function() { + _.remove(dictionary.perspectives, function(p) { + return p.equals(perspective); + }); + }, function(reason) { + responseHandler.error(reason); + }); + } + }); + }; + $scope.loadMyDictionaries = function() { var dictionaryQuery = { @@ -213,9 +212,11 @@ app.controller('createPerspectiveController', ['$scope', '$http', '$q', '$modalI $scope.isTemplate = false; $scope.controls = { - 'ok': true + 'ok': true, + 'cancel': true }; + $scope.addField = function () { $scope.perspective.fields.push({'entity_type': '', 'entity_type_translation': '', 'data_type': 'text', 'data_type_translation': 'text', 'status': 'enabled'}); }; @@ -254,13 +255,13 @@ app.controller('createPerspectiveController', ['$scope', '$http', '$q', '$modalI 'is_template': $scope.isTemplate }; - $scope.controls.ok = false; + enableControls($scope.controls, false); var fields = exportPerspective($scope.perspective); dictionaryService.createPerspective($scope.dictionary, perspectiveObj, fields).then(function(perspective) { - $scope.controls.ok = true; + enableControls($scope.controls, true); $modalInstance.close(perspective); }, function(reason) { - $scope.controls.ok = true; + enableControls($scope.controls, true); responseHandler.error(reason); }); }; @@ -293,12 +294,6 @@ app.controller('createPerspectiveController', ['$scope', '$http', '$q', '$modalI }); }]); - - - - - - app.controller('editDictionaryPropertiesController', ['$scope', '$http', '$q', '$modalInstance', '$log', 'dictionaryService', 'responseHandler', 'params', function ($scope, $http, $q, $modalInstance, $log, dictionaryService, responseHandler, params) { $scope.data = {}; @@ -320,8 +315,8 @@ app.controller('editDictionaryPropertiesController', ['$scope', '$http', '$q', ' }); $scope.languages = langs; - var url = '/dictionary/' + encodeURIComponent(params.dictionary.client_id) + '/' + encodeURIComponent(params.dictionary.object_id); - dictionaryService.getDictionaryProperties(url).then(function(dictionaryProperties) { + //var url = '/dictionary/' + encodeURIComponent(params.dictionary.client_id) + '/' + encodeURIComponent(params.dictionary.object_id); + dictionaryService.getDictionaryProperties(params.dictionary).then(function(dictionaryProperties) { var selectedLanguageCompositeId = getCompositeKey(dictionaryProperties, 'parent_client_id', 'parent_object_id'); $scope.dictionaryProperties = dictionaryProperties; $scope.data.selectedLanguage = selectedLanguageCompositeId; @@ -357,8 +352,8 @@ app.controller('editDictionaryPropertiesController', ['$scope', '$http', '$q', ' $scope.dictionaryProperties['parent_object_id'] = null; } - var url = '/dictionary/' + encodeURIComponent(params.dictionary.client_id) + '/' + encodeURIComponent(params.dictionary.object_id); - dictionaryService.setDictionaryProperties(url, $scope.dictionaryProperties).then(function() { + //var url = '/dictionary/' + encodeURIComponent(params.dictionary.client_id) + '/' + encodeURIComponent(params.dictionary.object_id); + dictionaryService.setDictionaryProperties(params.dictionary, $scope.dictionaryProperties).then(function() { $modalInstance.close(); }); }; @@ -370,15 +365,20 @@ app.controller('editDictionaryPropertiesController', ['$scope', '$http', '$q', ' }]); -app.controller('editPerspectivePropertiesController', ['$scope', '$http', '$q', '$modalInstance', '$log', 'dictionaryService', 'responseHandler', 'params', function ($scope, $http, $q, $modalInstance, $log, dictionaryService, responseHandler, params) { +app.controller('editPerspectivePropertiesController', ['$scope', '$http', '$q', '$modal', '$modalInstance', '$log', 'dictionaryService', 'responseHandler', 'params', function ($scope, $http, $q, $modal, $modalInstance, $log, dictionaryService, responseHandler, params) { $scope.dictionary = params.dictionary; $scope.perspective = {}; + $scope.blobs = []; + $scope.blobId = ''; $scope.controls = { - 'ok': true + 'ok': true, + 'cancel': true }; + $scope.authors = ''; + $scope.addField = function () { $scope.perspective.fields.push({'entity_type': '', 'data_type': 'text', 'status': 'enabled'}); }; @@ -393,19 +393,139 @@ app.controller('editPerspectivePropertiesController', ['$scope', '$http', '$q', } }; + $scope.editGeoLabels = function() { + + $modal.open({ + animation: true, + templateUrl: 'perspectiveGeoLabelsModal.html', + controller: 'perspectiveGeoLabelsController', + size: 'lg', + backdrop: 'static', + keyboard: false, + resolve: { + 'params': function() { + return { + 'dictionary': params.dictionary, + 'perspective': params.perspective + }; + } + } + }); + }; + + $scope.addBlob = function() { + + var b1 = _.find($scope.perspective.blobs, function(b) { return b.getId() == $scope.blobId; }); + $log.info(b1); + if (!!b1) { + return; + } + + var blob = _.find($scope.blobs, function(b) { + return b.getId() == $scope.blobId; + }); + + if (blob) { + // already existing blobs + var blobs = $scope.perspective.blobs.map(function(b) { + return { + 'info': { + 'type': 'blob', + 'content': { + 'client_id': b.client_id, + 'object_id': b.object_id + } + } + } + }); + + // add new blob + blobs.push({ + 'info': { + 'type': 'blob', + 'content': { + 'client_id': blob.client_id, + 'object_id': blob.object_id + } + } + }); + + var meta = { + 'info': { + 'type': 'list', + 'content': blobs + } + }; + + dictionaryService.setPerspectiveMeta(params.dictionary, params.perspective, meta).then(function(response) { + $scope.perspective.blobs.push(blob); + }, function(reason) { + responseHandler.error(reason); + }); + } + }; + + $scope.removeBlob = function(blob) { + + var blobs = _.filter($scope.perspective.blobs, function(b) { + return !b.equals(blob); + }); + + var blobsMeta = blobs.map(function(b) { + return { + 'info': { + 'type': 'blob', + 'content': { + 'client_id': b.client_id, + 'object_id': b.object_id + } + } + } + }); + + var meta = { + 'info': { + 'type': 'list', + 'content': blobsMeta + } + }; + + dictionaryService.setPerspectiveMeta(params.dictionary, params.perspective, meta).then(function(response) { + _.remove($scope.perspective.blobs, function(b) { + return b.equals(blob); + }); + }, function(reason) { + responseHandler.error(reason); + }); + + }; + $scope.ok = function() { - $scope.controls.ok = false; - dictionaryService.setPerspectiveProperties($scope.dictionary, $scope.perspective).then(function(data) { - var url = '/dictionary/' + encodeURIComponent(params.dictionary.client_id) + '/' + encodeURIComponent(params.dictionary.object_id) + '/perspective/' + encodeURIComponent(params.perspective.client_id) + '/' + encodeURIComponent(params.perspective.object_id) + '/fields'; - dictionaryService.setPerspectiveFields(url, exportPerspective($scope.perspective)).then(function(fields) { - $scope.controls.ok = true; - $modalInstance.close(); + enableControls($scope.controls, false); + + var meta = { + 'authors': { + 'type': 'authors', + 'content': $scope.authors + } + }; + + dictionaryService.setPerspectiveMeta($scope.dictionary, $scope.perspective, meta).then(function(response) { + dictionaryService.setPerspectiveProperties($scope.dictionary, $scope.perspective).then(function(data) { + var url = '/dictionary/' + encodeURIComponent(params.dictionary.client_id) + '/' + encodeURIComponent(params.dictionary.object_id) + '/perspective/' + encodeURIComponent(params.perspective.client_id) + '/' + encodeURIComponent(params.perspective.object_id) + '/fields'; + dictionaryService.setPerspectiveFields(url, exportPerspective($scope.perspective)).then(function(fields) { + enableControls($scope.controls, true); + $modalInstance.close(); + }, function(reason) { + enableControls($scope.controls, true); + responseHandler.error(reason); + }); }, function(reason) { - $scope.controls.ok = true; + enableControls($scope.controls, true); responseHandler.error(reason); }); }, function(reason) { - $scope.controls.ok = true; + enableControls($scope.controls, true); responseHandler.error(reason); }); }; @@ -421,6 +541,25 @@ app.controller('editPerspectivePropertiesController', ['$scope', '$http', '$q', }, function(reason) { responseHandler.error(reason); }); + + dictionaryService.getUserBlobs().then(function(blobs) { + $scope.blobs = blobs.filter(function(b) { + return b.data_type != 'dialeqt_dictionary'; + }); + + }, function(reason) { + responseHandler.error(reason); + }); + + dictionaryService.getPerspectiveMeta(params.dictionary, params.perspective).then(function(meta) { + + if (_.has(meta, 'authors') && _.has(meta.authors, 'content') && _.isString(meta.authors.content)) { + $scope.authors = meta.authors.content; + } + + }, function(reason) { + responseHandler.error(reason); + }); }]); @@ -744,15 +883,73 @@ app.controller('editPerspectiveRolesController', ['$scope', '$http', '$q', '$mod }); }]); +app.controller('perspectiveGeoLabelsController', ['$scope', '$http', '$q', '$modalInstance', '$log', 'NgMap', 'dictionaryService', 'responseHandler', 'params', function ($scope, $http, $q, $modalInstance, $log, NgMap, dictionaryService, responseHandler, params) { + var key = 'AIzaSyB6l1ciVMcP1pIUkqvSx8vmuRJL14lbPXk'; + $scope.googleMapsUrl = 'http://maps.google.com/maps/api/js?v=3.20&key=' + encodeURIComponent(key); + $scope.positions = []; + // resize map to match parent modal's size + $modalInstance.opened.then(function() { + NgMap.getMap().then(function(map) { + google.maps.event.trigger(map, 'resize'); + }); + }); + $scope.addMarker = function(event) { + if ($scope.positions.length > 0) { + return; + } + var latLng = event.latLng; + + var meta = { + 'location': { + 'type': 'location', + 'content': { + 'lat': latLng.lat(), + 'lng': latLng.lng() + } + } + }; + dictionaryService.setPerspectiveMeta(params.dictionary, params.perspective, meta).then(function(response) { + $scope.positions.push({'lat': latLng.lat(), 'lng': latLng.lng()}); + }, function(reason) { + responseHandler.error(reason); + }); + }; + $scope.removeMarker = function(marker) { + var meta = { + 'location': { + 'type': 'location', + 'content': { + 'lat': marker.latLng.lat(), + 'lng': marker.latLng.lng() + } + } + }; + dictionaryService.removePerspectiveMeta(params.dictionary, params.perspective, meta).then(function(response) { + _.remove($scope.positions, function(e) { + var p = new google.maps.LatLng(e.lat, e.lng); + return p.equals(marker.latLng); + }); + }, function(reason) { + responseHandler.error(reason); + }); + }; + $scope.ok = function() { + $modalInstance.close(); + }; + dictionaryService.getPerspectiveMeta(params.dictionary, params.perspective).then(function(data) { + $scope.positions = []; + if (!_.isEmpty(data) && _.has(data, 'location')) { + $scope.positions.push(data.location.content); + } + }); - - +}]); diff --git a/webui/src/js/edit_dictionary.js b/webui/src/js/edit_dictionary.js index a7fcad61e..92d487c6b 100755 --- a/webui/src/js/edit_dictionary.js +++ b/webui/src/js/edit_dictionary.js @@ -21,7 +21,7 @@ angular.module('EditDictionaryModule', ['ui.bootstrap']) wavesurfer.load($attrs.url, $attrs.data || null); } - $scope.$emit('wavesurferInit', wavesurfer); + $scope.$emit('wavesurferInit', wavesurfer, $element); } }; }) @@ -411,7 +411,7 @@ angular.module('EditDictionaryModule', ['ui.bootstrap']) }); }; - $scope.annotate = function(soundEntity, markupEntity) { + $scope.annotate = function(sound, markup) { var modalInstance = $modal.open({ animation: true, @@ -419,11 +419,11 @@ angular.module('EditDictionaryModule', ['ui.bootstrap']) controller: 'AnnotationController', size: 'lg', resolve: { - soundUrl: function() { - return soundEntity.content; - }, - annotationUrl: function() { - return markupEntity.content; + 'params': function() { + return { + 'sound': sound, + 'markup': markup + }; } } }); @@ -531,7 +531,7 @@ angular.module('EditDictionaryModule', ['ui.bootstrap']) }]) - .controller('AnnotationController', ['$scope', '$http', 'responseHandler', 'soundUrl', 'annotationUrl', function($scope, $http, responseHandler, soundUrl, annotationUrl) { + .controller('AnnotationController', ['$scope', '$http', 'dictionaryService', 'responseHandler', 'params', function($scope, $http, dictionaryService, responseHandler, params) { var activeUrl = null; @@ -555,26 +555,6 @@ angular.module('EditDictionaryModule', ['ui.bootstrap']) } }; - var loadAnnotation = function(url) { - // load annotation - $http.get(url).success(function(data, status, headers, config) { - - try { - var xml = (new DOMParser()).parseFromString(data, 'application/xml'); - var annotation = new elan.Document(); - annotation.importXML(xml); - $scope.annotation = annotation; - - createRegions(annotation); - - } catch (e) { - alert('Failed to parse ELAN annotation: ' + e); - } - - }).error(function(data, status, headers, config) { - }); - }; - $scope.paused = true; $scope.annotation = null; @@ -601,7 +581,6 @@ angular.module('EditDictionaryModule', ['ui.bootstrap']) $scope.wavesurfer = wavesurfer; - if ($scope.wavesurfer.enableDragSelection) { $scope.wavesurfer.enableDragSelection({ color: 'rgba(0, 255, 0, 0.1)' @@ -634,12 +613,25 @@ angular.module('EditDictionaryModule', ['ui.bootstrap']) $scope.wavesurfer.once('ready', function() { // load annotation once file is loaded - loadAnnotation(annotationUrl); + dictionaryService.convertMarkup(params.markup).then(function(data) { + try { + var xml = (new DOMParser()).parseFromString(data.content, 'application/xml'); + var annotation = new elan.Document(); + annotation.importXML(xml); + $scope.annotation = annotation; + createRegions(annotation); + } catch (e) { + responseHandler.error('Failed to parse ELAN annotation: ' + e); + } + }, function(reason) { + responseHandler.error(reason); + }); + $scope.$apply(); }); // load file once wavesurfer is ready - $scope.wavesurfer.load(soundUrl); + $scope.wavesurfer.load(params.sound.content); }); $scope.$on('modal.closing', function(e) { @@ -832,7 +824,6 @@ angular.module('EditDictionaryModule', ['ui.bootstrap']) var entryObject = value.export(); - // TODO: get locale_id from cookies entryObject['entity_type'] = field.entity_type; entryObject['locale_id'] = getCookie('locale_id'); diff --git a/webui/src/js/elan.js b/webui/src/js/elan.js old mode 100644 new mode 100755 index e612ae1b2..0cac1bf53 --- a/webui/src/js/elan.js +++ b/webui/src/js/elan.js @@ -128,8 +128,10 @@ var elan = (function() { var header = xml.querySelector('HEADER'); var inMilliseconds = header.getAttribute('TIME_UNITS') == 'milliseconds'; var media = header.querySelector('MEDIA_DESCRIPTOR'); - this.mediaUrl = media.getAttribute('MEDIA_URL'); - this.mediaType = media.getAttribute('MIME_TYPE'); + if (media) { + this.mediaUrl = media.getAttribute('MEDIA_URL'); + this.mediaType = media.getAttribute('MIME_TYPE'); + } var properties = xml.querySelectorAll('PROPERTY'); _forEach.call(properties, function(prop) { diff --git a/webui/src/js/home.js b/webui/src/js/home.js index 575a3c84a..7dd8600d1 100755 --- a/webui/src/js/home.js +++ b/webui/src/js/home.js @@ -3,58 +3,59 @@ angular.module('HomeModule', ['ui.bootstrap'], function($rootScopeProvider) { $rootScopeProvider.digestTtl(1000); }) - .service('dictionaryService', lingvodocAPI) + .factory('dictionaryService', ['$http', '$q', lingvodocAPI]) .factory('responseHandler', ['$timeout', '$modal', responseHandler]) - .controller('HomeController', ['$scope', '$http', '$modal', '$q', '$log', 'dictionaryService', 'responseHandler', function($scope, $http, $modal, $q, $log, dictionaryService, responseHandler) { + .controller('HomeController', ['$scope', '$http', '$log', 'dictionaryService', 'responseHandler', function($scope, $http, $log, dictionaryService, responseHandler) { - var languagesUrl = $('#languagesUrl').data('lingvodoc'); - var dictionariesUrl = $('#dictionariesUrl').data('lingvodoc'); - var getUserInfoUrl = $('#getUserInfoUrl').data('lingvodoc'); + $scope.languages = []; - $scope.languages = []; + $scope.getPerspectiveLink = function(dictionary, perspective) { + return '/dictionary/' + encodeURIComponent(dictionary.client_id) + '/' + encodeURIComponent(dictionary.object_id) + '/perspective/' + encodeURIComponent(perspective.client_id) + '/' + encodeURIComponent(perspective.object_id) + '/view'; + }; - $scope.getPerspectiveLink = function (dictionary, perspective) { - return '/dictionary/' + encodeURIComponent(dictionary.client_id) + '/' + encodeURIComponent(dictionary.object_id) + '/perspective/' + encodeURIComponent(perspective.client_id) + '/' + encodeURIComponent(perspective.object_id) + '/view'; - }; + $scope.getPerspectiveAuthors = function(perspective) { + var meta = JSON.parse(perspective.additional_metadata); + if (_.has(meta, 'authors') && _.has(meta.authors, 'content') && _.isString(meta.authors.content)) { + return meta.authors.content; + } + }; - var getPublishedPerspectives = function(dictionary) { - dictionaryService.getDictionaryPerspectives(dictionary).then(function(perspectives) { + var getPublishedPerspectives = function(dictionary) { + dictionaryService.getDictionaryPerspectives(dictionary).then(function(perspectives) { - var published = []; - angular.forEach(perspectives, function(perspective) { - if (perspective.status.toUpperCase() == 'published'.toUpperCase()) { - published.push(perspective); - } - }); - dictionary.perspectives = published; - }, function() { - - }); - }; + var published = []; + _.forEach(perspectives, function(perspective) { + if (perspective.status.toUpperCase() == 'published'.toUpperCase()) { + published.push(perspective); + } + }); + dictionary.perspectives = published; + }, function() { - - var setPerspectives = function(languages) { - for (var i = 0; i < languages.length; ++i) { - var lang = languages[i]; - angular.forEach(lang.dicts, function(dict) { - getPublishedPerspectives(dict); }); - if (angular.isArray(lang.contains)) { - setPerspectives(lang.contains); + }; + + var setPerspectives = function(languages) { + for (var i = 0; i < languages.length; ++i) { + var lang = languages[i]; + _.forEach(lang.dicts, function(dict) { + getPublishedPerspectives(dict); + }); + if (_.isArray(lang.contains)) { + setPerspectives(lang.contains); + } } - } - }; + }; - dictionaryService.getPublishedDictionaries().then(function(languages) { - $scope.languages = languages; - setPerspectives($scope.languages); - }, function(reason) { - responseHandler.error(reason); - }); - -}]); + dictionaryService.getPublishedDictionaries().then(function(languages) { + $scope.languages = languages; + setPerspectives($scope.languages); + }, function(reason) { + responseHandler.error(reason); + }); + }]); diff --git a/webui/src/js/lingvowave.js b/webui/src/js/lingvowave.js old mode 100644 new mode 100755 index 3f50d07e0..eec8e78cd --- a/webui/src/js/lingvowave.js +++ b/webui/src/js/lingvowave.js @@ -36,7 +36,7 @@ function WaveSurferController($scope) { }; // signal handlers - $scope.$on('wavesurferInit', function(e, wavesurfer) { + $scope.$on('wavesurferInit', function(e, wavesurfer, container) { $scope.wavesurfer = wavesurfer; @@ -53,6 +53,23 @@ function WaveSurferController($scope) { $scope.wavesurfer.seekTo(0); $scope.$apply(); }); + + //$scope.wavesurfer.on('ready', function () { + // + // var spectrogramContainer =_.find(container[0].parentElement.children, function(e) { + // return e.tagName.toUpperCase() == 'WAVESURFER-SPECTROGRAM'; + // }); + // + // if (spectrogramContainer) { + // var spectrogram = Object.create(WaveSurfer.Spectrogram); + // spectrogram.init({ + // wavesurfer: $scope.wavesurfer, + // container: spectrogramContainer, + // fftSamples: 128 + // }); + // } + //}); + }); $scope.$on('modal.closing', function(e) { diff --git a/webui/src/js/maps.js b/webui/src/js/maps.js new file mode 100755 index 000000000..168d64c61 --- /dev/null +++ b/webui/src/js/maps.js @@ -0,0 +1,727 @@ +'use strict'; + +angular.module('MapsModule', ['ui.bootstrap', 'ngAnimate', 'ngMap']) + + .factory('responseHandler', ['$timeout', '$modal', responseHandler]) + + .factory('dictionaryService', ['$http', '$q', lingvodocAPI]) + + .directive('wavesurfer', function() { + return { + restrict: 'E', + + link: function($scope, $element, $attrs) { + $element.css('display', 'block'); + + var options = angular.extend({container: $element[0]}, $attrs); + var wavesurfer = WaveSurfer.create(options); + + if ($attrs.url) { + wavesurfer.load($attrs.url, $attrs.data || null); + } + + $scope.$emit('wavesurferInit', wavesurfer, $element); + } + }; + }) + + .directive('indeterminate', [function() { + return { + require: '?ngModel', + link: function(scope, el, attrs, ctrl) { + ctrl.$formatters = []; + ctrl.$parsers = []; + ctrl.$render = function() { + var d = ctrl.$viewValue; + el.data('checked', d); + switch(d){ + case true: + el.prop('indeterminate', false); + el.prop('checked', true); + break; + case false: + el.prop('indeterminate', false); + el.prop('checked', false); + break; + default: + el.prop('indeterminate', true); + } + }; + el.bind('click', function() { + var d; + switch(el.data('checked')){ + case false: + d = true; + break; + case true: + d = null; + break; + default: + d = false; + } + ctrl.$setViewValue(d); + scope.$apply(ctrl.$render); + }); + } + }; + }]) + + .controller('MapsController', ['$scope', '$http', '$q', '$log', '$modal', 'NgMap', 'dictionaryService', 'responseHandler', function($scope, $http, $q, $log, $modal, NgMap, dictionaryService, responseHandler) { + + WaveSurferController.call(this, $scope); + + var key = 'AIzaSyB6l1ciVMcP1pIUkqvSx8vmuRJL14lbPXk'; + $scope.googleMapsUrl = 'http://maps.google.com/maps/api/js?v=3.20&key=' + encodeURIComponent(key); + + $scope.perspectives = []; + $scope.activePerspectives = []; + + + $scope.adoptedSearch = null; + $scope.etymologySearch = null; + + $scope.entries = []; + $scope.fields = []; + $scope.groups = []; + $scope.ge = []; + + $scope.allFields = []; + $scope.searchFields = []; + + $scope.fieldsIdx = []; + $scope.fieldsValues = []; + + $scope.search = [ + { + 'query': '', + 'type': '', + 'orFlag': true + } + ]; + + $scope.searchComplete = true; + + var mapFieldValues = function(allEntries, allFields) { + var result = []; + var getFieldValues = function(entry, field) { + var value; + var values = []; + if (entry && entry.contains) { + + if (field.isGroup) { + + for (var fieldIndex = 0; fieldIndex < field.contains.length; fieldIndex++) { + var subField = field.contains[fieldIndex]; + for (var valueIndex = 0; valueIndex < entry.contains.length; valueIndex++) { + value = entry.contains[valueIndex]; + if (value.entity_type == subField.entity_type) { + values.push(value); + } + } + } + } else { + for (var i = 0; i < entry.contains.length; i++) { + value = entry.contains[i]; + if (value.entity_type == field.entity_type) { + values.push(value); + } + } + } + } + return values; + }; + + for (var i = 0; i < allEntries.length; i++) { + var entryRow = []; + for (var j = 0; j < allFields.length; j++) { + entryRow.push(getFieldValues(allEntries[i], allFields[j])); + } + result.push(entryRow); + } + return result; + }; + + + $scope.getPerspectivesWithLocation = function() { + return _.filter($scope.perspectives, function(p) { + return _.has(p, 'location') && !_.isEmpty(p, 'location') && _.has(p.location, 'lat') && _.has(p.location, 'lng'); + }); + }; + + $scope.getDictionary = function(perspective) { + return _.find($scope.dictionaries, function(d) { + return d.client_id == perspective.parent_client_id && d.object_id == perspective.parent_object_id; + }); + }; + + $scope.isPerspectiveActive = function(perspective) { + return !!_.find($scope.activePerspectives, function(p) { + return p.equals(perspective); + }); + }; + + $scope.getSearchFields = function() { + + var activeFields = _.clone($scope.allFields); + _.remove(activeFields, function(f, i) { + var perspective = $scope.perspectives[i]; + return !_.find($scope.activePerspectives, function(p) { + return p.equals(perspective); + }); + }); + + var fields = _.reduce(activeFields, function(acc, perspectiveFields) { + var fields = []; + _.each(perspectiveFields, function(f) { + if (f.level === 'leveloneentity' && f.data_type === 'text') { + fields.push(f); + } + + if (_.isArray(f.contains)) { + _.each(f.contains, function(cf) { + if (cf.level === 'leveloneentity' && cf.data_type === 'text') { + fields.push(cf); + } + }); + } + }); + return acc.concat(fields); + }, []); + + // remove duplicates + var names = []; + var removed = _.remove(fields, function(f) { + if (_.indexOf(names, f.entity_type) >= 0) { + return true; + } + names.push(f.entity_type); + return false; + }); + + $scope.searchFields = fields; + return $scope.searchFields; + }; + + $scope.addSearchField = function() { + $scope.search.push({ + 'query': '', + 'type': '', + 'orFlag': false + }); + }; + + $scope.info = function(event, perspective) { + var self = this; + $scope.selectedPerspective = perspective; + NgMap.getMap().then(function(map) { + map.showInfoWindow('bar', self); + }); + }; + + $scope.toggle = function(event, perspective) { + if (!_.find($scope.activePerspectives, function(p) { return p.equals(perspective); })) { + $scope.activePerspectives.push(perspective); + } else { + _.remove($scope.activePerspectives, function(p) { + return p.equals(perspective); + }); + } + }; + + $scope.showBlob = function(blob) { + $modal.open({ + animation: true, + templateUrl: 'blobModal.html', + controller: 'BlobController', + size: 'lg', + backdrop: 'static', + keyboard: false, + resolve: { + 'params': function() { + return { + 'blob': blob + }; + } + } + }).result.then(function(req) { + + }, function() { + + }); + }; + + $scope.viewGroup = function(entry, field, values) { + + $modal.open({ + animation: true, + templateUrl: 'viewGroupModal.html', + controller: 'viewGroupController', + size: 'lg', + backdrop: 'static', + keyboard: false, + resolve: { + 'groupParams': function() { + return { + 'entry': entry, + 'field': field, + 'values': values + }; + } + } + }); + }; + + $scope.viewGroupingTag = function(entry, field, values) { + + $modal.open({ + animation: true, + templateUrl: 'viewGroupingTagModal.html', + controller: 'viewGroupingTagController', + size: 'lg', + resolve: { + 'groupParams': function() { + return { + 'entry': entry, + 'fields': $scope.fields + }; + } + } + }); + }; + + $scope.annotate = function(sound, markup) { + + var modalInstance = $modal.open({ + animation: true, + templateUrl: 'annotationModal.html', + controller: 'AnnotationController', + size: 'lg', + resolve: { + 'params': function() { + return { + 'sound': sound, + 'markup': markup + }; + } + } + }); + }; + + $scope.doSearch = function() { + + + var q = _.map($scope.search, function(s) { + return { + 'searchstring': s.query, + 'entity_type': s.type.entity_type, + 'search_by_or': s.orFlag + }; + }); + + // remove empty string + _.remove(q, function(s) { + _.isEmpty(s.searchstring) || _.isUndefined(s.entity_type); + }); + + $scope.searchComplete = false; + dictionaryService.advancedSearch(q, $scope.activePerspectives, $scope.adoptedSearch, $scope.etymologySearch).then(function(entries) { + + $scope.searchComplete = true; + if (!_.isEmpty(entries)) { + + var p = _.find(_.first(entries)['origin'], function(o) { + return o.type == 'perspective'; + }); + + // group entries by dictionary and perspective + var groups = []; + var ge = _.groupBy(entries, function(e) { + + var entryDictionary = _.find(e['origin'], function(o) { + return o.type == 'dictionary'; + }); + + var entryPerspective = _.find(e['origin'], function(o) { + return o.type == 'perspective'; + }); + + var i = _.findIndex(groups, function(g) { + return g.perspective.equals(entryPerspective) && g.dictionary.equals(entryDictionary); + }); + + if (i < 0) { + groups.push({ + 'dictionary': entryDictionary, + 'perspective': entryPerspective, + 'origin': e['origin'] + }); + return (_.size(groups) - 1); + } + return i; + }); + + dictionaryService.getPerspectiveDictionaryFieldsNew(p).then(function(fields) { + $scope.fields = fields; + $scope.entries = entries; + + _.each(groups, function(g, i) { + g['matrix'] = mapFieldValues(ge[i], fields); + }); + + $scope.groups = groups; + $scope.ge = ge; + + }, function(reason) { + responseHandler.error(reason); + }); + + } else { + $scope.fields = []; + $scope.groups = []; + $scope.ge = []; + } + + }, function(reason) { + responseHandler.error(reason); + }); + + + + + }; + + dictionaryService.getAllPerspectives().then(function(perspectives) { + $scope.perspectives = _.clone(perspectives); + $scope.activePerspectives = _.clone($scope.getPerspectivesWithLocation()); + + var reqs = _.map($scope.perspectives, function(p) { + return dictionaryService.getPerspectiveDictionaryFieldsNew(p); + }); + + $q.all(reqs).then(function(allFields) { + + $scope.allFields = allFields; + + }, function(reason) { + responseHandler.error(reason); + }); + + }, function(reason) { + responseHandler.error(reason); + }); + + dictionaryService.getDictionaries({}).then(function(dictionaries) { + $scope.dictionaries = dictionaries; + }, function(reason) { + responseHandler.error(reason); + }); + }]) + + .controller('viewGroupController', ['$scope', '$http', '$modalInstance', '$log', 'dictionaryService', 'responseHandler', 'groupParams', function($scope, $http, $modalInstance, $log, dictionaryService, responseHandler, groupParams) { + + WaveSurferController.call(this, $scope); + + $scope.title = groupParams.field.entity_type; + $scope.fields = groupParams.field.contains; + $scope.parentEntry = groupParams.entry; + + var createVirtualEntries = function(values) { + var virtualEntries = []; + + var addValue = function(value, entries) { + + if (value.additional_metadata) { + for (var entryIndex = 0; entryIndex < entries.length; entryIndex++) { + if (entries[entryIndex].client_id == value.client_id && + entries[entryIndex].row_id == value.additional_metadata.row_id) { + entries[entryIndex].contains.push(value); + return; + } + } + + entries.push( + { + 'client_id': $scope.parentEntry.client_id, + 'object_id': $scope.parentEntry.object_id, + 'row_id': value.additional_metadata.row_id, + 'contains': [value] + } + ); + } + }; + + _.forEach(values, function(v) { + addValue(v, virtualEntries); + }); + + return virtualEntries; + }; + + $scope.fieldsIdx = []; + $scope.fieldsValues = []; + $scope.mapFieldValues = function(allEntries, allFields) { + $scope.fieldsValues = []; + $scope.fieldsIdx = []; + + for (var i = 0; i < allEntries.length; i++) { + var entryRow = []; + for (var j = 0; j < allFields.length; j++) { + entryRow.push($scope.getFieldValues(allEntries[i], allFields[j])); + } + $scope.fieldsValues.push(entryRow); + } + + for (var k = 0; k < allFields.length; k++) { + $scope.fieldsIdx.push(allFields[k]); + } + }; + + $scope.getFieldValues = function(entry, field) { + + var value; + var values = []; + if (entry && entry.contains) { + + if (field.isGroup) { + + for (var fieldIndex = 0; fieldIndex < field.contains.length; fieldIndex++) { + var subField = field.contains[fieldIndex]; + + for (var valueIndex = 0; valueIndex < entry.contains.length; valueIndex++) { + value = entry.contains[valueIndex]; + if (value.entity_type == subField.entity_type) { + values.push(value); + } + } + } + } else { + for (var i = 0; i < entry.contains.length; i++) { + value = entry.contains[i]; + if (value.entity_type == field.entity_type) { + values.push(value); + } + } + } + } + return values; + }; + + $scope.ok = function() { + $modalInstance.close($scope.entries); + }; + + $scope.entries = createVirtualEntries(groupParams.values); + $scope.mapFieldValues($scope.entries, $scope.fields); + }]) + + .controller('viewGroupingTagController', ['$scope', '$http', '$modalInstance', '$q', '$log', 'dictionaryService', 'responseHandler', 'groupParams', function($scope, $http, $modalInstance, $q, $log, dictionaryService, responseHandler, groupParams) { + + WaveSurferController.call(this, $scope); + + $scope.fields = groupParams.fields; + $scope.connectedEntries = []; + $scope.suggestedEntries = []; + + $scope.fieldsIdx = []; + for (var k = 0; k < $scope.fields.length; k++) { + $scope.fieldsIdx.push($scope.fields[k]); + } + + $scope.fieldsValues = []; + $scope.suggestedFieldsValues = []; + $scope.mapFieldValues = function(allEntries, allFields) { + + var result = []; + for (var i = 0; i < allEntries.length; i++) { + var entryRow = []; + for (var j = 0; j < allFields.length; j++) { + entryRow.push($scope.getFieldValues(allEntries[i], allFields[j])); + } + result.push(entryRow); + } + return result; + }; + + $scope.getFieldValues = function(entry, field) { + + var value; + var values = []; + if (entry && entry.contains) { + + if (field.isGroup) { + + for (var fieldIndex = 0; fieldIndex < field.contains.length; fieldIndex++) { + var subField = field.contains[fieldIndex]; + + for (var valueIndex = 0; valueIndex < entry.contains.length; valueIndex++) { + value = entry.contains[valueIndex]; + if (value.entity_type == subField.entity_type) { + values.push(value); + } + } + } + } else { + for (var i = 0; i < entry.contains.length; i++) { + value = entry.contains[i]; + if (value.entity_type == field.entity_type) { + values.push(value); + } + } + } + } + return values; + }; + + $scope.getPerspectiveLink = function(p) { + return '/dictionary/' + encodeURIComponent(p.parent_client_id) + '/' + encodeURIComponent(p.parent_object_id) + '/perspective/' + encodeURIComponent(p.client_id) + '/' + encodeURIComponent(p.object_id) + '/view'; + }; + + $scope.ok = function() { + $modalInstance.close(); + }; + + $scope.$watch('connectedEntries', function(updatedEntries) { + $scope.fieldsValues = $scope.mapFieldValues(updatedEntries, $scope.fields); + }, true); + + dictionaryService.getConnectedWords(groupParams.entry.client_id, groupParams.entry.object_id).then(function(entries) { + + var r = entries.map(function(entry) { + var lexicalEntry = entry.lexical_entry; + return dictionaryService.getPerspectiveOriginById(lexicalEntry.parent_client_id, lexicalEntry.parent_object_id); + }); + + $q.all(r).then(function(paths) { + angular.forEach(entries, function(entry, i) { + entry.lexical_entry['origin'] = paths[i]; + $scope.connectedEntries.push(entry.lexical_entry); + }); + }, function(reason) { + responseHandler.error(reason); + }); + + }, function(reason) { + responseHandler.error(reason); + }); + + }]) + + .controller('AnnotationController', ['$scope', '$http', 'dictionaryService', 'responseHandler', 'params', function($scope, $http, dictionaryService, responseHandler, params) { + + var activeUrl = null; + + var createRegions = function(annotaion) { + if (annotaion instanceof elan.Document) { + annotaion.tiers.forEach(function(tier) { + + tier.annotations.forEach(function(a) { + + var offset1 = annotaion.timeSlotRefToSeconds(a.timeslotRef1); + var offset2 = annotaion.timeSlotRefToSeconds(a.timeslotRef2); + + var r = $scope.wavesurfer.addRegion({ + id: a.id, + start: offset1, + end: offset2, + color: 'rgba(0, 255, 0, 0.1)' + }); + }); + }); + } + }; + + $scope.paused = true; + $scope.annotation = null; + + $scope.playPause = function() { + if ($scope.wavesurfer) { + $scope.wavesurfer.playPause(); + } + }; + + $scope.playAnnotation = function(a) { + if ($scope.wavesurfer && $scope.annotation) { + var offset1 = $scope.annotation.timeSlotRefToSeconds(a.timeslotRef1); + var offset2 = $scope.annotation.timeSlotRefToSeconds(a.timeslotRef2); + $scope.wavesurfer.play(offset1, offset2); + } + }; + + $scope.selectRegion = function() { + + }; + + // signal handlers + $scope.$on('wavesurferInit', function(e, wavesurfer) { + + $scope.wavesurfer = wavesurfer; + + + if ($scope.wavesurfer.enableDragSelection) { + $scope.wavesurfer.enableDragSelection({ + color: 'rgba(0, 255, 0, 0.1)' + }); + } + + $scope.wavesurfer.on('play', function() { + $scope.paused = false; + }); + + $scope.wavesurfer.on('pause', function() { + $scope.paused = true; + }); + + $scope.wavesurfer.on('finish', function() { + $scope.paused = true; + $scope.wavesurfer.seekTo(0); + $scope.$apply(); + }); + + // regions events + $scope.wavesurfer.on('region-click', function(region, event) { + + }); + + $scope.wavesurfer.on('region-dblclick', function(region, event) { + region.remove(region); + }); + + + $scope.wavesurfer.once('ready', function() { + // load annotation once file is loaded + dictionaryService.convertMarkup(params.markup).then(function(data) { + try { + var xml = (new DOMParser()).parseFromString(data.content, 'application/xml'); + var annotation = new elan.Document(); + annotation.importXML(xml); + $scope.annotation = annotation; + createRegions(annotation); + } catch (e) { + responseHandler.error('Failed to parse ELAN annotation: ' + e); + } + }, function(reason) { + responseHandler.error(reason); + }); + $scope.$apply(); + }); + + // load file once wavesurfer is ready + $scope.wavesurfer.load(params.sound.content); + }); + + $scope.$on('modal.closing', function(e) { + $scope.wavesurfer.stop(); + $scope.wavesurfer.destroy(); + }); + + }]) + + .controller('BlobController', ['$scope', '$http', '$log', '$modal', '$modalInstance', 'NgMap', 'dictionaryService', 'responseHandler', 'params', function($scope, $http, $log, $modal, $modalInstance, NgMap, dictionaryService, responseHandler, params) { + $scope.blob = params.blob; + $scope.ok = function() { + $modalInstance.close(); + }; + }]); + + + diff --git a/webui/src/js/profile.js b/webui/src/js/profile.js index d7f1af4f4..3cc49feb7 100755 --- a/webui/src/js/profile.js +++ b/webui/src/js/profile.js @@ -34,9 +34,6 @@ app.controller('ProfileController', ['$scope', '$http', '$q', '$modal', '$log', }, function(reason) { responseHandler.error(reason); }); - - - }]); diff --git a/webui/src/js/publish_dictionary.js b/webui/src/js/publish_dictionary.js index 2f62664a8..24a203c4b 100755 --- a/webui/src/js/publish_dictionary.js +++ b/webui/src/js/publish_dictionary.js @@ -18,7 +18,7 @@ angular.module('PublishDictionaryModule', ['ui.bootstrap']) wavesurfer.load($attrs.url, $attrs.data || null); } - $scope.$emit('wavesurferInit', wavesurfer); + $scope.$emit('wavesurferInit', wavesurfer, $element); } }; }) @@ -206,7 +206,7 @@ angular.module('PublishDictionaryModule', ['ui.bootstrap']) }); }; - $scope.annotate = function(soundEntity, markupEntity) { + $scope.annotate = function(sound, markup) { var modalInstance = $modal.open({ animation: true, @@ -214,11 +214,11 @@ angular.module('PublishDictionaryModule', ['ui.bootstrap']) controller: 'AnnotationController', size: 'lg', resolve: { - soundUrl: function() { - return soundEntity.content; - }, - annotationUrl: function() { - return markupEntity.content; + 'params': function() { + return { + 'sound': sound, + 'markup': markup + }; } } }); @@ -301,7 +301,7 @@ angular.module('PublishDictionaryModule', ['ui.bootstrap']) }]) - .controller('AnnotationController', ['$scope', '$http', 'soundUrl', 'responseHandler', 'annotationUrl', function($scope, $http, soundUrl, responseHandler, annotationUrl) { + .controller('AnnotationController', ['$scope', '$http', 'dictionaryService', 'responseHandler', 'params', function($scope, $http, dictionaryService, responseHandler, params) { var activeUrl = null; @@ -325,26 +325,6 @@ angular.module('PublishDictionaryModule', ['ui.bootstrap']) } }; - var loadAnnotation = function(url) { - // load annotation - $http.get(url).success(function(data, status, headers, config) { - - try { - var xml = (new DOMParser()).parseFromString(data, 'application/xml'); - var annotation = new elan.Document(); - annotation.importXML(xml); - $scope.annotation = annotation; - - createRegions(annotation); - - } catch (e) { - alert('Failed to parse ELAN annotation: ' + e); - } - - }).error(function(data, status, headers, config) { - }); - }; - $scope.paused = true; $scope.annotation = null; @@ -404,12 +384,25 @@ angular.module('PublishDictionaryModule', ['ui.bootstrap']) $scope.wavesurfer.once('ready', function() { // load annotation once file is loaded - loadAnnotation(annotationUrl); + dictionaryService.convertMarkup(params.markup).then(function(data) { + try { + console.log(data.content); + var xml = (new DOMParser()).parseFromString(data.content, 'application/xml'); + var annotation = new elan.Document(); + annotation.importXML(xml); + $scope.annotation = annotation; + createRegions(annotation); + } catch (e) { + responseHandler.error('Failed to parse ELAN annotation: ' + e); + } + }, function(reason) { + responseHandler.error(reason); + }); $scope.$apply(); }); // load file once wavesurfer is ready - $scope.wavesurfer.load(soundUrl); + $scope.wavesurfer.load(params.sound.content); }); $scope.$on('modal.closing', function(e) { diff --git a/webui/src/js/response_handler.js b/webui/src/js/response_handler.js index 5e8bf980f..d3d41f6c8 100755 --- a/webui/src/js/response_handler.js +++ b/webui/src/js/response_handler.js @@ -35,8 +35,38 @@ function responseHandler($timeout, $modal) { show('error', message, 5000); } + function yesno(status, message, callback) { + + var controller = function($scope, $modalInstance) { + $scope.status = status; + $scope.message = message; + + $scope.yes = function() { + $modalInstance.close(true); + }; + + $scope.no = function() { + $modalInstance.close(false); + }; + }; + + $modal.open({ + animation: true, + templateUrl: 'responseHandlerYesNoModal.html', + controller: controller, + size: 'lg', + backdrop: 'static', + keyboard: false + }).result.then(function(result) { + callback(result); + }, function() { + callback(false); + }); + } + return { - success: success, - error: error + 'success': success, + 'error': error, + 'yesno': yesno }; } \ No newline at end of file diff --git a/webui/src/js/user_upload.js b/webui/src/js/user_upload.js index 01c3fbf2b..c2b993f90 100755 --- a/webui/src/js/user_upload.js +++ b/webui/src/js/user_upload.js @@ -37,7 +37,7 @@ angular.module('UserUploadModule', ['ui.bootstrap']) var fd = new FormData(); fd.append('blob', file); - fd.append('data_type', 'dialeqt_dictionary'); + fd.append('data_type', $scope.dataType); $scope.uploadMsg = true; diff --git a/webui/src/js/util.js b/webui/src/js/util.js old mode 100644 new mode 100755 index 0a771adae..c10cb9760 --- a/webui/src/js/util.js +++ b/webui/src/js/util.js @@ -51,7 +51,6 @@ var exportPerspective = function(perspective) { delete field._groupEnabled; } - if (field._containsEnabled) { delete field._containsEnabled; } @@ -73,5 +72,9 @@ var cloneObject = function(oldObject) { return JSON.parse(JSON.stringify(oldObject)); }; - +var enableControls = function(controls, enabled) { + _.each(controls, function(value, key) { + controls[key] = enabled; + }); +}; diff --git a/webui/src/js/view_dictionary.js b/webui/src/js/view_dictionary.js index 21d9ac151..7e144d0a5 100755 --- a/webui/src/js/view_dictionary.js +++ b/webui/src/js/view_dictionary.js @@ -18,7 +18,7 @@ angular.module('ViewDictionaryModule', ['ui.bootstrap']) wavesurfer.load($attrs.url, $attrs.data || null); } - $scope.$emit('wavesurferInit', wavesurfer); + $scope.$emit('wavesurferInit', wavesurfer, $element); } }; }) @@ -52,9 +52,6 @@ angular.module('ViewDictionaryModule', ['ui.bootstrap']) .controller('ViewDictionaryController', ['$scope', '$window', '$http', '$modal', '$log', 'dictionaryService', 'responseHandler', function($scope, $window, $http, $modal, $log, dictionaryService, responseHandler) { - - var dictionaryClientId = $('#dictionaryClientId').data('lingvodoc'); - var dictionaryObjectId = $('#dictionaryObjectId').data('lingvodoc'); var perspectiveClientId = $('#perspectiveClientId').data('lingvodoc'); var perspectiveId = $('#perspectiveId').data('lingvodoc'); @@ -124,6 +121,9 @@ angular.module('ViewDictionaryModule', ['ui.bootstrap']) $scope.viewGroup = function(entry, field, values) { + $log.info(entry); + $log.info(values); + $modal.open({ animation: true, templateUrl: 'viewGroupModal.html', @@ -161,7 +161,7 @@ angular.module('ViewDictionaryModule', ['ui.bootstrap']) }); }; - $scope.annotate = function(soundEntity, markupEntity) { + $scope.annotate = function(sound, markup) { var modalInstance = $modal.open({ animation: true, @@ -169,11 +169,11 @@ angular.module('ViewDictionaryModule', ['ui.bootstrap']) controller: 'AnnotationController', size: 'lg', resolve: { - soundUrl: function() { - return soundEntity.content; - }, - annotationUrl: function() { - return markupEntity.content; + 'params': function() { + return { + 'sound': sound, + 'markup': markup + }; } } }); @@ -256,7 +256,7 @@ angular.module('ViewDictionaryModule', ['ui.bootstrap']) }]) - .controller('AnnotationController', ['$scope', '$http', 'soundUrl', 'annotationUrl', 'responseHandler', function($scope, $http, soundUrl, annotationUrl, responseHandler) { + .controller('AnnotationController', ['$scope', '$http', 'dictionaryService', 'responseHandler', 'params', function($scope, $http, dictionaryService, responseHandler, params) { var activeUrl = null; @@ -280,27 +280,6 @@ angular.module('ViewDictionaryModule', ['ui.bootstrap']) } }; - var loadAnnotation = function(url) { - // load annotation - $http.get(url).success(function(data, status, headers, config) { - - try { - var xml = (new DOMParser()).parseFromString(data, 'application/xml'); - var annotation = new elan.Document(); - annotation.importXML(xml); - $scope.annotation = annotation; - - createRegions(annotation); - - } catch (e) { - responseHandler.error('Failed to parse ELAN annotation: ' + e); - } - - }).error(function(data, status, headers, config) { - responseHandler.error(data); - }); - }; - $scope.paused = true; $scope.annotation = null; @@ -360,12 +339,24 @@ angular.module('ViewDictionaryModule', ['ui.bootstrap']) $scope.wavesurfer.once('ready', function() { // load annotation once file is loaded - loadAnnotation(annotationUrl); + dictionaryService.convertMarkup(params.markup).then(function(data) { + try { + var xml = (new DOMParser()).parseFromString(data.content, 'application/xml'); + var annotation = new elan.Document(); + annotation.importXML(xml); + $scope.annotation = annotation; + createRegions(annotation); + } catch (e) { + responseHandler.error('Failed to parse ELAN annotation: ' + e); + } + }, function(reason) { + responseHandler.error(reason); + }); $scope.$apply(); }); // load file once wavesurfer is ready - $scope.wavesurfer.load(soundUrl); + $scope.wavesurfer.load(params.sound.content); }); $scope.$on('modal.closing', function(e) { @@ -378,11 +369,6 @@ angular.module('ViewDictionaryModule', ['ui.bootstrap']) .controller('viewGroupController', ['$scope', '$http', '$modalInstance', '$log', 'dictionaryService', 'responseHandler', 'groupParams', function($scope, $http, $modalInstance, $log, dictionaryService, responseHandler, groupParams) { - var dictionaryClientId = $('#dictionaryClientId').data('lingvodoc'); - var dictionaryObjectId = $('#dictionaryObjectId').data('lingvodoc'); - var perspectiveClientId = $('#perspectiveClientId').data('lingvodoc'); - var perspectiveId = $('#perspectiveId').data('lingvodoc'); - WaveSurferController.call(this, $scope); $scope.title = groupParams.field.entity_type; @@ -394,10 +380,8 @@ angular.module('ViewDictionaryModule', ['ui.bootstrap']) var addValue = function(value, entries) { - var createNewEntry = true; if (value.additional_metadata) { for (var entryIndex = 0; entryIndex < entries.length; entryIndex++) { - var currentEntry = entries[entryIndex]; if (entries[entryIndex].client_id == value.client_id && entries[entryIndex].row_id == value.additional_metadata.row_id) { @@ -476,32 +460,6 @@ angular.module('ViewDictionaryModule', ['ui.bootstrap']) return values; }; - $scope.approve = function(lexicalEntry, field, fieldValue, approved) { - - var url = $('#approveEntityUrl').data('lingvodoc'); - - var obj = { - 'type': field.level, - 'client_id': fieldValue.client_id, - 'object_id': fieldValue.object_id - }; - - dictionaryService.approve(url, { 'entities': [obj] }, approved).then(function(data) { - fieldValue['published'] = approved; - }, function(reason) { - responseHandler.error(reason); - }); - }; - - $scope.approved = function(lexicalEntry, field, fieldValue) { - - if (!fieldValue.published) { - return false; - } - - return !!fieldValue.published; - }; - $scope.ok = function() { $modalInstance.close($scope.entries); }; @@ -514,11 +472,6 @@ angular.module('ViewDictionaryModule', ['ui.bootstrap']) .controller('viewGroupingTagController', ['$scope', '$http', '$modalInstance', '$q', '$log', 'dictionaryService', 'responseHandler', 'groupParams', function($scope, $http, $modalInstance, $q, $log, dictionaryService, responseHandler, groupParams) { - var dictionaryClientId = $('#dictionaryClientId').data('lingvodoc'); - var dictionaryObjectId = $('#dictionaryObjectId').data('lingvodoc'); - var perspectiveClientId = $('#perspectiveClientId').data('lingvodoc'); - var perspectiveId = $('#perspectiveId').data('lingvodoc'); - WaveSurferController.call(this, $scope); $scope.fields = groupParams.fields; @@ -606,5 +559,4 @@ angular.module('ViewDictionaryModule', ['ui.bootstrap']) }, function(reason) { responseHandler.error(reason); }); - }]); diff --git a/webui/src/templates/annotation.pt b/webui/src/templates/annotation.pt new file mode 100755 index 000000000..152c0db79 --- /dev/null +++ b/webui/src/templates/annotation.pt @@ -0,0 +1,72 @@ + \ No newline at end of file diff --git a/webui/src/templates/create_dictionary.pt b/webui/src/templates/create_dictionary.pt index 77012e877..fc3f38cf5 100755 --- a/webui/src/templates/create_dictionary.pt +++ b/webui/src/templates/create_dictionary.pt @@ -82,11 +82,12 @@
                    (Upload dictionary) - + -
                    +
                    @@ -327,6 +328,68 @@ + + + + + + + + + + + + + + + + + +
                    diff --git a/webui/src/templates/dashboard.pt b/webui/src/templates/dashboard.pt index 2d8d40378..9f21e9eeb 100755 --- a/webui/src/templates/dashboard.pt +++ b/webui/src/templates/dashboard.pt @@ -54,6 +54,7 @@ @@ -73,6 +74,7 @@
                  • Published
                  • +

                    @@ -98,8 +100,8 @@
                  • Edit roles
                  • -
                  • Edit - properties
                  • +
                  • Edit properties
                  • +
                  • Remove perspective
                  • @@ -177,6 +179,10 @@ + + +
                    @@ -303,11 +309,42 @@
                    + +
                    +
                    + Files +
                    +
                    + + + + + +
                    {{ blob.name }}
                    + + + + +
                    + +
                    + +
                    +
                    + Location +
                    +
                    + +
                    +
                    + @@ -523,7 +560,6 @@ - + + + + + + + + + + +
                    + +
                    + + + + \ No newline at end of file diff --git a/webui/src/templates/nav.pt b/webui/src/templates/nav.pt old mode 100644 new mode 100755 index ca8ece018..5296065d9 --- a/webui/src/templates/nav.pt +++ b/webui/src/templates/nav.pt @@ -25,6 +25,7 @@
                  • Languages
                  • Organizations
                  • +
                  • Maps search
                  • My files
                  • diff --git a/webui/src/templates/publish_dictionary.pt b/webui/src/templates/publish_dictionary.pt index fb299d310..7fa23bdfe 100755 --- a/webui/src/templates/publish_dictionary.pt +++ b/webui/src/templates/publish_dictionary.pt @@ -60,6 +60,7 @@
                    +
                    @@ -221,79 +222,6 @@
                    - - - - +
                    +
                    diff --git a/webui/src/templates/response_handler.pt b/webui/src/templates/response_handler.pt index 4cd7efd33..c4fba9ca3 100755 --- a/webui/src/templates/response_handler.pt +++ b/webui/src/templates/response_handler.pt @@ -12,3 +12,20 @@ + + + + diff --git a/webui/src/templates/user_upload.pt b/webui/src/templates/user_upload.pt index 57d24208f..e12260c5a 100755 --- a/webui/src/templates/user_upload.pt +++ b/webui/src/templates/user_upload.pt @@ -73,7 +73,15 @@ - Upload + Upload + + + + +
                    diff --git a/webui/src/templates/view_dictionary.pt b/webui/src/templates/view_dictionary.pt index a92ef49c0..2fca22ce9 100755 --- a/webui/src/templates/view_dictionary.pt +++ b/webui/src/templates/view_dictionary.pt @@ -52,6 +52,7 @@
                    +
                    @@ -176,79 +177,6 @@
                    - - - - +
                    +